1 /*
2  * Copyright (c) 2007, Cameron Rich
3  *
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * * Redistributions of source code must retain the above copyright notice,
10  *   this list of conditions and the following disclaimer.
11  * * Redistributions in binary form must reproduce the above copyright notice,
12  *   this list of conditions and the following disclaimer in the documentation
13  *   and/or other materials provided with the distribution.
14  * * Neither the name of the axTLS project nor the names of its contributors
15  *   may be used to endorse or promote products derived from this software
16  *   without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 /**
32  * @defgroup bigint_api Big Integer API
33  * @brief The bigint implementation as used by the axTLS project.
34  *
35  * The bigint library is for RSA encryption/decryption as well as signing.
36  * This code tries to minimise use of malloc/free by maintaining a small
37  * cache. A bigint context may maintain state by being made "permanent".
38  * It be be later released with a bi_depermanent() and bi_free() call.
39  *
40  * It supports the following reduction techniques:
41  * - Classical
42  * - Barrett
43  * - Montgomery
44  *
45  * It also implements the following:
46  * - Karatsuba multiplication
47  * - Squaring
48  * - Sliding window exponentiation
49  * - Chinese Remainder Theorem (implemented in rsa.c).
50  *
51  * All the algorithms used are pretty standard, and designed for different
52  * data bus sizes. Negative numbers are not dealt with at all, so a subtraction
53  * may need to be tested for negativity.
54  *
55  * This library steals some ideas from Jef Poskanzer
56  * <http://cs.marlboro.edu/term/cs-fall02/algorithms/crypto/RSA/bigint>
57  * and GMP <http://www.swox.com/gmp>. It gets most of its implementation
58  * detail from "The Handbook of Applied Cryptography"
59  * <http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf>
60  * @{
61  */
62 
63 #include <stdlib.h>
64 #include <limits.h>
65 #include <string.h>
66 #include <stdio.h>
67 #include <time.h>
68 #include "os_port.h"
69 #include "bigint.h"
70 
71 #define V1      v->comps[v->size-1]                 /**< v1 for division */
72 #define V2      v->comps[v->size-2]                 /**< v2 for division */
73 #define U(j)    tmp_u->comps[tmp_u->size-j-1]       /**< uj for division */
74 #define Q(j)    quotient->comps[quotient->size-j-1] /**< qj for division */
75 
76 static bigint *bi_int_multiply(BI_CTX *ctx, bigint *bi, comp i);
77 static bigint *bi_int_divide(BI_CTX *ctx, bigint *biR, comp denom);
78 static bigint *alloc(BI_CTX *ctx, int size);
79 static bigint *trim(bigint *bi);
80 static void more_comps(bigint *bi, int n);
81 #if defined(CONFIG_BIGINT_KARATSUBA) || defined(CONFIG_BIGINT_BARRETT) || \
82     defined(CONFIG_BIGINT_MONTGOMERY)
83 static bigint *comp_right_shift(bigint *biR, int num_shifts);
84 static bigint *comp_left_shift(bigint *biR, int num_shifts);
85 #endif
86 
87 #ifdef CONFIG_BIGINT_CHECK_ON
88 static void check(const bigint *bi);
89 #else
90 #define check(A)                /**< disappears in normal production mode */
91 #endif
92 
93 
94 /**
95  * @brief Start a new bigint context.
96  * @return A bigint context.
97  */
bi_initialize(void)98 BI_CTX *bi_initialize(void)
99 {
100     /* calloc() sets everything to zero */
101     BI_CTX *ctx = (BI_CTX *)calloc(1, sizeof(BI_CTX));
102 
103     /* the radix */
104     ctx->bi_radix = alloc(ctx, 2);
105     ctx->bi_radix->comps[0] = 0;
106     ctx->bi_radix->comps[1] = 1;
107     bi_permanent(ctx->bi_radix);
108     return ctx;
109 }
110 
111 /**
112  * @brief Close the bigint context and free any resources.
113  *
114  * Free up any used memory - a check is done if all objects were not
115  * properly freed.
116  * @param ctx [in]   The bigint session context.
117  */
bi_terminate(BI_CTX * ctx)118 void bi_terminate(BI_CTX *ctx)
119 {
120     bi_depermanent(ctx->bi_radix);
121     bi_free(ctx, ctx->bi_radix);
122 
123     if (ctx->active_count != 0)
124     {
125 #ifdef CONFIG_SSL_FULL_MODE
126         printf("bi_terminate: there were %d un-freed bigints\n",
127                        ctx->active_count);
128 #endif
129         abort();
130     }
131 
132     bi_clear_cache(ctx);
133     free(ctx);
134 }
135 
136 /**
137  *@brief Clear the memory cache.
138  */
bi_clear_cache(BI_CTX * ctx)139 void bi_clear_cache(BI_CTX *ctx)
140 {
141     bigint *p, *pn;
142 
143     if (ctx->free_list == NULL)
144         return;
145 
146     for (p = ctx->free_list; p != NULL; p = pn)
147     {
148         pn = p->next;
149         free(p->comps);
150         free(p);
151     }
152 
153     ctx->free_count = 0;
154     ctx->free_list = NULL;
155 }
156 
157 /**
158  * @brief Increment the number of references to this object.
159  * It does not do a full copy.
160  * @param bi [in]   The bigint to copy.
161  * @return A reference to the same bigint.
162  */
bi_copy(bigint * bi)163 bigint *bi_copy(bigint *bi)
164 {
165     check(bi);
166     if (bi->refs != PERMANENT)
167         bi->refs++;
168     return bi;
169 }
170 
171 /**
172  * @brief Simply make a bigint object "unfreeable" if bi_free() is called on it.
173  *
174  * For this object to be freed, bi_depermanent() must be called.
175  * @param bi [in]   The bigint to be made permanent.
176  */
bi_permanent(bigint * bi)177 void bi_permanent(bigint *bi)
178 {
179     check(bi);
180     if (bi->refs != 1)
181     {
182 #ifdef CONFIG_SSL_FULL_MODE
183         printf("bi_permanent: refs was not 1\n");
184 #endif
185         abort();
186     }
187 
188     bi->refs = PERMANENT;
189 }
190 
191 /**
192  * @brief Take a permanent object and make it eligible for freedom.
193  * @param bi [in]   The bigint to be made back to temporary.
194  */
bi_depermanent(bigint * bi)195 void bi_depermanent(bigint *bi)
196 {
197     check(bi);
198     if (bi->refs != PERMANENT)
199     {
200 #ifdef CONFIG_SSL_FULL_MODE
201         printf("bi_depermanent: bigint was not permanent\n");
202 #endif
203         abort();
204     }
205 
206     bi->refs = 1;
207 }
208 
209 /**
210  * @brief Free a bigint object so it can be used again.
211  *
212  * The memory itself it not actually freed, just tagged as being available
213  * @param ctx [in]   The bigint session context.
214  * @param bi [in]    The bigint to be freed.
215  */
bi_free(BI_CTX * ctx,bigint * bi)216 void bi_free(BI_CTX *ctx, bigint *bi)
217 {
218     check(bi);
219     if (bi->refs == PERMANENT)
220     {
221         return;
222     }
223 
224     if (--bi->refs > 0)
225     {
226         return;
227     }
228 
229     bi->next = ctx->free_list;
230     ctx->free_list = bi;
231     ctx->free_count++;
232 
233     if (--ctx->active_count < 0)
234     {
235 #ifdef CONFIG_SSL_FULL_MODE
236         printf("bi_free: active_count went negative "
237                 "- double-freed bigint?\n");
238 #endif
239         abort();
240     }
241 }
242 
243 /**
244  * @brief Convert an (unsigned) integer into a bigint.
245  * @param ctx [in]   The bigint session context.
246  * @param i [in]     The (unsigned) integer to be converted.
247  *
248  */
int_to_bi(BI_CTX * ctx,comp i)249 bigint *int_to_bi(BI_CTX *ctx, comp i)
250 {
251     bigint *biR = alloc(ctx, 1);
252     biR->comps[0] = i;
253     return biR;
254 }
255 
256 /**
257  * @brief Do a full copy of the bigint object.
258  * @param ctx [in]   The bigint session context.
259  * @param bi  [in]   The bigint object to be copied.
260  */
bi_clone(BI_CTX * ctx,const bigint * bi)261 bigint *bi_clone(BI_CTX *ctx, const bigint *bi)
262 {
263     bigint *biR = alloc(ctx, bi->size);
264     check(bi);
265     memcpy(biR->comps, bi->comps, bi->size*COMP_BYTE_SIZE);
266     return biR;
267 }
268 
269 /**
270  * @brief Perform an addition operation between two bigints.
271  * @param ctx [in]  The bigint session context.
272  * @param bia [in]  A bigint.
273  * @param bib [in]  Another bigint.
274  * @return The result of the addition.
275  */
bi_add(BI_CTX * ctx,bigint * bia,bigint * bib)276 bigint *bi_add(BI_CTX *ctx, bigint *bia, bigint *bib)
277 {
278     int n;
279     comp carry = 0;
280     comp *pa, *pb;
281 
282     check(bia);
283     check(bib);
284 
285     n = max(bia->size, bib->size);
286     more_comps(bia, n+1);
287     more_comps(bib, n);
288     pa = bia->comps;
289     pb = bib->comps;
290 
291     do
292     {
293         comp  sl, rl, cy1;
294         sl = *pa + *pb++;
295         rl = sl + carry;
296         cy1 = sl < *pa;
297         carry = cy1 | (rl < sl);
298         *pa++ = rl;
299     } while (--n != 0);
300 
301     *pa = carry;                  /* do overflow */
302     bi_free(ctx, bib);
303     return trim(bia);
304 }
305 
306 /**
307  * @brief Perform a subtraction operation between two bigints.
308  * @param ctx [in]  The bigint session context.
309  * @param bia [in]  A bigint.
310  * @param bib [in]  Another bigint.
311  * @param is_negative [out] If defined, indicates that the result was negative.
312  * is_negative may be null.
313  * @return The result of the subtraction. The result is always positive.
314  */
bi_subtract(BI_CTX * ctx,bigint * bia,bigint * bib,int * is_negative)315 bigint *bi_subtract(BI_CTX *ctx,
316         bigint *bia, bigint *bib, int *is_negative)
317 {
318     int n = bia->size;
319     comp *pa, *pb, carry = 0;
320 
321     check(bia);
322     check(bib);
323 
324     more_comps(bib, n);
325     pa = bia->comps;
326     pb = bib->comps;
327 
328     do
329     {
330         comp sl, rl, cy1;
331         sl = *pa - *pb++;
332         rl = sl - carry;
333         cy1 = sl > *pa;
334         carry = cy1 | (rl > sl);
335         *pa++ = rl;
336     } while (--n != 0);
337 
338     if (is_negative)    /* indicate a negative result */
339     {
340         *is_negative = carry;
341     }
342 
343     bi_free(ctx, trim(bib));    /* put bib back to the way it was */
344     return trim(bia);
345 }
346 
347 /**
348  * Perform a multiply between a bigint an an (unsigned) integer
349  */
bi_int_multiply(BI_CTX * ctx,bigint * bia,comp b)350 static bigint *bi_int_multiply(BI_CTX *ctx, bigint *bia, comp b)
351 {
352     int j = 0, n = bia->size;
353     bigint *biR = alloc(ctx, n + 1);
354     comp carry = 0;
355     comp *r = biR->comps;
356     comp *a = bia->comps;
357 
358     check(bia);
359 
360     /* clear things to start with */
361     memset(r, 0, ((n+1)*COMP_BYTE_SIZE));
362 
363     do
364     {
365         long_comp tmp = *r + (long_comp)a[j]*b + carry;
366         *r++ = (comp)tmp;              /* downsize */
367         carry = (comp)(tmp >> COMP_BIT_SIZE);
368     } while (++j < n);
369 
370     *r = carry;
371     bi_free(ctx, bia);
372     return trim(biR);
373 }
374 
375 /**
376  * @brief Does both division and modulo calculations.
377  *
378  * Used extensively when doing classical reduction.
379  * @param ctx [in]  The bigint session context.
380  * @param u [in]    A bigint which is the numerator.
381  * @param v [in]    Either the denominator or the modulus depending on the mode.
382  * @param is_mod [n] Determines if this is a normal division (0) or a reduction
383  * (1).
384  * @return  The result of the division/reduction.
385  */
bi_divide(BI_CTX * ctx,bigint * u,bigint * v,int is_mod)386 bigint *bi_divide(BI_CTX *ctx, bigint *u, bigint *v, int is_mod)
387 {
388     int n = v->size, m = u->size-n;
389     int j = 0, orig_u_size = u->size;
390     uint8_t mod_offset = ctx->mod_offset;
391     comp d;
392     bigint *quotient, *tmp_u;
393     comp q_dash;
394 
395     check(u);
396     check(v);
397 
398     /* if doing reduction and we are < mod, then return mod */
399     if (is_mod && bi_compare(v, u) > 0)
400     {
401         bi_free(ctx, v);
402         return u;
403     }
404 
405     quotient = alloc(ctx, m+1);
406     tmp_u = alloc(ctx, n+1);
407     v = trim(v);        /* make sure we have no leading 0's */
408     d = (comp)((long_comp)COMP_RADIX/(V1+1));
409 
410     /* clear things to start with */
411     memset(quotient->comps, 0, ((quotient->size)*COMP_BYTE_SIZE));
412 
413     /* normalise */
414     if (d > 1)
415     {
416         u = bi_int_multiply(ctx, u, d);
417 
418         if (is_mod)
419         {
420             v = ctx->bi_normalised_mod[mod_offset];
421         }
422         else
423         {
424             v = bi_int_multiply(ctx, v, d);
425         }
426     }
427 
428     if (orig_u_size == u->size)  /* new digit position u0 */
429     {
430         more_comps(u, orig_u_size + 1);
431     }
432 
433     do
434     {
435         /* get a temporary short version of u */
436         memcpy(tmp_u->comps, &u->comps[u->size-n-1-j], (n+1)*COMP_BYTE_SIZE);
437 
438         /* calculate q' */
439         if (U(0) == V1)
440         {
441             q_dash = COMP_RADIX-1;
442         }
443         else
444         {
445             q_dash = (comp)(((long_comp)U(0)*COMP_RADIX + U(1))/V1);
446 
447             if (v->size > 1 && V2)
448             {
449                 /* we are implementing the following:
450                 if (V2*q_dash > (((U(0)*COMP_RADIX + U(1) -
451                         q_dash*V1)*COMP_RADIX) + U(2))) ... */
452                 comp inner = (comp)((long_comp)COMP_RADIX*U(0) + U(1) -
453                                             (long_comp)q_dash*V1);
454                 if ((long_comp)V2*q_dash > (long_comp)inner*COMP_RADIX + U(2))
455                 {
456                     q_dash--;
457                 }
458             }
459         }
460 
461         /* multiply and subtract */
462         if (q_dash)
463         {
464             int is_negative;
465             tmp_u = bi_subtract(ctx, tmp_u,
466                     bi_int_multiply(ctx, bi_copy(v), q_dash), &is_negative);
467             more_comps(tmp_u, n+1);
468 
469             Q(j) = q_dash;
470 
471             /* add back */
472             if (is_negative)
473             {
474                 Q(j)--;
475                 tmp_u = bi_add(ctx, tmp_u, bi_copy(v));
476 
477                 /* lop off the carry */
478                 tmp_u->size--;
479                 v->size--;
480             }
481         }
482         else
483         {
484             Q(j) = 0;
485         }
486 
487         /* copy back to u */
488         memcpy(&u->comps[u->size-n-1-j], tmp_u->comps, (n+1)*COMP_BYTE_SIZE);
489     } while (++j <= m);
490 
491     bi_free(ctx, tmp_u);
492     bi_free(ctx, v);
493 
494     if (is_mod)     /* get the remainder */
495     {
496         bi_free(ctx, quotient);
497         return bi_int_divide(ctx, trim(u), d);
498     }
499     else            /* get the quotient */
500     {
501         bi_free(ctx, u);
502         return trim(quotient);
503     }
504 }
505 
506 /*
507  * Perform an integer divide on a bigint.
508  */
bi_int_divide(BI_CTX * ctx,bigint * biR,comp denom)509 static bigint *bi_int_divide(BI_CTX *ctx, bigint *biR, comp denom)
510 {
511     int i = biR->size - 1;
512     long_comp r = 0;
513 
514     check(biR);
515 
516     do
517     {
518         r = (r<<COMP_BIT_SIZE) + biR->comps[i];
519         biR->comps[i] = (comp)(r / denom);
520         r %= denom;
521     } while (--i >= 0);
522 
523     return trim(biR);
524 }
525 
526 #ifdef CONFIG_BIGINT_MONTGOMERY
527 /**
528  * There is a need for the value of integer N' such that B^-1(B-1)-N^-1N'=1,
529  * where B^-1(B-1) mod N=1. Actually, only the least significant part of
530  * N' is needed, hence the definition N0'=N' mod b. We reproduce below the
531  * simple algorithm from an article by Dusse and Kaliski to efficiently
532  * find N0' from N0 and b */
modular_inverse(bigint * bim)533 static comp modular_inverse(bigint *bim)
534 {
535     int i;
536     comp t = 1;
537     comp two_2_i_minus_1 = 2;   /* 2^(i-1) */
538     long_comp two_2_i = 4;      /* 2^i */
539     comp N = bim->comps[0];
540 
541     for (i = 2; i <= COMP_BIT_SIZE; i++)
542     {
543         if ((long_comp)N*t%two_2_i >= two_2_i_minus_1)
544         {
545             t += two_2_i_minus_1;
546         }
547 
548         two_2_i_minus_1 <<= 1;
549         two_2_i <<= 1;
550     }
551 
552     return (comp)(COMP_RADIX-t);
553 }
554 #endif
555 
556 #if defined(CONFIG_BIGINT_KARATSUBA) || defined(CONFIG_BIGINT_BARRETT) || \
557     defined(CONFIG_BIGINT_MONTGOMERY)
558 /**
559  * Take each component and shift down (in terms of components)
560  */
comp_right_shift(bigint * biR,int num_shifts)561 static bigint *comp_right_shift(bigint *biR, int num_shifts)
562 {
563     int i = biR->size-num_shifts;
564     comp *x = biR->comps;
565     comp *y = &biR->comps[num_shifts];
566 
567     check(biR);
568 
569     if (i <= 0)     /* have we completely right shifted? */
570     {
571         biR->comps[0] = 0;  /* return 0 */
572         biR->size = 1;
573         return biR;
574     }
575 
576     do
577     {
578         *x++ = *y++;
579     } while (--i > 0);
580 
581     biR->size -= num_shifts;
582     return biR;
583 }
584 
585 /**
586  * Take each component and shift it up (in terms of components)
587  */
comp_left_shift(bigint * biR,int num_shifts)588 static bigint *comp_left_shift(bigint *biR, int num_shifts)
589 {
590     int i = biR->size-1;
591     comp *x, *y;
592 
593     check(biR);
594 
595     if (num_shifts <= 0)
596     {
597         return biR;
598     }
599 
600     more_comps(biR, biR->size + num_shifts);
601 
602     x = &biR->comps[i+num_shifts];
603     y = &biR->comps[i];
604 
605     do
606     {
607         *x-- = *y--;
608     } while (i--);
609 
610     memset(biR->comps, 0, num_shifts*COMP_BYTE_SIZE); /* zero LS comps */
611     return biR;
612 }
613 #endif
614 
615 /**
616  * @brief Allow a binary sequence to be imported as a bigint.
617  * @param ctx [in]  The bigint session context.
618  * @param data [in] The data to be converted.
619  * @param size [in] The number of bytes of data.
620  * @return A bigint representing this data.
621  */
bi_import(BI_CTX * ctx,const uint8_t * data,int size)622 bigint *bi_import(BI_CTX *ctx, const uint8_t *data, int size)
623 {
624     bigint *biR = alloc(ctx, (size+COMP_BYTE_SIZE-1)/COMP_BYTE_SIZE);
625     int i, j = 0, offset = 0;
626 
627     memset(biR->comps, 0, biR->size*COMP_BYTE_SIZE);
628 
629     for (i = size-1; i >= 0; i--)
630     {
631         biR->comps[offset] += (unsigned int)data[i] << (j*8);
632 
633         if (++j == COMP_BYTE_SIZE)
634         {
635             j = 0;
636             offset ++;
637         }
638     }
639 
640     return trim(biR);
641 }
642 
643 #ifdef CONFIG_SSL_FULL_MODE
644 /**
645  * @brief The testharness uses this code to import text hex-streams and
646  * convert them into bigints.
647  * @param ctx [in]  The bigint session context.
648  * @param data [in] A string consisting of hex characters. The characters must
649  * be in upper case.
650  * @return A bigint representing this data.
651  */
bi_str_import(BI_CTX * ctx,const char * data)652 bigint *bi_str_import(BI_CTX *ctx, const char *data)
653 {
654     int size = strlen(data);
655     bigint *biR = alloc(ctx, (size+COMP_NUM_NIBBLES-1)/COMP_NUM_NIBBLES);
656     int i, j = 0, offset = 0;
657     memset(biR->comps, 0, biR->size*COMP_BYTE_SIZE);
658 
659     for (i = size-1; i >= 0; i--)
660     {
661         int num = (data[i] <= '9') ? (data[i] - '0') : (data[i] - 'A' + 10);
662         biR->comps[offset] += num << (j*4);
663 
664         if (++j == COMP_NUM_NIBBLES)
665         {
666             j = 0;
667             offset ++;
668         }
669     }
670 
671     return biR;
672 }
673 
bi_print(const char * label,bigint * x)674 void bi_print(const char *label, bigint *x)
675 {
676     int i, j;
677 
678     if (x == NULL)
679     {
680         printf("%s: (null)\n", label);
681         return;
682     }
683 
684     printf("%s: (size %d)\n", label, x->size);
685     for (i = x->size-1; i >= 0; i--)
686     {
687         for (j = COMP_NUM_NIBBLES-1; j >= 0; j--)
688         {
689             comp mask = 0x0f << (j*4);
690             comp num = (x->comps[i] & mask) >> (j*4);
691             putc((num <= 9) ? (num + '0') : (num + 'A' - 10), stdout);
692         }
693     }
694 
695     printf("\n");
696 }
697 #endif
698 
699 /**
700  * @brief Take a bigint and convert it into a byte sequence.
701  *
702  * This is useful after a decrypt operation.
703  * @param ctx [in]  The bigint session context.
704  * @param x [in]  The bigint to be converted.
705  * @param data [out] The converted data as a byte stream.
706  * @param size [in] The maximum size of the byte stream. Unused bytes will be
707  * zeroed.
708  */
bi_export(BI_CTX * ctx,bigint * x,uint8_t * data,int size)709 void bi_export(BI_CTX *ctx, bigint *x, uint8_t *data, int size)
710 {
711     int i, j, k = size-1;
712 
713     check(x);
714     memset(data, 0, size);  /* ensure all leading 0's are cleared */
715 
716     for (i = 0; i < x->size; i++)
717     {
718         for (j = 0; j < COMP_BYTE_SIZE; j++)
719         {
720             comp mask = 0xff << (j*8);
721             int num = (x->comps[i] & mask) >> (j*8);
722             data[k--] = num;
723 
724             if (k < 0)
725             {
726                 goto buf_done;
727             }
728         }
729     }
730 buf_done:
731 
732     bi_free(ctx, x);
733 }
734 
735 /**
736  * @brief Pre-calculate some of the expensive steps in reduction.
737  *
738  * This function should only be called once (normally when a session starts).
739  * When the session is over, bi_free_mod() should be called. bi_mod_power()
740  * relies on this function being called.
741  * @param ctx [in]  The bigint session context.
742  * @param bim [in]  The bigint modulus that will be used.
743  * @param mod_offset [in] There are three moduluii that can be stored - the
744  * standard modulus, and its two primes p and q. This offset refers to which
745  * modulus we are referring to.
746  * @see bi_free_mod(), bi_mod_power().
747  */
bi_set_mod(BI_CTX * ctx,bigint * bim,int mod_offset)748 void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset)
749 {
750     int k = bim->size;
751     comp d = (comp)((long_comp)COMP_RADIX/(bim->comps[k-1]+1));
752 #ifdef CONFIG_BIGINT_MONTGOMERY
753     bigint *R, *R2;
754 #endif
755 
756     ctx->bi_mod[mod_offset] = bim;
757     bi_permanent(ctx->bi_mod[mod_offset]);
758     ctx->bi_normalised_mod[mod_offset] = bi_int_multiply(ctx, bim, d);
759     bi_permanent(ctx->bi_normalised_mod[mod_offset]);
760 
761 #if defined(CONFIG_BIGINT_MONTGOMERY)
762     /* set montgomery variables */
763     R = comp_left_shift(bi_clone(ctx, ctx->bi_radix), k-1);     /* R */
764     R2 = comp_left_shift(bi_clone(ctx, ctx->bi_radix), k*2-1);  /* R^2 */
765     ctx->bi_RR_mod_m[mod_offset] = bi_mod(ctx, R2);             /* R^2 mod m */
766     ctx->bi_R_mod_m[mod_offset] = bi_mod(ctx, R);               /* R mod m */
767 
768     bi_permanent(ctx->bi_RR_mod_m[mod_offset]);
769     bi_permanent(ctx->bi_R_mod_m[mod_offset]);
770 
771     ctx->N0_dash[mod_offset] = modular_inverse(ctx->bi_mod[mod_offset]);
772 
773 #elif defined (CONFIG_BIGINT_BARRETT)
774     ctx->bi_mu[mod_offset] =
775         bi_divide(ctx, comp_left_shift(
776             bi_clone(ctx, ctx->bi_radix), k*2-1), ctx->bi_mod[mod_offset], 0);
777     bi_permanent(ctx->bi_mu[mod_offset]);
778 #endif
779 }
780 
781 /**
782  * @brief Used when cleaning various bigints at the end of a session.
783  * @param ctx [in]  The bigint session context.
784  * @param mod_offset [in] The offset to use.
785  * @see bi_set_mod().
786  */
bi_free_mod(BI_CTX * ctx,int mod_offset)787 void bi_free_mod(BI_CTX *ctx, int mod_offset)
788 {
789     bi_depermanent(ctx->bi_mod[mod_offset]);
790     bi_free(ctx, ctx->bi_mod[mod_offset]);
791 #if defined (CONFIG_BIGINT_MONTGOMERY)
792     bi_depermanent(ctx->bi_RR_mod_m[mod_offset]);
793     bi_depermanent(ctx->bi_R_mod_m[mod_offset]);
794     bi_free(ctx, ctx->bi_RR_mod_m[mod_offset]);
795     bi_free(ctx, ctx->bi_R_mod_m[mod_offset]);
796 #elif defined(CONFIG_BIGINT_BARRETT)
797     bi_depermanent(ctx->bi_mu[mod_offset]);
798     bi_free(ctx, ctx->bi_mu[mod_offset]);
799 #endif
800     bi_depermanent(ctx->bi_normalised_mod[mod_offset]);
801     bi_free(ctx, ctx->bi_normalised_mod[mod_offset]);
802 }
803 
804 /**
805  * Perform a standard multiplication between two bigints.
806  *
807  * Barrett reduction has no need for some parts of the product, so ignore bits
808  * of the multiply. This routine gives Barrett its big performance
809  * improvements over Classical/Montgomery reduction methods.
810  */
regular_multiply(BI_CTX * ctx,bigint * bia,bigint * bib,int inner_partial,int outer_partial)811 static bigint *regular_multiply(BI_CTX *ctx, bigint *bia, bigint *bib,
812         int inner_partial, int outer_partial)
813 {
814     int i = 0, j;
815     int n = bia->size;
816     int t = bib->size;
817     bigint *biR = alloc(ctx, n + t);
818     comp *sr = biR->comps;
819     comp *sa = bia->comps;
820     comp *sb = bib->comps;
821 
822     check(bia);
823     check(bib);
824 
825     /* clear things to start with */
826     memset(biR->comps, 0, ((n+t)*COMP_BYTE_SIZE));
827 
828     do
829     {
830         long_comp tmp;
831         comp carry = 0;
832         int r_index = i;
833         j = 0;
834 
835         if (outer_partial && outer_partial-i > 0 && outer_partial < n)
836         {
837             r_index = outer_partial-1;
838             j = outer_partial-i-1;
839         }
840 
841         do
842         {
843             if (inner_partial && r_index >= inner_partial)
844             {
845                 break;
846             }
847 
848             tmp = sr[r_index] + ((long_comp)sa[j])*sb[i] + carry;
849             sr[r_index++] = (comp)tmp;              /* downsize */
850             carry = tmp >> COMP_BIT_SIZE;
851         } while (++j < n);
852 
853         sr[r_index] = carry;
854     } while (++i < t);
855 
856     bi_free(ctx, bia);
857     bi_free(ctx, bib);
858     return trim(biR);
859 }
860 
861 #ifdef CONFIG_BIGINT_KARATSUBA
862 /*
863  * Karatsuba improves on regular multiplication due to only 3 multiplications
864  * being done instead of 4. The additional additions/subtractions are O(N)
865  * rather than O(N^2) and so for big numbers it saves on a few operations
866  */
karatsuba(BI_CTX * ctx,bigint * bia,bigint * bib,int is_square)867 static bigint *karatsuba(BI_CTX *ctx, bigint *bia, bigint *bib, int is_square)
868 {
869     bigint *x0, *x1;
870     bigint *p0, *p1, *p2;
871     int m;
872 
873     if (is_square)
874     {
875         m = (bia->size + 1)/2;
876     }
877     else
878     {
879         m = (max(bia->size, bib->size) + 1)/2;
880     }
881 
882     x0 = bi_clone(ctx, bia);
883     x0->size = m;
884     x1 = bi_clone(ctx, bia);
885     comp_right_shift(x1, m);
886     bi_free(ctx, bia);
887 
888     /* work out the 3 partial products */
889     if (is_square)
890     {
891         p0 = bi_square(ctx, bi_copy(x0));
892         p2 = bi_square(ctx, bi_copy(x1));
893         p1 = bi_square(ctx, bi_add(ctx, x0, x1));
894     }
895     else /* normal multiply */
896     {
897         bigint *y0, *y1;
898         y0 = bi_clone(ctx, bib);
899         y0->size = m;
900         y1 = bi_clone(ctx, bib);
901         comp_right_shift(y1, m);
902         bi_free(ctx, bib);
903 
904         p0 = bi_multiply(ctx, bi_copy(x0), bi_copy(y0));
905         p2 = bi_multiply(ctx, bi_copy(x1), bi_copy(y1));
906         p1 = bi_multiply(ctx, bi_add(ctx, x0, x1), bi_add(ctx, y0, y1));
907     }
908 
909     p1 = bi_subtract(ctx,
910             bi_subtract(ctx, p1, bi_copy(p2), NULL), bi_copy(p0), NULL);
911 
912     comp_left_shift(p1, m);
913     comp_left_shift(p2, 2*m);
914     return bi_add(ctx, p1, bi_add(ctx, p0, p2));
915 }
916 #endif
917 
918 /**
919  * @brief Perform a multiplication operation between two bigints.
920  * @param ctx [in]  The bigint session context.
921  * @param bia [in]  A bigint.
922  * @param bib [in]  Another bigint.
923  * @return The result of the multiplication.
924  */
bi_multiply(BI_CTX * ctx,bigint * bia,bigint * bib)925 bigint *bi_multiply(BI_CTX *ctx, bigint *bia, bigint *bib)
926 {
927     check(bia);
928     check(bib);
929 
930 #ifdef CONFIG_BIGINT_KARATSUBA
931     if (min(bia->size, bib->size) < MUL_KARATSUBA_THRESH)
932     {
933         return regular_multiply(ctx, bia, bib, 0, 0);
934     }
935 
936     return karatsuba(ctx, bia, bib, 0);
937 #else
938     return regular_multiply(ctx, bia, bib, 0, 0);
939 #endif
940 }
941 
942 #ifdef CONFIG_BIGINT_SQUARE
943 /*
944  * Perform the actual square operion. It takes into account overflow.
945  */
regular_square(BI_CTX * ctx,bigint * bi)946 static bigint *regular_square(BI_CTX *ctx, bigint *bi)
947 {
948     int t = bi->size;
949     int i = 0, j;
950     bigint *biR = alloc(ctx, t*2+1);
951     comp *w = biR->comps;
952     comp *x = bi->comps;
953     long_comp carry;
954     memset(w, 0, biR->size*COMP_BYTE_SIZE);
955 
956     do
957     {
958         long_comp tmp = w[2*i] + (long_comp)x[i]*x[i];
959         w[2*i] = (comp)tmp;
960         carry = tmp >> COMP_BIT_SIZE;
961 
962         for (j = i+1; j < t; j++)
963         {
964             uint8_t c = 0;
965             long_comp xx = (long_comp)x[i]*x[j];
966             if ((COMP_MAX-xx) < xx)
967                 c = 1;
968 
969             tmp = (xx<<1);
970 
971             if ((COMP_MAX-tmp) < w[i+j])
972                 c = 1;
973 
974             tmp += w[i+j];
975 
976             if ((COMP_MAX-tmp) < carry)
977                 c = 1;
978 
979             tmp += carry;
980             w[i+j] = (comp)tmp;
981             carry = tmp >> COMP_BIT_SIZE;
982 
983             if (c)
984                 carry += COMP_RADIX;
985         }
986 
987         tmp = w[i+t] + carry;
988         w[i+t] = (comp)tmp;
989         w[i+t+1] = tmp >> COMP_BIT_SIZE;
990     } while (++i < t);
991 
992     bi_free(ctx, bi);
993     return trim(biR);
994 }
995 
996 /**
997  * @brief Perform a square operation on a bigint.
998  * @param ctx [in]  The bigint session context.
999  * @param bia [in]  A bigint.
1000  * @return The result of the multiplication.
1001  */
bi_square(BI_CTX * ctx,bigint * bia)1002 bigint *bi_square(BI_CTX *ctx, bigint *bia)
1003 {
1004     check(bia);
1005 
1006 #ifdef CONFIG_BIGINT_KARATSUBA
1007     if (bia->size < SQU_KARATSUBA_THRESH)
1008     {
1009         return regular_square(ctx, bia);
1010     }
1011 
1012     return karatsuba(ctx, bia, NULL, 1);
1013 #else
1014     return regular_square(ctx, bia);
1015 #endif
1016 }
1017 #endif
1018 
1019 /**
1020  * @brief Compare two bigints.
1021  * @param bia [in]  A bigint.
1022  * @param bib [in]  Another bigint.
1023  * @return -1 if smaller, 1 if larger and 0 if equal.
1024  */
bi_compare(bigint * bia,bigint * bib)1025 int bi_compare(bigint *bia, bigint *bib)
1026 {
1027     int r, i;
1028 
1029     check(bia);
1030     check(bib);
1031 
1032     if (bia->size > bib->size)
1033         r = 1;
1034     else if (bia->size < bib->size)
1035         r = -1;
1036     else
1037     {
1038         comp *a = bia->comps;
1039         comp *b = bib->comps;
1040 
1041         /* Same number of components.  Compare starting from the high end
1042          * and working down. */
1043         r = 0;
1044         i = bia->size - 1;
1045 
1046         do
1047         {
1048             if (a[i] > b[i])
1049             {
1050                 r = 1;
1051                 break;
1052             }
1053             else if (a[i] < b[i])
1054             {
1055                 r = -1;
1056                 break;
1057             }
1058         } while (--i >= 0);
1059     }
1060 
1061     return r;
1062 }
1063 
1064 /*
1065  * Allocate and zero more components.  Does not consume bi.
1066  */
more_comps(bigint * bi,int n)1067 static void more_comps(bigint *bi, int n)
1068 {
1069     if (n > bi->max_comps)
1070     {
1071         bi->max_comps = max(bi->max_comps * 2, n);
1072         bi->comps = (comp*)realloc(bi->comps, bi->max_comps * COMP_BYTE_SIZE);
1073     }
1074 
1075     if (n > bi->size)
1076     {
1077         memset(&bi->comps[bi->size], 0, (n-bi->size)*COMP_BYTE_SIZE);
1078     }
1079 
1080     bi->size = n;
1081 }
1082 
1083 /*
1084  * Make a new empty bigint. It may just use an old one if one is available.
1085  * Otherwise get one off the heap.
1086  */
alloc(BI_CTX * ctx,int size)1087 static bigint *alloc(BI_CTX *ctx, int size)
1088 {
1089     bigint *biR;
1090 
1091     /* Can we recycle an old bigint? */
1092     if (ctx->free_list != NULL)
1093     {
1094         biR = ctx->free_list;
1095         ctx->free_list = biR->next;
1096         ctx->free_count--;
1097 
1098         if (biR->refs != 0)
1099         {
1100 #ifdef CONFIG_SSL_FULL_MODE
1101             printf("alloc: refs was not 0\n");
1102 #endif
1103             abort();    /* create a stack trace from a core dump */
1104         }
1105 
1106         more_comps(biR, size);
1107     }
1108     else
1109     {
1110         /* No free bigints available - create a new one. */
1111         biR = (bigint *)malloc(sizeof(bigint));
1112         biR->comps = (comp*)malloc(size * COMP_BYTE_SIZE);
1113         biR->max_comps = size;  /* give some space to spare */
1114     }
1115 
1116     biR->size = size;
1117     biR->refs = 1;
1118     biR->next = NULL;
1119     ctx->active_count++;
1120     return biR;
1121 }
1122 
1123 /*
1124  * Work out the highest '1' bit in an exponent. Used when doing sliding-window
1125  * exponentiation.
1126  */
find_max_exp_index(bigint * biexp)1127 static int find_max_exp_index(bigint *biexp)
1128 {
1129     int i = COMP_BIT_SIZE-1;
1130     comp shift = COMP_RADIX/2;
1131     comp test = biexp->comps[biexp->size-1];    /* assume no leading zeroes */
1132 
1133     check(biexp);
1134 
1135     do
1136     {
1137         if (test & shift)
1138         {
1139             return i+(biexp->size-1)*COMP_BIT_SIZE;
1140         }
1141 
1142         shift >>= 1;
1143     } while (i-- != 0);
1144 
1145     return -1;      /* error - must have been a leading 0 */
1146 }
1147 
1148 /*
1149  * Is a particular bit is an exponent 1 or 0? Used when doing sliding-window
1150  * exponentiation.
1151  */
exp_bit_is_one(bigint * biexp,int offset)1152 static int exp_bit_is_one(bigint *biexp, int offset)
1153 {
1154     comp test = biexp->comps[offset / COMP_BIT_SIZE];
1155     int num_shifts = offset % COMP_BIT_SIZE;
1156     comp shift = 1;
1157     int i;
1158 
1159     check(biexp);
1160 
1161     for (i = 0; i < num_shifts; i++)
1162     {
1163         shift <<= 1;
1164     }
1165 
1166     return (test & shift) != 0;
1167 }
1168 
1169 #ifdef CONFIG_BIGINT_CHECK_ON
1170 /*
1171  * Perform a sanity check on bi.
1172  */
check(const bigint * bi)1173 static void check(const bigint *bi)
1174 {
1175     if (bi->refs <= 0)
1176     {
1177         printf("check: zero or negative refs in bigint\n");
1178         abort();
1179     }
1180 
1181     if (bi->next != NULL)
1182     {
1183         printf("check: attempt to use a bigint from "
1184                 "the free list\n");
1185         abort();
1186     }
1187 }
1188 #endif
1189 
1190 /*
1191  * Delete any leading 0's (and allow for 0).
1192  */
trim(bigint * bi)1193 static bigint *trim(bigint *bi)
1194 {
1195     check(bi);
1196 
1197     while (bi->comps[bi->size-1] == 0 && bi->size > 1)
1198     {
1199         bi->size--;
1200     }
1201 
1202     return bi;
1203 }
1204 
1205 #if defined(CONFIG_BIGINT_MONTGOMERY)
1206 /**
1207  * @brief Perform a single montgomery reduction.
1208  * @param ctx [in]  The bigint session context.
1209  * @param bixy [in]  A bigint.
1210  * @return The result of the montgomery reduction.
1211  */
bi_mont(BI_CTX * ctx,bigint * bixy)1212 bigint *bi_mont(BI_CTX *ctx, bigint *bixy)
1213 {
1214     int i = 0, n;
1215     uint8_t mod_offset = ctx->mod_offset;
1216     bigint *bim = ctx->bi_mod[mod_offset];
1217     comp mod_inv = ctx->N0_dash[mod_offset];
1218 
1219     check(bixy);
1220 
1221     if (ctx->use_classical)     /* just use classical instead */
1222     {
1223         return bi_mod(ctx, bixy);
1224     }
1225 
1226     n = bim->size;
1227 
1228     do
1229     {
1230         bixy = bi_add(ctx, bixy, comp_left_shift(
1231                     bi_int_multiply(ctx, bim, bixy->comps[i]*mod_inv), i));
1232     } while (++i < n);
1233 
1234     comp_right_shift(bixy, n);
1235 
1236     if (bi_compare(bixy, bim) >= 0)
1237     {
1238         bixy = bi_subtract(ctx, bixy, bim, NULL);
1239     }
1240 
1241     return bixy;
1242 }
1243 
1244 #elif defined(CONFIG_BIGINT_BARRETT)
1245 /*
1246  * Stomp on the most significant components to give the illusion of a "mod base
1247  * radix" operation
1248  */
comp_mod(bigint * bi,int mod)1249 static bigint *comp_mod(bigint *bi, int mod)
1250 {
1251     check(bi);
1252 
1253     if (bi->size > mod)
1254     {
1255         bi->size = mod;
1256     }
1257 
1258     return bi;
1259 }
1260 
1261 /**
1262  * @brief Perform a single Barrett reduction.
1263  * @param ctx [in]  The bigint session context.
1264  * @param bi [in]  A bigint.
1265  * @return The result of the Barrett reduction.
1266  */
bi_barrett(BI_CTX * ctx,bigint * bi)1267 bigint *bi_barrett(BI_CTX *ctx, bigint *bi)
1268 {
1269     bigint *q1, *q2, *q3, *r1, *r2, *r;
1270     uint8_t mod_offset = ctx->mod_offset;
1271     bigint *bim = ctx->bi_mod[mod_offset];
1272     int k = bim->size;
1273 
1274     check(bi);
1275     check(bim);
1276 
1277     /* use Classical method instead  - Barrett cannot help here */
1278     if (bi->size > k*2)
1279     {
1280         return bi_mod(ctx, bi);
1281     }
1282 
1283     q1 = comp_right_shift(bi_clone(ctx, bi), k-1);
1284 
1285     /* do outer partial multiply */
1286     q2 = regular_multiply(ctx, q1, ctx->bi_mu[mod_offset], 0, k-1);
1287     q3 = comp_right_shift(q2, k+1);
1288     r1 = comp_mod(bi, k+1);
1289 
1290     /* do inner partial multiply */
1291     r2 = comp_mod(regular_multiply(ctx, q3, bim, k+1, 0), k+1);
1292     r = bi_subtract(ctx, r1, r2, NULL);
1293 
1294     /* if (r >= m) r = r - m; */
1295     if (bi_compare(r, bim) >= 0)
1296     {
1297         r = bi_subtract(ctx, r, bim, NULL);
1298     }
1299 
1300     return r;
1301 }
1302 #endif /* CONFIG_BIGINT_BARRETT */
1303 
1304 #ifdef CONFIG_BIGINT_SLIDING_WINDOW
1305 /*
1306  * Work out g1, g3, g5, g7... etc for the sliding-window algorithm
1307  */
precompute_slide_window(BI_CTX * ctx,int window,bigint * g1)1308 static void precompute_slide_window(BI_CTX *ctx, int window, bigint *g1)
1309 {
1310     int k = 1, i;
1311     bigint *g2;
1312 
1313     for (i = 0; i < window-1; i++)   /* compute 2^(window-1) */
1314     {
1315         k <<= 1;
1316     }
1317 
1318     ctx->g = (bigint **)malloc(k*sizeof(bigint *));
1319     ctx->g[0] = bi_clone(ctx, g1);
1320     bi_permanent(ctx->g[0]);
1321     g2 = bi_residue(ctx, bi_square(ctx, ctx->g[0]));   /* g^2 */
1322 
1323     for (i = 1; i < k; i++)
1324     {
1325         ctx->g[i] = bi_residue(ctx, bi_multiply(ctx, ctx->g[i-1], bi_copy(g2)));
1326         bi_permanent(ctx->g[i]);
1327     }
1328 
1329     bi_free(ctx, g2);
1330     ctx->window = k;
1331 }
1332 #endif
1333 
1334 /**
1335  * @brief Perform a modular exponentiation.
1336  *
1337  * This function requires bi_set_mod() to have been called previously. This is
1338  * one of the optimisations used for performance.
1339  * @param ctx [in]  The bigint session context.
1340  * @param bi  [in]  The bigint on which to perform the mod power operation.
1341  * @param biexp [in] The bigint exponent.
1342  * @return The result of the mod exponentiation operation
1343  * @see bi_set_mod().
1344  */
bi_mod_power(BI_CTX * ctx,bigint * bi,bigint * biexp)1345 bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp)
1346 {
1347     int i = find_max_exp_index(biexp), j, window_size = 1;
1348     bigint *biR = int_to_bi(ctx, 1);
1349 
1350 #if defined(CONFIG_BIGINT_MONTGOMERY)
1351     uint8_t mod_offset = ctx->mod_offset;
1352     if (!ctx->use_classical)
1353     {
1354         /* preconvert */
1355         bi = bi_mont(ctx,
1356                 bi_multiply(ctx, bi, ctx->bi_RR_mod_m[mod_offset]));    /* x' */
1357         bi_free(ctx, biR);
1358         biR = ctx->bi_R_mod_m[mod_offset];                              /* A */
1359     }
1360 #endif
1361 
1362     check(bi);
1363     check(biexp);
1364 
1365 #ifdef CONFIG_BIGINT_SLIDING_WINDOW
1366     for (j = i; j > 32; j /= 5) /* work out an optimum size */
1367         window_size++;
1368 
1369     /* work out the slide constants */
1370     precompute_slide_window(ctx, window_size, bi);
1371 #else   /* just one constant */
1372     ctx->g = (bigint **)malloc(sizeof(bigint *));
1373     ctx->g[0] = bi_clone(ctx, bi);
1374     ctx->window = 1;
1375     bi_permanent(ctx->g[0]);
1376 #endif
1377 
1378     /* if sliding-window is off, then only one bit will be done at a time and
1379      * will reduce to standard left-to-right exponentiation */
1380     do
1381     {
1382 #ifdef __ets__
1383         void ets_loop_iter(void);
1384         ets_loop_iter();
1385 #endif
1386         if (exp_bit_is_one(biexp, i))
1387         {
1388             int l = i-window_size+1;
1389             int part_exp = 0;
1390 
1391             if (l < 0)  /* LSB of exponent will always be 1 */
1392                 l = 0;
1393             else
1394             {
1395                 while (exp_bit_is_one(biexp, l) == 0)
1396                     l++;    /* go back up */
1397             }
1398 
1399             /* build up the section of the exponent */
1400             for (j = i; j >= l; j--)
1401             {
1402                 biR = bi_residue(ctx, bi_square(ctx, biR));
1403                 if (exp_bit_is_one(biexp, j))
1404                     part_exp++;
1405 
1406                 if (j != l)
1407                     part_exp <<= 1;
1408             }
1409 
1410             part_exp = (part_exp-1)/2;  /* adjust for array */
1411             biR = bi_residue(ctx, bi_multiply(ctx, biR, ctx->g[part_exp]));
1412             i = l-1;
1413         }
1414         else    /* square it */
1415         {
1416             biR = bi_residue(ctx, bi_square(ctx, biR));
1417             i--;
1418         }
1419     } while (i >= 0);
1420 
1421     /* cleanup */
1422     for (i = 0; i < ctx->window; i++)
1423     {
1424         bi_depermanent(ctx->g[i]);
1425         bi_free(ctx, ctx->g[i]);
1426     }
1427 
1428     free(ctx->g);
1429     bi_free(ctx, bi);
1430     bi_free(ctx, biexp);
1431 #if defined CONFIG_BIGINT_MONTGOMERY
1432     return ctx->use_classical ? biR : bi_mont(ctx, biR); /* convert back */
1433 #else /* CONFIG_BIGINT_CLASSICAL or CONFIG_BIGINT_BARRETT */
1434     return biR;
1435 #endif
1436 }
1437 
1438 #ifdef CONFIG_SSL_CERT_VERIFICATION
1439 /**
1440  * @brief Perform a modular exponentiation using a temporary modulus.
1441  *
1442  * We need this function to check the signatures of certificates. The modulus
1443  * of this function is temporary as it's just used for authentication.
1444  * @param ctx [in]  The bigint session context.
1445  * @param bi  [in]  The bigint to perform the exp/mod.
1446  * @param bim [in]  The temporary modulus.
1447  * @param biexp [in] The bigint exponent.
1448  * @return The result of the mod exponentiation operation
1449  * @see bi_set_mod().
1450  */
bi_mod_power2(BI_CTX * ctx,bigint * bi,bigint * bim,bigint * biexp)1451 bigint *bi_mod_power2(BI_CTX *ctx, bigint *bi, bigint *bim, bigint *biexp)
1452 {
1453     bigint *biR, *tmp_biR;
1454 
1455     /* Set up a temporary bigint context and transfer what we need between
1456      * them. We need to do this since we want to keep the original modulus
1457      * which is already in this context. This operation is only called when
1458      * doing peer verification, and so is not expensive :-) */
1459     BI_CTX *tmp_ctx = bi_initialize();
1460     bi_set_mod(tmp_ctx, bi_clone(tmp_ctx, bim), BIGINT_M_OFFSET);
1461     tmp_biR = bi_mod_power(tmp_ctx,
1462                 bi_clone(tmp_ctx, bi),
1463                 bi_clone(tmp_ctx, biexp));
1464     biR = bi_clone(ctx, tmp_biR);
1465     bi_free(tmp_ctx, tmp_biR);
1466     bi_free_mod(tmp_ctx, BIGINT_M_OFFSET);
1467     bi_terminate(tmp_ctx);
1468 
1469     bi_free(ctx, bi);
1470     bi_free(ctx, bim);
1471     bi_free(ctx, biexp);
1472     return biR;
1473 }
1474 #endif
1475 
1476 #ifdef CONFIG_BIGINT_CRT
1477 /**
1478  * @brief Use the Chinese Remainder Theorem to quickly perform RSA decrypts.
1479  *
1480  * @param ctx [in]  The bigint session context.
1481  * @param bi  [in]  The bigint to perform the exp/mod.
1482  * @param dP [in] CRT's dP bigint
1483  * @param dQ [in] CRT's dQ bigint
1484  * @param p [in] CRT's p bigint
1485  * @param q [in] CRT's q bigint
1486  * @param qInv [in] CRT's qInv bigint
1487  * @return The result of the CRT operation
1488  */
bi_crt(BI_CTX * ctx,bigint * bi,bigint * dP,bigint * dQ,bigint * p,bigint * q,bigint * qInv)1489 bigint *bi_crt(BI_CTX *ctx, bigint *bi,
1490         bigint *dP, bigint *dQ,
1491         bigint *p, bigint *q, bigint *qInv)
1492 {
1493     bigint *m1, *m2, *h;
1494 
1495     /* Montgomery has a condition the 0 < x, y < m and these products violate
1496      * that condition. So disable Montgomery when using CRT */
1497 #if defined(CONFIG_BIGINT_MONTGOMERY)
1498     ctx->use_classical = 1;
1499 #endif
1500     ctx->mod_offset = BIGINT_P_OFFSET;
1501     m1 = bi_mod_power(ctx, bi_copy(bi), dP);
1502 
1503     ctx->mod_offset = BIGINT_Q_OFFSET;
1504     m2 = bi_mod_power(ctx, bi, dQ);
1505 
1506     h = bi_subtract(ctx, bi_add(ctx, m1, p), bi_copy(m2), NULL);
1507     h = bi_multiply(ctx, h, qInv);
1508     ctx->mod_offset = BIGINT_P_OFFSET;
1509     h = bi_residue(ctx, h);
1510 #if defined(CONFIG_BIGINT_MONTGOMERY)
1511     ctx->use_classical = 0;         /* reset for any further operation */
1512 #endif
1513     return bi_add(ctx, m2, bi_multiply(ctx, q, h));
1514 }
1515 #endif
1516 /** @} */
1517