Annotation of embedaddon/strongswan/src/libstrongswan/plugins/botan/botan_rsa_private_key.c, revision 1.1.1.2
1.1 misho 1: /*
2: * Copyright (C) 2018 Tobias Brunner
3: * Copyright (C) 2018 Andreas Steffen
4: * HSR Hochschule fuer Technik Rapperswil
5: *
6: * Copyright (C) 2018 René Korthaus
7: * Rohde & Schwarz Cybersecurity GmbH
8: *
9: * Permission is hereby granted, free of charge, to any person obtaining a copy
10: * of this software and associated documentation files (the "Software"), to deal
11: * in the Software without restriction, including without limitation the rights
12: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13: * copies of the Software, and to permit persons to whom the Software is
14: * furnished to do so, subject to the following conditions:
15: *
16: * The above copyright notice and this permission notice shall be included in
17: * all copies or substantial portions of the Software.
18: *
19: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25: * THE SOFTWARE.
26: */
27:
28: #include "botan_rsa_private_key.h"
29: #include "botan_rsa_public_key.h"
30:
31: #include <botan/build.h>
32:
33: #ifdef BOTAN_HAS_RSA
34:
35: #include "botan_util.h"
36:
37: #include <botan/ffi.h>
38:
39: #include <utils/debug.h>
40:
41: typedef struct private_botan_rsa_private_key_t private_botan_rsa_private_key_t;
42:
43: /**
44: * Private data of a botan_rsa_private_key_t object.
45: */
46: struct private_botan_rsa_private_key_t {
47:
48: /**
49: * Public interface for this signer.
50: */
51: botan_rsa_private_key_t public;
52:
53: /**
54: * Botan private key
55: */
56: botan_privkey_t key;
57:
58: /**
59: * reference count
60: */
61: refcount_t ref;
62: };
63:
64: /**
65: * Get the Botan string identifier for an EMSA PSS signature
66: */
67: bool botan_emsa_pss_identifier(rsa_pss_params_t *params, char *id, size_t len)
68: {
69: const char *hash;
70:
71: if (!params)
72: {
73: return FALSE;
74: }
75:
76: /* botan currently does not support passing the mgf1 hash */
77: if (params->hash != params->mgf1_hash)
78: {
79: DBG1(DBG_LIB, "passing mgf1 hash not supported via botan");
80: return FALSE;
81: }
82:
83: hash = botan_get_hash(params->hash);
84: if (!hash)
85: {
86: return FALSE;
87: }
88: return snprintf(id, len, "EMSA-PSS(%s,MGF1,%zd)", hash,
89: params->salt_len) < len;
90: }
91:
92: /**
93: * Build an EMSA PSS signature described in PKCS#1
94: */
95: static bool build_emsa_pss_signature(private_botan_rsa_private_key_t *this,
96: rsa_pss_params_t *params, chunk_t data,
97: chunk_t *sig)
98: {
99: char hash_and_padding[BUF_LEN];
100:
101: if (!botan_emsa_pss_identifier(params, hash_and_padding,
102: sizeof(hash_and_padding)))
103: {
104: return FALSE;
105: }
106: return botan_get_signature(this->key, hash_and_padding, data, sig);
107: }
108:
109: METHOD(private_key_t, get_type, key_type_t,
110: private_botan_rsa_private_key_t *this)
111: {
112: return KEY_RSA;
113: }
114:
115: METHOD(private_key_t, sign, bool,
116: private_botan_rsa_private_key_t *this, signature_scheme_t scheme,
117: void *params, chunk_t data, chunk_t *signature)
118: {
119: switch (scheme)
120: {
121: case SIGN_RSA_EMSA_PKCS1_NULL:
122: return botan_get_signature(this->key, "EMSA_PKCS1(Raw)", data,
123: signature);
124: case SIGN_RSA_EMSA_PKCS1_SHA1:
125: return botan_get_signature(this->key, "EMSA_PKCS1(SHA-1)", data,
126: signature);
127: case SIGN_RSA_EMSA_PKCS1_SHA2_224:
128: return botan_get_signature(this->key, "EMSA_PKCS1(SHA-224)", data,
129: signature);
130: case SIGN_RSA_EMSA_PKCS1_SHA2_256:
131: return botan_get_signature(this->key, "EMSA_PKCS1(SHA-256)", data,
132: signature);
133: case SIGN_RSA_EMSA_PKCS1_SHA2_384:
134: return botan_get_signature(this->key, "EMSA_PKCS1(SHA-384)", data,
135: signature);
136: case SIGN_RSA_EMSA_PKCS1_SHA2_512:
137: return botan_get_signature(this->key, "EMSA_PKCS1(SHA-512)", data,
138: signature);
139: case SIGN_RSA_EMSA_PKCS1_SHA3_224:
140: return botan_get_signature(this->key, "EMSA_PKCS1(SHA-3(224))", data,
141: signature);
142: case SIGN_RSA_EMSA_PKCS1_SHA3_256:
143: return botan_get_signature(this->key, "EMSA_PKCS1(SHA-3(256))", data,
144: signature);
145: case SIGN_RSA_EMSA_PKCS1_SHA3_384:
146: return botan_get_signature(this->key, "EMSA_PKCS1(SHA-3(384))", data,
147: signature);
148: case SIGN_RSA_EMSA_PKCS1_SHA3_512:
149: return botan_get_signature(this->key, "EMSA_PKCS1(SHA-3(512))", data,
150: signature);
151: case SIGN_RSA_EMSA_PSS:
152: return build_emsa_pss_signature(this, params, data, signature);
153: default:
154: DBG1(DBG_LIB, "signature scheme %N not supported via botan",
155: signature_scheme_names, scheme);
156: return FALSE;
157: }
158: }
159:
160: METHOD(private_key_t, decrypt, bool,
161: private_botan_rsa_private_key_t *this, encryption_scheme_t scheme,
162: chunk_t crypto, chunk_t *plain)
163: {
164: botan_pk_op_decrypt_t decrypt_op;
165: const char *padding;
166:
167: switch (scheme)
168: {
169: case ENCRYPT_RSA_PKCS1:
170: padding = "PKCS1v15";
171: break;
172: case ENCRYPT_RSA_OAEP_SHA1:
173: padding = "OAEP(SHA-1)";
174: break;
175: case ENCRYPT_RSA_OAEP_SHA224:
176: padding = "OAEP(SHA-224)";
177: break;
178: case ENCRYPT_RSA_OAEP_SHA256:
179: padding = "OAEP(SHA-256)";
180: break;
181: case ENCRYPT_RSA_OAEP_SHA384:
182: padding = "OAEP(SHA-384)";
183: break;
184: case ENCRYPT_RSA_OAEP_SHA512:
185: padding = "OAEP(SHA-512)";
186: break;
187: default:
188: DBG1(DBG_LIB, "encryption scheme %N not supported via botan",
189: encryption_scheme_names, scheme);
190: return FALSE;
191: }
192:
193: if (botan_pk_op_decrypt_create(&decrypt_op, this->key, padding, 0))
194: {
195: return FALSE;
196: }
197:
198: plain->len = 0;
199: if (botan_pk_op_decrypt_output_length(decrypt_op, crypto.len, &plain->len))
200: {
201: botan_pk_op_decrypt_destroy(decrypt_op);
202: return FALSE;
203: }
204:
205: *plain = chunk_alloc(plain->len);
206: if (botan_pk_op_decrypt(decrypt_op, plain->ptr, &plain->len, crypto.ptr,
207: crypto.len))
208: {
209: chunk_free(plain);
210: botan_pk_op_decrypt_destroy(decrypt_op);
211: return FALSE;
212: }
213: botan_pk_op_decrypt_destroy(decrypt_op);
214: return TRUE;
215: }
216:
217: METHOD(private_key_t, get_keysize, int,
218: private_botan_rsa_private_key_t *this)
219: {
220: botan_mp_t n;
221: size_t bits = 0;
222:
223: if (botan_mp_init(&n))
224: {
225: return 0;
226: }
227:
228: if (botan_privkey_get_field(n, this->key, "n") ||
229: botan_mp_num_bits(n, &bits))
230: {
231: botan_mp_destroy(n);
232: return 0;
233: }
234:
235: botan_mp_destroy(n);
236: return bits;
237: }
238:
239: METHOD(private_key_t, get_public_key, public_key_t*,
240: private_botan_rsa_private_key_t *this)
241: {
242: botan_pubkey_t pubkey;
243:
244: if (botan_privkey_export_pubkey(&pubkey, this->key))
245: {
246: return NULL;
247: }
248: return (public_key_t*)botan_rsa_public_key_adopt(pubkey);
249: }
250:
251: METHOD(private_key_t, get_fingerprint, bool,
252: private_botan_rsa_private_key_t *this, cred_encoding_type_t type,
253: chunk_t *fingerprint)
254: {
255: botan_pubkey_t pubkey;
256: bool success = FALSE;
257:
258: /* check the cache before doing the export */
259: if (lib->encoding->get_cache(lib->encoding, type, this, fingerprint))
260: {
261: return TRUE;
262: }
263:
264: if (botan_privkey_export_pubkey(&pubkey, this->key))
265: {
266: return FALSE;
267: }
268: success = botan_get_fingerprint(pubkey, this, type, fingerprint);
269: botan_pubkey_destroy(pubkey);
270: return success;
271: }
272:
273: METHOD(private_key_t, get_encoding, bool,
274: private_botan_rsa_private_key_t *this, cred_encoding_type_t type,
275: chunk_t *encoding)
276: {
277: return botan_get_privkey_encoding(this->key, type, encoding);
278: }
279:
280: METHOD(private_key_t, get_ref, private_key_t*,
281: private_botan_rsa_private_key_t *this)
282: {
283: ref_get(&this->ref);
284: return &this->public.key;
285: }
286:
287: METHOD(private_key_t, destroy, void,
288: private_botan_rsa_private_key_t *this)
289: {
290: if (ref_put(&this->ref))
291: {
292: lib->encoding->clear_cache(lib->encoding, this);
293: botan_privkey_destroy(this->key);
294: free(this);
295: }
296: }
297:
298: /**
299: * Internal generic constructor
300: */
301: static private_botan_rsa_private_key_t *create_empty()
302: {
303: private_botan_rsa_private_key_t *this;
304:
305: INIT(this,
306: .public = {
307: .key = {
308: .get_type = _get_type,
309: .sign = _sign,
310: .decrypt = _decrypt,
311: .get_keysize = _get_keysize,
312: .get_public_key = _get_public_key,
313: .equals = private_key_equals,
314: .belongs_to = private_key_belongs_to,
315: .get_fingerprint = _get_fingerprint,
316: .has_fingerprint = private_key_has_fingerprint,
317: .get_encoding = _get_encoding,
318: .get_ref = _get_ref,
319: .destroy = _destroy,
320: },
321: },
322: .ref = 1,
323: );
324:
325: return this;
326: }
327:
328: /*
329: * Described in header
330: */
331: botan_rsa_private_key_t *botan_rsa_private_key_adopt(botan_privkey_t key)
332: {
333: private_botan_rsa_private_key_t *this;
334:
335: this = create_empty();
336: this->key = key;
337:
338: return &this->public;
339: }
340:
341: /*
342: * Described in header
343: */
344: botan_rsa_private_key_t *botan_rsa_private_key_gen(key_type_t type,
345: va_list args)
346: {
347: private_botan_rsa_private_key_t *this;
348: botan_rng_t rng;
349: char buf[BUF_LEN];
350: u_int key_size = 0;
351:
352: while (TRUE)
353: {
354: switch (va_arg(args, builder_part_t))
355: {
356: case BUILD_KEY_SIZE:
357: key_size = va_arg(args, u_int);
358: continue;
359: case BUILD_END:
360: break;
361: default:
362: return NULL;
363: }
364: break;
365: }
366:
367: if (!key_size)
368: {
369: return NULL;
370: }
371:
1.1.1.2 ! misho 372: if (!botan_get_rng(&rng, RNG_TRUE))
1.1 misho 373: {
374: return NULL;
375: }
376:
377: this = create_empty();
378:
379: snprintf(buf, sizeof(buf), "%u", key_size);
380:
381: if (botan_privkey_create(&this->key, "RSA", buf, rng))
382: {
383: botan_rng_destroy(rng);
384: free(this);
385: return NULL;
386: }
387: botan_rng_destroy(rng);
388: return &this->public;
389: }
390:
391: /**
392: * Recover the primes from n, e and d using the algorithm described in
393: * Appendix C of NIST SP 800-56B.
394: */
395: static bool calculate_pq(botan_mp_t *n, botan_mp_t *e, botan_mp_t *d,
396: botan_mp_t *p, botan_mp_t *q)
397: {
398: botan_mp_t k = NULL, one = NULL, r = NULL, zero = NULL, two = NULL;
399: botan_mp_t n1 = NULL, x = NULL, y = NULL, g = NULL, rem = NULL;
400: botan_rng_t rng = NULL;
401: int i, t, j;
402: bool success = FALSE;
403:
404: if (botan_mp_init(&k) ||
405: botan_mp_init(&one) ||
406: botan_mp_set_from_int(one, 1))
407: {
408: goto error;
409: }
410:
411: /* 1. k = d * e - 1 */
412: if (botan_mp_mul(k, *d, *e) || botan_mp_sub(k, k, one))
413: {
414: goto error;
415: }
416:
417: /* k must be even */
418: if (botan_mp_get_bit(k, 0) != 0)
419: {
420: goto error;
421: }
422:
423: /* 2. k = 2^t * r, where r is the largest odd integer dividing k, and t >= 1 */
424: if (botan_mp_init(&r) ||
425: botan_mp_set_from_mp(r, k))
426: {
427: goto error;
428: }
429:
430: for (t = 0; botan_mp_get_bit(r, 0) != 1; t++)
431: {
432: if (botan_mp_rshift(r, r, 1))
433: {
434: goto error;
435: }
436: }
437:
438: /* need 0 and n-1 below */
439: if (botan_mp_init(&zero) ||
440: botan_mp_init(&n1) ||
441: botan_mp_sub(n1, *n, one))
442: {
443: goto error;
444: }
445:
446: if (botan_mp_init(&g))
447: {
448: goto error;
449: }
450:
1.1.1.2 ! misho 451: if (!botan_get_rng(&rng, RNG_STRONG))
1.1 misho 452: {
453: goto error;
454: }
455:
456: if (botan_mp_init(&two))
457: {
458: goto error;
459: }
460:
461: if (botan_mp_set_from_int(two, 2))
462: {
463: goto error;
464: }
465:
466: if (botan_mp_init(&y) ||
467: botan_mp_init(&x))
468: {
469: goto error;
470: }
471:
472: for (i = 0; i < 100; i++)
473: {
474: /* 3a. generate a random integer g in the range [0, n-1] */
475: if (botan_mp_rand_range(g, rng, zero, n1))
476: {
477: goto error;
478: }
479: /* 3b. y = g^r mod n */
480: if (botan_mp_powmod(y, g, r, *n))
481: {
482: goto error;
483: }
484:
485: /* 3c. If y = 1 or y = n – 1, try again */
486: if (botan_mp_equal(y, one) || botan_mp_equal(y, n1))
487: {
488: continue;
489: }
490:
491: for (j = 0; j < t; j++)
492: {
493: /* x = y^2 mod n */
494: if (botan_mp_powmod(x, y, two, *n))
495: {
496: goto error;
497: }
498:
499: /* stop if x == 1 */
500: if (botan_mp_equal(x, one))
501: {
502: goto done;
503: }
504:
505: /* retry with new g if x = n-1 */
506: if (botan_mp_equal(x, n1))
507: {
508: break;
509: }
510:
511: /* let y = x */
512: if (botan_mp_set_from_mp(y, x))
513: {
514: goto error;
515: }
516: }
517: }
518:
519: done:
520: /* 5. p = GCD(y – 1, n) and q = n/p */
521: if (botan_mp_sub(y, y, one))
522: {
523: goto error;
524: }
525:
526: if (botan_mp_init(p) ||
527: botan_mp_gcd(*p, y, *n))
528: {
529: goto error;
530: }
531:
532: if (botan_mp_init(q) ||
533: botan_mp_init(&rem) ||
534: botan_mp_div(*q, rem, *n, *p))
535: {
536: goto error;
537: }
538:
539: if (!botan_mp_is_zero(rem))
540: {
541: goto error;
542: }
543:
544: success = TRUE;
545:
546: error:
547: if (!success)
548: {
549: botan_mp_destroy(*p);
550: botan_mp_destroy(*q);
551: }
552: botan_rng_destroy(rng);
553: botan_mp_destroy(k);
554: botan_mp_destroy(one);
555: botan_mp_destroy(r);
556: botan_mp_destroy(zero);
557: botan_mp_destroy(two);
558: botan_mp_destroy(n1);
559: botan_mp_destroy(x);
560: botan_mp_destroy(y);
561: botan_mp_destroy(g);
562: botan_mp_destroy(rem);
563: return success;
564: }
565:
566: /*
567: * Described in header
568: */
569: botan_rsa_private_key_t *botan_rsa_private_key_load(key_type_t type,
570: va_list args)
571: {
572: private_botan_rsa_private_key_t *this;
573: chunk_t n, e, d, p, q, blob;
574:
575: n = e = d = p = q = blob = chunk_empty;
576: while (TRUE)
577: {
578: switch (va_arg(args, builder_part_t))
579: {
580: case BUILD_BLOB_ASN1_DER:
581: blob = va_arg(args, chunk_t);
582: continue;
583: case BUILD_RSA_MODULUS:
584: n = va_arg(args, chunk_t);
585: continue;
586: case BUILD_RSA_PUB_EXP:
587: e = va_arg(args, chunk_t);
588: continue;
589: case BUILD_RSA_PRIV_EXP:
590: d = va_arg(args, chunk_t);
591: continue;
592: case BUILD_RSA_PRIME1:
593: p = va_arg(args, chunk_t);
594: continue;
595: case BUILD_RSA_PRIME2:
596: q = va_arg(args, chunk_t);
597: continue;
598: case BUILD_RSA_EXP1:
599: case BUILD_RSA_EXP2:
600: case BUILD_RSA_COEFF:
601: /* not required for botan */
602: va_arg(args, chunk_t);
603: continue;
604: case BUILD_END:
605: break;
606: default:
607: return NULL;
608: }
609: break;
610: }
611:
612: if (type == KEY_ANY && !blob.ptr)
613: {
614: return NULL;
615: }
616:
617: if (blob.ptr)
618: {
619: this = create_empty();
620:
621: if (botan_privkey_load_rsa_pkcs1(&this->key, blob.ptr, blob.len))
622: {
623: free(this);
624: return NULL;
625: }
626: return &this->public;
627: }
628:
629: if (n.ptr && e.ptr && d.ptr)
630: {
631: botan_mp_t n_mp, e_mp, d_mp, p_mp = NULL, q_mp = NULL;
632:
633: if (!chunk_to_botan_mp(n, &n_mp))
634: {
635: return NULL;
636: }
637:
638: if (!chunk_to_botan_mp(e, &e_mp))
639: {
640: botan_mp_destroy(n_mp);
641: return NULL;
642: }
643:
644: if (!chunk_to_botan_mp(d, &d_mp))
645: {
646: botan_mp_destroy(n_mp);
647: botan_mp_destroy(e_mp);
648: return NULL;
649: }
650:
651: if (p.ptr && q.ptr)
652: {
653: if (!chunk_to_botan_mp(p, &p_mp))
654: {
655: botan_mp_destroy(n_mp);
656: botan_mp_destroy(e_mp);
657: botan_mp_destroy(d_mp);
658: return NULL;
659: }
660:
661: if (!chunk_to_botan_mp(q, &q_mp))
662: {
663: botan_mp_destroy(n_mp);
664: botan_mp_destroy(e_mp);
665: botan_mp_destroy(d_mp);
666: botan_mp_destroy(p_mp);
667: return NULL;
668: }
669: }
670: else
671: {
672: /* calculate p,q from n, e, d */
673: if (!calculate_pq(&n_mp, &e_mp, &d_mp, &p_mp, &q_mp))
674: {
675: botan_mp_destroy(n_mp);
676: botan_mp_destroy(e_mp);
677: botan_mp_destroy(d_mp);
678: return NULL;
679: }
680: }
681: botan_mp_destroy(n_mp);
682: botan_mp_destroy(d_mp);
683:
684: this = create_empty();
685:
686: if (botan_privkey_load_rsa(&this->key, p_mp, q_mp, e_mp))
687: {
688: botan_mp_destroy(e_mp);
689: botan_mp_destroy(p_mp);
690: botan_mp_destroy(q_mp);
691: free(this);
692: return NULL;
693: }
694:
695: botan_mp_destroy(e_mp);
696: botan_mp_destroy(p_mp);
697: botan_mp_destroy(q_mp);
698:
699: return &this->public;
700: }
701:
702: return NULL;
703: }
704:
705: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>