Francois Berder / cyassl-lib

Dependents:   TLS_cyassl TLS_cyassl

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