handle strong SHA-2 signatures in X.509 certificates
[strongswan.git] / src / pluto / pkcs1.c
1 /* Support of PKCS#1 private key data structures
2 * Copyright (C) 2005 Jan Hutter, Martin Willi
3 * Copyright (C) 2002-2005 Andreas Steffen
4 * Hochschule fuer Technik Rapperswil, Switzerland
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 * RCSID $Id: pkcs1.c,v 1.17 2006/01/04 21:00:43 as Exp $
17 */
18
19 #include <stddef.h>
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include <freeswan.h>
24 #include <libsha2/sha2.h>
25
26 #include "constants.h"
27 #include "defs.h"
28 #include "mp_defs.h"
29 #include "asn1.h"
30 #include "oid.h"
31 #include "log.h"
32 #include "pkcs1.h"
33 #include "md2.h"
34 #include "md5.h"
35 #include "sha1.h"
36 #include "rnd.h"
37
38 const struct fld RSA_private_field[] =
39 {
40 { "Modulus", offsetof(RSA_private_key_t, pub.n) },
41 { "PublicExponent", offsetof(RSA_private_key_t, pub.e) },
42
43 { "PrivateExponent", offsetof(RSA_private_key_t, d) },
44 { "Prime1", offsetof(RSA_private_key_t, p) },
45 { "Prime2", offsetof(RSA_private_key_t, q) },
46 { "Exponent1", offsetof(RSA_private_key_t, dP) },
47 { "Exponent2", offsetof(RSA_private_key_t, dQ) },
48 { "Coefficient", offsetof(RSA_private_key_t, qInv) },
49 };
50
51 /* ASN.1 definition of a PKCS#1 RSA private key */
52
53 static const asn1Object_t privkeyObjects[] = {
54 { 0, "RSAPrivateKey", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
55 { 1, "version", ASN1_INTEGER, ASN1_BODY }, /* 1 */
56 { 1, "modulus", ASN1_INTEGER, ASN1_BODY }, /* 2 */
57 { 1, "publicExponent", ASN1_INTEGER, ASN1_BODY }, /* 3 */
58 { 1, "privateExponent", ASN1_INTEGER, ASN1_BODY }, /* 4 */
59 { 1, "prime1", ASN1_INTEGER, ASN1_BODY }, /* 5 */
60 { 1, "prime2", ASN1_INTEGER, ASN1_BODY }, /* 6 */
61 { 1, "exponent1", ASN1_INTEGER, ASN1_BODY }, /* 7 */
62 { 1, "exponent2", ASN1_INTEGER, ASN1_BODY }, /* 8 */
63 { 1, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 9 */
64 { 1, "otherPrimeInfos", ASN1_SEQUENCE, ASN1_OPT |
65 ASN1_LOOP }, /* 10 */
66 { 2, "otherPrimeInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 11 */
67 { 3, "prime", ASN1_INTEGER, ASN1_BODY }, /* 12 */
68 { 3, "exponent", ASN1_INTEGER, ASN1_BODY }, /* 13 */
69 { 3, "coefficient", ASN1_INTEGER, ASN1_BODY }, /* 14 */
70 { 1, "end opt or loop", ASN1_EOC, ASN1_END } /* 15 */
71 };
72
73 #define PKCS1_PRIV_KEY_VERSION 1
74 #define PKCS1_PRIV_KEY_MODULUS 2
75 #define PKCS1_PRIV_KEY_PUB_EXP 3
76 #define PKCS1_PRIV_KEY_COEFF 9
77 #define PKCS1_PRIV_KEY_ROOF 16
78
79
80 /*
81 * forms the FreeS/WAN keyid from the public exponent e and modulus n
82 */
83 void
84 form_keyid(chunk_t e, chunk_t n, char* keyid, unsigned *keysize)
85 {
86 /* eliminate leading zero bytes in modulus from ASN.1 coding */
87 while (n.len > 1 && *n.ptr == 0x00)
88 {
89 n.ptr++; n.len--;
90 }
91
92 /* form the FreeS/WAN keyid */
93 keyid[0] = '\0'; /* in case of splitkeytoid failure */
94 splitkeytoid(e.ptr, e.len, n.ptr, n.len, keyid, KEYID_BUF);
95
96 /* return the RSA modulus size in octets */
97 *keysize = n.len;
98 }
99
100 /*
101 * initialize an RSA_public_key_t object
102 */
103 void
104 init_RSA_public_key(RSA_public_key_t *rsa, chunk_t e, chunk_t n)
105 {
106 n_to_mpz(&rsa->e, e.ptr, e.len);
107 n_to_mpz(&rsa->n, n.ptr, n.len);
108
109 form_keyid(e, n, rsa->keyid, &rsa->k);
110 }
111
112 #ifdef DEBUG
113 static void
114 RSA_show_key_fields(RSA_private_key_t *k, int fieldcnt)
115 {
116 const struct fld *p;
117
118 DBG_log(" keyid: *%s", k->pub.keyid);
119
120 for (p = RSA_private_field; p < &RSA_private_field[fieldcnt]; p++)
121 {
122 MP_INT *n = (MP_INT *) ((char *)k + p->offset);
123 size_t sz = mpz_sizeinbase(n, 16);
124 char buf[RSA_MAX_OCTETS * 2 + 2]; /* ought to be big enough */
125
126 passert(sz <= sizeof(buf));
127 mpz_get_str(buf, 16, n);
128
129 DBG_log(" %s: 0x%s", p->name, buf);
130 }
131 }
132
133 /* debugging info that compromises security! */
134 void
135 RSA_show_private_key(RSA_private_key_t *k)
136 {
137 RSA_show_key_fields(k, elemsof(RSA_private_field));
138 }
139
140 void
141 RSA_show_public_key(RSA_public_key_t *k)
142 {
143 /* Kludge: pretend that it is a private key, but only display the
144 * first two fields (which are the public key).
145 */
146 passert(offsetof(RSA_private_key_t, pub) == 0);
147 RSA_show_key_fields((RSA_private_key_t *)k, 2);
148 }
149 #endif
150
151 err_t
152 RSA_private_key_sanity(RSA_private_key_t *k)
153 {
154 /* note that the *last* error found is reported */
155 err_t ugh = NULL;
156 mpz_t t, u, q1;
157
158 #ifdef DEBUG /* debugging info that compromises security */
159 DBG(DBG_PRIVATE, RSA_show_private_key(k));
160 #endif
161
162 /* PKCS#1 1.5 section 6 requires modulus to have at least 12 octets.
163 * We actually require more (for security).
164 */
165 if (k->pub.k < RSA_MIN_OCTETS)
166 return RSA_MIN_OCTETS_UGH;
167
168 /* we picked a max modulus size to simplify buffer allocation */
169 if (k->pub.k > RSA_MAX_OCTETS)
170 return RSA_MAX_OCTETS_UGH;
171
172 mpz_init(t);
173 mpz_init(u);
174 mpz_init(q1);
175
176 /* check that n == p * q */
177 mpz_mul(u, &k->p, &k->q);
178 if (mpz_cmp(u, &k->pub.n) != 0)
179 ugh = "n != p * q";
180
181 /* check that e divides neither p-1 nor q-1 */
182 mpz_sub_ui(t, &k->p, 1);
183 mpz_mod(t, t, &k->pub.e);
184 if (mpz_cmp_ui(t, 0) == 0)
185 ugh = "e divides p-1";
186
187 mpz_sub_ui(t, &k->q, 1);
188 mpz_mod(t, t, &k->pub.e);
189 if (mpz_cmp_ui(t, 0) == 0)
190 ugh = "e divides q-1";
191
192 /* check that d is e^-1 (mod lcm(p-1, q-1)) */
193 /* see PKCS#1v2, aka RFC 2437, for the "lcm" */
194 mpz_sub_ui(q1, &k->q, 1);
195 mpz_sub_ui(u, &k->p, 1);
196 mpz_gcd(t, u, q1); /* t := gcd(p-1, q-1) */
197 mpz_mul(u, u, q1); /* u := (p-1) * (q-1) */
198 mpz_divexact(u, u, t); /* u := lcm(p-1, q-1) */
199
200 mpz_mul(t, &k->d, &k->pub.e);
201 mpz_mod(t, t, u);
202 if (mpz_cmp_ui(t, 1) != 0)
203 ugh = "(d * e) mod (lcm(p-1, q-1)) != 1";
204
205 /* check that dP is d mod (p-1) */
206 mpz_sub_ui(u, &k->p, 1);
207 mpz_mod(t, &k->d, u);
208 if (mpz_cmp(t, &k->dP) != 0)
209 ugh = "dP is not congruent to d mod (p-1)";
210
211 /* check that dQ is d mod (q-1) */
212 mpz_sub_ui(u, &k->q, 1);
213 mpz_mod(t, &k->d, u);
214 if (mpz_cmp(t, &k->dQ) != 0)
215 ugh = "dQ is not congruent to d mod (q-1)";
216
217 /* check that qInv is (q^-1) mod p */
218 mpz_mul(t, &k->qInv, &k->q);
219 mpz_mod(t, t, &k->p);
220 if (mpz_cmp_ui(t, 1) != 0)
221 ugh = "qInv is not conguent ot (q^-1) mod p";
222
223 mpz_clear(t);
224 mpz_clear(u);
225 mpz_clear(q1);
226 return ugh;
227 }
228
229 /*
230 * Check the equality of two RSA public keys
231 */
232 bool
233 same_RSA_public_key(const RSA_public_key_t *a, const RSA_public_key_t *b)
234 {
235 return a == b
236 || (a->k == b->k && mpz_cmp(&a->n, &b->n) == 0 && mpz_cmp(&a->e, &b->e) == 0);
237 }
238
239 /*
240 * Parses a PKCS#1 private key
241 */
242 bool
243 pkcs1_parse_private_key(chunk_t blob, RSA_private_key_t *key)
244 {
245 err_t ugh = NULL;
246 asn1_ctx_t ctx;
247 chunk_t object, modulus, exp;
248 u_int level;
249 int objectID = 0;
250
251 asn1_init(&ctx, blob, 0, FALSE, DBG_PRIVATE);
252
253 while (objectID < PKCS1_PRIV_KEY_ROOF) {
254
255 if (!extract_object(privkeyObjects, &objectID, &object, &level, &ctx))
256 return FALSE;
257
258 if (objectID == PKCS1_PRIV_KEY_VERSION)
259 {
260 if (object.len > 0 && *object.ptr != 0)
261 {
262 plog(" wrong PKCS#1 private key version");
263 return FALSE;
264 }
265 }
266 else if (objectID >= PKCS1_PRIV_KEY_MODULUS &&
267 objectID <= PKCS1_PRIV_KEY_COEFF)
268 {
269 MP_INT *u = (MP_INT *) ((char *)key
270 + RSA_private_field[objectID - PKCS1_PRIV_KEY_MODULUS].offset);
271
272 n_to_mpz(u, object.ptr, object.len);
273
274 if (objectID == PKCS1_PRIV_KEY_MODULUS)
275 modulus = object;
276 else if (objectID == PKCS1_PRIV_KEY_PUB_EXP)
277 exp = object;
278 }
279 objectID++;
280 }
281 form_keyid(exp, modulus, key->pub.keyid, &key->pub.k);
282 ugh = RSA_private_key_sanity(key);
283 return (ugh == NULL);
284 }
285
286 /*
287 * compute a digest over a binary blob
288 */
289 bool
290 compute_digest(chunk_t tbs, int alg, chunk_t *digest)
291 {
292 switch (alg)
293 {
294 case OID_MD2:
295 case OID_MD2_WITH_RSA:
296 {
297 MD2_CTX context;
298
299 MD2Init(&context);
300 MD2Update(&context, tbs.ptr, tbs.len);
301 MD2Final(digest->ptr, &context);
302 digest->len = MD2_DIGEST_SIZE;
303 return TRUE;
304 }
305 case OID_MD5:
306 case OID_MD5_WITH_RSA:
307 {
308 MD5_CTX context;
309
310 MD5Init(&context);
311 MD5Update(&context, tbs.ptr, tbs.len);
312 MD5Final(digest->ptr, &context);
313 digest->len = MD5_DIGEST_SIZE;
314 return TRUE;
315 }
316 case OID_SHA1:
317 case OID_SHA1_WITH_RSA:
318 case OID_SHA1_WITH_RSA_OIW:
319 {
320 SHA1_CTX context;
321
322 SHA1Init(&context);
323 SHA1Update(&context, tbs.ptr, tbs.len);
324 SHA1Final(digest->ptr, &context);
325 digest->len = SHA1_DIGEST_SIZE;
326 return TRUE;
327 }
328 case OID_SHA256:
329 case OID_SHA256_WITH_RSA:
330 {
331 sha256_context context;
332
333 sha256_init(&context);
334 sha256_write(&context, tbs.ptr, tbs.len);
335 sha256_final(&context);
336 memcpy(digest->ptr, context.sha_out, SHA2_256_DIGEST_SIZE);
337 digest->len = SHA2_256_DIGEST_SIZE;
338 return TRUE;
339 }
340 case OID_SHA384:
341 case OID_SHA384_WITH_RSA:
342 {
343 sha512_context context;
344
345 sha384_init(&context);
346 sha512_write(&context, tbs.ptr, tbs.len);
347 sha512_final(&context);
348 memcpy(digest->ptr, context.sha_out, SHA2_384_DIGEST_SIZE);
349 digest->len = SHA2_384_DIGEST_SIZE;
350 return TRUE;
351 }
352 case OID_SHA512:
353 case OID_SHA512_WITH_RSA:
354 {
355 sha512_context context;
356
357 sha512_init(&context);
358 sha512_write(&context, tbs.ptr, tbs.len);
359 sha512_final(&context);
360 memcpy(digest->ptr, context.sha_out, SHA2_512_DIGEST_SIZE);
361 digest->len = SHA2_512_DIGEST_SIZE;
362 return TRUE;
363 }
364 default:
365 digest->len = 0;
366 return FALSE;
367 }
368 }
369
370 /*
371 * compute an RSA signature with PKCS#1 padding
372 */
373 void
374 sign_hash(const RSA_private_key_t *k, const u_char *hash_val, size_t hash_len
375 , u_char *sig_val, size_t sig_len)
376 {
377 chunk_t ch;
378 mpz_t t1, t2;
379 size_t padlen;
380 u_char *p = sig_val;
381
382 DBG(DBG_CONTROL | DBG_CRYPT,
383 DBG_log("signing hash with RSA Key *%s", k->pub.keyid)
384 )
385 /* PKCS#1 v1.5 8.1 encryption-block formatting */
386 *p++ = 0x00;
387 *p++ = 0x01; /* BT (block type) 01 */
388 padlen = sig_len - 3 - hash_len;
389 memset(p, 0xFF, padlen);
390 p += padlen;
391 *p++ = 0x00;
392 memcpy(p, hash_val, hash_len);
393 passert(p + hash_len - sig_val == (ptrdiff_t)sig_len);
394
395 /* PKCS#1 v1.5 8.2 octet-string-to-integer conversion */
396 n_to_mpz(t1, sig_val, sig_len); /* (could skip leading 0x00) */
397
398 /* PKCS#1 v1.5 8.3 RSA computation y = x^c mod n
399 * Better described in PKCS#1 v2.0 5.1 RSADP.
400 * There are two methods, depending on the form of the private key.
401 * We use the one based on the Chinese Remainder Theorem.
402 */
403 mpz_init(t2);
404
405 mpz_powm(t2, t1, &k->dP, &k->p); /* m1 = c^dP mod p */
406
407 mpz_powm(t1, t1, &k->dQ, &k->q); /* m2 = c^dQ mod Q */
408
409 mpz_sub(t2, t2, t1); /* h = qInv (m1 - m2) mod p */
410 mpz_mod(t2, t2, &k->p);
411 mpz_mul(t2, t2, &k->qInv);
412 mpz_mod(t2, t2, &k->p);
413
414 mpz_mul(t2, t2, &k->q); /* m = m2 + h q */
415 mpz_add(t1, t1, t2);
416
417 /* PKCS#1 v1.5 8.4 integer-to-octet-string conversion */
418 ch = mpz_to_n(t1, sig_len);
419 memcpy(sig_val, ch.ptr, sig_len);
420 pfree(ch.ptr);
421
422 mpz_clear(t1);
423 mpz_clear(t2);
424 }
425
426 /*
427 * encrypt data with an RSA public key after padding
428 */
429 chunk_t
430 RSA_encrypt(const RSA_public_key_t *key, chunk_t in)
431 {
432 u_char padded[RSA_MAX_OCTETS];
433 u_char *pos = padded;
434 int padding = key->k - in.len - 3;
435 int i;
436
437 if (padding < 8 || key->k > RSA_MAX_OCTETS)
438 return empty_chunk;
439
440 /* add padding according to PKCS#1 7.2.1 1.+2. */
441 *pos++ = 0x00;
442 *pos++ = 0x02;
443
444 /* pad with pseudo random bytes unequal to zero */
445 get_rnd_bytes(pos, padding);
446 for (i = 0; i < padding; i++)
447 {
448 while (!*pos)
449 get_rnd_bytes(pos, 1);
450 pos++;
451 }
452
453 /* append the padding terminator */
454 *pos++ = 0x00;
455
456 /* now add the data */
457 memcpy(pos, in.ptr, in.len);
458 DBG(DBG_RAW,
459 DBG_dump_chunk("data for rsa encryption:\n", in);
460 DBG_dump("padded data for rsa encryption:\n", padded, key->k)
461 )
462
463 /* convert chunk to integer (PKCS#1 7.2.1 3.a) */
464 {
465 chunk_t out;
466 mpz_t m, c;
467
468 mpz_init(c);
469 n_to_mpz(m, padded, key->k);
470
471 /* encrypt(PKCS#1 7.2.1 3.b) */
472 mpz_powm(c, m, &key->e, &key->n);
473
474 /* convert integer back to a chunk (PKCS#1 7.2.1 3.c) */
475 out = mpz_to_n(c, key->k);
476 mpz_clear(c);
477 mpz_clear(m);
478
479 DBG(DBG_RAW,
480 DBG_dump_chunk("rsa encrypted data:\n", out)
481 )
482 return out;
483 }
484 }
485
486 /*
487 * decrypt data with an RSA private key and remove padding
488 */
489 bool
490 RSA_decrypt(const RSA_private_key_t *key, chunk_t in, chunk_t *out)
491 {
492 chunk_t padded;
493 u_char *pos;
494 mpz_t t1, t2;
495
496 n_to_mpz(t1, in.ptr,in.len);
497
498 /* PKCS#1 v1.5 8.3 RSA computation y = x^c mod n
499 * Better described in PKCS#1 v2.0 5.1 RSADP.
500 * There are two methods, depending on the form of the private key.
501 * We use the one based on the Chinese Remainder Theorem.
502 */
503 mpz_init(t2);
504
505 mpz_powm(t2, t1, &key->dP, &key->p); /* m1 = c^dP mod p */
506 mpz_powm(t1, t1, &key->dQ, &key->q); /* m2 = c^dQ mod Q */
507
508 mpz_sub(t2, t2, t1); /* h = qInv (m1 - m2) mod p */
509 mpz_mod(t2, t2, &key->p);
510 mpz_mul(t2, t2, &key->qInv);
511 mpz_mod(t2, t2, &key->p);
512
513 mpz_mul(t2, t2, &key->q); /* m = m2 + h q */
514 mpz_add(t1, t1, t2);
515
516 padded = mpz_to_n(t1, key->pub.k);
517 mpz_clear(t1);
518 mpz_clear(t2);
519
520 DBG(DBG_PRIVATE,
521 DBG_dump_chunk("rsa decrypted data with padding:\n", padded)
522 )
523 pos = padded.ptr;
524
525 /* PKCS#1 v1.5 8.1 encryption-block formatting (EB = 00 || 02 || PS || 00 || D) */
526
527 /* check for hex pattern 00 02 in decrypted message */
528 if ((*pos++ != 0x00) || (*(pos++) != 0x02))
529 {
530 plog("incorrect padding - probably wrong RSA key");
531 freeanychunk(padded);
532 return FALSE;
533 }
534 padded.len -= 2;
535
536 /* the plaintext data starts after first 0x00 byte */
537 while (padded.len-- > 0 && *pos++ != 0x00)
538
539 if (padded.len == 0)
540 {
541 plog("no plaintext data");
542 freeanychunk(padded);
543 return FALSE;
544 }
545
546 clonetochunk(*out, pos, padded.len, "decrypted data");
547 freeanychunk(padded);
548 return TRUE;
549 }
550
551 /*
552 * build signatureValue
553 */
554 chunk_t
555 pkcs1_build_signature(chunk_t tbs, int hash_alg, const RSA_private_key_t *key
556 , bool bit_string)
557 {
558
559 size_t siglen = key->pub.k;
560
561 u_char digest_buf[MAX_DIGEST_LEN];
562 chunk_t digest = { digest_buf, MAX_DIGEST_LEN };
563 chunk_t digestInfo, alg_id, signatureValue;
564 u_char *pos;
565
566 switch (hash_alg)
567 {
568 case OID_MD5:
569 case OID_MD5_WITH_RSA:
570 alg_id = ASN1_md5_id;
571 break;
572 case OID_SHA1:
573 case OID_SHA1_WITH_RSA:
574 alg_id = ASN1_sha1_id;
575 break;
576 default:
577 return empty_chunk;
578 }
579 compute_digest(tbs, hash_alg, &digest);
580
581 /* according to PKCS#1 v2.1 digest must be packaged into
582 * an ASN.1 structure for encryption
583 */
584 digestInfo = asn1_wrap(ASN1_SEQUENCE, "cm"
585 , alg_id
586 , asn1_simple_object(ASN1_OCTET_STRING, digest));
587
588 /* generate the RSA signature */
589 if (bit_string)
590 {
591 pos = build_asn1_object(&signatureValue, ASN1_BIT_STRING, 1 + siglen);
592 *pos++ = 0x00;
593 }
594 else
595 {
596 pos = build_asn1_object(&signatureValue, ASN1_OCTET_STRING, siglen);
597 }
598 sign_hash(key, digestInfo.ptr, digestInfo.len, pos, siglen);
599 pfree(digestInfo.ptr);
600
601 return signatureValue;
602 }
603
604 /*
605 * build a DER-encoded PKCS#1 private key object
606 */
607 chunk_t
608 pkcs1_build_private_key(const RSA_private_key_t *key)
609 {
610 chunk_t pkcs1 = asn1_wrap(ASN1_SEQUENCE, "cmmmmmmmm"
611 , ASN1_INTEGER_0
612 , asn1_integer_from_mpz(&key->pub.n)
613 , asn1_integer_from_mpz(&key->pub.e)
614 , asn1_integer_from_mpz(&key->d)
615 , asn1_integer_from_mpz(&key->p)
616 , asn1_integer_from_mpz(&key->q)
617 , asn1_integer_from_mpz(&key->dP)
618 , asn1_integer_from_mpz(&key->dQ)
619 , asn1_integer_from_mpz(&key->qInv));
620
621 DBG(DBG_PRIVATE,
622 DBG_dump_chunk("PKCS#1 encoded private key:", pkcs1)
623 )
624 return pkcs1;
625 }
626
627 /*
628 * build a DER-encoded PKCS#1 public key object
629 */
630 chunk_t
631 pkcs1_build_public_key(const RSA_public_key_t *rsa)
632 {
633 return asn1_wrap(ASN1_SEQUENCE, "mm"
634 , asn1_integer_from_mpz(&rsa->n)
635 , asn1_integer_from_mpz(&rsa->e));
636 }
637
638 /*
639 * build a DER-encoded publicKeyInfo object
640 */
641 chunk_t
642 pkcs1_build_publicKeyInfo(const RSA_public_key_t *rsa)
643 {
644 chunk_t publicKey;
645 chunk_t rawKey = pkcs1_build_public_key(rsa);
646
647 u_char *pos = build_asn1_object(&publicKey, ASN1_BIT_STRING
648 , 1 + rawKey.len);
649 *pos++ = 0x00;
650 mv_chunk(&pos, rawKey);
651
652 return asn1_wrap(ASN1_SEQUENCE, "cm"
653 , ASN1_rsaEncryption_id
654 , publicKey);
655 }
656 void
657 free_RSA_public_content(RSA_public_key_t *rsa)
658 {
659 mpz_clear(&rsa->n);
660 mpz_clear(&rsa->e);
661 }
662
663 void
664 free_RSA_private_content(RSA_private_key_t *rsak)
665 {
666 free_RSA_public_content(&rsak->pub);
667 mpz_clear(&rsak->d);
668 mpz_clear(&rsak->p);
669 mpz_clear(&rsak->q);
670 mpz_clear(&rsak->dP);
671 mpz_clear(&rsak->dQ);
672 mpz_clear(&rsak->qInv);
673 }
674