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