Renesas / SecureDweet
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers rsa.c Source File

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