support of SHA224-based certificate signatures
[strongswan.git] / src / libstrongswan / plugins / gcrypt / gcrypt_rsa_private_key.c
1 /*
2 * Copyright (C) 2005-2009 Martin Willi
3 * Hochschule fuer Technik Rapperswil
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include <gcrypt.h>
17
18 #include "gcrypt_rsa_private_key.h"
19
20 #include <debug.h>
21 #include <asn1/oid.h>
22 #include <asn1/asn1.h>
23 #include <asn1/asn1_parser.h>
24
25 typedef struct private_gcrypt_rsa_private_key_t private_gcrypt_rsa_private_key_t;
26
27 /**
28 * Private data of a gcrypt_rsa_private_key_t object.
29 */
30 struct private_gcrypt_rsa_private_key_t {
31
32 /**
33 * Public interface
34 */
35 gcrypt_rsa_private_key_t public;
36
37 /**
38 * gcrypt S-expression representing an RSA key
39 */
40 gcry_sexp_t key;
41
42 /**
43 * Keyid formed as a SHA-1 hash of a publicKey object
44 */
45 identification_t* keyid;
46
47 /**
48 * Keyid formed as a SHA-1 hash of a publicKeyInfo object
49 */
50 identification_t* keyid_info;
51
52 /**
53 * reference count
54 */
55 refcount_t ref;
56 };
57
58 /**
59 * Implemented in gcrypt_rsa_public_key.c
60 */
61 public_key_t *gcrypt_rsa_public_key_create_from_sexp(gcry_sexp_t key);
62
63 /**
64 * find a token in a S-expression. If a key is given, its length is used to
65 * pad the output to a given length.
66 */
67 chunk_t gcrypt_rsa_find_token(gcry_sexp_t sexp, char *name, gcry_sexp_t key)
68 {
69 gcry_sexp_t token;
70 chunk_t data = chunk_empty, tmp;
71 size_t len = 0;
72
73 token = gcry_sexp_find_token(sexp, name, 1);
74 if (token)
75 {
76 data.ptr = (char*)gcry_sexp_nth_data(token, 1, &data.len);
77 if (!data.ptr)
78 {
79 data.len = 0;
80 }
81 else
82 {
83 if (key)
84 {
85 /* gcrypt might return more bytes than necessary. Truncate
86 * to key lenght if key given, or prepend zeros if needed */
87 len = gcry_pk_get_nbits(key);
88 len = len / 8 + (len % 8 ? 1 : 0);
89 if (len > data.len)
90 {
91 tmp = chunk_alloc(len);
92 len -= data.len;
93 memset(tmp.ptr, 0, tmp.len - len);
94 memcpy(tmp.ptr + len, data.ptr, data.len);
95 data = tmp;
96 }
97 else if (len < data.len)
98 {
99 data = chunk_clone(chunk_skip(data, data.len - len));
100 }
101 else
102 {
103 data = chunk_clone(data);
104 }
105 }
106 else
107 {
108 data = chunk_clone(data);
109 }
110 }
111 gcry_sexp_release(token);
112 }
113 return data;
114 }
115
116 /**
117 * Sign a chunk of data with direct PKCS#1 encoding, no hash OID
118 */
119 static bool sign_raw(private_gcrypt_rsa_private_key_t *this,
120 chunk_t data, chunk_t *signature)
121 {
122 gcry_sexp_t in, out;
123 gcry_error_t err;
124 chunk_t em;
125 size_t k;
126
127 /* EM = 0x00 || 0x01 || PS || 0x00 || T
128 * PS = 0xFF padding, with length to fill em
129 * T = data
130 */
131 k = gcry_pk_get_nbits(this->key) / 8;
132 if (data.len > k - 3)
133 {
134 return FALSE;
135 }
136 em = chunk_alloc(k);
137 memset(em.ptr, 0xFF, em.len);
138 em.ptr[0] = 0x00;
139 em.ptr[1] = 0x01;
140 em.ptr[em.len - data.len - 1] = 0x00;
141 memcpy(em.ptr + em.len - data.len, data.ptr, data.len);
142
143 err = gcry_sexp_build(&in, NULL, "(data(flags raw)(value %b))",
144 em.len, em.ptr);
145 chunk_free(&em);
146 if (err)
147 {
148 DBG1("building signature S-expression failed: %s", gpg_strerror(err));
149 return FALSE;
150 }
151 err = gcry_pk_sign(&out, in, this->key);
152 gcry_sexp_release(in);
153 if (err)
154 {
155 DBG1("creating pkcs1 signature failed: %s", gpg_strerror(err));
156 return FALSE;
157 }
158 *signature = gcrypt_rsa_find_token(out, "s", this->key);
159 gcry_sexp_release(out);
160 return !!signature->len;
161 }
162
163 /**
164 * Sign a chunk of data using hashing and PKCS#1 encoding
165 */
166 static bool sign_pkcs1(private_gcrypt_rsa_private_key_t *this,
167 hash_algorithm_t hash_algorithm, char *hash_name,
168 chunk_t data, chunk_t *signature)
169 {
170 hasher_t *hasher;
171 chunk_t hash;
172 gcry_error_t err;
173 gcry_sexp_t in, out;
174 int hash_oid;
175
176 hash_oid = hasher_algorithm_to_oid(hash_algorithm);
177 if (hash_oid == OID_UNKNOWN)
178 {
179 return FALSE;
180 }
181 hasher = lib->crypto->create_hasher(lib->crypto, hash_algorithm);
182 if (!hasher)
183 {
184 return FALSE;
185 }
186 hasher->allocate_hash(hasher, data, &hash);
187 hasher->destroy(hasher);
188
189 err = gcry_sexp_build(&in, NULL, "(data(flags pkcs1)(hash %s %b))",
190 hash_name, hash.len, hash.ptr);
191 chunk_free(&hash);
192 if (err)
193 {
194 DBG1("building signature S-expression failed: %s", gpg_strerror(err));
195 return FALSE;
196 }
197 err = gcry_pk_sign(&out, in, this->key);
198 gcry_sexp_release(in);
199 if (err)
200 {
201 DBG1("creating pkcs1 signature failed: %s", gpg_strerror(err));
202 return FALSE;
203 }
204 *signature = gcrypt_rsa_find_token(out, "s", this->key);
205 gcry_sexp_release(out);
206 return !!signature->len;
207 }
208
209 /**
210 * Implementation of gcrypt_rsa_private_key.destroy.
211 */
212 static key_type_t get_type(private_gcrypt_rsa_private_key_t *this)
213 {
214 return KEY_RSA;
215 }
216
217 /**
218 * Implementation of gcrypt_rsa_private_key.destroy.
219 */
220 static bool sign(private_gcrypt_rsa_private_key_t *this, signature_scheme_t scheme,
221 chunk_t data, chunk_t *sig)
222 {
223 switch (scheme)
224 {
225 case SIGN_RSA_EMSA_PKCS1_NULL:
226 return sign_raw(this, data, sig);
227 case SIGN_RSA_EMSA_PKCS1_SHA1:
228 return sign_pkcs1(this, HASH_SHA1, "sha1", data, sig);
229 case SIGN_RSA_EMSA_PKCS1_SHA224:
230 return sign_pkcs1(this, HASH_SHA224, "sha224", data, sig);
231 case SIGN_RSA_EMSA_PKCS1_SHA256:
232 return sign_pkcs1(this, HASH_SHA256, "sha256", data, sig);
233 case SIGN_RSA_EMSA_PKCS1_SHA384:
234 return sign_pkcs1(this, HASH_SHA384, "sha384", data, sig);
235 case SIGN_RSA_EMSA_PKCS1_SHA512:
236 return sign_pkcs1(this, HASH_SHA512, "sha512", data, sig);
237 case SIGN_RSA_EMSA_PKCS1_MD5:
238 return sign_pkcs1(this, HASH_MD5, "md5", data, sig);
239 default:
240 DBG1("signature scheme %N not supported in RSA",
241 signature_scheme_names, scheme);
242 return FALSE;
243 }
244 }
245
246 /**
247 * Implementation of gcrypt_rsa_private_key.destroy.
248 */
249 static bool decrypt(private_gcrypt_rsa_private_key_t *this,
250 chunk_t encrypted, chunk_t *plain)
251 {
252 gcry_error_t err;
253 gcry_sexp_t in, out;
254 chunk_t padded;
255 u_char *pos = NULL;;
256
257 err = gcry_sexp_build(&in, NULL, "(enc-val(flags)(rsa(a %b)))",
258 encrypted.len, encrypted.ptr);
259 if (err)
260 {
261 DBG1("building decryption S-expression failed: %s", gpg_strerror(err));
262 return FALSE;
263 }
264 err = gcry_pk_decrypt(&out, in, this->key);
265 gcry_sexp_release(in);
266 if (err)
267 {
268 DBG1("decrypting pkcs1 data failed: %s", gpg_strerror(err));
269 return FALSE;
270 }
271 padded.ptr = (u_char*)gcry_sexp_nth_data(out, 1, &padded.len);
272 /* result is padded, but gcrypt strips leading zero:
273 * 00 | 02 | RANDOM | 00 | DATA */
274 if (padded.ptr && padded.len > 2 && padded.ptr[0] == 0x02)
275 {
276 pos = memchr(padded.ptr, 0x00, padded.len - 1);
277 if (pos)
278 {
279 pos++;
280 *plain = chunk_clone(chunk_create(
281 pos, padded.len - (pos - padded.ptr)));
282 }
283 }
284 gcry_sexp_release(out);
285 if (!pos)
286 {
287 DBG1("decrypted data has invalid pkcs1 padding");
288 return FALSE;
289 }
290 return TRUE;
291 }
292
293 /**
294 * Implementation of gcrypt_rsa_private_key.get_keysize.
295 */
296 static size_t get_keysize(private_gcrypt_rsa_private_key_t *this)
297 {
298 return gcry_pk_get_nbits(this->key) / 8;
299 }
300
301 /**
302 * Implementation of gcrypt_rsa_private_key.destroy.
303 */
304 static identification_t* get_id(private_gcrypt_rsa_private_key_t *this,
305 id_type_t type)
306 {
307 switch (type)
308 {
309 case ID_PUBKEY_INFO_SHA1:
310 return this->keyid_info;
311 case ID_PUBKEY_SHA1:
312 return this->keyid;
313 default:
314 return NULL;
315 }
316 }
317
318 /**
319 * Implementation of gcrypt_rsa_private_key.get_public_key.
320 */
321 static public_key_t* get_public_key(private_gcrypt_rsa_private_key_t *this)
322 {
323 return gcrypt_rsa_public_key_create_from_sexp(this->key);
324 }
325
326 /**
327 * Implementation of gcrypt_rsa_private_key.equals.
328 */
329 static bool equals(private_gcrypt_rsa_private_key_t *this, private_key_t *other)
330 {
331 identification_t *keyid;
332
333 if (&this->public.interface == other)
334 {
335 return TRUE;
336 }
337 if (other->get_type(other) != KEY_RSA)
338 {
339 return FALSE;
340 }
341 keyid = other->get_id(other, ID_PUBKEY_SHA1);
342 if (keyid && keyid->equals(keyid, this->keyid))
343 {
344 return TRUE;
345 }
346 keyid = other->get_id(other, ID_PUBKEY_INFO_SHA1);
347 if (keyid && keyid->equals(keyid, this->keyid_info))
348 {
349 return TRUE;
350 }
351 return FALSE;
352 }
353
354 /**
355 * Implementation of gcrypt_rsa_private_key.belongs_to.
356 */
357 static bool belongs_to(private_gcrypt_rsa_private_key_t *this,
358 public_key_t *public)
359 {
360 identification_t *keyid;
361
362 if (public->get_type(public) != KEY_RSA)
363 {
364 return FALSE;
365 }
366 keyid = public->get_id(public, ID_PUBKEY_SHA1);
367 if (keyid && keyid->equals(keyid, this->keyid))
368 {
369 return TRUE;
370 }
371 keyid = public->get_id(public, ID_PUBKEY_INFO_SHA1);
372 if (keyid && keyid->equals(keyid, this->keyid_info))
373 {
374 return TRUE;
375 }
376 return FALSE;
377 }
378
379 /**
380 * Implementation of private_key_t.get_encoding.
381 */
382 static chunk_t get_encoding(private_gcrypt_rsa_private_key_t *this)
383 {
384 chunk_t cp, cq, cd, cexp1 = chunk_empty, cexp2 = chunk_empty;
385 gcry_mpi_t p = NULL, q = NULL, d = NULL, exp1, exp2;
386 gcry_error_t err;
387
388 /* p and q are swapped, gcrypt expects p < q */
389 cp = gcrypt_rsa_find_token(this->key, "q", NULL);
390 cq = gcrypt_rsa_find_token(this->key, "p", NULL);
391 cd = gcrypt_rsa_find_token(this->key, "d", NULL);
392
393 err = gcry_mpi_scan(&p, GCRYMPI_FMT_USG, cp.ptr, cp.len, NULL)
394 | gcry_mpi_scan(&q, GCRYMPI_FMT_USG, cq.ptr, cq.len, NULL)
395 | gcry_mpi_scan(&d, GCRYMPI_FMT_USG, cd.ptr, cd.len, NULL);
396 if (err)
397 {
398 gcry_mpi_release(p);
399 gcry_mpi_release(q);
400 gcry_mpi_release(d);
401 chunk_clear(&cp);
402 chunk_clear(&cq);
403 chunk_clear(&cd);
404 DBG1("scanning mpi for export failed: %s", gpg_strerror(err));
405 return chunk_empty;
406 }
407
408 gcry_mpi_sub_ui(p, p, 1);
409 exp1 = gcry_mpi_new(gcry_pk_get_nbits(this->key));
410 gcry_mpi_mod(exp1, d, p);
411 gcry_mpi_release(p);
412
413 gcry_mpi_sub_ui(q, q, 1);
414 exp2 = gcry_mpi_new(gcry_pk_get_nbits(this->key));
415 gcry_mpi_mod(exp1, d, q);
416 gcry_mpi_release(q);
417
418 err = gcry_mpi_aprint(GCRYMPI_FMT_USG, &cexp1.ptr, &cexp1.len, exp1)
419 | gcry_mpi_aprint(GCRYMPI_FMT_USG, &cexp2.ptr, &cexp2.len, exp2);
420
421 gcry_mpi_release(d);
422 gcry_mpi_release(exp1);
423 gcry_mpi_release(exp2);
424
425 if (err)
426 {
427 DBG1("printing mpi for export failed: %s", gpg_strerror(err));
428 chunk_clear(&cp);
429 chunk_clear(&cq);
430 chunk_clear(&cd);
431 chunk_clear(&cexp1);
432 chunk_clear(&cexp2);
433 return chunk_empty;
434 }
435
436 return asn1_wrap(ASN1_SEQUENCE, "cmmmmmmmm", ASN1_INTEGER_0,
437 asn1_integer("m", gcrypt_rsa_find_token(this->key, "n", NULL)),
438 asn1_integer("m", gcrypt_rsa_find_token(this->key, "e", NULL)),
439 asn1_integer("m", cd),
440 asn1_integer("m", cp),
441 asn1_integer("m", cq),
442 asn1_integer("m", cexp1),
443 asn1_integer("m", cexp2),
444 asn1_integer("m", gcrypt_rsa_find_token(this->key, "u", NULL)));
445 }
446
447 /**
448 * Implementation of gcrypt_rsa_private_key.get_ref.
449 */
450 static private_key_t* get_ref(private_gcrypt_rsa_private_key_t *this)
451 {
452 ref_get(&this->ref);
453 return &this->public.interface;
454 }
455
456 /**
457 * Implementation of gcrypt_rsa_private_key.destroy.
458 */
459 static void destroy(private_gcrypt_rsa_private_key_t *this)
460 {
461 if (ref_put(&this->ref))
462 {
463 DESTROY_IF(this->keyid);
464 DESTROY_IF(this->keyid_info);
465 gcry_sexp_release(this->key);
466 free(this);
467 }
468 }
469
470 /**
471 * Internal generic constructor
472 */
473 static private_gcrypt_rsa_private_key_t *gcrypt_rsa_private_key_create_empty()
474 {
475 private_gcrypt_rsa_private_key_t *this = malloc_thing(private_gcrypt_rsa_private_key_t);
476
477 this->public.interface.get_type = (key_type_t (*)(private_key_t *this))get_type;
478 this->public.interface.sign = (bool (*)(private_key_t *this, signature_scheme_t scheme, chunk_t data, chunk_t *signature))sign;
479 this->public.interface.decrypt = (bool (*)(private_key_t *this, chunk_t crypto, chunk_t *plain))decrypt;
480 this->public.interface.get_keysize = (size_t (*) (private_key_t *this))get_keysize;
481 this->public.interface.get_id = (identification_t* (*) (private_key_t *this,id_type_t))get_id;
482 this->public.interface.get_public_key = (public_key_t* (*)(private_key_t *this))get_public_key;
483 this->public.interface.equals = (bool (*) (private_key_t*, private_key_t*))equals;
484 this->public.interface.belongs_to = (bool (*) (private_key_t *this, public_key_t *public))belongs_to;
485 this->public.interface.get_encoding = (chunk_t(*)(private_key_t*))get_encoding;
486 this->public.interface.get_ref = (private_key_t* (*)(private_key_t *this))get_ref;
487 this->public.interface.destroy = (void (*)(private_key_t *this))destroy;
488
489 this->key = NULL;
490 this->keyid = NULL;
491 this->keyid_info = NULL;
492 this->ref = 1;
493
494 return this;
495 }
496
497 /**
498 * build the keyids of a private/public key
499 */
500 bool gcrypt_rsa_build_keyids(gcry_sexp_t key, identification_t **keyid,
501 identification_t **keyid_info)
502 {
503 chunk_t publicKeyInfo, publicKey, hash;
504 hasher_t *hasher;
505
506 hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
507 if (!hasher)
508 {
509 DBG1("SHA1 hash algorithm not supported, unable to use RSA");
510 return FALSE;
511 }
512 publicKey = asn1_wrap(ASN1_SEQUENCE, "mm",
513 asn1_integer("m", gcrypt_rsa_find_token(key, "n", NULL)),
514 asn1_integer("m", gcrypt_rsa_find_token(key, "e", NULL)));
515 hasher->allocate_hash(hasher, publicKey, &hash);
516 *keyid = identification_create_from_encoding(ID_PUBKEY_SHA1, hash);
517 chunk_free(&hash);
518
519 publicKeyInfo = asn1_wrap(ASN1_SEQUENCE, "cm",
520 asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
521 asn1_bitstring("m", publicKey));
522 hasher->allocate_hash(hasher, publicKeyInfo, &hash);
523 *keyid_info = identification_create_from_encoding(ID_PUBKEY_INFO_SHA1, hash);
524 chunk_free(&hash);
525
526 hasher->destroy(hasher);
527 chunk_free(&publicKeyInfo);
528
529 return TRUE;
530 }
531
532 /**
533 * Generate an RSA key of specified key size
534 */
535 static gcrypt_rsa_private_key_t *generate(size_t key_size)
536 {
537 private_gcrypt_rsa_private_key_t *this;
538 gcry_sexp_t param, key;
539 gcry_error_t err;
540
541 err = gcry_sexp_build(&param, NULL, "(genkey(rsa(nbits %d)))", key_size);
542 if (err)
543 {
544 DBG1("building S-expression failed: %s", gpg_strerror(err));
545 return NULL;
546 }
547
548 err = gcry_pk_genkey(&key, param);
549 gcry_sexp_release(param);
550 if (err)
551 {
552 DBG1("generating RSA key failed: %s", gpg_strerror(err));
553 return NULL;
554 }
555 this = gcrypt_rsa_private_key_create_empty();
556 this->key = key;
557
558 if (!gcrypt_rsa_build_keyids(this->key, &this->keyid, &this->keyid_info))
559 {
560 destroy(this);
561 return NULL;
562 }
563
564 return &this->public;
565 }
566
567 /**
568 * ASN.1 definition of a PKCS#1 RSA private key
569 */
570 static const asn1Object_t privkeyObjects[] = {
571 { 0, "RSAPrivateKey", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
572 { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
573 { 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 2 */
574 { 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 3 */
575 { 1, "privateExponent", ASN1_INTEGER, ASN1_BODY }, /* 4 */
576 { 1, "prime1", ASN1_INTEGER, ASN1_BODY }, /* 5 */
577 { 1, "prime2", ASN1_INTEGER, ASN1_BODY }, /* 6 */
578 { 1, "exponent1", ASN1_INTEGER, ASN1_BODY }, /* 7 */
579 { 1, "exponent2", ASN1_INTEGER, ASN1_BODY }, /* 8 */
580 { 1, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 9 */
581 { 1, "otherPrimeInfos", ASN1_SEQUENCE, ASN1_OPT |
582 ASN1_LOOP }, /* 10 */
583 { 2, "otherPrimeInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 11 */
584 { 3, "prime", ASN1_INTEGER, ASN1_BODY }, /* 12 */
585 { 3, "exponent", ASN1_INTEGER, ASN1_BODY }, /* 13 */
586 { 3, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 14 */
587 { 1, "end opt or loop", ASN1_EOC, ASN1_END }, /* 15 */
588 { 0, "exit", ASN1_EOC, ASN1_EXIT }
589 };
590 #define PRIV_KEY_VERSION 1
591 #define PRIV_KEY_MODULUS 2
592 #define PRIV_KEY_PUB_EXP 3
593 #define PRIV_KEY_PRIV_EXP 4
594 #define PRIV_KEY_PRIME1 5
595 #define PRIV_KEY_PRIME2 6
596 #define PRIV_KEY_EXP1 7
597 #define PRIV_KEY_EXP2 8
598 #define PRIV_KEY_COEFF 9
599
600 /**
601 * load private key from a ASN1 encoded blob
602 */
603 static gcrypt_rsa_private_key_t *load(chunk_t blob)
604 {
605 private_gcrypt_rsa_private_key_t *this;
606 asn1_parser_t *parser;
607 chunk_t object;
608 int objectID ;
609 bool success = FALSE;
610 chunk_t n, e, d, u, p, q;
611 gcry_error_t err;
612
613 n = e = d = u = p = q = chunk_empty;
614
615 parser = asn1_parser_create(privkeyObjects, blob);
616 parser->set_flags(parser, FALSE, TRUE);
617
618 while (parser->iterate(parser, &objectID, &object))
619 {
620 switch (objectID)
621 {
622 case PRIV_KEY_VERSION:
623 if (object.len > 0 && *object.ptr != 0)
624 {
625 goto end;
626 }
627 break;
628 case PRIV_KEY_MODULUS:
629 n = object;
630 break;
631 case PRIV_KEY_PUB_EXP:
632 e = object;
633 break;
634 case PRIV_KEY_PRIV_EXP:
635 d = object;
636 break;
637 case PRIV_KEY_PRIME1:
638 /* p and q are swapped, as gcrypt expects p < q */
639 q = object;
640 break;
641 case PRIV_KEY_PRIME2:
642 p = object;
643 break;
644 case PRIV_KEY_EXP1:
645 case PRIV_KEY_EXP2:
646 break;
647 case PRIV_KEY_COEFF:
648 u = object;
649 break;
650 }
651 }
652 success = parser->success(parser);
653
654 end:
655 parser->destroy(parser);
656
657 if (!success)
658 {
659 return NULL;
660 }
661
662 this = gcrypt_rsa_private_key_create_empty();
663 err = gcry_sexp_build(&this->key, NULL,
664 "(private-key(rsa(n %b)(e %b)(d %b)(p %b)(q %b)(u %b)))",
665 n.len, n.ptr, e.len, e.ptr, d.len, d.ptr,
666 p.len, p.ptr, q.len, q.ptr, u.len, u.ptr);
667 if (err)
668 {
669 DBG1("loading private key failed: %s", gpg_strerror(err));
670 free(this);
671 return NULL;
672 }
673 err = gcry_pk_testkey(this->key);
674 if (err)
675 {
676 DBG1("private key sanity check failed: %s", gpg_strerror(err));
677 destroy(this);
678 return NULL;
679 }
680 if (!gcrypt_rsa_build_keyids(this->key, &this->keyid, &this->keyid_info))
681 {
682 destroy(this);
683 return NULL;
684 }
685 return &this->public;
686 }
687
688 typedef struct private_builder_t private_builder_t;
689
690 /**
691 * Builder implementation for key loading/generation
692 */
693 struct private_builder_t {
694 /** implements the builder interface */
695 builder_t public;
696 /** loaded/generated private key */
697 gcrypt_rsa_private_key_t *key;
698 };
699
700 /**
701 * Implementation of builder_t.build
702 */
703 static gcrypt_rsa_private_key_t *build(private_builder_t *this)
704 {
705 gcrypt_rsa_private_key_t *key = this->key;
706
707 free(this);
708 return key;
709 }
710
711 /**
712 * Implementation of builder_t.add
713 */
714 static void add(private_builder_t *this, builder_part_t part, ...)
715 {
716 if (!this->key)
717 {
718 va_list args;
719
720 switch (part)
721 {
722 case BUILD_BLOB_ASN1_DER:
723 {
724 va_start(args, part);
725 this->key = load(va_arg(args, chunk_t));
726 va_end(args);
727 return;
728 }
729 case BUILD_KEY_SIZE:
730 {
731 va_start(args, part);
732 this->key = generate(va_arg(args, u_int));
733 va_end(args);
734 return;
735 }
736 default:
737 break;
738 }
739 }
740 if (this->key)
741 {
742 destroy((private_gcrypt_rsa_private_key_t*)this->key);
743 }
744 builder_cancel(&this->public);
745 }
746
747 /**
748 * Builder construction function
749 */
750 builder_t *gcrypt_rsa_private_key_builder(key_type_t type)
751 {
752 private_builder_t *this;
753
754 if (type != KEY_RSA)
755 {
756 return NULL;
757 }
758
759 this = malloc_thing(private_builder_t);
760
761 this->key = NULL;
762 this->public.add = (void(*)(builder_t *this, builder_part_t part, ...))add;
763 this->public.build = (void*(*)(builder_t *this))build;
764
765 return &this->public;
766 }
767