]>
Commit | Line | Data |
---|---|---|
c92eade8 SP |
1 | /* |
2 | * Copyright (C) 2019 Sean Parkinson, wolfSSL Inc. | |
3 | * | |
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
5 | * of this software and associated documentation files (the "Software"), to deal | |
6 | * in the Software without restriction, including without limitation the rights | |
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
8 | * copies of the Software, and to permit persons to whom the Software is | |
9 | * furnished to do so, subject to the following conditions: | |
10 | * | |
11 | * The above copyright notice and this permission notice shall be included in | |
12 | * all copies or substantial portions of the Software. | |
13 | * | |
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
20 | * THE SOFTWARE. | |
21 | */ | |
22 | ||
23 | #include "wolfssl_common.h" | |
24 | ||
25 | #ifndef NO_RSA | |
26 | ||
27 | #include "wolfssl_rsa_private_key.h" | |
28 | #include "wolfssl_rsa_public_key.h" | |
29 | #include "wolfssl_util.h" | |
30 | ||
c92eade8 | 31 | #include <utils/debug.h> |
d3329ee5 | 32 | #include <crypto/hashers/hasher.h> |
c92eade8 SP |
33 | #include <credentials/keys/signature_params.h> |
34 | ||
35 | #include <wolfssl/wolfcrypt/rsa.h> | |
d3329ee5 | 36 | #include <wolfssl/wolfcrypt/asn.h> |
c92eade8 SP |
37 | |
38 | typedef struct private_wolfssl_rsa_private_key_t private_wolfssl_rsa_private_key_t; | |
39 | ||
40 | /** | |
d3329ee5 | 41 | * Private data of a wolfssl_rsa_private_key_t object |
c92eade8 SP |
42 | */ |
43 | struct private_wolfssl_rsa_private_key_t { | |
d3329ee5 | 44 | |
c92eade8 | 45 | /** |
d3329ee5 | 46 | * Public interface |
c92eade8 SP |
47 | */ |
48 | wolfssl_rsa_private_key_t public; | |
49 | ||
50 | /** | |
51 | * RSA key object from wolfSSL | |
52 | */ | |
53 | RsaKey rsa; | |
54 | ||
55 | /** | |
56 | * Random number generator to use with RSA operations. | |
57 | */ | |
58 | WC_RNG rng; | |
59 | ||
60 | /** | |
d3329ee5 | 61 | * Reference count |
c92eade8 SP |
62 | */ |
63 | refcount_t ref; | |
64 | }; | |
65 | ||
66 | /* implemented in rsa public key */ | |
d3329ee5 | 67 | bool wolfssl_rsa_encode_public(RsaKey *rsa, chunk_t *encoding); |
c92eade8 SP |
68 | bool wolfssl_rsa_fingerprint(RsaKey *rsa, cred_encoding_type_t type, chunk_t *fp); |
69 | ||
c92eade8 SP |
70 | /** |
71 | * Build RSA signature | |
72 | */ | |
73 | static bool build_signature(private_wolfssl_rsa_private_key_t *this, | |
74 | enum wc_HashType hash, chunk_t data, chunk_t *sig) | |
75 | { | |
76 | int ret = wc_RsaSSL_Sign(data.ptr, data.len, sig->ptr, sig->len, &this->rsa, | |
77 | &this->rng); | |
78 | if (ret > 0) | |
79 | { | |
80 | sig->len = ret; | |
81 | } | |
82 | return ret > 0; | |
83 | } | |
84 | ||
85 | /** | |
86 | * Build an EMSA PKCS1 signature described in PKCS#1 | |
87 | */ | |
88 | static bool build_emsa_pkcs1_signature(private_wolfssl_rsa_private_key_t *this, | |
89 | enum wc_HashType hash, chunk_t data, | |
90 | chunk_t *sig) | |
91 | { | |
92 | bool success = FALSE; | |
d3329ee5 TB |
93 | chunk_t dgst, digestInfo; |
94 | int len; | |
c92eade8 SP |
95 | |
96 | *sig = chunk_alloc(wc_RsaEncryptSize(&this->rsa)); | |
97 | ||
98 | if (hash == WC_HASH_TYPE_NONE) | |
99 | { | |
100 | success = build_signature(this, hash, data, sig); | |
101 | } | |
102 | else if (wolfssl_hash_chunk(hash, data, &dgst)) | |
103 | { | |
d3329ee5 TB |
104 | digestInfo = chunk_alloc(MAX_DER_DIGEST_SZ); |
105 | len = wc_EncodeSignature(digestInfo.ptr, dgst.ptr, dgst.len, | |
c92eade8 | 106 | wc_HashGetOID(hash)); |
d3329ee5 | 107 | if (len > 0) |
c92eade8 | 108 | { |
d3329ee5 TB |
109 | digestInfo.len = len; |
110 | success = build_signature(this, hash, digestInfo, sig); | |
c92eade8 | 111 | } |
d3329ee5 | 112 | chunk_free(&digestInfo); |
c92eade8 SP |
113 | chunk_free(&dgst); |
114 | } | |
115 | ||
116 | if (!success) | |
117 | { | |
118 | chunk_free(sig); | |
119 | } | |
120 | return success; | |
121 | } | |
122 | ||
123 | #ifdef WC_RSA_PSS | |
124 | /** | |
125 | * Build an EMSA PSS signature described in PKCS#1 | |
126 | */ | |
127 | static bool build_emsa_pss_signature(private_wolfssl_rsa_private_key_t *this, | |
128 | rsa_pss_params_t *params, chunk_t data, | |
129 | chunk_t *sig) | |
130 | { | |
131 | bool success = FALSE; | |
132 | chunk_t dgst = chunk_empty; | |
133 | enum wc_HashType hash; | |
d3329ee5 | 134 | int mgf, ret; |
c92eade8 SP |
135 | |
136 | if (!wolfssl_hash2type(params->hash, &hash)) | |
137 | { | |
138 | return FALSE; | |
139 | } | |
140 | if (!wolfssl_hash2mgf1(params->mgf1_hash, &mgf)) | |
141 | { | |
142 | return FALSE; | |
143 | } | |
144 | ||
145 | *sig = chunk_alloc(wc_RsaEncryptSize(&this->rsa)); | |
146 | ||
147 | if (wolfssl_hash_chunk(hash, data, &dgst)) | |
148 | { | |
149 | ret = wc_RsaPSS_Sign_ex(dgst.ptr, dgst.len, sig->ptr, sig->len, hash, | |
150 | mgf, params->salt_len, &this->rsa, &this->rng); | |
151 | if (ret > 0) | |
152 | { | |
153 | sig->len = ret; | |
154 | success = TRUE; | |
155 | } | |
156 | } | |
157 | ||
158 | chunk_free(&dgst); | |
159 | if (!success) | |
160 | { | |
161 | chunk_free(sig); | |
162 | } | |
163 | return success; | |
164 | } | |
165 | #endif | |
166 | ||
167 | ||
168 | METHOD(private_key_t, get_type, key_type_t, | |
169 | private_wolfssl_rsa_private_key_t *this) | |
170 | { | |
171 | return KEY_RSA; | |
172 | } | |
173 | ||
174 | METHOD(private_key_t, sign, bool, | |
175 | private_wolfssl_rsa_private_key_t *this, signature_scheme_t scheme, | |
176 | void *params, chunk_t data, chunk_t *signature) | |
177 | { | |
178 | switch (scheme) | |
179 | { | |
180 | case SIGN_RSA_EMSA_PKCS1_NULL: | |
181 | return build_emsa_pkcs1_signature(this, WC_HASH_TYPE_NONE, data, | |
182 | signature); | |
183 | #ifdef WOLFSSL_SHA224 | |
184 | case SIGN_RSA_EMSA_PKCS1_SHA2_224: | |
185 | return build_emsa_pkcs1_signature(this, WC_HASH_TYPE_SHA224, data, | |
186 | signature); | |
187 | #endif | |
188 | #ifndef NO_SHA256 | |
189 | case SIGN_RSA_EMSA_PKCS1_SHA2_256: | |
190 | return build_emsa_pkcs1_signature(this, WC_HASH_TYPE_SHA256, data, | |
191 | signature); | |
192 | #endif | |
193 | #ifdef WOLFSSL_SHA384 | |
194 | case SIGN_RSA_EMSA_PKCS1_SHA2_384: | |
195 | return build_emsa_pkcs1_signature(this, WC_HASH_TYPE_SHA384, data, | |
196 | signature); | |
197 | #endif | |
198 | #ifdef WOLFSSL_SHA512 | |
199 | case SIGN_RSA_EMSA_PKCS1_SHA2_512: | |
200 | return build_emsa_pkcs1_signature(this, WC_HASH_TYPE_SHA512, data, | |
201 | signature); | |
202 | #endif | |
8bbd7bbd AS |
203 | #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) |
204 | case SIGN_RSA_EMSA_PKCS1_SHA3_224: | |
205 | return build_emsa_pkcs1_signature(this, WC_HASH_TYPE_SHA3_224, | |
206 | data, signature); | |
207 | #endif | |
208 | #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) | |
209 | case SIGN_RSA_EMSA_PKCS1_SHA3_256: | |
210 | return build_emsa_pkcs1_signature(this, WC_HASH_TYPE_SHA3_256, | |
211 | data, signature); | |
212 | #endif | |
213 | #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384) | |
214 | case SIGN_RSA_EMSA_PKCS1_SHA3_384: | |
215 | return build_emsa_pkcs1_signature(this, WC_HASH_TYPE_SHA3_384, | |
216 | data, signature); | |
217 | #endif | |
218 | #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512) | |
219 | case SIGN_RSA_EMSA_PKCS1_SHA3_512: | |
220 | return build_emsa_pkcs1_signature(this, WC_HASH_TYPE_SHA3_512, | |
221 | data, signature); | |
222 | #endif | |
c92eade8 SP |
223 | #ifndef NO_SHA |
224 | case SIGN_RSA_EMSA_PKCS1_SHA1: | |
225 | return build_emsa_pkcs1_signature(this, WC_HASH_TYPE_SHA, data, | |
226 | signature); | |
227 | #endif | |
228 | #ifndef NO_MD5 | |
229 | case SIGN_RSA_EMSA_PKCS1_MD5: | |
230 | return build_emsa_pkcs1_signature(this, WC_HASH_TYPE_MD5, data, | |
231 | signature); | |
232 | #endif | |
233 | #ifdef WC_RSA_PSS | |
234 | case SIGN_RSA_EMSA_PSS: | |
235 | return build_emsa_pss_signature(this, params, data, signature); | |
236 | #endif | |
237 | default: | |
d3329ee5 | 238 | DBG1(DBG_LIB, "signature scheme %N not supported via wolfssl", |
c92eade8 SP |
239 | signature_scheme_names, scheme); |
240 | return FALSE; | |
241 | } | |
242 | } | |
243 | ||
244 | METHOD(private_key_t, decrypt, bool, | |
245 | private_wolfssl_rsa_private_key_t *this, encryption_scheme_t scheme, | |
4abb29f6 | 246 | void *params, chunk_t crypto, chunk_t *plain) |
c92eade8 SP |
247 | { |
248 | int padding, mgf, len; | |
249 | enum wc_HashType hash; | |
9cfdc325 AS |
250 | chunk_t label = chunk_empty; |
251 | ||
252 | if (params) | |
253 | { | |
254 | label = *(chunk_t *)params; | |
255 | } | |
c92eade8 SP |
256 | |
257 | switch (scheme) | |
258 | { | |
259 | case ENCRYPT_RSA_PKCS1: | |
260 | hash = WC_HASH_TYPE_NONE; | |
261 | padding = WC_RSA_PKCSV15_PAD; | |
262 | mgf = WC_MGF1NONE; | |
263 | break; | |
264 | #ifndef WC_NO_RSA_OAEP | |
265 | #ifndef NO_SHA | |
266 | case ENCRYPT_RSA_OAEP_SHA1: | |
267 | hash = WC_HASH_TYPE_SHA; | |
268 | padding = WC_RSA_OAEP_PAD; | |
269 | mgf = WC_MGF1SHA1; | |
270 | break; | |
271 | #endif | |
272 | #ifdef WOLFSSL_SHA224 | |
273 | case ENCRYPT_RSA_OAEP_SHA224: | |
274 | hash = WC_HASH_TYPE_SHA224; | |
275 | padding = WC_RSA_OAEP_PAD; | |
276 | mgf = WC_MGF1SHA224; | |
277 | break; | |
278 | #endif | |
279 | #ifndef NO_SHA256 | |
280 | case ENCRYPT_RSA_OAEP_SHA256: | |
281 | hash = WC_HASH_TYPE_SHA256; | |
282 | padding = WC_RSA_OAEP_PAD; | |
283 | mgf = WC_MGF1SHA256; | |
284 | break; | |
285 | #endif | |
286 | #ifdef WOLFSSL_SHA384 | |
287 | case ENCRYPT_RSA_OAEP_SHA384: | |
288 | hash = WC_HASH_TYPE_SHA384; | |
289 | padding = WC_RSA_OAEP_PAD; | |
290 | mgf = WC_MGF1SHA384; | |
291 | break; | |
292 | #endif | |
293 | #ifdef WOLFSSL_SHA512 | |
294 | case ENCRYPT_RSA_OAEP_SHA512: | |
295 | hash = WC_HASH_TYPE_SHA512; | |
296 | padding = WC_RSA_OAEP_PAD; | |
297 | mgf = WC_MGF1SHA512; | |
298 | break; | |
299 | #endif | |
300 | #endif | |
301 | default: | |
302 | DBG1(DBG_LIB, "encryption scheme %N not supported via wolfssl", | |
303 | encryption_scheme_names, scheme); | |
304 | return FALSE; | |
305 | } | |
306 | len = wc_RsaEncryptSize(&this->rsa); | |
d3329ee5 TB |
307 | *plain = chunk_alloc(len); |
308 | len = wc_RsaPrivateDecrypt_ex(crypto.ptr, crypto.len, plain->ptr, len, | |
9cfdc325 AS |
309 | &this->rsa, padding, hash, mgf, |
310 | label.ptr, label.len); | |
c92eade8 SP |
311 | if (len < 0) |
312 | { | |
313 | DBG1(DBG_LIB, "RSA decryption failed"); | |
d3329ee5 | 314 | chunk_free(plain); |
c92eade8 SP |
315 | return FALSE; |
316 | } | |
d3329ee5 | 317 | plain->len = len; |
c92eade8 SP |
318 | return TRUE; |
319 | } | |
320 | ||
321 | METHOD(private_key_t, get_keysize, int, | |
322 | private_wolfssl_rsa_private_key_t *this) | |
323 | { | |
324 | return wc_RsaEncryptSize(&this->rsa) * 8; | |
325 | } | |
326 | ||
327 | METHOD(private_key_t, get_public_key, public_key_t*, | |
328 | private_wolfssl_rsa_private_key_t *this) | |
329 | { | |
c92eade8 | 330 | public_key_t *key; |
d3329ee5 | 331 | chunk_t enc; |
c92eade8 | 332 | |
d3329ee5 TB |
333 | if (!wolfssl_rsa_encode_public(&this->rsa, &enc)) |
334 | { | |
335 | return NULL; | |
336 | } | |
c92eade8 SP |
337 | key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, |
338 | BUILD_BLOB_ASN1_DER, enc, BUILD_END); | |
d3329ee5 | 339 | chunk_free(&enc); |
c92eade8 SP |
340 | return key; |
341 | } | |
342 | ||
343 | METHOD(private_key_t, get_fingerprint, bool, | |
344 | private_wolfssl_rsa_private_key_t *this, cred_encoding_type_t type, | |
345 | chunk_t *fingerprint) | |
346 | { | |
347 | return wolfssl_rsa_fingerprint(&this->rsa, type, fingerprint); | |
348 | } | |
349 | ||
350 | METHOD(private_key_t, get_encoding, bool, | |
351 | private_wolfssl_rsa_private_key_t *this, cred_encoding_type_t type, | |
352 | chunk_t *encoding) | |
353 | { | |
354 | switch (type) | |
355 | { | |
356 | case PRIVKEY_ASN1_DER: | |
357 | case PRIVKEY_PEM: | |
358 | { | |
359 | bool success = TRUE; | |
d3329ee5 | 360 | int len; |
c92eade8 | 361 | |
d3329ee5 | 362 | /* n and d are of keysize length, p and q plus the three CRT |
02b34840 | 363 | * params roughly half that, the version and e are small */ |
d3329ee5 | 364 | len = wc_RsaEncryptSize(&this->rsa) * 5 + MAX_SEQ_SZ; |
c92eade8 SP |
365 | *encoding = chunk_alloc(len); |
366 | len = wc_RsaKeyToDer(&this->rsa, encoding->ptr, len); | |
367 | if (len < 0) | |
368 | { | |
369 | chunk_free(encoding); | |
370 | return FALSE; | |
371 | } | |
372 | encoding->len = len; | |
373 | ||
374 | if (type == PRIVKEY_PEM) | |
375 | { | |
376 | chunk_t asn1_encoding = *encoding; | |
377 | ||
378 | success = lib->encoding->encode(lib->encoding, PRIVKEY_PEM, | |
379 | NULL, encoding, CRED_PART_RSA_PRIV_ASN1_DER, | |
380 | asn1_encoding, CRED_PART_END); | |
381 | chunk_clear(&asn1_encoding); | |
382 | } | |
383 | return success; | |
384 | } | |
385 | default: | |
386 | return FALSE; | |
387 | } | |
388 | } | |
389 | ||
390 | METHOD(private_key_t, get_ref, private_key_t*, | |
391 | private_wolfssl_rsa_private_key_t *this) | |
392 | { | |
393 | ref_get(&this->ref); | |
394 | return &this->public.key; | |
395 | } | |
396 | ||
397 | METHOD(private_key_t, destroy, void, | |
398 | private_wolfssl_rsa_private_key_t *this) | |
399 | { | |
400 | if (ref_put(&this->ref)) | |
401 | { | |
402 | lib->encoding->clear_cache(lib->encoding, &this->rsa); | |
403 | wc_FreeRsaKey(&this->rsa); | |
404 | wc_FreeRng(&this->rng); | |
405 | free(this); | |
406 | } | |
407 | } | |
408 | ||
409 | /** | |
410 | * Internal generic constructor | |
411 | */ | |
412 | static private_wolfssl_rsa_private_key_t *create_empty() | |
413 | { | |
414 | private_wolfssl_rsa_private_key_t *this; | |
415 | ||
416 | INIT(this, | |
417 | .public = { | |
418 | .key = { | |
419 | .get_type = _get_type, | |
420 | .sign = _sign, | |
421 | .decrypt = _decrypt, | |
422 | .get_keysize = _get_keysize, | |
423 | .get_public_key = _get_public_key, | |
424 | .equals = private_key_equals, | |
425 | .belongs_to = private_key_belongs_to, | |
426 | .get_fingerprint = _get_fingerprint, | |
427 | .has_fingerprint = private_key_has_fingerprint, | |
428 | .get_encoding = _get_encoding, | |
429 | .get_ref = _get_ref, | |
430 | .destroy = _destroy, | |
431 | }, | |
432 | }, | |
433 | .ref = 1, | |
434 | ); | |
435 | ||
436 | if (wc_InitRng(&this->rng) != 0) | |
437 | { | |
d3329ee5 | 438 | DBG1(DBG_LIB, "init RNG failed, rsa private key create failed"); |
c92eade8 SP |
439 | free(this); |
440 | return NULL; | |
441 | } | |
442 | if (wc_InitRsaKey(&this->rsa, NULL) != 0) | |
443 | { | |
d3329ee5 | 444 | DBG1(DBG_LIB, "init RSA failed, rsa private key create failed"); |
c92eade8 SP |
445 | wc_FreeRng(&this->rng); |
446 | free(this); | |
447 | return NULL; | |
448 | } | |
29f70176 | 449 | #ifdef WC_RSA_BLINDING |
c92eade8 | 450 | this->rsa.rng = &this->rng; |
29f70176 | 451 | #endif |
c92eade8 SP |
452 | |
453 | return this; | |
454 | } | |
455 | ||
456 | /* | |
d3329ee5 | 457 | * Described in header |
c92eade8 SP |
458 | */ |
459 | wolfssl_rsa_private_key_t *wolfssl_rsa_private_key_gen(key_type_t type, | |
460 | va_list args) | |
461 | { | |
462 | private_wolfssl_rsa_private_key_t *this; | |
463 | u_int key_size = 0; | |
464 | ||
465 | while (TRUE) | |
466 | { | |
467 | switch (va_arg(args, builder_part_t)) | |
468 | { | |
469 | case BUILD_KEY_SIZE: | |
470 | key_size = va_arg(args, u_int); | |
471 | continue; | |
472 | case BUILD_END: | |
473 | break; | |
474 | default: | |
475 | return NULL; | |
476 | } | |
477 | break; | |
478 | } | |
479 | if (!key_size) | |
480 | { | |
481 | return NULL; | |
482 | } | |
483 | ||
484 | this = create_empty(); | |
d3329ee5 | 485 | if (!this) |
c92eade8 SP |
486 | { |
487 | return NULL; | |
488 | } | |
489 | ||
490 | if (wc_MakeRsaKey(&this->rsa, key_size, WC_RSA_EXPONENT, &this->rng) < 0) | |
491 | { | |
492 | destroy(this); | |
493 | return NULL; | |
494 | } | |
495 | return &this->public; | |
496 | } | |
497 | ||
d3329ee5 TB |
498 | /** |
499 | * Allocate a random number in the range [0, n-1] | |
500 | */ | |
501 | static bool wolfssl_mp_rand(mp_int *n, WC_RNG *rng, mp_int *r) | |
c92eade8 | 502 | { |
d3329ee5 | 503 | int len, ret; |
c92eade8 | 504 | |
d3329ee5 | 505 | /* ensure the number has enough memory. */ |
c92eade8 SP |
506 | ret = mp_set_bit(r, mp_count_bits(n)); |
507 | if (ret == 0) | |
508 | { | |
509 | len = sizeof(*r->dp) * n->used; | |
510 | ret = wc_RNG_GenerateBlock(rng, (byte *)r->dp, len); | |
511 | } | |
512 | if (ret == 0) | |
513 | { | |
514 | ret = mp_mod(r, n, r); | |
515 | } | |
c92eade8 SP |
516 | return ret == 0; |
517 | } | |
518 | ||
519 | /** | |
520 | * Recover the primes from n, e and d using the algorithm described in | |
521 | * Appendix C of NIST SP 800-56B. | |
522 | */ | |
523 | static bool calculate_pq(mp_int *n, mp_int *e, mp_int *d, mp_int *p, mp_int *q, | |
524 | mp_int *t1, mp_int *t2, WC_RNG* rng) | |
525 | { | |
526 | int i, t, j; | |
527 | bool success = FALSE; | |
d3329ee5 TB |
528 | mp_int *k = p; |
529 | mp_int *r = p; | |
530 | mp_int *n1 = q; | |
531 | mp_int *g = t2; | |
532 | mp_int *y = t2; | |
533 | mp_int *x = t1; | |
c92eade8 SP |
534 | |
535 | /* k = (d * e) - 1 */ | |
d3329ee5 | 536 | if (mp_mul(d, e, k) != 0) |
c92eade8 SP |
537 | { |
538 | goto error; | |
539 | } | |
540 | if (mp_sub_d(k, 1, k) != 0) | |
541 | { | |
542 | goto error; | |
543 | } | |
544 | /* k must be even */ | |
545 | if (mp_isodd(k)) | |
546 | { | |
547 | goto error; | |
548 | } | |
549 | /* k = 2^t * r, where r is the largest odd integer dividing k, and t >= 1 */ | |
d3329ee5 | 550 | if (mp_copy(k, r) != 0) |
c92eade8 SP |
551 | { |
552 | goto error; | |
553 | } | |
554 | for (t = 0; !mp_isodd(r); t++) | |
555 | { /* r = r/2 */ | |
556 | if (mp_div_2(r, r) != 0) | |
557 | goto error; | |
558 | } | |
559 | /* we need n-1 below */ | |
560 | if (mp_sub_d(n, 1, n1) != 0) | |
561 | { | |
562 | goto error; | |
563 | } | |
564 | for (i = 0; i < 100; i++) | |
565 | { /* generate random integer g in [0, n-1] */ | |
566 | if (!wolfssl_mp_rand(n, rng, g)) | |
567 | { | |
568 | goto error; | |
569 | } | |
570 | /* y = g^r mod n */ | |
571 | if (mp_exptmod(g, r, n, y) != 0) | |
572 | { | |
573 | goto error; | |
574 | } | |
575 | /* try again if y == 1 or y == n-1 */ | |
576 | if (mp_isone(y) || mp_cmp(y, n1) == MP_EQ) | |
577 | { | |
578 | continue; | |
579 | } | |
580 | for (j = 0; j < t; j++) | |
581 | { /* x = y^2 mod n */ | |
582 | if (mp_sqrmod(y, n, x) != 0) | |
583 | { | |
584 | goto error; | |
585 | } | |
586 | /* stop if x == 1 */ | |
587 | if (mp_isone(x)) | |
588 | { | |
589 | goto done; | |
590 | } | |
591 | /* retry with new g if x = n-1 */ | |
592 | if (mp_cmp(x, n1) == MP_EQ) | |
593 | { | |
594 | break; | |
595 | } | |
596 | /* y = x */ | |
d3329ee5 | 597 | if (mp_copy(x, y) != 0) |
c92eade8 SP |
598 | { |
599 | goto error; | |
600 | } | |
601 | } | |
602 | } | |
603 | goto error; | |
d3329ee5 | 604 | |
c92eade8 SP |
605 | done: |
606 | /* p = gcd(y-1, n) */ | |
607 | if (mp_sub_d(y, 1, y) != 0) | |
608 | { | |
609 | goto error; | |
610 | } | |
611 | if (mp_gcd(y, n, p) != 0) | |
612 | { | |
613 | goto error; | |
614 | } | |
615 | /* q = n/p */ | |
616 | if (mp_div(n, p, q, NULL) != 0) | |
617 | { | |
618 | goto error; | |
619 | } | |
620 | ||
621 | success = TRUE; | |
d3329ee5 | 622 | |
c92eade8 SP |
623 | error: |
624 | return success; | |
625 | } | |
626 | ||
627 | /** | |
628 | * Calculates dp = d (mod p-1) or dq = d (mod q-1) for the Chinese remainder | |
629 | * algorithm. | |
630 | */ | |
d3329ee5 | 631 | static bool dmodpq1(mp_int *d, mp_int *pq, mp_int *res) |
c92eade8 | 632 | { |
d3329ee5 TB |
633 | /* p|q - 1 |
634 | * d (mod p|q -1) */ | |
635 | return mp_sub_d(pq, 1, res) == 0 && | |
636 | mp_mod(d, res, res) == 0; | |
c92eade8 SP |
637 | } |
638 | ||
639 | /** | |
640 | * Calculates qinv = q^-1 (mod p) for the Chinese remainder algorithm. | |
641 | */ | |
642 | static int qinv(mp_int *q, mp_int *p, mp_int *res) | |
643 | { | |
644 | /* q^-1 (mod p) */ | |
645 | return mp_invmod(q, p, res) == 0; | |
646 | } | |
647 | ||
648 | /* | |
d3329ee5 | 649 | * Described in header |
c92eade8 SP |
650 | */ |
651 | wolfssl_rsa_private_key_t *wolfssl_rsa_private_key_load(key_type_t type, | |
652 | va_list args) | |
653 | { | |
654 | private_wolfssl_rsa_private_key_t *this; | |
655 | chunk_t blob, n, e, d, p, q, exp1, exp2, coeff; | |
656 | word32 idx; | |
657 | int ret; | |
658 | ||
659 | blob = n = e = d = p = q = exp1 = exp2 = coeff = chunk_empty; | |
660 | while (TRUE) | |
661 | { | |
662 | switch (va_arg(args, builder_part_t)) | |
663 | { | |
664 | case BUILD_BLOB_ASN1_DER: | |
665 | blob = va_arg(args, chunk_t); | |
666 | continue; | |
667 | case BUILD_RSA_MODULUS: | |
668 | n = va_arg(args, chunk_t); | |
669 | continue; | |
670 | case BUILD_RSA_PUB_EXP: | |
671 | e = va_arg(args, chunk_t); | |
672 | continue; | |
673 | case BUILD_RSA_PRIV_EXP: | |
674 | d = va_arg(args, chunk_t); | |
675 | continue; | |
676 | case BUILD_RSA_PRIME1: | |
677 | p = va_arg(args, chunk_t); | |
678 | continue; | |
679 | case BUILD_RSA_PRIME2: | |
680 | q = va_arg(args, chunk_t); | |
681 | continue; | |
682 | case BUILD_RSA_EXP1: | |
683 | exp1 = va_arg(args, chunk_t); | |
684 | continue; | |
685 | case BUILD_RSA_EXP2: | |
686 | exp2 = va_arg(args, chunk_t); | |
687 | continue; | |
688 | case BUILD_RSA_COEFF: | |
689 | coeff = va_arg(args, chunk_t); | |
690 | continue; | |
691 | case BUILD_END: | |
692 | break; | |
693 | default: | |
694 | return NULL; | |
695 | } | |
696 | break; | |
697 | } | |
698 | ||
699 | this = create_empty(); | |
d3329ee5 | 700 | if (!this) |
c92eade8 SP |
701 | { |
702 | return NULL; | |
703 | } | |
704 | ||
705 | if (blob.ptr) | |
706 | { | |
707 | idx = 0; | |
708 | ret = wc_RsaPrivateKeyDecode(blob.ptr, &idx, &this->rsa, blob.len); | |
709 | if (ret == 0) | |
710 | { | |
711 | return &this->public; | |
712 | } | |
713 | } | |
714 | else if (n.ptr && e.ptr && d.ptr) | |
715 | { | |
62c5ef03 AS |
716 | this->rsa.type = RSA_PRIVATE; |
717 | ||
c92eade8 SP |
718 | if (mp_read_unsigned_bin(&this->rsa.n, n.ptr, n.len) != 0) |
719 | { | |
720 | goto error; | |
721 | } | |
722 | if (mp_read_unsigned_bin(&this->rsa.e, e.ptr, e.len) != 0) | |
723 | { | |
724 | goto error; | |
725 | } | |
726 | if (mp_read_unsigned_bin(&this->rsa.d, d.ptr, d.len) != 0) | |
727 | { | |
728 | goto error; | |
729 | } | |
730 | if (p.ptr && q.ptr) | |
731 | { | |
732 | if (mp_read_unsigned_bin(&this->rsa.p, p.ptr, p.len) != 0) | |
733 | { | |
734 | goto error; | |
735 | } | |
736 | if (mp_read_unsigned_bin(&this->rsa.q, q.ptr, q.len) != 0) | |
737 | { | |
738 | goto error; | |
739 | } | |
740 | } | |
741 | else if (!calculate_pq(&this->rsa.n, &this->rsa.e, &this->rsa.d, | |
742 | &this->rsa.p, &this->rsa.q, &this->rsa.dP, | |
743 | &this->rsa.dQ, &this->rng)) | |
744 | { | |
c92eade8 SP |
745 | goto error; |
746 | } | |
747 | if (exp1.ptr) | |
748 | { | |
749 | if (mp_read_unsigned_bin(&this->rsa.dP, exp1.ptr, exp1.len) != 0) | |
750 | { | |
751 | goto error; | |
752 | } | |
753 | } | |
754 | else if (!dmodpq1(&this->rsa.d, &this->rsa.p, &this->rsa.dP)) | |
755 | { | |
756 | goto error; | |
757 | } | |
758 | if (exp2.ptr) | |
759 | { | |
760 | if (mp_read_unsigned_bin(&this->rsa.dQ, exp2.ptr, exp2.len) != 0) | |
761 | { | |
762 | goto error; | |
763 | } | |
764 | } | |
765 | else if (!dmodpq1(&this->rsa.d, &this->rsa.q, &this->rsa.dQ)) | |
766 | { | |
767 | goto error; | |
768 | } | |
769 | if (coeff.ptr) | |
770 | { | |
771 | if (mp_read_unsigned_bin(&this->rsa.u, coeff.ptr, coeff.len) != 0) | |
772 | { | |
773 | goto error; | |
774 | } | |
775 | } | |
776 | else if (!qinv(&this->rsa.q, &this->rsa.p, &this->rsa.u)) | |
777 | { | |
778 | goto error; | |
779 | } | |
780 | ||
781 | return &this->public; | |
782 | } | |
783 | error: | |
784 | destroy(this); | |
785 | return NULL; | |
786 | } | |
787 | ||
788 | #endif /* NO_RSA */ |