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