]> begriffs open source - freertos/blob - FreeRTOS-Plus/Source/WolfSSL/wolfcrypt/src/rsa.c
Update WolfSSL library to the latest version.
[freertos] / FreeRTOS-Plus / Source / WolfSSL / wolfcrypt / src / rsa.c
1 /* rsa.c
2  *
3  * Copyright (C) 2006-2015 wolfSSL Inc.
4  *
5  * This file is part of wolfSSL. (formerly known as CyaSSL)
6  *
7  * wolfSSL 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  * wolfSSL 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 #ifdef HAVE_CONFIG_H
23     #include <config.h>
24 #endif
25
26 #include <wolfssl/wolfcrypt/settings.h>
27
28 #ifndef NO_RSA
29
30 #include <wolfssl/wolfcrypt/rsa.h>
31
32 #ifdef HAVE_FIPS
33 int  wc_InitRsaKey(RsaKey* key, void* ptr)
34 {
35     return InitRsaKey_fips(key, ptr);
36 }
37
38
39 int  wc_FreeRsaKey(RsaKey* key)
40 {
41     return FreeRsaKey_fips(key);
42 }
43
44
45 int  wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out,
46                                  word32 outLen, RsaKey* key, RNG* rng)
47 {
48     return RsaPublicEncrypt_fips(in, inLen, out, outLen, key, rng);
49 }
50
51
52 int  wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out,
53                                         RsaKey* key)
54 {
55     return RsaPrivateDecryptInline_fips(in, inLen, out, key);
56 }
57
58
59 int  wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out,
60                                   word32 outLen, RsaKey* key)
61 {
62     return RsaPrivateDecrypt_fips(in, inLen, out, outLen, key);
63 }
64
65
66 int  wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out,
67                             word32 outLen, RsaKey* key, RNG* rng)
68 {
69     return RsaSSL_Sign_fips(in, inLen, out, outLen, key, rng);
70 }
71
72
73 int  wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key)
74 {
75     return RsaSSL_VerifyInline_fips(in, inLen, out, key);
76 }
77
78
79 int  wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out,
80                               word32 outLen, RsaKey* key)
81 {
82     return RsaSSL_Verify_fips(in, inLen, out, outLen, key);
83 }
84
85
86 int  wc_RsaEncryptSize(RsaKey* key)
87 {
88     return RsaEncryptSize_fips(key);
89 }
90
91
92 int wc_RsaFlattenPublicKey(RsaKey* key, byte* a, word32* aSz, byte* b,
93                            word32* bSz)
94 {
95     /* not specified as fips so not needing _fips */
96     return RsaFlattenPublicKey(key, a, aSz, b, bSz);
97 }
98 #ifdef WOLFSSL_KEY_GEN
99     int wc_MakeRsaKey(RsaKey* key, int size, long e, RNG* rng)
100     {
101         return MakeRsaKey(key, size, e, rng);
102     }
103 #endif
104
105
106 #ifdef HAVE_CAVIUM
107     int  wc_RsaInitCavium(RsaKey* key, int i)
108     {
109         return RsaInitCavium(key, i);
110     }
111
112
113     void wc_RsaFreeCavium(RsaKey* key)
114     {
115         RsaFreeCavium(key);
116     }
117 #endif
118
119 /* these are functions in asn and are routed to wolfssl/wolfcrypt/asn.c
120 * wc_RsaPrivateKeyDecode
121 * wc_RsaPublicKeyDecode
122 */
123
124 #else /* else build without fips */
125 #include <wolfssl/wolfcrypt/random.h>
126 #include <wolfssl/wolfcrypt/error-crypt.h>
127 #include <wolfssl/wolfcrypt/logging.h>
128 #ifdef NO_INLINE
129     #include <wolfssl/wolfcrypt/misc.h>
130 #else
131     #include <wolfcrypt/src/misc.c>
132 #endif
133
134 #ifdef SHOW_GEN
135     #ifdef FREESCALE_MQX
136         #include <fio.h>
137     #else
138         #include <stdio.h>
139     #endif
140 #endif
141
142 #ifdef HAVE_CAVIUM
143     static int  InitCaviumRsaKey(RsaKey* key, void* heap);
144     static int  FreeCaviumRsaKey(RsaKey* key);
145     static int  CaviumRsaPublicEncrypt(const byte* in, word32 inLen, byte* out,
146                                        word32 outLen, RsaKey* key);
147     static int  CaviumRsaPrivateDecrypt(const byte* in, word32 inLen, byte* out,
148                                         word32 outLen, RsaKey* key);
149     static int  CaviumRsaSSL_Sign(const byte* in, word32 inLen, byte* out,
150                                   word32 outLen, RsaKey* key);
151     static int  CaviumRsaSSL_Verify(const byte* in, word32 inLen, byte* out,
152                                     word32 outLen, RsaKey* key);
153 #endif
154
155 enum {
156     RSA_PUBLIC_ENCRYPT  = 0,
157     RSA_PUBLIC_DECRYPT  = 1,
158     RSA_PRIVATE_ENCRYPT = 2,
159     RSA_PRIVATE_DECRYPT = 3,
160
161     RSA_BLOCK_TYPE_1 = 1,
162     RSA_BLOCK_TYPE_2 = 2,
163
164     RSA_MIN_SIZE = 512,
165     RSA_MAX_SIZE = 4096,
166
167     RSA_MIN_PAD_SZ   = 11      /* seperator + 0 + pad value + 8 pads */
168 };
169
170
171 int wc_InitRsaKey(RsaKey* key, void* heap)
172 {
173 #ifdef HAVE_CAVIUM
174     if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC)
175         return InitCaviumRsaKey(key, heap);
176 #endif
177
178     key->type = -1;  /* haven't decided yet */
179     key->heap = heap;
180
181 /* TomsFastMath doesn't use memory allocation */
182 #ifndef USE_FAST_MATH
183     key->n.dp = key->e.dp = 0;  /* public  alloc parts */
184
185     key->d.dp = key->p.dp  = 0;  /* private alloc parts */
186     key->q.dp = key->dP.dp = 0;  
187     key->u.dp = key->dQ.dp = 0;
188 #else
189     mp_init(&key->n);
190     mp_init(&key->e);
191     mp_init(&key->d);
192     mp_init(&key->p);
193     mp_init(&key->q);
194     mp_init(&key->dP);
195     mp_init(&key->dQ);
196     mp_init(&key->u);
197 #endif
198
199     return 0;
200 }
201
202
203 int wc_FreeRsaKey(RsaKey* key)
204 {
205     (void)key;
206
207 #ifdef HAVE_CAVIUM
208     if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC)
209         return FreeCaviumRsaKey(key);
210 #endif
211
212 /* TomsFastMath doesn't use memory allocation */
213 #ifndef USE_FAST_MATH
214     if (key->type == RSA_PRIVATE) {
215         mp_clear(&key->u);
216         mp_clear(&key->dQ);
217         mp_clear(&key->dP);
218         mp_clear(&key->q);
219         mp_clear(&key->p);
220         mp_clear(&key->d);
221     }
222     mp_clear(&key->e);
223     mp_clear(&key->n);
224 #endif
225
226     return 0;
227 }
228
229 static int wc_RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock,
230                    word32 pkcsBlockLen, byte padValue, RNG* rng)
231 {
232     if (inputLen == 0)
233         return 0;
234
235     pkcsBlock[0] = 0x0;       /* set first byte to zero and advance */
236     pkcsBlock++; pkcsBlockLen--;
237     pkcsBlock[0] = padValue;  /* insert padValue */
238
239     if (padValue == RSA_BLOCK_TYPE_1)
240         /* pad with 0xff bytes */
241         XMEMSET(&pkcsBlock[1], 0xFF, pkcsBlockLen - inputLen - 2);
242     else {
243         /* pad with non-zero random bytes */
244         word32 padLen = pkcsBlockLen - inputLen - 1, i;
245         int    ret    = wc_RNG_GenerateBlock(rng, &pkcsBlock[1], padLen);
246
247         if (ret != 0)
248             return ret;
249
250         /* remove zeros */
251         for (i = 1; i < padLen; i++)
252             if (pkcsBlock[i] == 0) pkcsBlock[i] = 0x01;
253     }
254
255     pkcsBlock[pkcsBlockLen-inputLen-1] = 0;     /* separator */
256     XMEMCPY(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen);
257
258     return 0;
259 }
260
261
262 /* UnPad plaintext, set start to *output, return length of plaintext,
263  * < 0 on error */
264 static int RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen,
265                        byte **output, byte padValue)
266 {
267     word32 maxOutputLen = (pkcsBlockLen > 10) ? (pkcsBlockLen - 10) : 0,
268            invalid = 0,
269            i = 1,
270            outputLen;
271
272     if (pkcsBlock[0] != 0x0) /* skip past zero */
273         invalid = 1;
274     pkcsBlock++; pkcsBlockLen--;
275
276     /* Require block type padValue */
277     invalid = (pkcsBlock[0] != padValue) || invalid;
278
279     /* verify the padding until we find the separator */
280     if (padValue == RSA_BLOCK_TYPE_1) {
281         while (i<pkcsBlockLen && pkcsBlock[i++] == 0xFF) {/* Null body */}
282     }
283     else {
284         while (i<pkcsBlockLen && pkcsBlock[i++]) {/* Null body */}
285     }
286
287     if(!(i==pkcsBlockLen || pkcsBlock[i-1]==0)) {
288         WOLFSSL_MSG("RsaUnPad error, bad formatting");
289         return RSA_PAD_E;
290     }
291
292     outputLen = pkcsBlockLen - i;
293     invalid = (outputLen > maxOutputLen) || invalid;
294
295     if (invalid) {
296         WOLFSSL_MSG("RsaUnPad error, bad formatting");
297         return RSA_PAD_E;
298     }
299
300     *output = (byte *)(pkcsBlock + i);
301     return outputLen;
302 }
303
304
305 static int wc_RsaFunction(const byte* in, word32 inLen, byte* out,
306                           word32* outLen, int type, RsaKey* key)
307 {
308     #define ERROR_OUT(x) { ret = (x); goto done;}
309
310     mp_int tmp;
311     int    ret = 0;
312     word32 keyLen, len;
313
314     if (mp_init(&tmp) != MP_OKAY)
315         return MP_INIT_E;
316
317     if (mp_read_unsigned_bin(&tmp, (byte*)in, inLen) != MP_OKAY)
318         ERROR_OUT(MP_READ_E);
319
320     if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) {
321         #ifdef RSA_LOW_MEM      /* half as much memory but twice as slow */
322             if (mp_exptmod(&tmp, &key->d, &key->n, &tmp) != MP_OKAY)
323                 ERROR_OUT(MP_EXPTMOD_E);
324         #else
325             #define INNER_ERROR_OUT(x) { ret = (x); goto inner_done; }
326
327             mp_int tmpa, tmpb;
328
329             if (mp_init(&tmpa) != MP_OKAY)
330                 ERROR_OUT(MP_INIT_E);
331
332             if (mp_init(&tmpb) != MP_OKAY) {
333                 mp_clear(&tmpa);
334                 ERROR_OUT(MP_INIT_E);
335             }
336
337             /* tmpa = tmp^dP mod p */
338             if (mp_exptmod(&tmp, &key->dP, &key->p, &tmpa) != MP_OKAY)
339                 INNER_ERROR_OUT(MP_EXPTMOD_E);
340
341             /* tmpb = tmp^dQ mod q */
342             if (mp_exptmod(&tmp, &key->dQ, &key->q, &tmpb) != MP_OKAY)
343                 INNER_ERROR_OUT(MP_EXPTMOD_E);
344
345             /* tmp = (tmpa - tmpb) * qInv (mod p) */
346             if (mp_sub(&tmpa, &tmpb, &tmp) != MP_OKAY)
347                 INNER_ERROR_OUT(MP_SUB_E);
348
349             if (mp_mulmod(&tmp, &key->u, &key->p, &tmp) != MP_OKAY)
350                 INNER_ERROR_OUT(MP_MULMOD_E);
351
352             /* tmp = tmpb + q * tmp */
353             if (mp_mul(&tmp, &key->q, &tmp) != MP_OKAY)
354                 INNER_ERROR_OUT(MP_MUL_E);
355
356             if (mp_add(&tmp, &tmpb, &tmp) != MP_OKAY)
357                 INNER_ERROR_OUT(MP_ADD_E);
358
359         inner_done:
360             mp_clear(&tmpa);
361             mp_clear(&tmpb);
362
363             if (ret != 0) return ret;
364
365         #endif   /* RSA_LOW_MEM */
366     }
367     else if (type == RSA_PUBLIC_ENCRYPT || type == RSA_PUBLIC_DECRYPT) {
368         if (mp_exptmod(&tmp, &key->e, &key->n, &tmp) != MP_OKAY)
369             ERROR_OUT(MP_EXPTMOD_E);
370     }
371     else
372         ERROR_OUT(RSA_WRONG_TYPE_E);
373
374     keyLen = mp_unsigned_bin_size(&key->n);
375     if (keyLen > *outLen)
376         ERROR_OUT(RSA_BUFFER_E);
377
378     len = mp_unsigned_bin_size(&tmp);
379
380     /* pad front w/ zeros to match key length */
381     while (len < keyLen) {
382         *out++ = 0x00;
383         len++;
384     }
385
386     *outLen = keyLen;
387
388     /* convert */
389     if (mp_to_unsigned_bin(&tmp, out) != MP_OKAY)
390         ERROR_OUT(MP_TO_E);
391
392 done:
393     mp_clear(&tmp);
394     if (ret == MP_EXPTMOD_E) {
395         WOLFSSL_MSG("RSA_FUNCTION MP_EXPTMOD_E: memory/config problem");
396     }
397     return ret;
398 }
399
400
401 int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen,
402                      RsaKey* key, RNG* rng)
403 {
404     int sz, ret;
405
406 #ifdef HAVE_CAVIUM
407     if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC)
408         return CaviumRsaPublicEncrypt(in, inLen, out, outLen, key);
409 #endif
410
411     sz = mp_unsigned_bin_size(&key->n);
412     if (sz > (int)outLen)
413         return RSA_BUFFER_E;
414
415     if (inLen > (word32)(sz - RSA_MIN_PAD_SZ))
416         return RSA_BUFFER_E;
417
418     ret = wc_RsaPad(in, inLen, out, sz, RSA_BLOCK_TYPE_2, rng);
419     if (ret != 0)
420         return ret;
421
422     if ((ret = wc_RsaFunction(out, sz, out, &outLen,
423                               RSA_PUBLIC_ENCRYPT, key)) < 0)
424         sz = ret;
425
426     return sz;
427 }
428
429
430 int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, RsaKey* key)
431 {
432     int ret;
433
434 #ifdef HAVE_CAVIUM
435     if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) {
436         ret = CaviumRsaPrivateDecrypt(in, inLen, in, inLen, key);
437         if (ret > 0)
438             *out = in;
439         return ret;
440     }
441 #endif
442
443     if ((ret = wc_RsaFunction(in, inLen, in, &inLen, RSA_PRIVATE_DECRYPT, key))
444             < 0) {
445         return ret;
446     }
447  
448     return RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_2);
449 }
450
451
452 int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, word32 outLen,
453                      RsaKey* key)
454 {
455     int plainLen;
456     byte*  tmp;
457     byte*  pad = 0;
458
459 #ifdef HAVE_CAVIUM
460     if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC)
461         return CaviumRsaPrivateDecrypt(in, inLen, out, outLen, key);
462 #endif
463
464     tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA);
465     if (tmp == NULL) {
466         return MEMORY_E;
467     }
468
469     XMEMCPY(tmp, in, inLen);
470
471     if ( (plainLen = wc_RsaPrivateDecryptInline(tmp, inLen, &pad, key) ) < 0) {
472         XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
473         return plainLen;
474     }
475     if (plainLen > (int)outLen)
476         plainLen = BAD_FUNC_ARG;
477     else
478         XMEMCPY(out, pad, plainLen);
479
480     ForceZero(tmp, inLen);
481     XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
482
483     return plainLen;
484 }
485
486
487 /* for Rsa Verify */
488 int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key)
489 {
490     int ret;
491
492 #ifdef HAVE_CAVIUM
493     if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC) {
494         ret = CaviumRsaSSL_Verify(in, inLen, in, inLen, key);
495         if (ret > 0)
496             *out = in;
497         return ret;
498     }
499 #endif
500
501     if ((ret = wc_RsaFunction(in, inLen, in, &inLen, RSA_PUBLIC_DECRYPT, key))
502             < 0) {
503         return ret;
504     }
505   
506     return RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_1);
507 }
508
509
510 int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen,
511                      RsaKey* key)
512 {
513     int plainLen;
514     byte*  tmp;
515     byte*  pad = 0;
516
517 #ifdef HAVE_CAVIUM
518     if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC)
519         return CaviumRsaSSL_Verify(in, inLen, out, outLen, key);
520 #endif
521
522     tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_RSA);
523     if (tmp == NULL) {
524         return MEMORY_E;
525     }
526
527     XMEMCPY(tmp, in, inLen);
528
529     if ( (plainLen = wc_RsaSSL_VerifyInline(tmp, inLen, &pad, key) ) < 0) {
530         XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
531         return plainLen;
532     }
533
534     if (plainLen > (int)outLen)
535         plainLen = BAD_FUNC_ARG;
536     else
537         XMEMCPY(out, pad, plainLen);
538
539     ForceZero(tmp, inLen);
540     XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA);
541
542     return plainLen;
543 }
544
545
546 /* for Rsa Sign */
547 int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen,
548                       RsaKey* key, RNG* rng)
549 {
550     int sz, ret;
551
552 #ifdef HAVE_CAVIUM
553     if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC)
554         return CaviumRsaSSL_Sign(in, inLen, out, outLen, key);
555 #endif
556
557     sz = mp_unsigned_bin_size(&key->n);
558     if (sz > (int)outLen)
559         return RSA_BUFFER_E;
560
561     if (inLen > (word32)(sz - RSA_MIN_PAD_SZ))
562         return RSA_BUFFER_E;
563
564     ret = wc_RsaPad(in, inLen, out, sz, RSA_BLOCK_TYPE_1, rng);
565     if (ret != 0)
566         return ret;
567
568     if ((ret = wc_RsaFunction(out, sz, out, &outLen,
569                               RSA_PRIVATE_ENCRYPT,key)) < 0)
570         sz = ret;
571     
572     return sz;
573 }
574
575
576 int wc_RsaEncryptSize(RsaKey* key)
577 {
578 #ifdef HAVE_CAVIUM
579     if (key->magic == WOLFSSL_RSA_CAVIUM_MAGIC)
580         return key->c_nSz;
581 #endif
582     return mp_unsigned_bin_size(&key->n);
583 }
584
585 /* flatten RsaKey structure into individual elements (e, n) */
586 int wc_RsaFlattenPublicKey(RsaKey* key, byte* e, word32* eSz, byte* n,
587                            word32* nSz)
588 {
589     int sz, ret;
590
591     if (key == NULL || e == NULL || eSz == NULL || n == NULL || nSz == NULL)
592        return BAD_FUNC_ARG;
593
594     sz = mp_unsigned_bin_size(&key->e);
595     if ((word32)sz > *nSz)
596         return RSA_BUFFER_E;
597     ret = mp_to_unsigned_bin(&key->e, e);
598     if (ret != MP_OKAY)
599         return ret;
600     *eSz = (word32)sz;
601
602     sz = mp_unsigned_bin_size(&key->n);
603     if ((word32)sz > *nSz)
604         return RSA_BUFFER_E;
605     ret = mp_to_unsigned_bin(&key->n, n);
606     if (ret != MP_OKAY)
607         return ret;
608     *nSz = (word32)sz;
609
610     return 0;
611 }
612
613
614 #ifdef WOLFSSL_KEY_GEN
615
616 static const int USE_BBS = 1;
617
618 static int rand_prime(mp_int* N, int len, RNG* rng, void* heap)
619 {
620     int   err, res, type;
621     byte* buf;
622
623     (void)heap;
624     if (N == NULL || rng == NULL)
625        return BAD_FUNC_ARG; 
626
627     /* get type */
628     if (len < 0) {
629         type = USE_BBS;
630         len = -len;
631     } else {
632         type = 0;
633     }
634
635     /* allow sizes between 2 and 512 bytes for a prime size */
636     if (len < 2 || len > 512) { 
637         return BAD_FUNC_ARG;
638     }
639    
640     /* allocate buffer to work with */
641     buf = (byte*)XMALLOC(len, heap, DYNAMIC_TYPE_RSA);
642     if (buf == NULL) {
643         return MEMORY_E;
644     }
645     XMEMSET(buf, 0, len);
646
647     do {
648 #ifdef SHOW_GEN
649         printf(".");
650         fflush(stdout);
651 #endif
652         /* generate value */
653         err = wc_RNG_GenerateBlock(rng, buf, len);
654         if (err != 0) {
655             XFREE(buf, heap, DYNAMIC_TYPE_RSA);
656             return err;
657         }
658
659         /* munge bits */
660         buf[0]     |= 0x80 | 0x40;
661         buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00);
662  
663         /* load value */
664         if ((err = mp_read_unsigned_bin(N, buf, len)) != MP_OKAY) {
665             XFREE(buf, heap, DYNAMIC_TYPE_RSA);
666             return err;
667         }
668
669         /* test */
670         if ((err = mp_prime_is_prime(N, 8, &res)) != MP_OKAY) {
671             XFREE(buf, heap, DYNAMIC_TYPE_RSA);
672             return err;
673         }
674     } while (res == MP_NO);
675
676     ForceZero(buf, len);
677     XFREE(buf, heap, DYNAMIC_TYPE_RSA);
678
679     return 0;
680 }
681
682
683 /* Make an RSA key for size bits, with e specified, 65537 is a good e */
684 int wc_MakeRsaKey(RsaKey* key, int size, long e, RNG* rng)
685 {
686     mp_int p, q, tmp1, tmp2, tmp3;
687     int    err;
688
689     if (key == NULL || rng == NULL)
690         return BAD_FUNC_ARG;
691
692     if (size < RSA_MIN_SIZE || size > RSA_MAX_SIZE)
693         return BAD_FUNC_ARG;
694
695     if (e < 3 || (e & 1) == 0)
696         return BAD_FUNC_ARG;
697
698     if ((err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL)) != MP_OKAY)
699         return err;
700
701     err = mp_set_int(&tmp3, e);
702
703     /* make p */
704     if (err == MP_OKAY) {
705         do {
706             err = rand_prime(&p, size/16, rng, key->heap); /* size in bytes/2 */
707
708             if (err == MP_OKAY)
709                 err = mp_sub_d(&p, 1, &tmp1);  /* tmp1 = p-1 */
710
711             if (err == MP_OKAY)
712                 err = mp_gcd(&tmp1, &tmp3, &tmp2);  /* tmp2 = gcd(p-1, e) */
713         } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0);  /* e divdes p-1 */
714     }
715
716     /* make q */
717     if (err == MP_OKAY) {
718         do {
719             err = rand_prime(&q, size/16, rng, key->heap); /* size in bytes/2 */
720
721             if (err == MP_OKAY)
722                 err = mp_sub_d(&q, 1, &tmp1);  /* tmp1 = q-1 */
723
724             if (err == MP_OKAY)
725                 err = mp_gcd(&tmp1, &tmp3, &tmp2);  /* tmp2 = gcd(q-1, e) */
726         } while (err == MP_OKAY && mp_cmp_d(&tmp2, 1) != 0);  /* e divdes q-1 */
727     }
728
729     if (err == MP_OKAY)
730         err = mp_init_multi(&key->n, &key->e, &key->d, &key->p, &key->q, NULL);
731
732     if (err == MP_OKAY)
733         err = mp_init_multi(&key->dP, &key->dQ, &key->u, NULL, NULL, NULL);
734
735     if (err == MP_OKAY)
736         err = mp_sub_d(&p, 1, &tmp2);  /* tmp2 = p-1 */
737
738     if (err == MP_OKAY)
739         err = mp_lcm(&tmp1, &tmp2, &tmp1);  /* tmp1 = lcm(p-1, q-1),last loop */
740
741     /* make key */
742     if (err == MP_OKAY)
743         err = mp_set_int(&key->e, e);  /* key->e = e */
744
745     if (err == MP_OKAY)                /* key->d = 1/e mod lcm(p-1, q-1) */
746         err = mp_invmod(&key->e, &tmp1, &key->d);
747
748     if (err == MP_OKAY)
749         err = mp_mul(&p, &q, &key->n);  /* key->n = pq */
750
751     if (err == MP_OKAY)
752         err = mp_sub_d(&p, 1, &tmp1);
753
754     if (err == MP_OKAY)
755         err = mp_sub_d(&q, 1, &tmp2);
756
757     if (err == MP_OKAY)
758         err = mp_mod(&key->d, &tmp1, &key->dP);
759
760     if (err == MP_OKAY)
761         err = mp_mod(&key->d, &tmp2, &key->dQ);
762
763     if (err == MP_OKAY)
764         err = mp_invmod(&q, &p, &key->u);
765
766     if (err == MP_OKAY)
767         err = mp_copy(&p, &key->p);
768
769     if (err == MP_OKAY)
770         err = mp_copy(&q, &key->q);
771
772     if (err == MP_OKAY)
773         key->type = RSA_PRIVATE; 
774
775     mp_clear(&tmp3); 
776     mp_clear(&tmp2); 
777     mp_clear(&tmp1); 
778     mp_clear(&q); 
779     mp_clear(&p);
780
781     if (err != MP_OKAY) {
782         wc_FreeRsaKey(key);        
783         return err;
784     }
785
786     return 0;
787 }
788
789
790 #endif /* WOLFSSL_KEY_GEN */
791
792
793 #ifdef HAVE_CAVIUM
794
795 #include <cyassl/ctaocrypt/logging.h>
796 #include "cavium_common.h"
797
798 /* Initiliaze RSA for use with Nitrox device */
799 int RsaInitCavium(RsaKey* rsa, int devId)
800 {
801     if (rsa == NULL)
802         return -1;
803
804     if (CspAllocContext(CONTEXT_SSL, &rsa->contextHandle, devId) != 0)
805         return -1;
806
807     rsa->devId = devId;
808     rsa->magic = WOLFSSL_RSA_CAVIUM_MAGIC;
809    
810     return 0;
811 }
812
813
814 /* Free RSA from use with Nitrox device */
815 void wc_RsaFreeCavium(RsaKey* rsa)
816 {
817     if (rsa == NULL)
818         return;
819
820     CspFreeContext(CONTEXT_SSL, rsa->contextHandle, rsa->devId);
821     rsa->magic = 0;
822 }
823
824
825 /* Initialize cavium RSA key */
826 static int InitCaviumRsaKey(RsaKey* key, void* heap)
827 {
828     if (key == NULL)
829         return BAD_FUNC_ARG;
830
831     key->heap = heap;
832     key->type = -1;   /* don't know yet */
833
834     key->c_n  = NULL;
835     key->c_e  = NULL;
836     key->c_d  = NULL;
837     key->c_p  = NULL;
838     key->c_q  = NULL;
839     key->c_dP = NULL;
840     key->c_dQ = NULL;
841     key->c_u  = NULL;
842
843     key->c_nSz   = 0;
844     key->c_eSz   = 0;
845     key->c_dSz   = 0;
846     key->c_pSz   = 0;
847     key->c_qSz   = 0;
848     key->c_dP_Sz = 0;
849     key->c_dQ_Sz = 0;
850     key->c_uSz   = 0;
851     
852     return 0;
853 }
854
855
856 /* Free cavium RSA key */
857 static int FreeCaviumRsaKey(RsaKey* key)
858 {
859     if (key == NULL)
860         return BAD_FUNC_ARG;
861
862     XFREE(key->c_n,  key->heap, DYNAMIC_TYPE_CAVIUM_TMP);
863     XFREE(key->c_e,  key->heap, DYNAMIC_TYPE_CAVIUM_TMP);
864     XFREE(key->c_d,  key->heap, DYNAMIC_TYPE_CAVIUM_TMP);
865     XFREE(key->c_p,  key->heap, DYNAMIC_TYPE_CAVIUM_TMP);
866     XFREE(key->c_q,  key->heap, DYNAMIC_TYPE_CAVIUM_TMP);
867     XFREE(key->c_dP, key->heap, DYNAMIC_TYPE_CAVIUM_TMP);
868     XFREE(key->c_dQ, key->heap, DYNAMIC_TYPE_CAVIUM_TMP);
869     XFREE(key->c_u,  key->heap, DYNAMIC_TYPE_CAVIUM_TMP);
870
871     return InitCaviumRsaKey(key, key->heap);  /* reset pointers */
872 }
873
874
875 static int CaviumRsaPublicEncrypt(const byte* in, word32 inLen, byte* out,
876                                    word32 outLen, RsaKey* key)
877 {
878     word32 requestId;
879     word32 ret;
880
881     if (key == NULL || in == NULL || out == NULL || outLen < (word32)key->c_nSz)
882         return -1;
883
884     ret = CspPkcs1v15Enc(CAVIUM_BLOCKING, BT2, key->c_nSz, key->c_eSz,
885                          (word16)inLen, key->c_n, key->c_e, (byte*)in, out,
886                          &requestId, key->devId);
887     if (ret != 0) {
888         WOLFSSL_MSG("Cavium Enc BT2 failed");
889         return -1;
890     }
891     return key->c_nSz;
892 }
893
894
895 static INLINE void ato16(const byte* c, word16* u16)
896 {
897     *u16 = (c[0] << 8) | (c[1]);
898 }
899
900
901 static int CaviumRsaPrivateDecrypt(const byte* in, word32 inLen, byte* out,
902                                     word32 outLen, RsaKey* key)
903 {
904     word32 requestId;
905     word32 ret;
906     word16 outSz = (word16)outLen;
907
908     if (key == NULL || in == NULL || out == NULL || inLen != (word32)key->c_nSz)
909         return -1;
910
911     ret = CspPkcs1v15CrtDec(CAVIUM_BLOCKING, BT2, key->c_nSz, key->c_q,
912                             key->c_dQ, key->c_p, key->c_dP, key->c_u,
913                             (byte*)in, &outSz, out, &requestId, key->devId);
914     if (ret != 0) {
915         WOLFSSL_MSG("Cavium CRT Dec BT2 failed");
916         return -1;
917     }
918     ato16((const byte*)&outSz, &outSz); 
919
920     return outSz;
921 }
922
923
924 static int CaviumRsaSSL_Sign(const byte* in, word32 inLen, byte* out,
925                              word32 outLen, RsaKey* key)
926 {
927     word32 requestId;
928     word32 ret;
929
930     if (key == NULL || in == NULL || out == NULL || inLen == 0 || outLen <
931                                                              (word32)key->c_nSz)
932         return -1;
933
934     ret = CspPkcs1v15CrtEnc(CAVIUM_BLOCKING, BT1, key->c_nSz, (word16)inLen,
935                             key->c_q, key->c_dQ, key->c_p, key->c_dP, key->c_u,
936                             (byte*)in, out, &requestId, key->devId);
937     if (ret != 0) {
938         WOLFSSL_MSG("Cavium CRT Enc BT1 failed");
939         return -1;
940     }
941     return key->c_nSz;
942 }
943
944
945 static int CaviumRsaSSL_Verify(const byte* in, word32 inLen, byte* out,
946                                word32 outLen, RsaKey* key)
947 {
948     word32 requestId;
949     word32 ret;
950     word16 outSz = (word16)outLen;
951
952     if (key == NULL || in == NULL || out == NULL || inLen != (word32)key->c_nSz)
953         return -1;
954
955     ret = CspPkcs1v15Dec(CAVIUM_BLOCKING, BT1, key->c_nSz, key->c_eSz,
956                          key->c_n, key->c_e, (byte*)in, &outSz, out,
957                          &requestId, key->devId);
958     if (ret != 0) {
959         WOLFSSL_MSG("Cavium Dec BT1 failed");
960         return -1;
961     }
962     outSz = ntohs(outSz);
963
964     return outSz;
965 }
966
967
968 #endif /* HAVE_CAVIUM */
969
970 #endif /* HAVE_FIPS */
971 #endif /* NO_RSA */
972