cyassl re-port with cellular comms, PSK test

Dependencies:   VodafoneUSBModem_bleedingedge2 mbed-rtos mbed-src

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