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