]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/CyaSSL/ctaocrypt/src/rsa.c
Final commit before tagging - cosmetic changes only.
[freertos] / FreeRTOS-Plus / Source / CyaSSL / ctaocrypt / src / rsa.c
1 /* rsa.c
2  *
3  * Copyright (C) 2006-2014 wolfSSL Inc.
4  *
5  * This file is part of CyaSSL.
6  *
7  * CyaSSL is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * CyaSSL is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22
23 #ifdef HAVE_CONFIG_H
24     #include <config.h>
25 #endif
26
27 #include <cyassl/ctaocrypt/settings.h>
28
29 #ifndef NO_RSA
30
31 #ifdef HAVE_FIPS
32     /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
33     #define FIPS_NO_WRAPPERS
34 #endif
35
36 #include <cyassl/ctaocrypt/rsa.h>
37 #include <cyassl/ctaocrypt/random.h>
38 #include <cyassl/ctaocrypt/error-crypt.h>
39 #include <cyassl/ctaocrypt/logging.h>
40
41 #ifdef SHOW_GEN
42     #ifdef FREESCALE_MQX
43         #include <fio.h>
44     #else
45         #include <stdio.h>
46     #endif
47 #endif
48
49 #ifdef HAVE_CAVIUM
50     static int  InitCaviumRsaKey(RsaKey* key, void* heap);
51     static int  FreeCaviumRsaKey(RsaKey* key);
52     static int  CaviumRsaPublicEncrypt(const byte* in, word32 inLen, byte* out,
53                                        word32 outLen, RsaKey* key);
54     static int  CaviumRsaPrivateDecrypt(const byte* in, word32 inLen, byte* out,
55                                         word32 outLen, RsaKey* key);
56     static int  CaviumRsaSSL_Sign(const byte* in, word32 inLen, byte* out,
57                                   word32 outLen, RsaKey* key);
58     static int  CaviumRsaSSL_Verify(const byte* in, word32 inLen, byte* out,
59                                     word32 outLen, RsaKey* key);
60 #endif
61
62 enum {
63     RSA_PUBLIC_ENCRYPT  = 0,
64     RSA_PUBLIC_DECRYPT  = 1,
65     RSA_PRIVATE_ENCRYPT = 2,
66     RSA_PRIVATE_DECRYPT = 3,
67
68     RSA_BLOCK_TYPE_1 = 1,
69     RSA_BLOCK_TYPE_2 = 2,
70
71     RSA_MIN_SIZE = 512,
72     RSA_MAX_SIZE = 4096,
73
74     RSA_MIN_PAD_SZ   = 11      /* seperator + 0 + pad value + 8 pads */
75 };
76
77
78 int InitRsaKey(RsaKey* key, void* heap)
79 {
80 #ifdef HAVE_CAVIUM
81     if (key->magic == CYASSL_RSA_CAVIUM_MAGIC)
82         return InitCaviumRsaKey(key, heap);
83 #endif
84
85     key->type = -1;  /* haven't decided yet */
86     key->heap = heap;
87
88 /* TomsFastMath doesn't use memory allocation */
89 #ifndef USE_FAST_MATH
90     key->n.dp = key->e.dp = 0;  /* public  alloc parts */
91
92     key->d.dp = key->p.dp  = 0;  /* private alloc parts */
93     key->q.dp = key->dP.dp = 0;  
94     key->u.dp = key->dQ.dp = 0;
95 #endif
96
97     return 0;
98 }
99
100
101 int FreeRsaKey(RsaKey* key)
102 {
103     (void)key;
104
105 #ifdef HAVE_CAVIUM
106     if (key->magic == CYASSL_RSA_CAVIUM_MAGIC)
107         return FreeCaviumRsaKey(key);
108 #endif
109
110 /* TomsFastMath doesn't use memory allocation */
111 #ifndef USE_FAST_MATH
112     if (key->type == RSA_PRIVATE) {
113         mp_clear(&key->u);
114         mp_clear(&key->dQ);
115         mp_clear(&key->dP);
116         mp_clear(&key->q);
117         mp_clear(&key->p);
118         mp_clear(&key->d);
119     }
120     mp_clear(&key->e);
121     mp_clear(&key->n);
122 #endif
123
124     return 0;
125 }
126
127 static int RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock,
128                    word32 pkcsBlockLen, byte padValue, RNG* rng)
129 {
130     if (inputLen == 0)
131         return 0;
132
133     pkcsBlock[0] = 0x0;       /* set first byte to zero and advance */
134     pkcsBlock++; pkcsBlockLen--;
135     pkcsBlock[0] = padValue;  /* insert padValue */
136
137     if (padValue == RSA_BLOCK_TYPE_1)
138         /* pad with 0xff bytes */
139         XMEMSET(&pkcsBlock[1], 0xFF, pkcsBlockLen - inputLen - 2);
140     else {
141         /* pad with non-zero random bytes */
142         word32 padLen = pkcsBlockLen - inputLen - 1, i;
143         int    ret    = RNG_GenerateBlock(rng, &pkcsBlock[1], padLen);
144
145         if (ret != 0)
146             return ret;
147
148         /* remove zeros */
149         for (i = 1; i < padLen; i++)
150             if (pkcsBlock[i] == 0) pkcsBlock[i] = 0x01;
151     }
152
153     pkcsBlock[pkcsBlockLen-inputLen-1] = 0;     /* separator */
154     XMEMCPY(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen);
155
156     return 0;
157 }
158
159
160 static word32 RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen,
161                        byte **output, byte padValue)
162 {
163     word32 maxOutputLen = (pkcsBlockLen > 10) ? (pkcsBlockLen - 10) : 0,
164            invalid = 0,
165            i = 1,
166            outputLen;
167
168     if (pkcsBlock[0] != 0x0) /* skip past zero */
169         invalid = 1;
170     pkcsBlock++; pkcsBlockLen--;
171
172     /* Require block type padValue */
173     invalid = (pkcsBlock[0] != padValue) || invalid;
174
175     /* skip past the padding until we find the separator */
176     while (i<pkcsBlockLen && pkcsBlock[i++]) { /* null body */
177         }
178     if(!(i==pkcsBlockLen || pkcsBlock[i-1]==0)) {
179         CYASSL_MSG("RsaUnPad error, bad formatting");
180         return 0;
181     }
182
183     outputLen = pkcsBlockLen - i;
184     invalid = (outputLen > maxOutputLen) || invalid;
185
186     if (invalid) {
187         CYASSL_MSG("RsaUnPad error, bad formatting");
188         return 0;
189     }
190
191     *output = (byte *)(pkcsBlock + i);
192     return outputLen;
193 }
194
195
196 static int RsaFunction(const byte* in, word32 inLen, byte* out, word32* outLen,
197                        int type, RsaKey* key)
198 {
199     #define ERROR_OUT(x) { ret = x; goto done;}
200
201     mp_int tmp;
202     int    ret = 0;
203     word32 keyLen, len;
204
205     if (mp_init(&tmp) != MP_OKAY)
206         return MP_INIT_E;
207
208     if (mp_read_unsigned_bin(&tmp, (byte*)in, inLen) != MP_OKAY)
209         ERROR_OUT(MP_READ_E);
210
211     if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) {
212         #ifdef RSA_LOW_MEM      /* half as much memory but twice as slow */
213             if (mp_exptmod(&tmp, &key->d, &key->n, &tmp) != MP_OKAY)
214                 ERROR_OUT(MP_EXPTMOD_E);
215         #else
216             #define INNER_ERROR_OUT(x) { ret = x; goto inner_done; }
217
218             mp_int tmpa, tmpb;
219
220             if (mp_init(&tmpa) != MP_OKAY)
221                 ERROR_OUT(MP_INIT_E);
222
223             if (mp_init(&tmpb) != MP_OKAY) {
224                 mp_clear(&tmpa);
225                 ERROR_OUT(MP_INIT_E);
226             }
227
228             /* tmpa = tmp^dP mod p */
229             if (mp_exptmod(&tmp, &key->dP, &key->p, &tmpa) != MP_OKAY)
230                 INNER_ERROR_OUT(MP_EXPTMOD_E);
231
232             /* tmpb = tmp^dQ mod q */
233             if (mp_exptmod(&tmp, &key->dQ, &key->q, &tmpb) != MP_OKAY)
234                 INNER_ERROR_OUT(MP_EXPTMOD_E);
235
236             /* tmp = (tmpa - tmpb) * qInv (mod p) */
237             if (mp_sub(&tmpa, &tmpb, &tmp) != MP_OKAY)
238                 INNER_ERROR_OUT(MP_SUB_E);
239
240             if (mp_mulmod(&tmp, &key->u, &key->p, &tmp) != MP_OKAY)
241                 INNER_ERROR_OUT(MP_MULMOD_E);
242
243             /* tmp = tmpb + q * tmp */
244             if (mp_mul(&tmp, &key->q, &tmp) != MP_OKAY)
245                 INNER_ERROR_OUT(MP_MUL_E);
246
247             if (mp_add(&tmp, &tmpb, &tmp) != MP_OKAY)
248                 INNER_ERROR_OUT(MP_ADD_E);
249
250         inner_done:
251             mp_clear(&tmpa);
252             mp_clear(&tmpb);
253
254             if (ret != 0) return ret;
255
256         #endif   /* RSA_LOW_MEM */
257     }
258     else if (type == RSA_PUBLIC_ENCRYPT || type == RSA_PUBLIC_DECRYPT) {
259         if (mp_exptmod(&tmp, &key->e, &key->n, &tmp) != MP_OKAY)
260             ERROR_OUT(MP_EXPTMOD_E);
261     }
262     else
263         ERROR_OUT(RSA_WRONG_TYPE_E);
264
265     keyLen = mp_unsigned_bin_size(&key->n);
266     if (keyLen > *outLen)
267         ERROR_OUT(RSA_BUFFER_E);
268
269     len = mp_unsigned_bin_size(&tmp);
270
271     /* pad front w/ zeros to match key length */
272     while (len < keyLen) {
273         *out++ = 0x00;
274         len++;
275     }
276
277     *outLen = keyLen;
278
279     /* convert */
280     if (mp_to_unsigned_bin(&tmp, out) != MP_OKAY)
281         ERROR_OUT(MP_TO_E);
282    
283 done: 
284     mp_clear(&tmp);
285     return ret;
286 }
287
288
289 int RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen,
290                      RsaKey* key, RNG* rng)
291 {
292     int sz, ret;
293
294 #ifdef HAVE_CAVIUM
295     if (key->magic == CYASSL_RSA_CAVIUM_MAGIC)
296         return CaviumRsaPublicEncrypt(in, inLen, out, outLen, key);
297 #endif
298
299     sz = mp_unsigned_bin_size(&key->n);
300     if (sz > (int)outLen)
301         return RSA_BUFFER_E;
302
303     if (inLen > (word32)(sz - RSA_MIN_PAD_SZ))
304         return RSA_BUFFER_E;
305
306     ret = RsaPad(in, inLen, out, sz, RSA_BLOCK_TYPE_2, rng);
307     if (ret != 0)
308         return ret;
309
310     if ((ret = RsaFunction(out, sz, out, &outLen, RSA_PUBLIC_ENCRYPT, key)) < 0)
311         sz = ret;
312
313     return sz;
314 }
315
316
317 int RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, RsaKey* key)
318 {
319     int plainLen, ret;
320
321 #ifdef HAVE_CAVIUM
322     if (key->magic == CYASSL_RSA_CAVIUM_MAGIC) {
323         ret = CaviumRsaPrivateDecrypt(in, inLen, in, inLen, key);
324         if (ret > 0)
325             *out = in;
326         return ret;
327     }
328 #endif
329
330     if ((ret = RsaFunction(in, inLen, in, &inLen, RSA_PRIVATE_DECRYPT, key))
331             < 0) {
332         return ret;
333     }
334  
335     plainLen = RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_2);
336
337     return plainLen;
338 }
339
340
341 int RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, word32 outLen,
342                      RsaKey* key)
343 {
344     int plainLen, ret;
345     byte*  tmp;
346     byte*  pad = 0;
347
348 #ifdef HAVE_CAVIUM
349     if (key->magic == CYASSL_RSA_CAVIUM_MAGIC)
350         return CaviumRsaPrivateDecrypt(in, inLen, out, outLen, key);
351 #endif
352
353     tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA);
354     if (tmp == NULL) {
355         return MEMORY_E;
356     }
357
358     XMEMCPY(tmp, in, inLen);
359
360     if ((ret = plainLen = RsaPrivateDecryptInline(tmp, inLen, &pad, key))
361             < 0) {
362         XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
363         return ret;
364     }
365     if (plainLen > (int)outLen)
366         plainLen = BAD_FUNC_ARG;
367     else
368         XMEMCPY(out, pad, plainLen);
369     XMEMSET(tmp, 0x00, inLen); 
370
371     XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
372     return plainLen;
373 }
374
375
376 /* for Rsa Verify */
377 int RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key)
378 {
379     int plainLen, ret;
380
381 #ifdef HAVE_CAVIUM
382     if (key->magic == CYASSL_RSA_CAVIUM_MAGIC) {
383         ret = CaviumRsaSSL_Verify(in, inLen, in, inLen, key);
384         if (ret > 0)
385             *out = in;
386         return ret;
387     }
388 #endif
389
390     if ((ret = RsaFunction(in, inLen, in, &inLen, RSA_PUBLIC_DECRYPT, key))
391             < 0) {
392         return ret;
393     }
394   
395     plainLen = RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_1);
396
397     return plainLen;
398 }
399
400
401 int RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen,
402                      RsaKey* key)
403 {
404     int plainLen, ret;
405     byte*  tmp;
406     byte*  pad = 0;
407
408 #ifdef HAVE_CAVIUM
409     if (key->magic == CYASSL_RSA_CAVIUM_MAGIC)
410         return CaviumRsaSSL_Verify(in, inLen, out, outLen, key);
411 #endif
412
413     tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA);
414     if (tmp == NULL) {
415         return MEMORY_E;
416     }
417
418     XMEMCPY(tmp, in, inLen);
419
420     if ((ret = plainLen = RsaSSL_VerifyInline(tmp, inLen, &pad, key))
421             < 0) {
422         XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
423         return ret;
424     }
425
426     if (plainLen > (int)outLen)
427         plainLen = BAD_FUNC_ARG;
428     else 
429         XMEMCPY(out, pad, plainLen);
430     XMEMSET(tmp, 0x00, inLen); 
431
432     XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
433     return plainLen;
434 }
435
436
437 /* for Rsa Sign */
438 int RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen,
439                       RsaKey* key, RNG* rng)
440 {
441     int sz, ret;
442
443 #ifdef HAVE_CAVIUM
444     if (key->magic == CYASSL_RSA_CAVIUM_MAGIC)
445         return CaviumRsaSSL_Sign(in, inLen, out, outLen, key);
446 #endif
447
448     sz = mp_unsigned_bin_size(&key->n);
449     if (sz > (int)outLen)
450         return RSA_BUFFER_E;
451
452     if (inLen > (word32)(sz - RSA_MIN_PAD_SZ))
453         return RSA_BUFFER_E;
454
455     ret = RsaPad(in, inLen, out, sz, RSA_BLOCK_TYPE_1, rng);
456     if (ret != 0)
457         return ret;
458
459     if ((ret = RsaFunction(out, sz, out, &outLen, RSA_PRIVATE_ENCRYPT,key)) < 0)
460         sz = ret;
461     
462     return sz;
463 }
464
465
466 int RsaEncryptSize(RsaKey* key)
467 {
468 #ifdef HAVE_CAVIUM
469     if (key->magic == CYASSL_RSA_CAVIUM_MAGIC)
470         return key->c_nSz;
471 #endif
472     return mp_unsigned_bin_size(&key->n);
473 }
474
475
476 #ifdef CYASSL_KEY_GEN
477
478 static const int USE_BBS = 1;
479
480 static int rand_prime(mp_int* N, int len, RNG* rng, void* heap)
481 {
482     int   err, res, type;
483     byte* buf;
484
485     (void)heap;
486     if (N == NULL || rng == NULL)
487        return BAD_FUNC_ARG; 
488
489     /* get type */
490     if (len < 0) {
491         type = USE_BBS;
492         len = -len;
493     } else {
494         type = 0;
495     }
496
497     /* allow sizes between 2 and 512 bytes for a prime size */
498     if (len < 2 || len > 512) { 
499         return BAD_FUNC_ARG;
500     }
501    
502     /* allocate buffer to work with */
503     buf = (byte*)XMALLOC(len, heap, DYNAMIC_TYPE_RSA);
504     if (buf == NULL) {
505         return MEMORY_E;
506     }
507     XMEMSET(buf, 0, len);
508
509     do {
510 #ifdef SHOW_GEN
511         printf(".");
512         fflush(stdout);
513 #endif
514         /* generate value */
515         err = RNG_GenerateBlock(rng, buf, len);
516         if (err != 0) {
517             XFREE(buf, heap, DYNAMIC_TYPE_RSA);
518             return err;
519         }
520
521         /* munge bits */
522         buf[0]     |= 0x80 | 0x40;
523         buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00);
524  
525         /* load value */
526         if ((err = mp_read_unsigned_bin(N, buf, len)) != MP_OKAY) {
527             XFREE(buf, heap, DYNAMIC_TYPE_RSA);
528             return err;
529         }
530
531         /* test */
532         if ((err = mp_prime_is_prime(N, 8, &res)) != MP_OKAY) {
533             XFREE(buf, heap, DYNAMIC_TYPE_RSA);
534             return err;
535         }
536     } while (res == MP_NO);
537
538 #ifdef LTC_CLEAN_STACK
539     XMEMSET(buf, 0, len);
540 #endif
541
542     XFREE(buf, heap, DYNAMIC_TYPE_RSA);
543     return 0;
544 }
545
546
547 /* Make an RSA key for size bits, with e specified, 65537 is a good e */
548 int MakeRsaKey(RsaKey* key, int size, long e, RNG* rng)
549 {
550     mp_int p, q, tmp1, tmp2, tmp3;
551     int    err;
552
553     if (key == NULL || rng == NULL)
554         return BAD_FUNC_ARG;
555
556     if (size < RSA_MIN_SIZE || size > RSA_MAX_SIZE)
557         return BAD_FUNC_ARG;
558
559     if (e < 3 || (e & 1) == 0)
560         return BAD_FUNC_ARG;
561
562     if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != MP_OKAY)
563         return err;
564
565     err = mp_set_int(&tmp3, e);
566
567     /* make p */
568     if (err == MP_OKAY) {
569         do {
570             err = rand_prime(&p, size/16, rng, key->heap); /* size in bytes/2 */
571
572             if (err == MP_OKAY)
573                 err = mp_sub_d(&p, 1, &tmp1);  /* tmp1 = p-1 */
574
575             if (err == MP_OKAY)
576                 err = mp_gcd(&tmp1, &tmp3, &tmp2);  /* tmp2 = gcd(p-1, e) */
577         } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0);  /* e divdes p-1 */
578     }
579
580     /* make q */
581     if (err == MP_OKAY) {
582         do {
583             err = rand_prime(&q, size/16, rng, key->heap); /* size in bytes/2 */
584
585             if (err == MP_OKAY)
586                 err = mp_sub_d(&q, 1, &tmp1);  /* tmp1 = q-1 */
587
588             if (err == MP_OKAY)
589                 err = mp_gcd(&tmp1, &tmp3, &tmp2);  /* tmp2 = gcd(q-1, e) */
590         } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0);  /* e divdes q-1 */
591     }
592
593     if (err == MP_OKAY)
594         err = mp_init_multi(&key->n, &key->e, &key->d, &key->p, &key->q, NULL);
595
596     if (err == MP_OKAY)
597         err = mp_init_multi(&key->dP, &key->dQ, &key->u, NULL, NULL, NULL);
598
599     if (err == MP_OKAY)
600         err = mp_sub_d(&p, 1, &tmp2);  /* tmp2 = p-1 */
601
602     if (err == MP_OKAY)
603         err = mp_lcm(&tmp1, &tmp2, &tmp1);  /* tmp1 = lcm(p-1, q-1),last loop */
604
605     /* make key */
606     if (err == MP_OKAY)
607         err = mp_set_int(&key->e, e);  /* key->e = e */
608
609     if (err == MP_OKAY)                /* key->d = 1/e mod lcm(p-1, q-1) */
610         err = mp_invmod(&key->e, &tmp1, &key->d);
611
612     if (err == MP_OKAY)
613         err = mp_mul(&p, &q, &key->n);  /* key->n = pq */
614
615     if (err == MP_OKAY)
616         err = mp_sub_d(&p, 1, &tmp1);
617
618     if (err == MP_OKAY)
619         err = mp_sub_d(&q, 1, &tmp2);
620
621     if (err == MP_OKAY)
622         err = mp_mod(&key->d, &tmp1, &key->dP);
623
624     if (err == MP_OKAY)
625         err = mp_mod(&key->d, &tmp2, &key->dQ);
626
627     if (err == MP_OKAY)
628         err = mp_invmod(&q, &p, &key->u);
629
630     if (err == MP_OKAY)
631         err = mp_copy(&p, &key->p);
632
633     if (err == MP_OKAY)
634         err = mp_copy(&q, &key->q);
635
636     if (err == MP_OKAY)
637         key->type = RSA_PRIVATE; 
638
639     mp_clear(&tmp3); 
640     mp_clear(&tmp2); 
641     mp_clear(&tmp1); 
642     mp_clear(&q); 
643     mp_clear(&p);
644
645     if (err != MP_OKAY) {
646         FreeRsaKey(key);        
647         return err;
648     }
649
650     return 0;
651 }
652
653
654 #endif /* CYASSL_KEY_GEN */
655
656
657 #ifdef HAVE_CAVIUM
658
659 #include <cyassl/ctaocrypt/logging.h>
660 #include "cavium_common.h"
661
662 /* Initiliaze RSA for use with Nitrox device */
663 int RsaInitCavium(RsaKey* rsa, int devId)
664 {
665     if (rsa == NULL)
666         return -1;
667
668     if (CspAllocContext(CONTEXT_SSL, &rsa->contextHandle, devId) != 0)
669         return -1;
670
671     rsa->devId = devId;
672     rsa->magic = CYASSL_RSA_CAVIUM_MAGIC;
673    
674     return 0;
675 }
676
677
678 /* Free RSA from use with Nitrox device */
679 void RsaFreeCavium(RsaKey* rsa)
680 {
681     if (rsa == NULL)
682         return;
683
684     CspFreeContext(CONTEXT_SSL, rsa->contextHandle, rsa->devId);
685     rsa->magic = 0;
686 }
687
688
689 /* Initialize cavium RSA key */
690 static int InitCaviumRsaKey(RsaKey* key, void* heap)
691 {
692     if (key == NULL)
693         return BAD_FUNC_ARG;
694
695     key->heap = heap;
696     key->type = -1;   /* don't know yet */
697
698     key->c_n  = NULL;
699     key->c_e  = NULL;
700     key->c_d  = NULL;
701     key->c_p  = NULL;
702     key->c_q  = NULL;
703     key->c_dP = NULL;
704     key->c_dQ = NULL;
705     key->c_u  = NULL;
706
707     key->c_nSz   = 0;
708     key->c_eSz   = 0;
709     key->c_dSz   = 0;
710     key->c_pSz   = 0;
711     key->c_qSz   = 0;
712     key->c_dP_Sz = 0;
713     key->c_dQ_Sz = 0;
714     key->c_uSz   = 0;
715     
716     return 0;
717 }
718
719
720 /* Free cavium RSA key */
721 static int FreeCaviumRsaKey(RsaKey* key)
722 {
723     if (key == NULL)
724         return BAD_FUNC_ARG;
725
726     XFREE(key->c_n,  key->heap, DYNAMIC_TYPE_CAVIUM_TMP);
727     XFREE(key->c_e,  key->heap, DYNAMIC_TYPE_CAVIUM_TMP);
728     XFREE(key->c_d,  key->heap, DYNAMIC_TYPE_CAVIUM_TMP);
729     XFREE(key->c_p,  key->heap, DYNAMIC_TYPE_CAVIUM_TMP);
730     XFREE(key->c_q,  key->heap, DYNAMIC_TYPE_CAVIUM_TMP);
731     XFREE(key->c_dP, key->heap, DYNAMIC_TYPE_CAVIUM_TMP);
732     XFREE(key->c_dQ, key->heap, DYNAMIC_TYPE_CAVIUM_TMP);
733     XFREE(key->c_u,  key->heap, DYNAMIC_TYPE_CAVIUM_TMP);
734
735     return InitCaviumRsaKey(key, key->heap);  /* reset pointers */
736 }
737
738
739 static int CaviumRsaPublicEncrypt(const byte* in, word32 inLen, byte* out,
740                                    word32 outLen, RsaKey* key)
741 {
742     word32 requestId;
743     word32 ret;
744
745     if (key == NULL || in == NULL || out == NULL || outLen < (word32)key->c_nSz)
746         return -1;
747
748     ret = CspPkcs1v15Enc(CAVIUM_BLOCKING, BT2, key->c_nSz, key->c_eSz,
749                          (word16)inLen, key->c_n, key->c_e, (byte*)in, out,
750                          &requestId, key->devId);
751     if (ret != 0) {
752         CYASSL_MSG("Cavium Enc BT2 failed");
753         return -1;
754     }
755     return key->c_nSz;
756 }
757
758
759 static INLINE void ato16(const byte* c, word16* u16)
760 {
761     *u16 = (c[0] << 8) | (c[1]);
762 }
763
764
765 static int CaviumRsaPrivateDecrypt(const byte* in, word32 inLen, byte* out,
766                                     word32 outLen, RsaKey* key)
767 {
768     word32 requestId;
769     word32 ret;
770     word16 outSz = (word16)outLen;
771
772     if (key == NULL || in == NULL || out == NULL || inLen != (word32)key->c_nSz)
773         return -1;
774
775     ret = CspPkcs1v15CrtDec(CAVIUM_BLOCKING, BT2, key->c_nSz, key->c_q,
776                             key->c_dQ, key->c_p, key->c_dP, key->c_u,
777                             (byte*)in, &outSz, out, &requestId, key->devId);
778     if (ret != 0) {
779         CYASSL_MSG("Cavium CRT Dec BT2 failed");
780         return -1;
781     }
782     ato16((const byte*)&outSz, &outSz); 
783
784     return outSz;
785 }
786
787
788 static int CaviumRsaSSL_Sign(const byte* in, word32 inLen, byte* out,
789                              word32 outLen, RsaKey* key)
790 {
791     word32 requestId;
792     word32 ret;
793
794     if (key == NULL || in == NULL || out == NULL || inLen == 0 || outLen <
795                                                              (word32)key->c_nSz)
796         return -1;
797
798     ret = CspPkcs1v15CrtEnc(CAVIUM_BLOCKING, BT1, key->c_nSz, (word16)inLen,
799                             key->c_q, key->c_dQ, key->c_p, key->c_dP, key->c_u,
800                             (byte*)in, out, &requestId, key->devId);
801     if (ret != 0) {
802         CYASSL_MSG("Cavium CRT Enc BT1 failed");
803         return -1;
804     }
805     return key->c_nSz;
806 }
807
808
809 static int CaviumRsaSSL_Verify(const byte* in, word32 inLen, byte* out,
810                                word32 outLen, RsaKey* key)
811 {
812     word32 requestId;
813     word32 ret;
814     word16 outSz = (word16)outLen;
815
816     if (key == NULL || in == NULL || out == NULL || inLen != (word32)key->c_nSz)
817         return -1;
818
819     ret = CspPkcs1v15Dec(CAVIUM_BLOCKING, BT1, key->c_nSz, key->c_eSz,
820                          key->c_n, key->c_e, (byte*)in, &outSz, out,
821                          &requestId, key->devId);
822     if (ret != 0) {
823         CYASSL_MSG("Cavium Dec BT1 failed");
824         return -1;
825     }
826     outSz = ntohs(outSz);
827
828     return outSz;
829 }
830
831
832 #endif /* HAVE_CAVIUM */
833
834 #endif /* NO_RSA */