]> git.ipfire.org Git - people/ms/strongswan.git/blob - src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c
gcrypt: Support RSA OAEP SHA1 encryption/decryption
[people/ms/strongswan.git] / src / libstrongswan / plugins / gcrypt / gcrypt_rsa_private_key.c
1 /*
2 * Copyright (C) 2017 Tobias Brunner
3 * Copyright (C) 2005-2009 Martin Willi
4 * HSR 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 <gcrypt.h>
18
19 #include "gcrypt_rsa_private_key.h"
20
21 #include <utils/debug.h>
22 #include <asn1/oid.h>
23 #include <asn1/asn1.h>
24 #include <asn1/asn1_parser.h>
25 #include <credentials/keys/signature_params.h>
26
27 typedef struct private_gcrypt_rsa_private_key_t private_gcrypt_rsa_private_key_t;
28
29 /**
30 * Private data of a gcrypt_rsa_private_key_t object.
31 */
32 struct private_gcrypt_rsa_private_key_t {
33
34 /**
35 * Public interface
36 */
37 gcrypt_rsa_private_key_t public;
38
39 /**
40 * gcrypt S-expression representing an RSA key
41 */
42 gcry_sexp_t key;
43
44 /**
45 * reference count
46 */
47 refcount_t ref;
48 };
49
50 /**
51 * find a token in a S-expression. If a key is given, its length is used to
52 * pad the output to a given length.
53 */
54 chunk_t gcrypt_rsa_find_token(gcry_sexp_t sexp, char *name, gcry_sexp_t key)
55 {
56 gcry_sexp_t token;
57 chunk_t data = chunk_empty, tmp;
58 size_t len = 0;
59
60 token = gcry_sexp_find_token(sexp, name, 1);
61 if (token)
62 {
63 data.ptr = (char*)gcry_sexp_nth_data(token, 1, &data.len);
64 if (!data.ptr)
65 {
66 data.len = 0;
67 }
68 else
69 {
70 if (key)
71 {
72 /* gcrypt might return more bytes than necessary. Truncate
73 * to key length if key given, or prepend zeros if needed */
74 len = gcry_pk_get_nbits(key);
75 len = len / 8 + (len % 8 ? 1 : 0);
76 if (len > data.len)
77 {
78 tmp = chunk_alloc(len);
79 len -= data.len;
80 memset(tmp.ptr, 0, tmp.len - len);
81 memcpy(tmp.ptr + len, data.ptr, data.len);
82 data = tmp;
83 }
84 else if (len < data.len)
85 {
86 data = chunk_clone(chunk_skip(data, data.len - len));
87 }
88 else
89 {
90 data = chunk_clone(data);
91 }
92 }
93 else
94 {
95 data = chunk_clone(data);
96 }
97 }
98 gcry_sexp_release(token);
99 }
100 return data;
101 }
102
103 /**
104 * Sign a chunk of data with direct PKCS#1 encoding, no hash OID
105 */
106 static bool sign_raw(private_gcrypt_rsa_private_key_t *this,
107 chunk_t data, chunk_t *signature)
108 {
109 gcry_sexp_t in, out;
110 gcry_error_t err;
111 chunk_t em;
112 size_t k;
113
114 /* EM = 0x00 || 0x01 || PS || 0x00 || T
115 * PS = 0xFF padding, with length to fill em
116 * T = data
117 */
118 k = gcry_pk_get_nbits(this->key) / 8;
119 if (data.len > k - 3)
120 {
121 return FALSE;
122 }
123 em = chunk_alloc(k);
124 memset(em.ptr, 0xFF, em.len);
125 em.ptr[0] = 0x00;
126 em.ptr[1] = 0x01;
127 em.ptr[em.len - data.len - 1] = 0x00;
128 memcpy(em.ptr + em.len - data.len, data.ptr, data.len);
129
130 err = gcry_sexp_build(&in, NULL, "(data(flags raw)(value %b))",
131 em.len, em.ptr);
132 chunk_free(&em);
133 if (err)
134 {
135 DBG1(DBG_LIB, "building signature S-expression failed: %s",
136 gpg_strerror(err));
137 return FALSE;
138 }
139 err = gcry_pk_sign(&out, in, this->key);
140 gcry_sexp_release(in);
141 if (err)
142 {
143 DBG1(DBG_LIB, "creating pkcs1 signature failed: %s", gpg_strerror(err));
144 return FALSE;
145 }
146 *signature = gcrypt_rsa_find_token(out, "s", this->key);
147 gcry_sexp_release(out);
148 return !!signature->len;
149 }
150
151 /**
152 * Sign a chunk of data using hashing and PKCS#1v1.5/EMSA-PSS encoding
153 */
154 static bool sign_pkcs1(private_gcrypt_rsa_private_key_t *this,
155 hash_algorithm_t hash_algorithm, rsa_pss_params_t *pss,
156 chunk_t data, chunk_t *signature)
157 {
158 hasher_t *hasher;
159 chunk_t hash;
160 gcry_error_t err;
161 gcry_sexp_t in, out;
162 char *hash_name = enum_to_name(hash_algorithm_short_names, hash_algorithm);
163
164 hasher = lib->crypto->create_hasher(lib->crypto, hash_algorithm);
165 if (!hasher)
166 {
167 DBG1(DBG_LIB, "hash algorithm %N not supported",
168 hash_algorithm_names, hash_algorithm);
169 return FALSE;
170 }
171 if (!hasher->allocate_hash(hasher, data, &hash))
172 {
173 hasher->destroy(hasher);
174 return FALSE;
175 }
176 hasher->destroy(hasher);
177
178 if (pss)
179 {
180 if (pss->salt.len)
181 {
182 err = gcry_sexp_build(&in, NULL,
183 "(data(flags pss)(salt-length %u)"
184 "(random-override %b)(hash %s %b))",
185 pss->salt.len, pss->salt.len, pss->salt.ptr,
186 hash_name, hash.len, hash.ptr);
187 }
188 else
189 {
190 u_int slen = pss->salt_len;
191 err = gcry_sexp_build(&in, NULL,
192 "(data(flags pss)(salt-length %u)(hash %s %b))",
193 slen, hash_name, hash.len, hash.ptr);
194 }
195 }
196 else
197 {
198 err = gcry_sexp_build(&in, NULL, "(data(flags pkcs1)(hash %s %b))",
199 hash_name, hash.len, hash.ptr);
200 }
201 chunk_free(&hash);
202 if (err)
203 {
204 DBG1(DBG_LIB, "building signature S-expression failed: %s",
205 gpg_strerror(err));
206 return FALSE;
207 }
208 err = gcry_pk_sign(&out, in, this->key);
209 gcry_sexp_release(in);
210 if (err)
211 {
212 DBG1(DBG_LIB, "creating pkcs1 signature failed: %s",
213 gpg_strerror(err));
214 return FALSE;
215 }
216
217 *signature = gcrypt_rsa_find_token(out, "s", this->key);
218 gcry_sexp_release(out);
219 return !!signature->len;
220 }
221
222 #if GCRYPT_VERSION_NUMBER >= 0x010700
223 /**
224 * Sign a chunk of data using hashing and EMSA-PSS encoding
225 */
226 static bool sign_pss(private_gcrypt_rsa_private_key_t *this,
227 rsa_pss_params_t *params, chunk_t data, chunk_t *signature)
228 {
229 if (!params)
230 {
231 return FALSE;
232 }
233 if (params->mgf1_hash != params->hash)
234 {
235 DBG1(DBG_LIB, "unable to use a different MGF1 hash for RSA-PSS");
236 return FALSE;
237 }
238 return sign_pkcs1(this, params->hash, params, data, signature);
239 }
240 #endif
241
242 METHOD(private_key_t, get_type, key_type_t,
243 private_gcrypt_rsa_private_key_t *this)
244 {
245 return KEY_RSA;
246 }
247
248 METHOD(private_key_t, sign, bool,
249 private_gcrypt_rsa_private_key_t *this, signature_scheme_t scheme,
250 void *params, chunk_t data, chunk_t *sig)
251 {
252 switch (scheme)
253 {
254 case SIGN_RSA_EMSA_PKCS1_NULL:
255 return sign_raw(this, data, sig);
256 case SIGN_RSA_EMSA_PKCS1_SHA2_224:
257 return sign_pkcs1(this, HASH_SHA224, NULL, data, sig);
258 case SIGN_RSA_EMSA_PKCS1_SHA2_256:
259 return sign_pkcs1(this, HASH_SHA256, NULL, data, sig);
260 case SIGN_RSA_EMSA_PKCS1_SHA2_384:
261 return sign_pkcs1(this, HASH_SHA384, NULL, data, sig);
262 case SIGN_RSA_EMSA_PKCS1_SHA2_512:
263 return sign_pkcs1(this, HASH_SHA512, NULL, data, sig);
264 case SIGN_RSA_EMSA_PKCS1_SHA1:
265 return sign_pkcs1(this, HASH_SHA1, NULL, data, sig);
266 case SIGN_RSA_EMSA_PKCS1_MD5:
267 return sign_pkcs1(this, HASH_MD5, NULL, data, sig);
268 #if GCRYPT_VERSION_NUMBER >= 0x010700
269 case SIGN_RSA_EMSA_PSS:
270 return sign_pss(this, params, data, sig);
271 #endif
272 default:
273 DBG1(DBG_LIB, "signature scheme %N not supported in RSA",
274 signature_scheme_names, scheme);
275 return FALSE;
276 }
277 }
278
279 METHOD(private_key_t, decrypt, bool,
280 private_gcrypt_rsa_private_key_t *this, encryption_scheme_t scheme,
281 void *params, chunk_t encrypted, chunk_t *plain)
282 {
283 gcry_error_t err;
284 gcry_sexp_t in, out;
285 chunk_t label = chunk_empty, decrypted;
286 u_char *sexp;
287
288 switch (scheme)
289 {
290 case ENCRYPT_RSA_PKCS1:
291 sexp = "(enc-val(flags pkcs1)(rsa(a %b)))";
292 break;
293 case ENCRYPT_RSA_OAEP_SHA1:
294 sexp = "(enc-val(flags oaep)(rsa(a %b)))";
295 break;
296 default:
297 DBG1(DBG_LIB, "encryption scheme %N not supported",
298 encryption_scheme_names, scheme);
299 return FALSE;
300 }
301
302 if (scheme == ENCRYPT_RSA_OAEP_SHA1 && params != NULL)
303 {
304 label = *(chunk_t *)params;
305 if (label.len > 0)
306 {
307 DBG1(DBG_LIB, "RSA OAEP decryption with a label not supported");
308 return FALSE;
309 }
310 }
311
312 err = gcry_sexp_build(&in, NULL, sexp, encrypted.len, encrypted.ptr);
313 if (err)
314 {
315 DBG1(DBG_LIB, "building decryption S-expression failed: %s",
316 gpg_strerror(err));
317 return FALSE;
318 }
319
320 err = gcry_pk_decrypt(&out, in, this->key);
321 gcry_sexp_release(in);
322 if (err)
323 {
324 DBG1(DBG_LIB, "RSA decryption failed: %s", gpg_strerror(err));
325 return FALSE;
326 }
327
328 decrypted.ptr = (u_char*)gcry_sexp_nth_data(out, 1, &decrypted.len);
329 *plain = chunk_clone(decrypted);
330 gcry_sexp_release(out);
331
332 return TRUE;
333 }
334
335 METHOD(private_key_t, get_keysize, int,
336 private_gcrypt_rsa_private_key_t *this)
337 {
338 return gcry_pk_get_nbits(this->key);
339 }
340
341 METHOD(private_key_t, get_public_key, public_key_t*,
342 private_gcrypt_rsa_private_key_t *this)
343 {
344 chunk_t n, e;
345 public_key_t *public;
346
347 n = gcrypt_rsa_find_token(this->key, "n", NULL);
348 e = gcrypt_rsa_find_token(this->key, "e", NULL);
349
350 public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA,
351 BUILD_RSA_MODULUS, n, BUILD_RSA_PUB_EXP, e, BUILD_END);
352 chunk_free(&n);
353 chunk_free(&e);
354
355 return public;
356 }
357
358 METHOD(private_key_t, get_encoding, bool,
359 private_gcrypt_rsa_private_key_t *this, cred_encoding_type_t type,
360 chunk_t *encoding)
361 {
362 chunk_t cn, ce, cp, cq, cd, cu, cexp1 = chunk_empty, cexp2 = chunk_empty;
363 gcry_mpi_t p = NULL, q = NULL, d = NULL, exp1, exp2;
364 gcry_error_t err;
365 bool success;
366
367 /* p and q are swapped, gcrypt expects p < q */
368 cp = gcrypt_rsa_find_token(this->key, "q", NULL);
369 cq = gcrypt_rsa_find_token(this->key, "p", NULL);
370 cd = gcrypt_rsa_find_token(this->key, "d", NULL);
371
372 err = gcry_mpi_scan(&p, GCRYMPI_FMT_USG, cp.ptr, cp.len, NULL)
373 | gcry_mpi_scan(&q, GCRYMPI_FMT_USG, cq.ptr, cq.len, NULL)
374 | gcry_mpi_scan(&d, GCRYMPI_FMT_USG, cd.ptr, cd.len, NULL);
375 if (err)
376 {
377 gcry_mpi_release(p);
378 gcry_mpi_release(q);
379 gcry_mpi_release(d);
380 chunk_clear(&cp);
381 chunk_clear(&cq);
382 chunk_clear(&cd);
383 DBG1(DBG_LIB, "scanning mpi for export failed: %s", gpg_strerror(err));
384 return FALSE;
385 }
386
387 gcry_mpi_sub_ui(p, p, 1);
388 exp1 = gcry_mpi_new(gcry_pk_get_nbits(this->key));
389 gcry_mpi_mod(exp1, d, p);
390 gcry_mpi_release(p);
391
392 gcry_mpi_sub_ui(q, q, 1);
393 exp2 = gcry_mpi_new(gcry_pk_get_nbits(this->key));
394 gcry_mpi_mod(exp2, d, q);
395 gcry_mpi_release(q);
396
397 err = gcry_mpi_aprint(GCRYMPI_FMT_USG, &cexp1.ptr, &cexp1.len, exp1)
398 | gcry_mpi_aprint(GCRYMPI_FMT_USG, &cexp2.ptr, &cexp2.len, exp2);
399
400 gcry_mpi_release(d);
401 gcry_mpi_release(exp1);
402 gcry_mpi_release(exp2);
403
404 if (err)
405 {
406 DBG1(DBG_LIB, "printing mpi for export failed: %s", gpg_strerror(err));
407 chunk_clear(&cp);
408 chunk_clear(&cq);
409 chunk_clear(&cd);
410 chunk_clear(&cexp1);
411 chunk_clear(&cexp2);
412 return FALSE;
413 }
414
415 cn = gcrypt_rsa_find_token(this->key, "n", NULL);
416 ce = gcrypt_rsa_find_token(this->key, "e", NULL);
417 cu = gcrypt_rsa_find_token(this->key, "u", NULL);
418
419 success = lib->encoding->encode(lib->encoding, type, NULL, encoding,
420 CRED_PART_RSA_MODULUS, cn,
421 CRED_PART_RSA_PUB_EXP, ce, CRED_PART_RSA_PRIV_EXP, cd,
422 CRED_PART_RSA_PRIME1, cp, CRED_PART_RSA_PRIME2, cq,
423 CRED_PART_RSA_EXP1, cexp1, CRED_PART_RSA_EXP2, cexp2,
424 CRED_PART_RSA_COEFF, cu, CRED_PART_END);
425 chunk_free(&cn);
426 chunk_free(&ce);
427 chunk_clear(&cd);
428 chunk_clear(&cp);
429 chunk_clear(&cq);
430 chunk_clear(&cexp1);
431 chunk_clear(&cexp2);
432 chunk_clear(&cu);
433
434 return success;
435 }
436
437 METHOD(private_key_t, get_fingerprint, bool,
438 private_gcrypt_rsa_private_key_t *this, cred_encoding_type_t type,
439 chunk_t *fp)
440 {
441 chunk_t n, e;
442 bool success;
443
444 if (lib->encoding->get_cache(lib->encoding, type, this, fp))
445 {
446 return TRUE;
447 }
448 n = gcrypt_rsa_find_token(this->key, "n", NULL);
449 e = gcrypt_rsa_find_token(this->key, "e", NULL);
450
451 success = lib->encoding->encode(lib->encoding,
452 type, this, fp, CRED_PART_RSA_MODULUS, n,
453 CRED_PART_RSA_PUB_EXP, e, CRED_PART_END);
454 chunk_free(&n);
455 chunk_free(&e);
456 return success;
457 }
458
459 METHOD(private_key_t, get_ref, private_key_t*,
460 private_gcrypt_rsa_private_key_t *this)
461 {
462 ref_get(&this->ref);
463 return &this->public.key;
464 }
465
466 METHOD(private_key_t, destroy, void,
467 private_gcrypt_rsa_private_key_t *this)
468 {
469 if (ref_put(&this->ref))
470 {
471 gcry_sexp_release(this->key);
472 lib->encoding->clear_cache(lib->encoding, this);
473 free(this);
474 }
475 }
476
477 /**
478 * Internal generic constructor
479 */
480 static private_gcrypt_rsa_private_key_t *create_empty()
481 {
482 private_gcrypt_rsa_private_key_t *this;
483
484 INIT(this,
485 .public = {
486 .key = {
487 .get_type = _get_type,
488 .sign = _sign,
489 .decrypt = _decrypt,
490 .get_keysize = _get_keysize,
491 .get_public_key = _get_public_key,
492 .equals = private_key_equals,
493 .belongs_to = private_key_belongs_to,
494 .get_fingerprint = _get_fingerprint,
495 .has_fingerprint = private_key_has_fingerprint,
496 .get_encoding = _get_encoding,
497 .get_ref = _get_ref,
498 .destroy = _destroy,
499 },
500 },
501 .ref = 1,
502 );
503
504 return this;
505 }
506
507 /**
508 * See header.
509 */
510 gcrypt_rsa_private_key_t *gcrypt_rsa_private_key_gen(key_type_t type,
511 va_list args)
512 {
513 private_gcrypt_rsa_private_key_t *this;
514 gcry_sexp_t param;
515 gcry_error_t err;
516 u_int key_size = 0;
517
518 while (TRUE)
519 {
520 switch (va_arg(args, builder_part_t))
521 {
522 case BUILD_KEY_SIZE:
523 key_size = va_arg(args, u_int);
524 continue;
525 case BUILD_END:
526 break;
527 default:
528 return NULL;
529 }
530 break;
531 }
532 if (!key_size)
533 {
534 return NULL;
535 }
536
537 err = gcry_sexp_build(&param, NULL, "(genkey(rsa(nbits %d)))", key_size);
538 if (err)
539 {
540 DBG1(DBG_LIB, "building S-expression failed: %s", gpg_strerror(err));
541 return NULL;
542 }
543 this = create_empty();
544 err = gcry_pk_genkey(&this->key, param);
545 gcry_sexp_release(param);
546 if (err)
547 {
548 free(this);
549 DBG1(DBG_LIB, "generating RSA key failed: %s", gpg_strerror(err));
550 return NULL;
551 }
552 return &this->public;
553 }
554
555 /**
556 * Recover the primes from n, e and d using the algorithm described in
557 * Appendix C of NIST SP 800-56B.
558 */
559 static bool calculate_pqu(chunk_t cn, chunk_t ce, chunk_t cd, chunk_t *cp,
560 chunk_t *cq, chunk_t *cu)
561 {
562 gcry_mpi_t n, e, d, p, q, u, k, r, g, y, n1, x, two;
563 int i, t, j;
564 gcry_error_t err;
565 bool success = FALSE;
566
567 n = e = d = p = q = u = k = r = g = y = n1 = x = two = NULL;
568 err = gcry_mpi_scan(&n, GCRYMPI_FMT_USG, cn.ptr, cn.len, NULL)
569 | gcry_mpi_scan(&e, GCRYMPI_FMT_USG, ce.ptr, ce.len, NULL)
570 | gcry_mpi_scan(&d, GCRYMPI_FMT_USG, cd.ptr, cd.len, NULL);
571 if (err)
572 {
573 goto error;
574 }
575 /* k = (d * e) - 1 */
576 k = gcry_mpi_new(gcry_mpi_get_nbits(n));
577 gcry_mpi_mul(k, d, e);
578 gcry_mpi_sub_ui(k, k, 1);
579 if (gcry_mpi_test_bit(k, 0))
580 {
581 goto error;
582 }
583 /* k = 2^t * r, where r is the largest odd integer dividing k, and t >= 1 */
584 r = gcry_mpi_copy(k);
585 for (t = 0; !gcry_mpi_test_bit(r, 0); t++)
586 { /* r = r/2 */
587 gcry_mpi_rshift(r, r, 1);
588 }
589 /* we need n-1 below */
590 n1 = gcry_mpi_new(gcry_mpi_get_nbits(n));
591 gcry_mpi_sub_ui(n1, n, 1);
592 y = gcry_mpi_new(gcry_mpi_get_nbits(n));
593 g = gcry_mpi_new(gcry_mpi_get_nbits(n));
594 x = gcry_mpi_new(gcry_mpi_get_nbits(n));
595 two = gcry_mpi_set_ui(NULL, 2);
596 for (i = 0; i < 100; i++)
597 { /* generate random integer g in [0, n-1] */
598 do
599 {
600 gcry_mpi_randomize(g, gcry_mpi_get_nbits(n), GCRY_WEAK_RANDOM);
601 }
602 while (gcry_mpi_cmp(n, g) <= 0);
603 /* y = g^r mod n */
604 gcry_mpi_powm(y, g, r, n);
605 /* try again if y == 1 or y == n-1 */
606 if (gcry_mpi_cmp_ui(y, 1) == 0 || gcry_mpi_cmp(y, n1) == 0)
607 {
608 continue;
609 }
610 for (j = 0; j < t; j++)
611 { /* x = y^2 mod n */
612 gcry_mpi_powm(x, y, two, n);
613 /* stop if x == 1 */
614 if (gcry_mpi_cmp_ui(x, 1) == 0)
615 {
616 goto done;
617 }
618 /* retry with new g if x = n-1 */
619 if (gcry_mpi_cmp(x, n1) == 0)
620 {
621 break;
622 }
623 /* y = x */
624 gcry_mpi_set(y, x);
625 }
626 }
627 goto error;
628
629 done:
630 /* p = gcd(y-1, n) */
631 gcry_mpi_sub_ui(y, y, 1);
632 p = gcry_mpi_new(gcry_mpi_get_nbits(n));
633 gcry_mpi_gcd(p, y, n);
634 /* q = n/p */
635 q = gcry_mpi_new(gcry_mpi_get_nbits(n));
636 gcry_mpi_div(q, NULL, n, p, 0);
637 if (gcry_mpi_cmp(p, q) > 0)
638 { /* gcrypt expects q < p */
639 gcry_mpi_swap(p, q);
640 }
641 /* u = q^-1 mod p */
642 u = gcry_mpi_new(gcry_mpi_get_nbits(n));
643 gcry_mpi_invm(u, p, q);
644 err = gcry_mpi_aprint(GCRYMPI_FMT_USG, &cp->ptr, &cp->len, p)
645 | gcry_mpi_aprint(GCRYMPI_FMT_USG, &cq->ptr, &cq->len, q)
646 | gcry_mpi_aprint(GCRYMPI_FMT_USG, &cu->ptr, &cu->len, u);
647 if (err)
648 {
649 goto error;
650 }
651 success = TRUE;
652
653 error:
654 gcry_mpi_release(n);
655 gcry_mpi_release(e);
656 gcry_mpi_release(d);
657 gcry_mpi_release(p);
658 gcry_mpi_release(q);
659 gcry_mpi_release(u);
660 gcry_mpi_release(k);
661 gcry_mpi_release(r);
662 gcry_mpi_release(g);
663 gcry_mpi_release(y);
664 gcry_mpi_release(n1);
665 gcry_mpi_release(x);
666 gcry_mpi_release(two);
667 return success;
668 }
669
670 /**
671 * See header.
672 */
673 gcrypt_rsa_private_key_t *gcrypt_rsa_private_key_load(key_type_t type,
674 va_list args)
675 {
676 private_gcrypt_rsa_private_key_t *this;
677 chunk_t n, e, d, p, q, u, np, nq, nu;
678 gcry_error_t err;
679
680 n = e = d = p = q = u = np = nq = nu = chunk_empty;
681 while (TRUE)
682 {
683 switch (va_arg(args, builder_part_t))
684 {
685 case BUILD_RSA_MODULUS:
686 n = va_arg(args, chunk_t);
687 continue;
688 case BUILD_RSA_PUB_EXP:
689 e = va_arg(args, chunk_t);
690 continue;
691 case BUILD_RSA_PRIV_EXP:
692 d = va_arg(args, chunk_t);
693 continue;
694 case BUILD_RSA_PRIME1:
695 /* swap p and q, gcrypt expects p < q */
696 q = va_arg(args, chunk_t);
697 continue;
698 case BUILD_RSA_PRIME2:
699 p = va_arg(args, chunk_t);
700 continue;
701 case BUILD_RSA_EXP1:
702 case BUILD_RSA_EXP2:
703 /* not required for gcrypt */
704 va_arg(args, chunk_t);
705 continue;
706 case BUILD_RSA_COEFF:
707 u = va_arg(args, chunk_t);
708 continue;
709 case BUILD_END:
710 break;
711 default:
712 return NULL;
713 }
714 break;
715 }
716 if (!p.len || !q.len || !u.len)
717 {
718 if (!calculate_pqu(n, e, d, &np, &nq, &nu))
719 {
720 return NULL;
721 }
722 p = np;
723 q = nq;
724 u = nu;
725 }
726 this = create_empty();
727 err = gcry_sexp_build(&this->key, NULL,
728 "(private-key(rsa(n %b)(e %b)(d %b)(p %b)(q %b)(u %b)))",
729 n.len, n.ptr, e.len, e.ptr, d.len, d.ptr,
730 p.len, p.ptr, q.len, q.ptr, u.len, u.ptr);
731
732 chunk_clear(&np);
733 chunk_clear(&nq);
734 chunk_clear(&nu);
735 if (err)
736 {
737 DBG1(DBG_LIB, "loading private key failed: %s", gpg_strerror(err));
738 free(this);
739 return NULL;
740 }
741 err = gcry_pk_testkey(this->key);
742 if (err)
743 {
744 DBG1(DBG_LIB, "private key sanity check failed: %s", gpg_strerror(err));
745 destroy(this);
746 return NULL;
747 }
748 return &this->public;
749 }
750