wolf SSL / CyaSSL-2.9.4

Dependents:  

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-2013 wolfSSL Inc.
00004  *
00005  * This file is part of CyaSSL.
00006  *
00007  * CyaSSL 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  * CyaSSL 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
00020  */
00021 
00022 
00023 #ifdef HAVE_CONFIG_H
00024     #include <config.h>
00025 #endif
00026 
00027 #include <cyassl/ctaocrypt/settings.h>
00028 
00029 #ifndef NO_RSA
00030 
00031 #ifdef HAVE_FIPS
00032     /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
00033     #define FIPS_NO_WRAPPERS
00034 #endif
00035 
00036 #include <cyassl/ctaocrypt/rsa.h>
00037 #include <cyassl/ctaocrypt/random.h>
00038 #include <cyassl/ctaocrypt/error-crypt.h>
00039 #include <cyassl/ctaocrypt/logging.h>
00040 
00041 #ifdef SHOW_GEN
00042     #ifdef FREESCALE_MQX
00043         #include <fio.h>
00044     #else
00045         #include <stdio.h>
00046     #endif
00047 #endif
00048 
00049 #ifdef HAVE_CAVIUM
00050     static int  InitCaviumRsaKey(RsaKey* key, void* heap);
00051     static int  FreeCaviumRsaKey(RsaKey* key);
00052     static int  CaviumRsaPublicEncrypt(const byte* in, word32 inLen, byte* out,
00053                                        word32 outLen, RsaKey* key);
00054     static int  CaviumRsaPrivateDecrypt(const byte* in, word32 inLen, byte* out,
00055                                         word32 outLen, RsaKey* key);
00056     static int  CaviumRsaSSL_Sign(const byte* in, word32 inLen, byte* out,
00057                                   word32 outLen, RsaKey* key);
00058     static int  CaviumRsaSSL_Verify(const byte* in, word32 inLen, byte* out,
00059                                     word32 outLen, RsaKey* key);
00060 #endif
00061 
00062 enum {
00063     RSA_PUBLIC_ENCRYPT  = 0,
00064     RSA_PUBLIC_DECRYPT  = 1,
00065     RSA_PRIVATE_ENCRYPT = 2,
00066     RSA_PRIVATE_DECRYPT = 3,
00067 
00068     RSA_BLOCK_TYPE_1 = 1,
00069     RSA_BLOCK_TYPE_2 = 2,
00070 
00071     RSA_MIN_SIZE = 512,
00072     RSA_MAX_SIZE = 4096,
00073 
00074     RSA_MIN_PAD_SZ   = 11      /* seperator + 0 + pad value + 8 pads */
00075 };
00076 
00077 
00078 int InitRsaKey(RsaKey* key, void* heap)
00079 {
00080 #ifdef HAVE_CAVIUM
00081     if (key->magic == CYASSL_RSA_CAVIUM_MAGIC)
00082         return InitCaviumRsaKey(key, heap);
00083 #endif
00084 
00085     key->type = -1;  /* haven't decided yet */
00086     key->heap = heap;
00087 
00088 /* TomsFastMath doesn't use memory allocation */
00089 #ifndef USE_FAST_MATH
00090     key->n.dp = key->e.dp = 0;  /* public  alloc parts */
00091 
00092     key->d.dp = key->p.dp  = 0;  /* private alloc parts */
00093     key->q.dp = key->dP.dp = 0;  
00094     key->u.dp = key->dQ.dp = 0;
00095 #endif
00096 
00097     return 0;
00098 }
00099 
00100 
00101 int FreeRsaKey(RsaKey* key)
00102 {
00103     (void)key;
00104 
00105 #ifdef HAVE_CAVIUM
00106     if (key->magic == CYASSL_RSA_CAVIUM_MAGIC)
00107         return FreeCaviumRsaKey(key);
00108 #endif
00109 
00110 /* TomsFastMath doesn't use memory allocation */
00111 #ifndef USE_FAST_MATH
00112     if (key->type == RSA_PRIVATE) {
00113         mp_clear(&key->u);
00114         mp_clear(&key->dQ);
00115         mp_clear(&key->dP);
00116         mp_clear(&key->q);
00117         mp_clear(&key->p);
00118         mp_clear(&key->d);
00119     }
00120     mp_clear(&key->e);
00121     mp_clear(&key->n);
00122 #endif
00123 
00124     return 0;
00125 }
00126 
00127 static void RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock,
00128                    word32 pkcsBlockLen, byte padValue, RNG* rng)
00129 {
00130     if (inputLen == 0) return;
00131 
00132     pkcsBlock[0] = 0x0;       /* set first byte to zero and advance */
00133     pkcsBlock++; pkcsBlockLen--;
00134     pkcsBlock[0] = padValue;  /* insert padValue */
00135 
00136     if (padValue == RSA_BLOCK_TYPE_1)
00137         /* pad with 0xff bytes */
00138         XMEMSET(&pkcsBlock[1], 0xFF, pkcsBlockLen - inputLen - 2);
00139     else {
00140         /* pad with non-zero random bytes */
00141         word32 padLen = pkcsBlockLen - inputLen - 1, i;
00142         RNG_GenerateBlock(rng, &pkcsBlock[1], padLen);
00143 
00144         /* remove zeros */
00145         for (i = 1; i < padLen; i++)
00146             if (pkcsBlock[i] == 0) pkcsBlock[i] = 0x01;
00147     }
00148 
00149     pkcsBlock[pkcsBlockLen-inputLen-1] = 0;     /* separator */
00150     XMEMCPY(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen);
00151 }
00152 
00153 
00154 static word32 RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen,
00155                        byte **output, byte padValue)
00156 {
00157     word32 maxOutputLen = (pkcsBlockLen > 10) ? (pkcsBlockLen - 10) : 0,
00158            invalid = 0,
00159            i = 1,
00160            outputLen;
00161 
00162     if (pkcsBlock[0] != 0x0) /* skip past zero */
00163         invalid = 1;
00164     pkcsBlock++; pkcsBlockLen--;
00165 
00166     /* Require block type padValue */
00167     invalid = (pkcsBlock[0] != padValue) || invalid;
00168 
00169     /* skip past the padding until we find the separator */
00170     while (i<pkcsBlockLen && pkcsBlock[i++]) { /* null body */
00171         }
00172     if(!(i==pkcsBlockLen || pkcsBlock[i-1]==0)) {
00173         CYASSL_MSG("RsaUnPad error, bad formatting");
00174         return 0;
00175     }
00176 
00177     outputLen = pkcsBlockLen - i;
00178     invalid = (outputLen > maxOutputLen) || invalid;
00179 
00180     if (invalid) {
00181         CYASSL_MSG("RsaUnPad error, bad formatting");
00182         return 0;
00183     }
00184 
00185     *output = (byte *)(pkcsBlock + i);
00186     return outputLen;
00187 }
00188 
00189 
00190 static int RsaFunction(const byte* in, word32 inLen, byte* out, word32* outLen,
00191                        int type, RsaKey* key)
00192 {
00193     #define ERROR_OUT(x) { ret = x; goto done;}
00194 
00195     mp_int tmp;
00196     int    ret = 0;
00197     word32 keyLen, len;
00198 
00199     if (mp_init(&tmp) != MP_OKAY)
00200         return MP_INIT_E;
00201 
00202     if (mp_read_unsigned_bin(&tmp, (byte*)in, inLen) != MP_OKAY)
00203         ERROR_OUT(MP_READ_E);
00204 
00205     if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) {
00206         #ifdef RSA_LOW_MEM      /* half as much memory but twice as slow */
00207             if (mp_exptmod(&tmp, &key->d, &key->n, &tmp) != MP_OKAY)
00208                 ERROR_OUT(MP_EXPTMOD_E);
00209         #else
00210             #define INNER_ERROR_OUT(x) { ret = x; goto inner_done; }
00211 
00212             mp_int tmpa, tmpb;
00213 
00214             if (mp_init(&tmpa) != MP_OKAY)
00215                 ERROR_OUT(MP_INIT_E);
00216 
00217             if (mp_init(&tmpb) != MP_OKAY) {
00218                 mp_clear(&tmpa);
00219                 ERROR_OUT(MP_INIT_E);
00220             }
00221 
00222             /* tmpa = tmp^dP mod p */
00223             if (mp_exptmod(&tmp, &key->dP, &key->p, &tmpa) != MP_OKAY)
00224                 INNER_ERROR_OUT(MP_EXPTMOD_E);
00225 
00226             /* tmpb = tmp^dQ mod q */
00227             if (mp_exptmod(&tmp, &key->dQ, &key->q, &tmpb) != MP_OKAY)
00228                 INNER_ERROR_OUT(MP_EXPTMOD_E);
00229 
00230             /* tmp = (tmpa - tmpb) * qInv (mod p) */
00231             if (mp_sub(&tmpa, &tmpb, &tmp) != MP_OKAY)
00232                 INNER_ERROR_OUT(MP_SUB_E);
00233 
00234             if (mp_mulmod(&tmp, &key->u, &key->p, &tmp) != MP_OKAY)
00235                 INNER_ERROR_OUT(MP_MULMOD_E);
00236 
00237             /* tmp = tmpb + q * tmp */
00238             if (mp_mul(&tmp, &key->q, &tmp) != MP_OKAY)
00239                 INNER_ERROR_OUT(MP_MUL_E);
00240 
00241             if (mp_add(&tmp, &tmpb, &tmp) != MP_OKAY)
00242                 INNER_ERROR_OUT(MP_ADD_E);
00243 
00244         inner_done:
00245             mp_clear(&tmpa);
00246             mp_clear(&tmpb);
00247 
00248             if (ret != 0) return ret;
00249 
00250         #endif   /* RSA_LOW_MEM */
00251     }
00252     else if (type == RSA_PUBLIC_ENCRYPT || type == RSA_PUBLIC_DECRYPT) {
00253         if (mp_exptmod(&tmp, &key->e, &key->n, &tmp) != MP_OKAY)
00254             ERROR_OUT(MP_EXPTMOD_E);
00255     }
00256     else
00257         ERROR_OUT(RSA_WRONG_TYPE_E);
00258 
00259     keyLen = mp_unsigned_bin_size(&key->n);
00260     if (keyLen > *outLen)
00261         ERROR_OUT(RSA_BUFFER_E);
00262 
00263     len = mp_unsigned_bin_size(&tmp);
00264 
00265     /* pad front w/ zeros to match key length */
00266     while (len < keyLen) {
00267         *out++ = 0x00;
00268         len++;
00269     }
00270 
00271     *outLen = keyLen;
00272 
00273     /* convert */
00274     if (mp_to_unsigned_bin(&tmp, out) != MP_OKAY)
00275         ERROR_OUT(MP_TO_E);
00276    
00277 done: 
00278     mp_clear(&tmp);
00279     return ret;
00280 }
00281 
00282 
00283 int RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen,
00284                      RsaKey* key, RNG* rng)
00285 {
00286     int sz, ret;
00287 
00288 #ifdef HAVE_CAVIUM
00289     if (key->magic == CYASSL_RSA_CAVIUM_MAGIC)
00290         return CaviumRsaPublicEncrypt(in, inLen, out, outLen, key);
00291 #endif
00292 
00293     sz = mp_unsigned_bin_size(&key->n);
00294     if (sz > (int)outLen)
00295         return RSA_BUFFER_E;
00296 
00297     if (inLen > (word32)(sz - RSA_MIN_PAD_SZ))
00298         return RSA_BUFFER_E;
00299 
00300     RsaPad(in, inLen, out, sz, RSA_BLOCK_TYPE_2, rng);
00301 
00302     if ((ret = RsaFunction(out, sz, out, &outLen, RSA_PUBLIC_ENCRYPT, key)) < 0)
00303         sz = ret;
00304 
00305     return sz;
00306 }
00307 
00308 
00309 int RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, RsaKey* key)
00310 {
00311     int plainLen, ret;
00312 
00313 #ifdef HAVE_CAVIUM
00314     if (key->magic == CYASSL_RSA_CAVIUM_MAGIC) {
00315         ret = CaviumRsaPrivateDecrypt(in, inLen, in, inLen, key);
00316         if (ret > 0)
00317             *out = in;
00318         return ret;
00319     }
00320 #endif
00321 
00322     if ((ret = RsaFunction(in, inLen, in, &inLen, RSA_PRIVATE_DECRYPT, key))
00323             < 0) {
00324         return ret;
00325     }
00326  
00327     plainLen = RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_2);
00328 
00329     return plainLen;
00330 }
00331 
00332 
00333 int RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, word32 outLen,
00334                      RsaKey* key)
00335 {
00336     int plainLen, ret;
00337     byte*  tmp;
00338     byte*  pad = 0;
00339 
00340 #ifdef HAVE_CAVIUM
00341     if (key->magic == CYASSL_RSA_CAVIUM_MAGIC)
00342         return CaviumRsaPrivateDecrypt(in, inLen, out, outLen, key);
00343 #endif
00344 
00345     tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA);
00346     if (tmp == NULL) {
00347         return MEMORY_E;
00348     }
00349 
00350     XMEMCPY(tmp, in, inLen);
00351 
00352     if ((ret = plainLen = RsaPrivateDecryptInline(tmp, inLen, &pad, key))
00353             < 0) {
00354         XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
00355         return ret;
00356     }
00357     if (plainLen > (int)outLen)
00358         plainLen = BAD_FUNC_ARG;
00359     else
00360         XMEMCPY(out, pad, plainLen);
00361     XMEMSET(tmp, 0x00, inLen); 
00362 
00363     XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
00364     return plainLen;
00365 }
00366 
00367 
00368 /* for Rsa Verify */
00369 int RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key)
00370 {
00371     int plainLen, ret;
00372 
00373 #ifdef HAVE_CAVIUM
00374     if (key->magic == CYASSL_RSA_CAVIUM_MAGIC) {
00375         ret = CaviumRsaSSL_Verify(in, inLen, in, inLen, key);
00376         if (ret > 0)
00377             *out = in;
00378         return ret;
00379     }
00380 #endif
00381 
00382     if ((ret = RsaFunction(in, inLen, in, &inLen, RSA_PUBLIC_DECRYPT, key))
00383             < 0) {
00384         return ret;
00385     }
00386   
00387     plainLen = RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_1);
00388 
00389     return plainLen;
00390 }
00391 
00392 
00393 int RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen,
00394                      RsaKey* key)
00395 {
00396     int plainLen, ret;
00397     byte*  tmp;
00398     byte*  pad = 0;
00399 
00400 #ifdef HAVE_CAVIUM
00401     if (key->magic == CYASSL_RSA_CAVIUM_MAGIC)
00402         return CaviumRsaSSL_Verify(in, inLen, out, outLen, key);
00403 #endif
00404 
00405     tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA);
00406     if (tmp == NULL) {
00407         return MEMORY_E;
00408     }
00409 
00410     XMEMCPY(tmp, in, inLen);
00411 
00412     if ((ret = plainLen = RsaSSL_VerifyInline(tmp, inLen, &pad, key))
00413             < 0) {
00414         XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
00415         return ret;
00416     }
00417 
00418     if (plainLen > (int)outLen)
00419         plainLen = BAD_FUNC_ARG;
00420     else 
00421         XMEMCPY(out, pad, plainLen);
00422     XMEMSET(tmp, 0x00, inLen); 
00423 
00424     XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
00425     return plainLen;
00426 }
00427 
00428 
00429 /* for Rsa Sign */
00430 int RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen,
00431                       RsaKey* key, RNG* rng)
00432 {
00433     int sz, ret;
00434 
00435 #ifdef HAVE_CAVIUM
00436     if (key->magic == CYASSL_RSA_CAVIUM_MAGIC)
00437         return CaviumRsaSSL_Sign(in, inLen, out, outLen, key);
00438 #endif
00439 
00440     sz = mp_unsigned_bin_size(&key->n);
00441     if (sz > (int)outLen)
00442         return RSA_BUFFER_E;
00443 
00444     if (inLen > (word32)(sz - RSA_MIN_PAD_SZ))
00445         return RSA_BUFFER_E;
00446 
00447     RsaPad(in, inLen, out, sz, RSA_BLOCK_TYPE_1, rng);
00448 
00449     if ((ret = RsaFunction(out, sz, out, &outLen, RSA_PRIVATE_ENCRYPT,key)) < 0)
00450         sz = ret;
00451     
00452     return sz;
00453 }
00454 
00455 
00456 int RsaEncryptSize(RsaKey* key)
00457 {
00458 #ifdef HAVE_CAVIUM
00459     if (key->magic == CYASSL_RSA_CAVIUM_MAGIC)
00460         return key->c_nSz;
00461 #endif
00462     return mp_unsigned_bin_size(&key->n);
00463 }
00464 
00465 
00466 #ifdef CYASSL_KEY_GEN
00467 
00468 static const int USE_BBS = 1;
00469 
00470 static int rand_prime(mp_int* N, int len, RNG* rng, void* heap)
00471 {
00472     int   err, res, type;
00473     byte* buf;
00474 
00475     (void)heap;
00476     if (N == NULL || rng == NULL)
00477        return BAD_FUNC_ARG; 
00478 
00479     /* get type */
00480     if (len < 0) {
00481         type = USE_BBS;
00482         len = -len;
00483     } else {
00484         type = 0;
00485     }
00486 
00487     /* allow sizes between 2 and 512 bytes for a prime size */
00488     if (len < 2 || len > 512) { 
00489         return BAD_FUNC_ARG;
00490     }
00491    
00492     /* allocate buffer to work with */
00493     buf = (byte*)XMALLOC(len, heap, DYNAMIC_TYPE_RSA);
00494     if (buf == NULL) {
00495         return MEMORY_E;
00496     }
00497     XMEMSET(buf, 0, len);
00498 
00499     do {
00500 #ifdef SHOW_GEN
00501         printf(".");
00502         fflush(stdout);
00503 #endif
00504         /* generate value */
00505         RNG_GenerateBlock(rng, buf, len);
00506 
00507         /* munge bits */
00508         buf[0]     |= 0x80 | 0x40;
00509         buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00);
00510  
00511         /* load value */
00512         if ((err = mp_read_unsigned_bin(N, buf, len)) != MP_OKAY) {
00513             XFREE(buf, heap, DYNAMIC_TYPE_RSA);
00514             return err;
00515         }
00516 
00517         /* test */
00518         if ((err = mp_prime_is_prime(N, 8, &res)) != MP_OKAY) {
00519             XFREE(buf, heap, DYNAMIC_TYPE_RSA);
00520             return err;
00521         }
00522     } while (res == MP_NO);
00523 
00524 #ifdef LTC_CLEAN_STACK
00525     XMEMSET(buf, 0, len);
00526 #endif
00527 
00528     XFREE(buf, heap, DYNAMIC_TYPE_RSA);
00529     return 0;
00530 }
00531 
00532 
00533 /* Make an RSA key for size bits, with e specified, 65537 is a good e */
00534 int MakeRsaKey(RsaKey* key, int size, long e, RNG* rng)
00535 {
00536     mp_int p, q, tmp1, tmp2, tmp3;
00537     int    err;
00538 
00539     if (key == NULL || rng == NULL)
00540         return BAD_FUNC_ARG;
00541 
00542     if (size < RSA_MIN_SIZE || size > RSA_MAX_SIZE)
00543         return BAD_FUNC_ARG;
00544 
00545     if (e < 3 || (e & 1) == 0)
00546         return BAD_FUNC_ARG;
00547 
00548     if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != MP_OKAY)
00549         return err;
00550 
00551     err = mp_set_int(&tmp3, e);
00552 
00553     /* make p */
00554     if (err == MP_OKAY) {
00555         do {
00556             err = rand_prime(&p, size/16, rng, key->heap); /* size in bytes/2 */
00557 
00558             if (err == MP_OKAY)
00559                 err = mp_sub_d(&p, 1, &tmp1);  /* tmp1 = p-1 */
00560 
00561             if (err == MP_OKAY)
00562                 err = mp_gcd(&tmp1, &tmp3, &tmp2);  /* tmp2 = gcd(p-1, e) */
00563         } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0);  /* e divdes p-1 */
00564     }
00565 
00566     /* make q */
00567     if (err == MP_OKAY) {
00568         do {
00569             err = rand_prime(&q, size/16, rng, key->heap); /* size in bytes/2 */
00570 
00571             if (err == MP_OKAY)
00572                 err = mp_sub_d(&q, 1, &tmp1);  /* tmp1 = q-1 */
00573 
00574             if (err == MP_OKAY)
00575                 err = mp_gcd(&tmp1, &tmp3, &tmp2);  /* tmp2 = gcd(q-1, e) */
00576         } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0);  /* e divdes q-1 */
00577     }
00578 
00579     if (err == MP_OKAY)
00580         err = mp_init_multi(&key->n, &key->e, &key->d, &key->p, &key->q, NULL);
00581 
00582     if (err == MP_OKAY)
00583         err = mp_init_multi(&key->dP, &key->dQ, &key->u, NULL, NULL, NULL);
00584 
00585     if (err == MP_OKAY)
00586         err = mp_sub_d(&p, 1, &tmp2);  /* tmp2 = p-1 */
00587 
00588     if (err == MP_OKAY)
00589         err = mp_lcm(&tmp1, &tmp2, &tmp1);  /* tmp1 = lcm(p-1, q-1),last loop */
00590 
00591     /* make key */
00592     if (err == MP_OKAY)
00593         err = mp_set_int(&key->e, e);  /* key->e = e */
00594 
00595     if (err == MP_OKAY)                /* key->d = 1/e mod lcm(p-1, q-1) */
00596         err = mp_invmod(&key->e, &tmp1, &key->d);
00597 
00598     if (err == MP_OKAY)
00599         err = mp_mul(&p, &q, &key->n);  /* key->n = pq */
00600 
00601     if (err == MP_OKAY)
00602         err = mp_sub_d(&p, 1, &tmp1);
00603 
00604     if (err == MP_OKAY)
00605         err = mp_sub_d(&q, 1, &tmp2);
00606 
00607     if (err == MP_OKAY)
00608         err = mp_mod(&key->d, &tmp1, &key->dP);
00609 
00610     if (err == MP_OKAY)
00611         err = mp_mod(&key->d, &tmp2, &key->dQ);
00612 
00613     if (err == MP_OKAY)
00614         err = mp_invmod(&q, &p, &key->u);
00615 
00616     if (err == MP_OKAY)
00617         err = mp_copy(&p, &key->p);
00618 
00619     if (err == MP_OKAY)
00620         err = mp_copy(&q, &key->q);
00621 
00622     if (err == MP_OKAY)
00623         key->type = RSA_PRIVATE; 
00624 
00625     mp_clear(&tmp3); 
00626     mp_clear(&tmp2); 
00627     mp_clear(&tmp1); 
00628     mp_clear(&q); 
00629     mp_clear(&p);
00630 
00631     if (err != MP_OKAY) {
00632         FreeRsaKey(key);        
00633         return err;
00634     }
00635 
00636     return 0;
00637 }
00638 
00639 
00640 #endif /* CYASSL_KEY_GEN */
00641 
00642 
00643 #ifdef HAVE_CAVIUM
00644 
00645 #include <cyassl/ctaocrypt/logging.h>
00646 #include "cavium_common.h"
00647 
00648 /* Initiliaze RSA for use with Nitrox device */
00649 int RsaInitCavium(RsaKey* rsa, int devId)
00650 {
00651     if (rsa == NULL)
00652         return -1;
00653 
00654     if (CspAllocContext(CONTEXT_SSL, &rsa->contextHandle, devId) != 0)
00655         return -1;
00656 
00657     rsa->devId = devId;
00658     rsa->magic = CYASSL_RSA_CAVIUM_MAGIC;
00659    
00660     return 0;
00661 }
00662 
00663 
00664 /* Free RSA from use with Nitrox device */
00665 void RsaFreeCavium(RsaKey* rsa)
00666 {
00667     if (rsa == NULL)
00668         return;
00669 
00670     CspFreeContext(CONTEXT_SSL, rsa->contextHandle, rsa->devId);
00671     rsa->magic = 0;
00672 }
00673 
00674 
00675 /* Initialize cavium RSA key */
00676 static int InitCaviumRsaKey(RsaKey* key, void* heap)
00677 {
00678     if (key == NULL)
00679         return BAD_FUNC_ARG;
00680 
00681     key->heap = heap;
00682     key->type = -1;   /* don't know yet */
00683 
00684     key->c_n  = NULL;
00685     key->c_e  = NULL;
00686     key->c_d  = NULL;
00687     key->c_p  = NULL;
00688     key->c_q  = NULL;
00689     key->c_dP = NULL;
00690     key->c_dQ = NULL;
00691     key->c_u  = NULL;
00692 
00693     key->c_nSz   = 0;
00694     key->c_eSz   = 0;
00695     key->c_dSz   = 0;
00696     key->c_pSz   = 0;
00697     key->c_qSz   = 0;
00698     key->c_dP_Sz = 0;
00699     key->c_dQ_Sz = 0;
00700     key->c_uSz   = 0;
00701     
00702     return 0;
00703 }
00704 
00705 
00706 /* Free cavium RSA key */
00707 static int FreeCaviumRsaKey(RsaKey* key)
00708 {
00709     if (key == NULL)
00710         return BAD_FUNC_ARG;
00711 
00712     XFREE(key->c_n,  key->heap, DYNAMIC_TYPE_CAVIUM_TMP);
00713     XFREE(key->c_e,  key->heap, DYNAMIC_TYPE_CAVIUM_TMP);
00714     XFREE(key->c_d,  key->heap, DYNAMIC_TYPE_CAVIUM_TMP);
00715     XFREE(key->c_p,  key->heap, DYNAMIC_TYPE_CAVIUM_TMP);
00716     XFREE(key->c_q,  key->heap, DYNAMIC_TYPE_CAVIUM_TMP);
00717     XFREE(key->c_dP, key->heap, DYNAMIC_TYPE_CAVIUM_TMP);
00718     XFREE(key->c_dQ, key->heap, DYNAMIC_TYPE_CAVIUM_TMP);
00719     XFREE(key->c_u,  key->heap, DYNAMIC_TYPE_CAVIUM_TMP);
00720 
00721     return InitCaviumRsaKey(key, key->heap);  /* reset pointers */
00722 }
00723 
00724 
00725 static int CaviumRsaPublicEncrypt(const byte* in, word32 inLen, byte* out,
00726                                    word32 outLen, RsaKey* key)
00727 {
00728     word32 requestId;
00729     word32 ret;
00730 
00731     if (key == NULL || in == NULL || out == NULL || outLen < (word32)key->c_nSz)
00732         return -1;
00733 
00734     ret = CspPkcs1v15Enc(CAVIUM_BLOCKING, BT2, key->c_nSz, key->c_eSz,
00735                          (word16)inLen, key->c_n, key->c_e, (byte*)in, out,
00736                          &requestId, key->devId);
00737     if (ret != 0) {
00738         CYASSL_MSG("Cavium Enc BT2 failed");
00739         return -1;
00740     }
00741     return key->c_nSz;
00742 }
00743 
00744 
00745 static INLINE void ato16(const byte* c, word16* u16)
00746 {
00747     *u16 = (c[0] << 8) | (c[1]);
00748 }
00749 
00750 
00751 static int CaviumRsaPrivateDecrypt(const byte* in, word32 inLen, byte* out,
00752                                     word32 outLen, RsaKey* key)
00753 {
00754     word32 requestId;
00755     word32 ret;
00756     word16 outSz = (word16)outLen;
00757 
00758     if (key == NULL || in == NULL || out == NULL || inLen != (word32)key->c_nSz)
00759         return -1;
00760 
00761     ret = CspPkcs1v15CrtDec(CAVIUM_BLOCKING, BT2, key->c_nSz, key->c_q,
00762                             key->c_dQ, key->c_p, key->c_dP, key->c_u,
00763                             (byte*)in, &outSz, out, &requestId, key->devId);
00764     if (ret != 0) {
00765         CYASSL_MSG("Cavium CRT Dec BT2 failed");
00766         return -1;
00767     }
00768     ato16((const byte*)&outSz, &outSz); 
00769 
00770     return outSz;
00771 }
00772 
00773 
00774 static int CaviumRsaSSL_Sign(const byte* in, word32 inLen, byte* out,
00775                              word32 outLen, RsaKey* key)
00776 {
00777     word32 requestId;
00778     word32 ret;
00779 
00780     if (key == NULL || in == NULL || out == NULL || inLen == 0 || outLen <
00781                                                              (word32)key->c_nSz)
00782         return -1;
00783 
00784     ret = CspPkcs1v15CrtEnc(CAVIUM_BLOCKING, BT1, key->c_nSz, (word16)inLen,
00785                             key->c_q, key->c_dQ, key->c_p, key->c_dP, key->c_u,
00786                             (byte*)in, out, &requestId, key->devId);
00787     if (ret != 0) {
00788         CYASSL_MSG("Cavium CRT Enc BT1 failed");
00789         return -1;
00790     }
00791     return key->c_nSz;
00792 }
00793 
00794 
00795 static int CaviumRsaSSL_Verify(const byte* in, word32 inLen, byte* out,
00796                                word32 outLen, RsaKey* key)
00797 {
00798     word32 requestId;
00799     word32 ret;
00800     word16 outSz = (word16)outLen;
00801 
00802     if (key == NULL || in == NULL || out == NULL || inLen != (word32)key->c_nSz)
00803         return -1;
00804 
00805     ret = CspPkcs1v15Dec(CAVIUM_BLOCKING, BT1, key->c_nSz, key->c_eSz,
00806                          key->c_n, key->c_e, (byte*)in, &outSz, out,
00807                          &requestId, key->devId);
00808     if (ret != 0) {
00809         CYASSL_MSG("Cavium Dec BT1 failed");
00810         return -1;
00811     }
00812     outSz = ntohs(outSz);
00813 
00814     return outSz;
00815 }
00816 
00817 
00818 #endif /* HAVE_CAVIUM */
00819 
00820 #endif /* NO_RSA */