updated openssl plugin to new private/public key API, use encoder framework
[strongswan.git] / src / libstrongswan / plugins / openssl / openssl_rsa_private_key.c
1 /*
2 * Copyright (C) 2009 Martin Willi
3 * Copyright (C) 2008 Tobias Brunner
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 */
16
17 #include "openssl_rsa_private_key.h"
18 #include "openssl_rsa_public_key.h"
19
20 #include <debug.h>
21
22 #include <openssl/evp.h>
23 #include <openssl/rsa.h>
24 #include <openssl/engine.h>
25
26 /**
27 * Public exponent to use for key generation.
28 */
29 #define PUBLIC_EXPONENT 0x10001
30
31 typedef struct private_openssl_rsa_private_key_t private_openssl_rsa_private_key_t;
32
33 /**
34 * Private data of a openssl_rsa_private_key_t object.
35 */
36 struct private_openssl_rsa_private_key_t {
37 /**
38 * Public interface for this signer.
39 */
40 openssl_rsa_private_key_t public;
41
42 /**
43 * RSA object from OpenSSL
44 */
45 RSA *rsa;
46
47 /**
48 * TRUE if the key is from an OpenSSL ENGINE and might not be readable
49 */
50 bool engine;
51
52 /**
53 * reference count
54 */
55 refcount_t ref;
56 };
57
58 /**
59 * Build an EMPSA PKCS1 signature described in PKCS#1
60 */
61 static bool build_emsa_pkcs1_signature(private_openssl_rsa_private_key_t *this,
62 int type, chunk_t data, chunk_t *sig)
63 {
64 bool success = FALSE;
65
66 *sig = chunk_alloc(RSA_size(this->rsa));
67
68 if (type == NID_undef)
69 {
70 if (RSA_private_encrypt(data.len, data.ptr, sig->ptr, this->rsa,
71 RSA_PKCS1_PADDING) == sig->len)
72 {
73 success = TRUE;
74 }
75 }
76 else
77 {
78 EVP_MD_CTX *ctx;
79 EVP_PKEY *key;
80 const EVP_MD *hasher;
81 u_int len;
82
83 hasher = EVP_get_digestbynid(type);
84 if (!hasher)
85 {
86 return FALSE;
87 }
88
89 ctx = EVP_MD_CTX_create();
90 key = EVP_PKEY_new();
91 if (!ctx || !key)
92 {
93 goto error;
94 }
95 if (!EVP_PKEY_set1_RSA(key, this->rsa))
96 {
97 goto error;
98 }
99 if (!EVP_SignInit_ex(ctx, hasher, NULL))
100 {
101 goto error;
102 }
103 if (!EVP_SignUpdate(ctx, data.ptr, data.len))
104 {
105 goto error;
106 }
107 if (EVP_SignFinal(ctx, sig->ptr, &len, key))
108 {
109 success = TRUE;
110 }
111
112 error:
113 if (key)
114 {
115 EVP_PKEY_free(key);
116 }
117 if (ctx)
118 {
119 EVP_MD_CTX_destroy(ctx);
120 }
121 }
122 if (!success)
123 {
124 free(sig->ptr);
125 }
126 return success;
127 }
128
129 /**
130 * Implementation of openssl_rsa_private_key.get_type.
131 */
132 static key_type_t get_type(private_openssl_rsa_private_key_t *this)
133 {
134 return KEY_RSA;
135 }
136
137 /**
138 * Implementation of openssl_rsa_private_key.sign.
139 */
140 static bool sign(private_openssl_rsa_private_key_t *this, signature_scheme_t scheme,
141 chunk_t data, chunk_t *signature)
142 {
143 switch (scheme)
144 {
145 case SIGN_RSA_EMSA_PKCS1_NULL:
146 return build_emsa_pkcs1_signature(this, NID_undef, data, signature);
147 case SIGN_RSA_EMSA_PKCS1_SHA1:
148 return build_emsa_pkcs1_signature(this, NID_sha1, data, signature);
149 case SIGN_RSA_EMSA_PKCS1_SHA224:
150 return build_emsa_pkcs1_signature(this, NID_sha224, data, signature);
151 case SIGN_RSA_EMSA_PKCS1_SHA256:
152 return build_emsa_pkcs1_signature(this, NID_sha256, data, signature);
153 case SIGN_RSA_EMSA_PKCS1_SHA384:
154 return build_emsa_pkcs1_signature(this, NID_sha384, data, signature);
155 case SIGN_RSA_EMSA_PKCS1_SHA512:
156 return build_emsa_pkcs1_signature(this, NID_sha512, data, signature);
157 case SIGN_RSA_EMSA_PKCS1_MD5:
158 return build_emsa_pkcs1_signature(this, NID_md5, data, signature);
159 default:
160 DBG1("signature scheme %N not supported in RSA",
161 signature_scheme_names, scheme);
162 return FALSE;
163 }
164 }
165
166 /**
167 * Implementation of openssl_rsa_private_key.decrypt.
168 */
169 static bool decrypt(private_openssl_rsa_private_key_t *this,
170 chunk_t crypto, chunk_t *plain)
171 {
172 DBG1("RSA private key decryption not implemented");
173 return FALSE;
174 }
175
176 /**
177 * Implementation of openssl_rsa_private_key.get_keysize.
178 */
179 static size_t get_keysize(private_openssl_rsa_private_key_t *this)
180 {
181 return RSA_size(this->rsa);
182 }
183
184 /**
185 * Implementation of openssl_rsa_private_key.get_public_key.
186 */
187 static public_key_t* get_public_key(private_openssl_rsa_private_key_t *this)
188 {
189 chunk_t enc;
190 public_key_t *key;
191 u_char *p;
192
193 enc = chunk_alloc(i2d_RSAPublicKey(this->rsa, NULL));
194 p = enc.ptr;
195 i2d_RSAPublicKey(this->rsa, &p);
196 key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
197 BUILD_BLOB_ASN1_DER, enc, BUILD_END);
198 free(enc.ptr);
199 return key;
200 }
201
202 /**
203 * Implementation of public_key_t.get_fingerprint.
204 */
205 static bool get_fingerprint(private_openssl_rsa_private_key_t *this,
206 key_encoding_type_t type, chunk_t *fingerprint)
207 {
208 chunk_t enc;
209 bool success;
210 u_char *p;
211
212 if (lib->encoding->get_cache(lib->encoding, type, this, fingerprint))
213 {
214 return TRUE;
215 }
216 enc = chunk_alloc(i2d_RSAPublicKey(this->rsa, NULL));
217 p = enc.ptr;
218 i2d_RSAPublicKey(this->rsa, &p);
219 success = lib->encoding->encode(lib->encoding, type, this, fingerprint,
220 KEY_PART_RSA_PUB_ASN1_DER, enc, KEY_PART_END);
221 free(enc.ptr);
222 return success;
223 }
224
225 /*
226 * Implementation of public_key_t.get_encoding.
227 */
228 static bool get_encoding(private_openssl_rsa_private_key_t *this,
229 key_encoding_type_t type, chunk_t *encoding)
230 {
231 chunk_t enc;
232 bool success;
233 u_char *p;
234
235 if (!this->engine)
236 {
237 return FALSE;
238 }
239 enc = chunk_alloc(i2d_RSAPrivateKey(this->rsa, NULL));
240 p = enc.ptr;
241 i2d_RSAPrivateKey(this->rsa, &p);
242 success = lib->encoding->encode(lib->encoding, type, NULL, encoding,
243 KEY_PART_RSA_PUB_ASN1_DER, enc, KEY_PART_END);
244 free(enc.ptr);
245 return success;
246 }
247
248 /**
249 * Implementation of openssl_rsa_private_key.get_ref.
250 */
251 static private_openssl_rsa_private_key_t* get_ref(private_openssl_rsa_private_key_t *this)
252 {
253 ref_get(&this->ref);
254 return this;
255 }
256
257 /**
258 * Implementation of openssl_rsa_private_key.destroy.
259 */
260 static void destroy(private_openssl_rsa_private_key_t *this)
261 {
262 if (ref_put(&this->ref))
263 {
264 if (this->rsa)
265 {
266 RSA_free(this->rsa);
267 }
268 lib->encoding->clear_cache(lib->encoding, this);
269 free(this);
270 }
271 }
272
273 /**
274 * Internal generic constructor
275 */
276 static private_openssl_rsa_private_key_t *create_empty(void)
277 {
278 private_openssl_rsa_private_key_t *this = malloc_thing(private_openssl_rsa_private_key_t);
279
280 this->public.interface.get_type = (key_type_t (*) (private_key_t*))get_type;
281 this->public.interface.sign = (bool (*) (private_key_t*, signature_scheme_t, chunk_t, chunk_t*))sign;
282 this->public.interface.decrypt = (bool (*) (private_key_t*, chunk_t, chunk_t*))decrypt;
283 this->public.interface.get_keysize = (size_t (*) (private_key_t*))get_keysize;
284 this->public.interface.get_public_key = (public_key_t* (*) (private_key_t*))get_public_key;
285 this->public.interface.equals = private_key_equals;
286 this->public.interface.belongs_to = private_key_belongs_to;
287 this->public.interface.get_fingerprint = (bool(*)(private_key_t*, key_encoding_type_t type, chunk_t *fp))get_fingerprint;
288 this->public.interface.get_encoding = (bool(*)(private_key_t*, key_encoding_type_t type, chunk_t *encoding))get_encoding;
289 this->public.interface.get_ref = (private_key_t* (*) (private_key_t*))get_ref;
290 this->public.interface.destroy = (void (*) (private_key_t*))destroy;
291
292 this->engine = FALSE;
293 this->ref = 1;
294
295 return this;
296 }
297
298 /**
299 * Generate an RSA key of specified key size
300 */
301 static openssl_rsa_private_key_t *generate(size_t key_size)
302 {
303 private_openssl_rsa_private_key_t *this = create_empty();
304
305 this->rsa = RSA_generate_key(key_size, PUBLIC_EXPONENT, NULL, NULL);
306
307 return &this->public;
308 }
309
310 /**
311 * load private key from an ASN1 encoded blob
312 */
313 static openssl_rsa_private_key_t *load(chunk_t blob)
314 {
315 u_char *p = blob.ptr;
316 private_openssl_rsa_private_key_t *this = create_empty();
317
318 this->rsa = d2i_RSAPrivateKey(NULL, (const u_char**)&p, blob.len);
319 if (!this->rsa)
320 {
321 destroy(this);
322 return NULL;
323 }
324 if (!RSA_check_key(this->rsa))
325 {
326 destroy(this);
327 return NULL;
328 }
329 return &this->public;
330 }
331
332 /**
333 * load private key from a smart card
334 */
335 static openssl_rsa_private_key_t *load_from_smartcard(char *keyid, char *pin)
336 {
337 private_openssl_rsa_private_key_t *this = NULL;
338 EVP_PKEY *key;
339 char *engine_id = lib->settings->get_str(lib->settings,
340 "library.plugins.openssl.engine_id", "pkcs11");
341
342 ENGINE *engine = ENGINE_by_id(engine_id);
343 if (!engine)
344 {
345 DBG1("engine '%s' is not available", engine_id);
346 return NULL;
347 }
348
349 if (!ENGINE_init(engine))
350 {
351 DBG1("failed to initialize engine '%s'", engine_id);
352 goto error;
353 }
354
355 if (!ENGINE_ctrl_cmd_string(engine, "PIN", pin, 0))
356 {
357 DBG1("failed to set PIN on engine '%s'", engine_id);
358 goto error;
359 }
360
361 key = ENGINE_load_private_key(engine, keyid, NULL, NULL);
362
363 if (!key)
364 {
365 DBG1("failed to load private key with ID '%s' from engine '%s'", keyid,
366 engine_id);
367 goto error;
368 }
369 ENGINE_free(engine);
370
371 this = create_empty();
372 this->rsa = EVP_PKEY_get1_RSA(key);
373 this->engine = TRUE;
374
375 return &this->public;
376
377 error:
378 ENGINE_free(engine);
379 return NULL;
380 }
381
382 typedef struct private_builder_t private_builder_t;
383
384 /**
385 * Builder implementation for key loading/generation
386 */
387 struct private_builder_t {
388 /** implements the builder interface */
389 builder_t public;
390 /** loaded/generated private key */
391 openssl_rsa_private_key_t *key;
392 /** temporary stored smartcard key ID */
393 char *keyid;
394 /** temporary stored smartcard pin */
395 char *pin;
396 };
397
398 /**
399 * Implementation of builder_t.build
400 */
401 static openssl_rsa_private_key_t *build(private_builder_t *this)
402 {
403 openssl_rsa_private_key_t *key = this->key;
404
405 if (this->keyid && this->pin)
406 {
407 key = load_from_smartcard(this->keyid, this->pin);
408 }
409 free(this);
410 return key;
411 }
412
413 /**
414 * Implementation of builder_t.add
415 */
416 static void add(private_builder_t *this, builder_part_t part, ...)
417 {
418 if (!this->key)
419 {
420 va_list args;
421
422 switch (part)
423 {
424 case BUILD_BLOB_ASN1_DER:
425 {
426 va_start(args, part);
427 this->key = load(va_arg(args, chunk_t));
428 va_end(args);
429 return;
430 }
431 case BUILD_KEY_SIZE:
432 {
433 va_start(args, part);
434 this->key = generate(va_arg(args, u_int));
435 va_end(args);
436 return;
437 }
438 case BUILD_SMARTCARD_KEYID:
439 {
440 va_start(args, part);
441 this->keyid = va_arg(args, char*);
442 va_end(args);
443 return;
444 }
445 case BUILD_SMARTCARD_PIN:
446 {
447 va_start(args, part);
448 this->pin = va_arg(args, char*);
449 va_end(args);
450 return;
451 }
452 default:
453 break;
454 }
455 }
456 if (this->key)
457 {
458 destroy((private_openssl_rsa_private_key_t*)this->key);
459 }
460 builder_cancel(&this->public);
461 }
462
463 /**
464 * Builder construction function
465 */
466 builder_t *openssl_rsa_private_key_builder(key_type_t type)
467 {
468 private_builder_t *this;
469
470 if (type != KEY_RSA)
471 {
472 return NULL;
473 }
474
475 this = malloc_thing(private_builder_t);
476
477 this->key = NULL;
478 this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add;
479 this->public.build = (void*(*)(builder_t *this))build;
480 this->keyid = NULL;
481 this->pin = NULL;
482
483 return &this->public;
484 }
485