Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
rsa.c
00001 /* rsa.c 00002 * 00003 * Copyright (C) 2006-2016 wolfSSL Inc. 00004 * 00005 * This file is part of wolfSSL. 00006 * 00007 * wolfSSL is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * wolfSSL is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with this program; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA 00020 */ 00021 00022 00023 #ifdef HAVE_CONFIG_H 00024 #include <config.h> 00025 #endif 00026 00027 #include <wolfssl/wolfcrypt/settings.h> 00028 00029 #ifndef NO_RSA 00030 00031 #include <wolfssl/wolfcrypt/rsa.h> 00032 00033 #ifdef HAVE_FIPS 00034 int wc_InitRsaKey(RsaKey* key, void* ptr) 00035 { 00036 return InitRsaKey_fips(key, ptr); 00037 } 00038 00039 00040 int wc_FreeRsaKey(RsaKey* key) 00041 { 00042 return FreeRsaKey_fips(key); 00043 } 00044 00045 00046 int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, 00047 word32 outLen, RsaKey* key, WC_RNG* rng) 00048 { 00049 return RsaPublicEncrypt_fips(in, inLen, out, outLen, key, rng); 00050 } 00051 00052 00053 int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, 00054 RsaKey* key) 00055 { 00056 return RsaPrivateDecryptInline_fips(in, inLen, out, key); 00057 } 00058 00059 00060 int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, 00061 word32 outLen, RsaKey* key) 00062 { 00063 return RsaPrivateDecrypt_fips(in, inLen, out, outLen, key); 00064 } 00065 00066 00067 int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, 00068 word32 outLen, RsaKey* key, WC_RNG* rng) 00069 { 00070 return RsaSSL_Sign_fips(in, inLen, out, outLen, key, rng); 00071 } 00072 00073 00074 int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key) 00075 { 00076 return RsaSSL_VerifyInline_fips(in, inLen, out, key); 00077 } 00078 00079 00080 int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, 00081 word32 outLen, RsaKey* key) 00082 { 00083 return RsaSSL_Verify_fips(in, inLen, out, outLen, key); 00084 } 00085 00086 00087 int wc_RsaEncryptSize(RsaKey* key) 00088 { 00089 return RsaEncryptSize_fips(key); 00090 } 00091 00092 00093 int wc_RsaFlattenPublicKey(RsaKey* key, byte* a, word32* aSz, byte* b, 00094 word32* bSz) 00095 { 00096 /* not specified as fips so not needing _fips */ 00097 return RsaFlattenPublicKey(key, a, aSz, b, bSz); 00098 } 00099 #ifdef WOLFSSL_KEY_GEN 00100 int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) 00101 { 00102 return MakeRsaKey(key, size, e, rng); 00103 } 00104 #endif 00105 00106 00107 #ifdef HAVE_CAVIUM 00108 int wc_RsaInitCavium(RsaKey* key, int i) 00109 { 00110 return RsaInitCavium(key, i); 00111 } 00112 00113 00114 void wc_RsaFreeCavium(RsaKey* key) 00115 { 00116 RsaFreeCavium(key); 00117 } 00118 #endif 00119 00120 /* these are functions in asn and are routed to wolfssl/wolfcrypt/asn.c 00121 * wc_RsaPrivateKeyDecode 00122 * wc_RsaPublicKeyDecode 00123 */ 00124 00125 #else /* else build without fips */ 00126 #include <wolfssl/wolfcrypt/random.h> 00127 #include <wolfssl/wolfcrypt/error-crypt.h> 00128 #include <wolfssl/wolfcrypt/logging.h> 00129 #ifdef NO_INLINE 00130 #include <wolfssl/wolfcrypt/misc.h> 00131 #else 00132 #include <wolfcrypt/src/misc.c> 00133 #endif 00134 00135 #ifdef HAVE_CAVIUM 00136 static int InitCaviumRsaKey(RsaKey* key, void* heap); 00137 static int FreeCaviumRsaKey(RsaKey* key); 00138 static int CaviumRsaPublicEncrypt(const byte* in, word32 inLen, byte* out, 00139 word32 outLen, RsaKey* key); 00140 static int CaviumRsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, 00141 word32 outLen, RsaKey* key); 00142 static int CaviumRsaSSL_Sign(const byte* in, word32 inLen, byte* out, 00143 word32 outLen, RsaKey* key); 00144 static int CaviumRsaSSL_Verify(const byte* in, word32 inLen, byte* out, 00145 word32 outLen, RsaKey* key); 00146 #endif 00147 00148 enum { 00149 RSA_PUBLIC_ENCRYPT = 0, 00150 RSA_PUBLIC_DECRYPT = 1, 00151 RSA_PRIVATE_ENCRYPT = 2, 00152 RSA_PRIVATE_DECRYPT = 3, 00153 00154 RSA_BLOCK_TYPE_1 = 1, 00155 RSA_BLOCK_TYPE_2 = 2, 00156 00157 RSA_MIN_SIZE = 512, 00158 RSA_MAX_SIZE = 4096, 00159 00160 RSA_MIN_PAD_SZ = 11 /* separator + 0 + pad value + 8 pads */ 00161 }; 00162 00163 00164 int wc_InitRsaKey(RsaKey* key, void* heap) 00165 { 00166 #ifdef HAVE_CAVIUM 00167 if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) 00168 return InitCaviumRsaKey(key, heap); 00169 #endif 00170 00171 key->type = -1; /* haven't decided yet */ 00172 key->heap = heap; 00173 00174 /* TomsFastMath doesn't use memory allocation */ 00175 #ifndef USE_FAST_MATH 00176 key->n.dp = key->e.dp = 0; /* public alloc parts */ 00177 00178 key->d.dp = key->p.dp = 0; /* private alloc parts */ 00179 key->q.dp = key->dP.dp = 0; 00180 key->u.dp = key->dQ.dp = 0; 00181 #else 00182 mp_init(&key->n); 00183 mp_init(&key->e); 00184 mp_init(&key->d); 00185 mp_init(&key->p); 00186 mp_init(&key->q); 00187 mp_init(&key->dP); 00188 mp_init(&key->dQ); 00189 mp_init(&key->u); 00190 #endif 00191 00192 return 0; 00193 } 00194 00195 00196 int wc_FreeRsaKey(RsaKey* key) 00197 { 00198 (void)key; 00199 00200 if (key == NULL) 00201 return 0; 00202 00203 #ifdef HAVE_CAVIUM 00204 if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) 00205 return FreeCaviumRsaKey(key); 00206 #endif 00207 00208 /* TomsFastMath doesn't use memory allocation */ 00209 #ifndef USE_FAST_MATH 00210 if (key->type == RSA_PRIVATE) { 00211 mp_clear(&key->u); 00212 mp_clear(&key->dQ); 00213 mp_clear(&key->dP); 00214 mp_clear(&key->q); 00215 mp_clear(&key->p); 00216 mp_clear(&key->d); 00217 } 00218 mp_clear(&key->e); 00219 mp_clear(&key->n); 00220 #else 00221 /* still clear private key memory information when free'd */ 00222 if (key->type == RSA_PRIVATE) { 00223 mp_clear(&key->u); 00224 mp_clear(&key->dQ); 00225 mp_clear(&key->u); 00226 mp_clear(&key->dP); 00227 mp_clear(&key->q); 00228 mp_clear(&key->p); 00229 mp_clear(&key->d); 00230 } 00231 #endif 00232 00233 return 0; 00234 } 00235 00236 00237 #ifndef WC_NO_RSA_OAEP 00238 /* Uses MGF1 standard as a mask generation function 00239 hType: hash type used 00240 seed: seed to use for generating mask 00241 seedSz: size of seed buffer 00242 out: mask output after generation 00243 outSz: size of output buffer 00244 */ 00245 static int wc_MGF1(enum wc_HashType hType, byte* seed, word32 seedSz, 00246 byte* out, word32 outSz) 00247 { 00248 byte* tmp; 00249 /* needs to be large enough for seed size plus counter(4) */ 00250 byte tmpA[WC_MAX_DIGEST_SIZE + 4]; 00251 byte tmpF; /* 1 if dynamic memory needs freed */ 00252 word32 tmpSz; 00253 int hLen; 00254 int ret; 00255 word32 counter; 00256 word32 idx; 00257 hLen = wc_HashGetDigestSize(hType); 00258 counter = 0; 00259 idx = 0; 00260 00261 /* check error return of wc_HashGetDigestSize */ 00262 if (hLen < 0) { 00263 return hLen; 00264 } 00265 00266 /* if tmp is not large enough than use some dynamic memory */ 00267 if ((seedSz + 4) > sizeof(tmpA) || (word32)hLen > sizeof(tmpA)) { 00268 /* find largest amount of memory needed which will be the max of 00269 * hLen and (seedSz + 4) since tmp is used to store the hash digest */ 00270 tmpSz = ((seedSz + 4) > (word32)hLen)? seedSz + 4: (word32)hLen; 00271 tmp = (byte*)XMALLOC(tmpSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00272 if (tmp == NULL) { 00273 return MEMORY_E; 00274 } 00275 tmpF = 1; /* make sure to free memory when done */ 00276 } 00277 else { 00278 /* use array on the stack */ 00279 tmpSz = sizeof(tmpA); 00280 tmp = tmpA; 00281 tmpF = 0; /* no need to free memory at end */ 00282 } 00283 00284 do { 00285 int i = 0; 00286 XMEMCPY(tmp, seed, seedSz); 00287 00288 /* counter to byte array appended to tmp */ 00289 tmp[seedSz] = (counter >> 24) & 0xFF; 00290 tmp[seedSz + 1] = (counter >> 16) & 0xFF; 00291 tmp[seedSz + 2] = (counter >> 8) & 0xFF; 00292 tmp[seedSz + 3] = (counter) & 0xFF; 00293 00294 /* hash and append to existing output */ 00295 if ((ret = wc_Hash(hType, tmp, (seedSz + 4), tmp, tmpSz)) != 0) { 00296 /* check for if dynamic memory was needed, then free */ 00297 if (tmpF) { 00298 XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00299 } 00300 return ret; 00301 } 00302 00303 for (i = 0; i < hLen && idx < outSz; i++) { 00304 out[idx++] = tmp[i]; 00305 } 00306 counter++; 00307 } 00308 while (idx < outSz); 00309 00310 /* check for if dynamic memory was needed, then free */ 00311 if (tmpF) { 00312 XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00313 } 00314 00315 return 0; 00316 } 00317 00318 00319 /* helper function to direct which mask generation function is used 00320 switeched on type input 00321 */ 00322 static int wc_MGF(int type, byte* seed, word32 seedSz, 00323 byte* out, word32 outSz) 00324 { 00325 int ret; 00326 00327 switch(type) { 00328 #ifndef NO_SHA 00329 case WC_MGF1SHA1: 00330 ret = wc_MGF1(WC_HASH_TYPE_SHA, seed, seedSz, out, outSz); 00331 break; 00332 #endif 00333 #ifndef NO_SHA256 00334 case WC_MGF1SHA256: 00335 ret = wc_MGF1(WC_HASH_TYPE_SHA256, seed, seedSz, out, outSz); 00336 break; 00337 #endif 00338 #ifdef WOLFSSL_SHA512 00339 #ifdef WOLFSSL_SHA384 00340 case WC_MGF1SHA384: 00341 ret = wc_MGF1(WC_HASH_TYPE_SHA384, seed, seedSz, out, outSz); 00342 break; 00343 #endif 00344 case WC_MGF1SHA512: 00345 ret = wc_MGF1(WC_HASH_TYPE_SHA512, seed, seedSz, out, outSz); 00346 break; 00347 #endif 00348 default: 00349 WOLFSSL_MSG("Unknown MGF function: check build options"); 00350 ret = BAD_FUNC_ARG; 00351 } 00352 00353 /* in case of default avoid unused warning */ 00354 (void)seed; 00355 (void)seedSz; 00356 (void)out; 00357 (void)outSz; 00358 00359 return ret; 00360 } 00361 00362 00363 static int wc_RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, 00364 word32 pkcsBlockLen, byte padValue, WC_RNG* rng, 00365 enum wc_HashType hType, int mgf, byte* optLabel, word32 labelLen) 00366 { 00367 int ret; 00368 int hLen; 00369 int psLen; 00370 int i; 00371 word32 idx; 00372 00373 byte* dbMask; 00374 00375 #ifdef WOLFSSL_SMALL_STACK 00376 byte* lHash = NULL; 00377 byte* seed = NULL; 00378 #else 00379 /* must be large enough to contain largest hash */ 00380 byte lHash[WC_MAX_DIGEST_SIZE]; 00381 byte seed[ WC_MAX_DIGEST_SIZE]; 00382 #endif 00383 00384 /* can use with no lable but catch if no lable provided while having 00385 length > 0 */ 00386 if (optLabel == NULL && labelLen > 0) { 00387 return BUFFER_E; 00388 } 00389 00390 /* limit of label is the same as limit of hash function which is massive */ 00391 hLen = wc_HashGetDigestSize(hType); 00392 if (hLen < 0) { 00393 return hLen; 00394 } 00395 00396 #ifdef WOLFSSL_SMALL_STACK 00397 lHash = (byte*)XMALLOC(hLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00398 if (lHash == NULL) { 00399 return MEMORY_E; 00400 } 00401 seed = (byte*)XMALLOC(hLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00402 if (seed == NULL) { 00403 XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00404 return MEMORY_E; 00405 } 00406 #else 00407 /* hLen should never be larger than lHash since size is max digest size, 00408 but check before blindly calling wc_Hash */ 00409 if ((word32)hLen > sizeof(lHash)) { 00410 WOLFSSL_MSG("OAEP lHash to small for digest!!"); 00411 return MEMORY_E; 00412 } 00413 #endif 00414 00415 if ((ret = wc_Hash(hType, optLabel, labelLen, 00416 lHash, hLen)) != 0) { 00417 WOLFSSL_MSG("OAEP hash type possibly not supported or lHash to small"); 00418 #ifdef WOLFSSL_SMALL_STACK 00419 XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00420 XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00421 #endif 00422 return ret; 00423 } 00424 00425 /* handles check of location for idx as well as psLen, cast to int to check 00426 for pkcsBlockLen(k) - 2 * hLen - 2 being negative 00427 This check is similar to decryption where k > 2 * hLen + 2 as msg 00428 size aproaches 0. In decryption if k is less than or equal -- then there 00429 is no possible room for msg. 00430 k = RSA key size 00431 hLen = hash digest size -- will always be >= 0 at this point 00432 */ 00433 if ((word32)(2 * hLen + 2) > pkcsBlockLen) { 00434 WOLFSSL_MSG("OAEP pad error hash to big for RSA key size"); 00435 #ifdef WOLFSSL_SMALL_STACK 00436 XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00437 XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00438 #endif 00439 return BAD_FUNC_ARG; 00440 } 00441 00442 if (inputLen > (pkcsBlockLen - 2 * hLen - 2)) { 00443 WOLFSSL_MSG("OAEP pad error message too long"); 00444 #ifdef WOLFSSL_SMALL_STACK 00445 XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00446 XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00447 #endif 00448 return BAD_FUNC_ARG; 00449 } 00450 00451 /* concatenate lHash || PS || 0x01 || msg */ 00452 idx = pkcsBlockLen - 1 - inputLen; 00453 psLen = pkcsBlockLen - inputLen - 2 * hLen - 2; 00454 if (pkcsBlockLen < inputLen) { /*make sure not writing over end of buffer */ 00455 #ifdef WOLFSSL_SMALL_STACK 00456 XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00457 XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00458 #endif 00459 return BUFFER_E; 00460 } 00461 XMEMCPY(pkcsBlock + (pkcsBlockLen - inputLen), input, inputLen); 00462 pkcsBlock[idx--] = 0x01; /* PS and M separator */ 00463 while (psLen > 0 && idx > 0) { 00464 pkcsBlock[idx--] = 0x00; 00465 psLen--; 00466 } 00467 00468 idx = idx - hLen + 1; 00469 XMEMCPY(pkcsBlock + idx, lHash, hLen); 00470 00471 /* generate random seed */ 00472 if ((ret = wc_RNG_GenerateBlock(rng, seed, hLen)) != 0) { 00473 #ifdef WOLFSSL_SMALL_STACK 00474 XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00475 XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00476 #endif 00477 return ret; 00478 } 00479 00480 /* create maskedDB from dbMask */ 00481 dbMask = (byte*)XMALLOC(pkcsBlockLen - hLen - 1, NULL, DYNAMIC_TYPE_RSA); 00482 if (dbMask == NULL) { 00483 #ifdef WOLFSSL_SMALL_STACK 00484 XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00485 XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00486 #endif 00487 return MEMORY_E; 00488 } 00489 XMEMSET(dbMask, 0, pkcsBlockLen - hLen - 1); /* help static analyzer */ 00490 00491 ret = wc_MGF(mgf, seed, hLen, dbMask, pkcsBlockLen - hLen - 1); 00492 if (ret != 0) { 00493 XFREE(dbMask, NULL, DYNAMIC_TYPE_RSA); 00494 #ifdef WOLFSSL_SMALL_STACK 00495 XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00496 XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00497 #endif 00498 return ret; 00499 } 00500 00501 i = 0; 00502 idx = hLen + 1; 00503 while (idx < pkcsBlockLen && (word32)i < (pkcsBlockLen - hLen -1)) { 00504 pkcsBlock[idx] = dbMask[i++] ^ pkcsBlock[idx]; 00505 idx++; 00506 } 00507 XFREE(dbMask, NULL, DYNAMIC_TYPE_RSA); 00508 00509 00510 /* create maskedSeed from seedMask */ 00511 idx = 0; 00512 pkcsBlock[idx++] = 0x00; 00513 /* create seedMask inline */ 00514 if ((ret = wc_MGF(mgf, pkcsBlock + hLen + 1, pkcsBlockLen - hLen - 1, 00515 pkcsBlock + 1, hLen)) != 0) { 00516 #ifdef WOLFSSL_SMALL_STACK 00517 XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00518 XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00519 #endif 00520 return ret; 00521 } 00522 00523 /* xor created seedMask with seed to make maskedSeed */ 00524 i = 0; 00525 while (idx < (word32)(hLen + 1) && i < hLen) { 00526 pkcsBlock[idx] = pkcsBlock[idx] ^ seed[i++]; 00527 idx++; 00528 } 00529 00530 #ifdef WOLFSSL_SMALL_STACK 00531 XFREE(lHash, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00532 XFREE(seed, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00533 #endif 00534 (void)padValue; 00535 00536 return 0; 00537 } 00538 #endif /* WC_NO_RSA_OAEP */ 00539 00540 00541 static int wc_RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock, 00542 word32 pkcsBlockLen, byte padValue, WC_RNG* rng) 00543 { 00544 if (inputLen == 0) 00545 return 0; 00546 00547 pkcsBlock[0] = 0x0; /* set first byte to zero and advance */ 00548 pkcsBlock++; pkcsBlockLen--; 00549 pkcsBlock[0] = padValue; /* insert padValue */ 00550 00551 if (padValue == RSA_BLOCK_TYPE_1) 00552 /* pad with 0xff bytes */ 00553 XMEMSET(&pkcsBlock[1], 0xFF, pkcsBlockLen - inputLen - 2); 00554 else { 00555 /* pad with non-zero random bytes */ 00556 word32 padLen = pkcsBlockLen - inputLen - 1, i; 00557 int ret = wc_RNG_GenerateBlock(rng, &pkcsBlock[1], padLen); 00558 00559 if (ret != 0) 00560 return ret; 00561 00562 /* remove zeros */ 00563 for (i = 1; i < padLen; i++) 00564 if (pkcsBlock[i] == 0) pkcsBlock[i] = 0x01; 00565 } 00566 00567 pkcsBlock[pkcsBlockLen-inputLen-1] = 0; /* separator */ 00568 XMEMCPY(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen); 00569 00570 return 0; 00571 } 00572 00573 00574 #ifndef WC_NO_RSA_OAEP 00575 /* helper function to direct which padding is used */ 00576 static int wc_RsaPad_ex(const byte* input, word32 inputLen, byte* pkcsBlock, 00577 word32 pkcsBlockLen, byte padValue, WC_RNG* rng, int padType, 00578 enum wc_HashType hType, int mgf, byte* optLabel, word32 labelLen) 00579 { 00580 int ret; 00581 00582 switch (padType) 00583 { 00584 case WC_RSA_PKCSV15_PAD: 00585 WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 padding"); 00586 ret = wc_RsaPad(input, inputLen, pkcsBlock, pkcsBlockLen, 00587 padValue, rng); 00588 break; 00589 00590 case WC_RSA_OAEP_PAD: 00591 WOLFSSL_MSG("wolfSSL Using RSA OAEP padding"); 00592 ret = wc_RsaPad_OAEP(input, inputLen, pkcsBlock, pkcsBlockLen, 00593 padValue, rng, hType, mgf, optLabel, labelLen); 00594 break; 00595 00596 default: 00597 WOLFSSL_MSG("Unknown RSA Pad Type"); 00598 ret = RSA_PAD_E; 00599 } 00600 00601 /* silence warning if not used with padding scheme */ 00602 (void)padType; 00603 (void)hType; 00604 (void)mgf; 00605 (void)optLabel; 00606 (void)labelLen; 00607 00608 return ret; 00609 } 00610 00611 00612 /* UnPad plaintext, set start to *output, return length of plaintext, 00613 * < 0 on error */ 00614 static int wc_RsaUnPad_OAEP(byte *pkcsBlock, unsigned int pkcsBlockLen, 00615 byte **output, enum wc_HashType hType, int mgf, 00616 byte* optLabel, word32 labelLen) 00617 { 00618 int hLen; 00619 int ret; 00620 byte h[WC_MAX_DIGEST_SIZE]; /* max digest size */ 00621 byte* tmp; 00622 word32 idx; 00623 00624 hLen = wc_HashGetDigestSize(hType); 00625 if ((hLen < 0) || (pkcsBlockLen < (2 * (word32)hLen + 2))) { 00626 return BAD_FUNC_ARG; 00627 } 00628 00629 tmp = (byte*)XMALLOC(pkcsBlockLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00630 if (tmp == NULL) { 00631 return MEMORY_E; 00632 } 00633 XMEMSET(tmp, 0, pkcsBlockLen); 00634 00635 /* find seedMask value */ 00636 if ((ret = wc_MGF(mgf, (byte*)(pkcsBlock + (hLen + 1)), 00637 pkcsBlockLen - hLen - 1, tmp, hLen)) != 0) { 00638 XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00639 return ret; 00640 } 00641 00642 /* xor seedMask value with maskedSeed to get seed value */ 00643 for (idx = 0; idx < (word32)hLen; idx++) { 00644 tmp[idx] = tmp[idx] ^ pkcsBlock[1 + idx]; 00645 } 00646 00647 /* get dbMask value */ 00648 if ((ret = wc_MGF(mgf, tmp, hLen, tmp + hLen, 00649 pkcsBlockLen - hLen - 1)) != 0) { 00650 XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00651 return ret; 00652 } 00653 00654 /* get DB value by doing maskedDB xor dbMask */ 00655 for (idx = 0; idx < (pkcsBlockLen - hLen - 1); idx++) { 00656 pkcsBlock[hLen + 1 + idx] = pkcsBlock[hLen + 1 + idx] ^ tmp[idx + hLen]; 00657 } 00658 00659 /* done with use of tmp buffer */ 00660 XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); 00661 00662 /* advance idx to index of PS and msg separator */ 00663 idx = hLen + 2 + hLen; 00664 while (idx < pkcsBlockLen && pkcsBlock[idx] == 0) {idx++;} 00665 00666 /* create hash of label for comparision with hash sent */ 00667 if ((ret = wc_Hash(hType, optLabel, labelLen, h, hLen)) != 0) { 00668 return ret; 00669 } 00670 00671 /* say no to chosen ciphertext attack. 00672 Comparison of lHash, Y, and separator value needs to all happen in 00673 constant time. 00674 Attackers should not be able to get error condition from the timing of 00675 these checks. 00676 */ 00677 ret = 0; 00678 ret |= ConstantCompare(pkcsBlock + hLen + 1, h, hLen); 00679 ret += pkcsBlock[idx++] ^ 0x01; /* separator value is 0x01 */ 00680 ret += pkcsBlock[0] ^ 0x00; /* Y, the first value, should be 0 */ 00681 00682 if (ret != 0) { 00683 return BAD_PADDING_E; 00684 } 00685 00686 /* adjust pointer to correct location in array and return size of M */ 00687 *output = (byte*)(pkcsBlock + idx); 00688 return pkcsBlockLen - idx; 00689 } 00690 #endif /* WC_NO_RSA_OAEP */ 00691 00692 00693 /* UnPad plaintext, set start to *output, return length of plaintext, 00694 * < 0 on error */ 00695 static int RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen, 00696 byte **output, byte padValue) 00697 { 00698 word32 maxOutputLen = (pkcsBlockLen > 10) ? (pkcsBlockLen - 10) : 0, 00699 invalid = 0, 00700 i = 1, 00701 outputLen; 00702 00703 if (pkcsBlock[0] != 0x0) /* skip past zero */ 00704 invalid = 1; 00705 pkcsBlock++; pkcsBlockLen--; 00706 00707 /* Require block type padValue */ 00708 invalid = (pkcsBlock[0] != padValue) || invalid; 00709 00710 /* verify the padding until we find the separator */ 00711 if (padValue == RSA_BLOCK_TYPE_1) { 00712 while (i<pkcsBlockLen && pkcsBlock[i++] == 0xFF) {/* Null body */} 00713 } 00714 else { 00715 while (i<pkcsBlockLen && pkcsBlock[i++]) {/* Null body */} 00716 } 00717 00718 if(!(i==pkcsBlockLen || pkcsBlock[i-1]==0)) { 00719 WOLFSSL_MSG("RsaUnPad error, bad formatting"); 00720 return RSA_PAD_E; 00721 } 00722 00723 outputLen = pkcsBlockLen - i; 00724 invalid = (outputLen > maxOutputLen) || invalid; 00725 00726 if (invalid) { 00727 WOLFSSL_MSG("RsaUnPad error, bad formatting"); 00728 return RSA_PAD_E; 00729 } 00730 00731 *output = (byte *)(pkcsBlock + i); 00732 return outputLen; 00733 } 00734 00735 00736 #ifndef WC_NO_RSA_OAEP 00737 /* helper function to direct unpadding */ 00738 static int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, byte** out, 00739 byte padValue, int padType, enum wc_HashType hType, 00740 int mgf, byte* optLabel, word32 labelLen) 00741 { 00742 int ret; 00743 00744 switch (padType) 00745 { 00746 case WC_RSA_PKCSV15_PAD: 00747 WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 padding"); 00748 ret = RsaUnPad(pkcsBlock, pkcsBlockLen, out, padValue); 00749 break; 00750 00751 case WC_RSA_OAEP_PAD: 00752 WOLFSSL_MSG("wolfSSL Using RSA OAEP padding"); 00753 ret = wc_RsaUnPad_OAEP((byte*)pkcsBlock, pkcsBlockLen, out, 00754 hType, mgf, optLabel, labelLen); 00755 break; 00756 00757 default: 00758 WOLFSSL_MSG("Unknown RSA Pad Type"); 00759 ret = RSA_PAD_E; 00760 } 00761 00762 /* silence warning if not used with padding scheme */ 00763 (void)padType; 00764 (void)hType; 00765 (void)mgf; 00766 (void)optLabel; 00767 (void)labelLen; 00768 00769 return ret; 00770 } 00771 #endif /* WC_NO_RSA_OAEP */ 00772 00773 00774 static int wc_RsaFunction(const byte* in, word32 inLen, byte* out, 00775 word32* outLen, int type, RsaKey* key) 00776 { 00777 #define ERROR_OUT(x) { ret = (x); goto done;} 00778 00779 mp_int tmp; 00780 int ret = 0; 00781 word32 keyLen, len; 00782 00783 if (mp_init(&tmp) != MP_OKAY) 00784 return MP_INIT_E; 00785 00786 if (mp_read_unsigned_bin(&tmp, (byte*)in, inLen) != MP_OKAY) 00787 ERROR_OUT(MP_READ_E); 00788 00789 if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) { 00790 #ifdef RSA_LOW_MEM /* half as much memory but twice as slow */ 00791 if (mp_exptmod(&tmp, &key->d, &key->n, &tmp) != MP_OKAY) 00792 ERROR_OUT(MP_EXPTMOD_E); 00793 #else 00794 #define INNER_ERROR_OUT(x) { ret = (x); goto inner_done; } 00795 00796 mp_int tmpa, tmpb; 00797 00798 if (mp_init(&tmpa) != MP_OKAY) 00799 ERROR_OUT(MP_INIT_E); 00800 00801 if (mp_init(&tmpb) != MP_OKAY) { 00802 mp_clear(&tmpa); 00803 ERROR_OUT(MP_INIT_E); 00804 } 00805 00806 /* tmpa = tmp^dP mod p */ 00807 if (mp_exptmod(&tmp, &key->dP, &key->p, &tmpa) != MP_OKAY) 00808 INNER_ERROR_OUT(MP_EXPTMOD_E); 00809 00810 /* tmpb = tmp^dQ mod q */ 00811 if (mp_exptmod(&tmp, &key->dQ, &key->q, &tmpb) != MP_OKAY) 00812 INNER_ERROR_OUT(MP_EXPTMOD_E); 00813 00814 /* tmp = (tmpa - tmpb) * qInv (mod p) */ 00815 if (mp_sub(&tmpa, &tmpb, &tmp) != MP_OKAY) 00816 INNER_ERROR_OUT(MP_SUB_E); 00817 00818 if (mp_mulmod(&tmp, &key->u, &key->p, &tmp) != MP_OKAY) 00819 INNER_ERROR_OUT(MP_MULMOD_E); 00820 00821 /* tmp = tmpb + q * tmp */ 00822 if (mp_mul(&tmp, &key->q, &tmp) != MP_OKAY) 00823 INNER_ERROR_OUT(MP_MUL_E); 00824 00825 if (mp_add(&tmp, &tmpb, &tmp) != MP_OKAY) 00826 INNER_ERROR_OUT(MP_ADD_E); 00827 00828 inner_done: 00829 mp_clear(&tmpa); 00830 mp_clear(&tmpb); 00831 00832 if (ret != 0) return ret; 00833 00834 #endif /* RSA_LOW_MEM */ 00835 } 00836 else if (type == RSA_PUBLIC_ENCRYPT || type == RSA_PUBLIC_DECRYPT) { 00837 if (mp_exptmod(&tmp, &key->e, &key->n, &tmp) != MP_OKAY) 00838 ERROR_OUT(MP_EXPTMOD_E); 00839 } 00840 else 00841 ERROR_OUT(RSA_WRONG_TYPE_E); 00842 00843 keyLen = mp_unsigned_bin_size(&key->n); 00844 if (keyLen > *outLen) 00845 ERROR_OUT(RSA_BUFFER_E); 00846 00847 len = mp_unsigned_bin_size(&tmp); 00848 00849 /* pad front w/ zeros to match key length */ 00850 while (len < keyLen) { 00851 *out++ = 0x00; 00852 len++; 00853 } 00854 00855 *outLen = keyLen; 00856 00857 /* convert */ 00858 if (mp_to_unsigned_bin(&tmp, out) != MP_OKAY) 00859 ERROR_OUT(MP_TO_E); 00860 00861 done: 00862 mp_clear(&tmp); 00863 if (ret == MP_EXPTMOD_E) { 00864 WOLFSSL_MSG("RSA_FUNCTION MP_EXPTMOD_E: memory/config problem"); 00865 } 00866 return ret; 00867 } 00868 00869 00870 int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen, 00871 RsaKey* key, WC_RNG* rng) 00872 { 00873 int sz, ret; 00874 00875 #ifdef HAVE_CAVIUM 00876 if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) 00877 return CaviumRsaPublicEncrypt(in, inLen, out, outLen, key); 00878 #endif 00879 00880 sz = mp_unsigned_bin_size(&key->n); 00881 if (sz > (int)outLen) 00882 return RSA_BUFFER_E; 00883 00884 if (inLen > (word32)(sz - RSA_MIN_PAD_SZ)) 00885 return RSA_BUFFER_E; 00886 00887 ret = wc_RsaPad(in, inLen, out, sz, RSA_BLOCK_TYPE_2, rng); 00888 if (ret != 0) 00889 return ret; 00890 00891 if ((ret = wc_RsaFunction(out, sz, out, &outLen, 00892 RSA_PUBLIC_ENCRYPT, key)) < 0) 00893 sz = ret; 00894 00895 return sz; 00896 } 00897 00898 00899 #ifndef WC_NO_RSA_OAEP 00900 /* Gives the option of choosing padding type 00901 in : input to be encrypted 00902 inLen: length of input buffer 00903 out: encrypted output 00904 outLen: length of encrypted output buffer 00905 key : wolfSSL initialized RSA key struct 00906 rng : wolfSSL initialized random number struct 00907 type : type of padding to use ie WC_RSA_OAEP_PAD 00908 hash : type of hash algorithm to use found in wolfssl/wolfcrypt/hash.h 00909 mgf : type of mask generation function to use 00910 label : optional label 00911 labelSz : size of optional label buffer */ 00912 int wc_RsaPublicEncrypt_ex(const byte* in, word32 inLen, byte* out, 00913 word32 outLen, RsaKey* key, WC_RNG* rng, int type, 00914 enum wc_HashType hash, int mgf, byte* label, word32 labelSz) 00915 { 00916 int sz, ret; 00917 00918 #ifdef HAVE_CAVIUM 00919 if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) 00920 return CaviumRsaPublicEncrypt(in, inLen, out, outLen, key); 00921 #endif 00922 00923 sz = mp_unsigned_bin_size(&key->n); 00924 if (sz > (int)outLen) 00925 return RSA_BUFFER_E; 00926 00927 if (inLen > (word32)(sz - RSA_MIN_PAD_SZ)) 00928 return RSA_BUFFER_E; 00929 00930 ret = wc_RsaPad_ex(in, inLen, out, sz, RSA_BLOCK_TYPE_2, rng, 00931 type, hash, mgf, label, labelSz); 00932 if (ret != 0) 00933 return ret; 00934 00935 if ((ret = wc_RsaFunction(out, sz, out, &outLen, 00936 RSA_PUBLIC_ENCRYPT, key)) < 0) 00937 sz = ret; 00938 00939 return sz; 00940 } 00941 #endif /* WC_NO_RSA_OAEP */ 00942 00943 00944 int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, RsaKey* key) 00945 { 00946 int ret; 00947 00948 #ifdef HAVE_CAVIUM 00949 if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) { 00950 ret = CaviumRsaPrivateDecrypt(in, inLen, in, inLen, key); 00951 if (ret > 0) 00952 *out = in; 00953 return ret; 00954 } 00955 #endif 00956 00957 if ((ret = wc_RsaFunction(in, inLen, in, &inLen, RSA_PRIVATE_DECRYPT, key)) 00958 < 0) { 00959 return ret; 00960 } 00961 00962 return RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_2); 00963 } 00964 00965 00966 #ifndef WC_NO_RSA_OAEP 00967 /* Gives the option of choosing padding type 00968 in : input to be decrypted 00969 inLen: length of input buffer 00970 out: pointer to place of decrypted message 00971 key : wolfSSL initialized RSA key struct 00972 type : type of padding to use ie WC_RSA_OAEP_PAD 00973 hash : type of hash algorithm to use found in wolfssl/wolfcrypt/hash.h 00974 mgf : type of mask generation function to use 00975 label : optional label 00976 labelSz : size of optional label buffer */ 00977 int wc_RsaPrivateDecryptInline_ex(byte* in, word32 inLen, byte** out, 00978 RsaKey* key, int type, enum wc_HashType hash, int mgf, 00979 byte* label, word32 labelSz) 00980 { 00981 int ret; 00982 00983 /* sanity check on arguments */ 00984 if (in == NULL || key == NULL) { 00985 return BAD_FUNC_ARG; 00986 } 00987 00988 /* check if given a label size but not given a label buffer */ 00989 if (label == NULL && labelSz > 0) { 00990 return BAD_FUNC_ARG; 00991 } 00992 00993 #ifdef HAVE_CAVIUM 00994 if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) { 00995 ret = CaviumRsaPrivateDecrypt(in, inLen, in, inLen, key); 00996 if (ret > 0) 00997 *out = in; 00998 return ret; 00999 } 01000 #endif 01001 01002 if ((ret = wc_RsaFunction(in, inLen, in, &inLen, RSA_PRIVATE_DECRYPT, key)) 01003 < 0) { 01004 return ret; 01005 } 01006 01007 return wc_RsaUnPad_ex(in, inLen, out, RSA_BLOCK_TYPE_2, type, hash, mgf, 01008 label, labelSz); 01009 } 01010 #endif /* WC_NO_RSA_OAEP */ 01011 01012 01013 int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, word32 outLen, 01014 RsaKey* key) 01015 { 01016 int plainLen; 01017 byte* tmp; 01018 byte* pad = 0; 01019 01020 #ifdef HAVE_CAVIUM 01021 if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) 01022 return CaviumRsaPrivateDecrypt(in, inLen, out, outLen, key); 01023 #endif 01024 01025 tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA); 01026 if (tmp == NULL) { 01027 return MEMORY_E; 01028 } 01029 01030 XMEMCPY(tmp, in, inLen); 01031 01032 if ( (plainLen = wc_RsaPrivateDecryptInline(tmp, inLen, &pad, key) ) < 0) { 01033 XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); 01034 return plainLen; 01035 } 01036 if (plainLen > (int)outLen) 01037 plainLen = BAD_FUNC_ARG; 01038 else 01039 XMEMCPY(out, pad, plainLen); 01040 01041 ForceZero(tmp, inLen); 01042 XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); 01043 01044 return plainLen; 01045 } 01046 01047 01048 #ifndef WC_NO_RSA_OAEP 01049 /* Gives the option of choosing padding type 01050 in : input to be decrypted 01051 inLen: length of input buffer 01052 out: decrypted message 01053 outLen: length of decrypted message in bytes 01054 key : wolfSSL initialized RSA key struct 01055 type : type of padding to use ie WC_RSA_OAEP_PAD 01056 hash : type of hash algorithm to use found in wolfssl/wolfcrypt/hash.h 01057 mgf : type of mask generation function to use 01058 label : optional label 01059 labelSz : size of optional label buffer */ 01060 int wc_RsaPrivateDecrypt_ex(const byte* in, word32 inLen, byte* out, word32 outLen, 01061 RsaKey* key, int type, enum wc_HashType hash, int mgf, 01062 byte* label, word32 labelSz) 01063 { 01064 int plainLen; 01065 byte* tmp; 01066 byte* pad = 0; 01067 01068 /* sanity check on arguments */ 01069 if (out == NULL || in == NULL || key == NULL) { 01070 return BAD_FUNC_ARG; 01071 } 01072 01073 /* check if given a label size but not given a label buffer */ 01074 if (label == NULL && labelSz > 0) { 01075 return BAD_FUNC_ARG; 01076 } 01077 01078 #ifdef HAVE_CAVIUM 01079 if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) 01080 return CaviumRsaPrivateDecrypt(in, inLen, out, outLen, key); 01081 #endif 01082 01083 tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA); 01084 if (tmp == NULL) { 01085 return MEMORY_E; 01086 } 01087 01088 XMEMCPY(tmp, in, inLen); 01089 01090 if ( (plainLen = wc_RsaPrivateDecryptInline_ex(tmp, inLen, &pad, key, 01091 type, hash, mgf, label, labelSz) ) < 0) { 01092 XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); 01093 return plainLen; 01094 } 01095 if (plainLen > (int)outLen || pad == NULL) 01096 plainLen = BAD_FUNC_ARG; 01097 else 01098 XMEMCPY(out, pad, plainLen); 01099 01100 ForceZero(tmp, inLen); 01101 XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); 01102 01103 return plainLen; 01104 } 01105 #endif /* WC_NO_RSA_OAEP */ 01106 01107 01108 /* for Rsa Verify */ 01109 int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key) 01110 { 01111 int ret; 01112 01113 #ifdef HAVE_CAVIUM 01114 if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) { 01115 ret = CaviumRsaSSL_Verify(in, inLen, in, inLen, key); 01116 if (ret > 0) 01117 *out = in; 01118 return ret; 01119 } 01120 #endif 01121 01122 if ((ret = wc_RsaFunction(in, inLen, in, &inLen, RSA_PUBLIC_DECRYPT, key)) 01123 < 0) { 01124 return ret; 01125 } 01126 01127 return RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_1); 01128 } 01129 01130 01131 int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen, 01132 RsaKey* key) 01133 { 01134 int plainLen; 01135 byte* tmp; 01136 byte* pad = 0; 01137 01138 #ifdef HAVE_CAVIUM 01139 if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) 01140 return CaviumRsaSSL_Verify(in, inLen, out, outLen, key); 01141 #endif 01142 01143 tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA); 01144 if (tmp == NULL) { 01145 return MEMORY_E; 01146 } 01147 01148 XMEMCPY(tmp, in, inLen); 01149 01150 if ( (plainLen = wc_RsaSSL_VerifyInline(tmp, inLen, &pad, key) ) < 0) { 01151 XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); 01152 return plainLen; 01153 } 01154 01155 if (plainLen > (int)outLen) 01156 plainLen = BAD_FUNC_ARG; 01157 else 01158 XMEMCPY(out, pad, plainLen); 01159 01160 ForceZero(tmp, inLen); 01161 XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); 01162 01163 return plainLen; 01164 } 01165 01166 01167 /* for Rsa Sign */ 01168 int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen, 01169 RsaKey* key, WC_RNG* rng) 01170 { 01171 int sz, ret; 01172 01173 #ifdef HAVE_CAVIUM 01174 if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) 01175 return CaviumRsaSSL_Sign(in, inLen, out, outLen, key); 01176 #endif 01177 01178 sz = mp_unsigned_bin_size(&key->n); 01179 if (sz > (int)outLen) 01180 return RSA_BUFFER_E; 01181 01182 if (inLen > (word32)(sz - RSA_MIN_PAD_SZ)) 01183 return RSA_BUFFER_E; 01184 01185 ret = wc_RsaPad(in, inLen, out, sz, RSA_BLOCK_TYPE_1, rng); 01186 if (ret != 0) 01187 return ret; 01188 01189 if ((ret = wc_RsaFunction(out, sz, out, &outLen, 01190 RSA_PRIVATE_ENCRYPT,key)) < 0) 01191 sz = ret; 01192 01193 return sz; 01194 } 01195 01196 01197 int wc_RsaEncryptSize(RsaKey* key) 01198 { 01199 #ifdef HAVE_CAVIUM 01200 if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) 01201 return key->c_nSz; 01202 #endif 01203 return mp_unsigned_bin_size(&key->n); 01204 } 01205 01206 /* flatten RsaKey structure into individual elements (e, n) */ 01207 int wc_RsaFlattenPublicKey(RsaKey* key, byte* e, word32* eSz, byte* n, 01208 word32* nSz) 01209 { 01210 int sz, ret; 01211 01212 if (key == NULL || e == NULL || eSz == NULL || n == NULL || nSz == NULL) 01213 return BAD_FUNC_ARG; 01214 01215 sz = mp_unsigned_bin_size(&key->e); 01216 if ((word32)sz > *nSz) 01217 return RSA_BUFFER_E; 01218 ret = mp_to_unsigned_bin(&key->e, e); 01219 if (ret != MP_OKAY) 01220 return ret; 01221 *eSz = (word32)sz; 01222 01223 sz = mp_unsigned_bin_size(&key->n); 01224 if ((word32)sz > *nSz) 01225 return RSA_BUFFER_E; 01226 ret = mp_to_unsigned_bin(&key->n, n); 01227 if (ret != MP_OKAY) 01228 return ret; 01229 *nSz = (word32)sz; 01230 01231 return 0; 01232 } 01233 01234 #ifdef WOLFSSL_KEY_GEN 01235 /* Make an RSA key for size bits, with e specified, 65537 is a good e */ 01236 int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) 01237 { 01238 mp_int p, q, tmp1, tmp2, tmp3; 01239 int err; 01240 01241 if (key == NULL || rng == NULL) 01242 return BAD_FUNC_ARG; 01243 01244 if (size < RSA_MIN_SIZE || size > RSA_MAX_SIZE) 01245 return BAD_FUNC_ARG; 01246 01247 if (e < 3 || (e & 1) == 0) 01248 return BAD_FUNC_ARG; 01249 01250 if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != MP_OKAY) 01251 return err; 01252 01253 err = mp_set_int(&tmp3, e); 01254 01255 /* make p */ 01256 if (err == MP_OKAY) { 01257 do { 01258 err = mp_rand_prime(&p, size/16, rng, key->heap); /* size in bytes/2 */ 01259 01260 if (err == MP_OKAY) 01261 err = mp_sub_d(&p, 1, &tmp1); /* tmp1 = p-1 */ 01262 01263 if (err == MP_OKAY) 01264 err = mp_gcd(&tmp1, &tmp3, &tmp2); /* tmp2 = gcd(p-1, e) */ 01265 } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0); /* e divides p-1 */ 01266 } 01267 01268 /* make q */ 01269 if (err == MP_OKAY) { 01270 do { 01271 err = mp_rand_prime(&q, size/16, rng, key->heap); /* size in bytes/2 */ 01272 01273 if (err == MP_OKAY) 01274 err = mp_sub_d(&q, 1, &tmp1); /* tmp1 = q-1 */ 01275 01276 if (err == MP_OKAY) 01277 err = mp_gcd(&tmp1, &tmp3, &tmp2); /* tmp2 = gcd(q-1, e) */ 01278 } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0); /* e divides q-1 */ 01279 } 01280 01281 if (err == MP_OKAY) 01282 err = mp_init_multi(&key->n, &key->e, &key->d, &key->p, &key->q, NULL); 01283 01284 if (err == MP_OKAY) 01285 err = mp_init_multi(&key->dP, &key->dQ, &key->u, NULL, NULL, NULL); 01286 01287 if (err == MP_OKAY) 01288 err = mp_sub_d(&p, 1, &tmp2); /* tmp2 = p-1 */ 01289 01290 if (err == MP_OKAY) 01291 err = mp_lcm(&tmp1, &tmp2, &tmp1); /* tmp1 = lcm(p-1, q-1),last loop */ 01292 01293 /* make key */ 01294 if (err == MP_OKAY) 01295 err = mp_set_int(&key->e, e); /* key->e = e */ 01296 01297 if (err == MP_OKAY) /* key->d = 1/e mod lcm(p-1, q-1) */ 01298 err = mp_invmod(&key->e, &tmp1, &key->d); 01299 01300 if (err == MP_OKAY) 01301 err = mp_mul(&p, &q, &key->n); /* key->n = pq */ 01302 01303 if (err == MP_OKAY) 01304 err = mp_sub_d(&p, 1, &tmp1); 01305 01306 if (err == MP_OKAY) 01307 err = mp_sub_d(&q, 1, &tmp2); 01308 01309 if (err == MP_OKAY) 01310 err = mp_mod(&key->d, &tmp1, &key->dP); 01311 01312 if (err == MP_OKAY) 01313 err = mp_mod(&key->d, &tmp2, &key->dQ); 01314 01315 if (err == MP_OKAY) 01316 err = mp_invmod(&q, &p, &key->u); 01317 01318 if (err == MP_OKAY) 01319 err = mp_copy(&p, &key->p); 01320 01321 if (err == MP_OKAY) 01322 err = mp_copy(&q, &key->q); 01323 01324 if (err == MP_OKAY) 01325 key->type = RSA_PRIVATE; 01326 01327 mp_clear(&tmp3); 01328 mp_clear(&tmp2); 01329 mp_clear(&tmp1); 01330 mp_clear(&q); 01331 mp_clear(&p); 01332 01333 if (err != MP_OKAY) { 01334 wc_FreeRsaKey(key); 01335 return err; 01336 } 01337 01338 return 0; 01339 } 01340 01341 01342 #endif /* WOLFSSL_KEY_GEN */ 01343 01344 01345 #ifdef HAVE_CAVIUM 01346 01347 #include <wolfssl/wolfcrypt/logging.h> 01348 #include "cavium_common.h" 01349 01350 /* Initialize RSA for use with Nitrox device */ 01351 int wc_RsaInitCavium(RsaKey* rsa, int devId) 01352 { 01353 if (rsa == NULL) 01354 return -1; 01355 01356 if (CspAllocContext(CONTEXT_SSL, &rsa->contextHandle, devId) != 0) 01357 return -1; 01358 01359 rsa->devId = devId; 01360 rsa->magic = WOLFSSL_RSA_CAVIUM_MAGIC; 01361 01362 return 0; 01363 } 01364 01365 01366 /* Free RSA from use with Nitrox device */ 01367 void wc_RsaFreeCavium(RsaKey* rsa) 01368 { 01369 if (rsa == NULL) 01370 return; 01371 01372 CspFreeContext(CONTEXT_SSL, rsa->contextHandle, rsa->devId); 01373 rsa->magic = 0; 01374 } 01375 01376 01377 /* Initialize cavium RSA key */ 01378 static int InitCaviumRsaKey(RsaKey* key, void* heap) 01379 { 01380 if (key == NULL) 01381 return BAD_FUNC_ARG; 01382 01383 key->heap = heap; 01384 key->type = -1; /* don't know yet */ 01385 01386 key->c_n = NULL; 01387 key->c_e = NULL; 01388 key->c_d = NULL; 01389 key->c_p = NULL; 01390 key->c_q = NULL; 01391 key->c_dP = NULL; 01392 key->c_dQ = NULL; 01393 key->c_u = NULL; 01394 01395 key->c_nSz = 0; 01396 key->c_eSz = 0; 01397 key->c_dSz = 0; 01398 key->c_pSz = 0; 01399 key->c_qSz = 0; 01400 key->c_dP_Sz = 0; 01401 key->c_dQ_Sz = 0; 01402 key->c_uSz = 0; 01403 01404 return 0; 01405 } 01406 01407 01408 /* Free cavium RSA key */ 01409 static int FreeCaviumRsaKey(RsaKey* key) 01410 { 01411 if (key == NULL) 01412 return BAD_FUNC_ARG; 01413 01414 XFREE(key->c_n, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); 01415 XFREE(key->c_e, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); 01416 XFREE(key->c_d, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); 01417 XFREE(key->c_p, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); 01418 XFREE(key->c_q, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); 01419 XFREE(key->c_dP, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); 01420 XFREE(key->c_dQ, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); 01421 XFREE(key->c_u, key->heap, DYNAMIC_TYPE_CAVIUM_TMP); 01422 01423 return InitCaviumRsaKey(key, key->heap); /* reset pointers */ 01424 } 01425 01426 01427 static int CaviumRsaPublicEncrypt(const byte* in, word32 inLen, byte* out, 01428 word32 outLen, RsaKey* key) 01429 { 01430 word32 requestId; 01431 word32 ret; 01432 01433 if (key == NULL || in == NULL || out == NULL || outLen < (word32)key->c_nSz) 01434 return -1; 01435 01436 ret = CspPkcs1v15Enc(CAVIUM_BLOCKING, BT2, key->c_nSz, key->c_eSz, 01437 (word16)inLen, key->c_n, key->c_e, (byte*)in, out, 01438 &requestId, key->devId); 01439 if (ret != 0) { 01440 WOLFSSL_MSG("Cavium Enc BT2 failed"); 01441 return -1; 01442 } 01443 return key->c_nSz; 01444 } 01445 01446 01447 static INLINE void ato16(const byte* c, word16* u16) 01448 { 01449 *u16 = (c[0] << 8) | (c[1]); 01450 } 01451 01452 01453 static int CaviumRsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, 01454 word32 outLen, RsaKey* key) 01455 { 01456 word32 requestId; 01457 word32 ret; 01458 word16 outSz = (word16)outLen; 01459 01460 if (key == NULL || in == NULL || out == NULL || inLen != (word32)key->c_nSz) 01461 return -1; 01462 01463 ret = CspPkcs1v15CrtDec(CAVIUM_BLOCKING, BT2, key->c_nSz, key->c_q, 01464 key->c_dQ, key->c_p, key->c_dP, key->c_u, 01465 (byte*)in, &outSz, out, &requestId, key->devId); 01466 if (ret != 0) { 01467 WOLFSSL_MSG("Cavium CRT Dec BT2 failed"); 01468 return -1; 01469 } 01470 ato16((const byte*)&outSz, &outSz); 01471 01472 return outSz; 01473 } 01474 01475 01476 static int CaviumRsaSSL_Sign(const byte* in, word32 inLen, byte* out, 01477 word32 outLen, RsaKey* key) 01478 { 01479 word32 requestId; 01480 word32 ret; 01481 01482 if (key == NULL || in == NULL || out == NULL || inLen == 0 || outLen < 01483 (word32)key->c_nSz) 01484 return -1; 01485 01486 ret = CspPkcs1v15CrtEnc(CAVIUM_BLOCKING, BT1, key->c_nSz, (word16)inLen, 01487 key->c_q, key->c_dQ, key->c_p, key->c_dP, key->c_u, 01488 (byte*)in, out, &requestId, key->devId); 01489 if (ret != 0) { 01490 WOLFSSL_MSG("Cavium CRT Enc BT1 failed"); 01491 return -1; 01492 } 01493 return key->c_nSz; 01494 } 01495 01496 01497 static int CaviumRsaSSL_Verify(const byte* in, word32 inLen, byte* out, 01498 word32 outLen, RsaKey* key) 01499 { 01500 word32 requestId; 01501 word32 ret; 01502 word16 outSz = (word16)outLen; 01503 01504 if (key == NULL || in == NULL || out == NULL || inLen != (word32)key->c_nSz) 01505 return -1; 01506 01507 ret = CspPkcs1v15Dec(CAVIUM_BLOCKING, BT1, key->c_nSz, key->c_eSz, 01508 key->c_n, key->c_e, (byte*)in, &outSz, out, 01509 &requestId, key->devId); 01510 if (ret != 0) { 01511 WOLFSSL_MSG("Cavium Dec BT1 failed"); 01512 return -1; 01513 } 01514 outSz = ntohs(outSz); 01515 01516 return outSz; 01517 } 01518 01519 01520 #endif /* HAVE_CAVIUM */ 01521 01522 #endif /* HAVE_FIPS */ 01523 #endif /* NO_RSA */ 01524 01525
Generated on Tue Jul 12 2022 15:55:20 by
1.7.2