Merged silc_1_0_branch to trunk.
[silc.git] / lib / silcmath / tma.c
1 /* Start: bn_error.c */
2 #include "tma.h"
3 #ifdef BN_ERROR_C
4 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5  *
6  * LibTomMath is a library that provides multiple-precision
7  * integer arithmetic as well as number theoretic functionality.
8  *
9  * The library was designed directly after the MPI library by
10  * Michael Fromberger but has been written from scratch with
11  * additional optimizations in place.
12  *
13  * The library is free for all purposes without any express
14  * guarantee it works.
15  *
16  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
17  */
18
19 static const struct {
20      int code;
21      char *msg;
22 } msgs[] = {
23      { MP_OKAY, "Successful" },
24      { MP_MEM,  "Out of heap" },
25      { MP_VAL,  "Value out of range" }
26 };
27
28 /* return a char * string for a given code */
29 char *mp_error_to_string(int code)
30 {
31    int x;
32
33    /* scan the lookup table for the given message */
34    for (x = 0; x < (int)(sizeof(msgs) / sizeof(msgs[0])); x++) {
35        if (msgs[x].code == code) {
36           return msgs[x].msg;
37        }
38    }
39
40    /* generic reply for invalid code */
41    return "Invalid error code";
42 }
43
44 #endif
45
46 /* End: bn_error.c */
47
48 /* Start: bn_fast_mp_invmod.c */
49 #include "tma.h"
50 #ifdef BN_FAST_MP_INVMOD_C
51 /* LibTomMath, multiple-precision integer library -- Tom St Denis
52  *
53  * LibTomMath is a library that provides multiple-precision
54  * integer arithmetic as well as number theoretic functionality.
55  *
56  * The library was designed directly after the MPI library by
57  * Michael Fromberger but has been written from scratch with
58  * additional optimizations in place.
59  *
60  * The library is free for all purposes without any express
61  * guarantee it works.
62  *
63  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
64  */
65
66 /* computes the modular inverse via binary extended euclidean algorithm, 
67  * that is c = 1/a mod b 
68  *
69  * Based on slow invmod except this is optimized for the case where b is 
70  * odd as per HAC Note 14.64 on pp. 610
71  */
72 int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c)
73 {
74   mp_int  x, y, u, v, B, D;
75   int     res, neg;
76
77   /* 2. [modified] b must be odd   */
78   if (mp_iseven (b) == 1) {
79     return MP_VAL;
80   }
81
82   /* init all our temps */
83   if ((res = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) {
84      return res;
85   }
86
87   /* x == modulus, y == value to invert */
88   if ((res = mp_copy (b, &x)) != MP_OKAY) {
89     goto LBL_ERR;
90   }
91
92   /* we need y = |a| */
93   if ((res = mp_mod (a, b, &y)) != MP_OKAY) {
94     goto LBL_ERR;
95   }
96
97   /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
98   if ((res = mp_copy (&x, &u)) != MP_OKAY) {
99     goto LBL_ERR;
100   }
101   if ((res = mp_copy (&y, &v)) != MP_OKAY) {
102     goto LBL_ERR;
103   }
104   mp_set (&D, 1);
105
106 top:
107   /* 4.  while u is even do */
108   while (mp_iseven (&u) == 1) {
109     /* 4.1 u = u/2 */
110     if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
111       goto LBL_ERR;
112     }
113     /* 4.2 if B is odd then */
114     if (mp_isodd (&B) == 1) {
115       if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
116         goto LBL_ERR;
117       }
118     }
119     /* B = B/2 */
120     if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
121       goto LBL_ERR;
122     }
123   }
124
125   /* 5.  while v is even do */
126   while (mp_iseven (&v) == 1) {
127     /* 5.1 v = v/2 */
128     if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
129       goto LBL_ERR;
130     }
131     /* 5.2 if D is odd then */
132     if (mp_isodd (&D) == 1) {
133       /* D = (D-x)/2 */
134       if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
135         goto LBL_ERR;
136       }
137     }
138     /* D = D/2 */
139     if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
140       goto LBL_ERR;
141     }
142   }
143
144   /* 6.  if u >= v then */
145   if (mp_cmp (&u, &v) != MP_LT) {
146     /* u = u - v, B = B - D */
147     if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
148       goto LBL_ERR;
149     }
150
151     if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
152       goto LBL_ERR;
153     }
154   } else {
155     /* v - v - u, D = D - B */
156     if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
157       goto LBL_ERR;
158     }
159
160     if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
161       goto LBL_ERR;
162     }
163   }
164
165   /* if not zero goto step 4 */
166   if (mp_iszero (&u) == 0) {
167     goto top;
168   }
169
170   /* now a = C, b = D, gcd == g*v */
171
172   /* if v != 1 then there is no inverse */
173   if (mp_cmp_d (&v, 1) != MP_EQ) {
174     res = MP_VAL;
175     goto LBL_ERR;
176   }
177
178   /* b is now the inverse */
179   neg = a->sign;
180   while (D.sign == MP_NEG) {
181     if ((res = mp_add (&D, b, &D)) != MP_OKAY) {
182       goto LBL_ERR;
183     }
184   }
185   mp_exch (&D, c);
186   c->sign = neg;
187   res = MP_OKAY;
188
189 LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &B, &D, NULL);
190   return res;
191 }
192 #endif
193
194 /* End: bn_fast_mp_invmod.c */
195
196 /* Start: bn_fast_mp_montgomery_reduce.c */
197 #include "tma.h"
198 #ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
199 /* LibTomMath, multiple-precision integer library -- Tom St Denis
200  *
201  * LibTomMath is a library that provides multiple-precision
202  * integer arithmetic as well as number theoretic functionality.
203  *
204  * The library was designed directly after the MPI library by
205  * Michael Fromberger but has been written from scratch with
206  * additional optimizations in place.
207  *
208  * The library is free for all purposes without any express
209  * guarantee it works.
210  *
211  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
212  */
213
214 /* computes xR**-1 == x (mod N) via Montgomery Reduction
215  *
216  * This is an optimized implementation of montgomery_reduce
217  * which uses the comba method to quickly calculate the columns of the
218  * reduction.
219  *
220  * Based on Algorithm 14.32 on pp.601 of HAC.
221 */
222 int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
223 {
224   int     ix, res, olduse;
225   mp_word W[MP_WARRAY];
226
227   /* get old used count */
228   olduse = x->used;
229
230   /* grow a as required */
231   if (x->alloc < n->used + 1) {
232     if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) {
233       return res;
234     }
235   }
236
237   /* first we have to get the digits of the input into
238    * an array of double precision words W[...]
239    */
240   {
241     register mp_word *_W;
242     register mp_digit *tmpx;
243
244     /* alias for the W[] array */
245     _W   = W;
246
247     /* alias for the digits of  x*/
248     tmpx = x->dp;
249
250     /* copy the digits of a into W[0..a->used-1] */
251     for (ix = 0; ix < x->used; ix++) {
252       *_W++ = *tmpx++;
253     }
254
255     /* zero the high words of W[a->used..m->used*2] */
256     for (; ix < n->used * 2 + 1; ix++) {
257       *_W++ = 0;
258     }
259   }
260
261   /* now we proceed to zero successive digits
262    * from the least significant upwards
263    */
264   for (ix = 0; ix < n->used; ix++) {
265     /* mu = ai * m' mod b
266      *
267      * We avoid a double precision multiplication (which isn't required)
268      * by casting the value down to a mp_digit.  Note this requires
269      * that W[ix-1] have  the carry cleared (see after the inner loop)
270      */
271     register mp_digit mu;
272     mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK);
273
274     /* a = a + mu * m * b**i
275      *
276      * This is computed in place and on the fly.  The multiplication
277      * by b**i is handled by offseting which columns the results
278      * are added to.
279      *
280      * Note the comba method normally doesn't handle carries in the
281      * inner loop In this case we fix the carry from the previous
282      * column since the Montgomery reduction requires digits of the
283      * result (so far) [see above] to work.  This is
284      * handled by fixing up one carry after the inner loop.  The
285      * carry fixups are done in order so after these loops the
286      * first m->used words of W[] have the carries fixed
287      */
288     {
289       register int iy;
290       register mp_digit *tmpn;
291       register mp_word *_W;
292
293       /* alias for the digits of the modulus */
294       tmpn = n->dp;
295
296       /* Alias for the columns set by an offset of ix */
297       _W = W + ix;
298
299       /* inner loop */
300       for (iy = 0; iy < n->used; iy++) {
301           *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++);
302       }
303     }
304
305     /* now fix carry for next digit, W[ix+1] */
306     W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT);
307   }
308
309   /* now we have to propagate the carries and
310    * shift the words downward [all those least
311    * significant digits we zeroed].
312    */
313   {
314     register mp_digit *tmpx;
315     register mp_word *_W, *_W1;
316
317     /* nox fix rest of carries */
318
319     /* alias for current word */
320     _W1 = W + ix;
321
322     /* alias for next word, where the carry goes */
323     _W = W + ++ix;
324
325     for (; ix <= n->used * 2 + 1; ix++) {
326       *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT);
327     }
328
329     /* copy out, A = A/b**n
330      *
331      * The result is A/b**n but instead of converting from an
332      * array of mp_word to mp_digit than calling mp_rshd
333      * we just copy them in the right order
334      */
335
336     /* alias for destination word */
337     tmpx = x->dp;
338
339     /* alias for shifted double precision result */
340     _W = W + n->used;
341
342     for (ix = 0; ix < n->used + 1; ix++) {
343       *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK));
344     }
345
346     /* zero oldused digits, if the input a was larger than
347      * m->used+1 we'll have to clear the digits
348      */
349     for (; ix < olduse; ix++) {
350       *tmpx++ = 0;
351     }
352   }
353
354   /* set the max used and clamp */
355   x->used = n->used + 1;
356   mp_clamp (x);
357
358   /* if A >= m then A = A - m */
359   if (mp_cmp_mag (x, n) != MP_LT) {
360     return s_mp_sub (x, n, x);
361   }
362   return MP_OKAY;
363 }
364 #endif
365
366 /* End: bn_fast_mp_montgomery_reduce.c */
367
368 /* Start: bn_fast_s_mp_mul_digs.c */
369 #include "tma.h"
370 #ifdef BN_FAST_S_MP_MUL_DIGS_C
371 /* LibTomMath, multiple-precision integer library -- Tom St Denis
372  *
373  * LibTomMath is a library that provides multiple-precision
374  * integer arithmetic as well as number theoretic functionality.
375  *
376  * The library was designed directly after the MPI library by
377  * Michael Fromberger but has been written from scratch with
378  * additional optimizations in place.
379  *
380  * The library is free for all purposes without any express
381  * guarantee it works.
382  *
383  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
384  */
385
386 /* Fast (comba) multiplier
387  *
388  * This is the fast column-array [comba] multiplier.  It is 
389  * designed to compute the columns of the product first 
390  * then handle the carries afterwards.  This has the effect 
391  * of making the nested loops that compute the columns very
392  * simple and schedulable on super-scalar processors.
393  *
394  * This has been modified to produce a variable number of 
395  * digits of output so if say only a half-product is required 
396  * you don't have to compute the upper half (a feature 
397  * required for fast Barrett reduction).
398  *
399  * Based on Algorithm 14.12 on pp.595 of HAC.
400  *
401  */
402 int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
403 {
404   int     olduse, res, pa, ix, iz;
405   mp_digit W[MP_WARRAY];
406   register mp_word  _W;
407
408   /* grow the destination as required */
409   if (c->alloc < digs) {
410     if ((res = mp_grow (c, digs)) != MP_OKAY) {
411       return res;
412     }
413   }
414
415   /* number of output digits to produce */
416   pa = MIN(digs, a->used + b->used);
417
418   /* clear the carry */
419   _W = 0;
420   for (ix = 0; ix < pa; ix++) { 
421       int      tx, ty;
422       int      iy;
423       mp_digit *tmpx, *tmpy;
424
425       /* get offsets into the two bignums */
426       ty = MIN(b->used-1, ix);
427       tx = ix - ty;
428
429       /* setup temp aliases */
430       tmpx = a->dp + tx;
431       tmpy = b->dp + ty;
432
433       /* this is the number of times the loop will iterrate, essentially 
434          while (tx++ < a->used && ty-- >= 0) { ... }
435        */
436       iy = MIN(a->used-tx, ty+1);
437
438       /* execute loop */
439       for (iz = 0; iz < iy; ++iz) {
440          _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
441       }
442
443       /* store term */
444       W[ix] = ((mp_digit)_W) & MP_MASK;
445
446       /* make next carry */
447       _W = _W >> ((mp_word)DIGIT_BIT);
448   }
449
450   /* store final carry */
451   W[ix] = (mp_digit)(_W & MP_MASK);
452
453   /* setup dest */
454   olduse  = c->used;
455   c->used = pa;
456
457   {
458     register mp_digit *tmpc;
459     tmpc = c->dp;
460     for (ix = 0; ix < pa+1; ix++) {
461       /* now extract the previous digit [below the carry] */
462       *tmpc++ = W[ix];
463     }
464
465     /* clear unused digits [that existed in the old copy of c] */
466     for (; ix < olduse; ix++) {
467       *tmpc++ = 0;
468     }
469   }
470   mp_clamp (c);
471   return MP_OKAY;
472 }
473 #endif
474
475 /* End: bn_fast_s_mp_mul_digs.c */
476
477 /* Start: bn_fast_s_mp_mul_high_digs.c */
478 #include "tma.h"
479 #ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
480 /* LibTomMath, multiple-precision integer library -- Tom St Denis
481  *
482  * LibTomMath is a library that provides multiple-precision
483  * integer arithmetic as well as number theoretic functionality.
484  *
485  * The library was designed directly after the MPI library by
486  * Michael Fromberger but has been written from scratch with
487  * additional optimizations in place.
488  *
489  * The library is free for all purposes without any express
490  * guarantee it works.
491  *
492  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
493  */
494
495 /* this is a modified version of fast_s_mul_digs that only produces
496  * output digits *above* digs.  See the comments for fast_s_mul_digs
497  * to see how it works.
498  *
499  * This is used in the Barrett reduction since for one of the multiplications
500  * only the higher digits were needed.  This essentially halves the work.
501  *
502  * Based on Algorithm 14.12 on pp.595 of HAC.
503  */
504 int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
505 {
506   int     olduse, res, pa, ix, iz;
507   mp_digit W[MP_WARRAY];
508   mp_word  _W;
509
510   /* grow the destination as required */
511   pa = a->used + b->used;
512   if (c->alloc < pa) {
513     if ((res = mp_grow (c, pa)) != MP_OKAY) {
514       return res;
515     }
516   }
517
518   /* number of output digits to produce */
519   pa = a->used + b->used;
520   _W = 0;
521   for (ix = digs; ix < pa; ix++) { 
522       int      tx, ty, iy;
523       mp_digit *tmpx, *tmpy;
524
525       /* get offsets into the two bignums */
526       ty = MIN(b->used-1, ix);
527       tx = ix - ty;
528
529       /* setup temp aliases */
530       tmpx = a->dp + tx;
531       tmpy = b->dp + ty;
532
533       /* this is the number of times the loop will iterrate, essentially its 
534          while (tx++ < a->used && ty-- >= 0) { ... }
535        */
536       iy = MIN(a->used-tx, ty+1);
537
538       /* execute loop */
539       for (iz = 0; iz < iy; iz++) {
540          _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
541       }
542
543       /* store term */
544       W[ix] = ((mp_digit)_W) & MP_MASK;
545
546       /* make next carry */
547       _W = _W >> ((mp_word)DIGIT_BIT);
548   }
549   
550   /* store final carry */
551   W[ix] = (mp_digit)(_W & MP_MASK);
552
553   /* setup dest */
554   olduse  = c->used;
555   c->used = pa;
556
557   {
558     register mp_digit *tmpc;
559
560     tmpc = c->dp + digs;
561     for (ix = digs; ix <= pa; ix++) {
562       /* now extract the previous digit [below the carry] */
563       *tmpc++ = W[ix];
564     }
565
566     /* clear unused digits [that existed in the old copy of c] */
567     for (; ix < olduse; ix++) {
568       *tmpc++ = 0;
569     }
570   }
571   mp_clamp (c);
572   return MP_OKAY;
573 }
574 #endif
575
576 /* End: bn_fast_s_mp_mul_high_digs.c */
577
578 /* Start: bn_fast_s_mp_sqr.c */
579 #include "tma.h"
580 #ifdef BN_FAST_S_MP_SQR_C
581 /* LibTomMath, multiple-precision integer library -- Tom St Denis
582  *
583  * LibTomMath is a library that provides multiple-precision
584  * integer arithmetic as well as number theoretic functionality.
585  *
586  * The library was designed directly after the MPI library by
587  * Michael Fromberger but has been written from scratch with
588  * additional optimizations in place.
589  *
590  * The library is free for all purposes without any express
591  * guarantee it works.
592  *
593  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
594  */
595
596 /* the jist of squaring...
597  * you do like mult except the offset of the tmpx [one that 
598  * starts closer to zero] can't equal the offset of tmpy.  
599  * So basically you set up iy like before then you min it with
600  * (ty-tx) so that it never happens.  You double all those 
601  * you add in the inner loop
602
603 After that loop you do the squares and add them in.
604 */
605
606 int fast_s_mp_sqr (mp_int * a, mp_int * b)
607 {
608   int       olduse, res, pa, ix, iz;
609   mp_digit   W[MP_WARRAY], *tmpx;
610   mp_word   W1;
611
612   /* grow the destination as required */
613   pa = a->used + a->used;
614   if (b->alloc < pa) {
615     if ((res = mp_grow (b, pa)) != MP_OKAY) {
616       return res;
617     }
618   }
619
620   /* number of output digits to produce */
621   W1 = 0;
622   for (ix = 0; ix < pa; ix++) { 
623       int      tx, ty, iy;
624       mp_word  _W;
625       mp_digit *tmpy;
626
627       /* clear counter */
628       _W = 0;
629
630       /* get offsets into the two bignums */
631       ty = MIN(a->used-1, ix);
632       tx = ix - ty;
633
634       /* setup temp aliases */
635       tmpx = a->dp + tx;
636       tmpy = a->dp + ty;
637
638       /* this is the number of times the loop will iterrate, essentially
639          while (tx++ < a->used && ty-- >= 0) { ... }
640        */
641       iy = MIN(a->used-tx, ty+1);
642
643       /* now for squaring tx can never equal ty 
644        * we halve the distance since they approach at a rate of 2x
645        * and we have to round because odd cases need to be executed
646        */
647       iy = MIN(iy, (ty-tx+1)>>1);
648
649       /* execute loop */
650       for (iz = 0; iz < iy; iz++) {
651          _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
652       }
653
654       /* double the inner product and add carry */
655       _W = _W + _W + W1;
656
657       /* even columns have the square term in them */
658       if ((ix&1) == 0) {
659          _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]);
660       }
661
662       /* store it */
663       W[ix] = (mp_digit)(_W & MP_MASK);
664
665       /* make next carry */
666       W1 = _W >> ((mp_word)DIGIT_BIT);
667   }
668
669   /* setup dest */
670   olduse  = b->used;
671   b->used = a->used+a->used;
672
673   {
674     mp_digit *tmpb;
675     tmpb = b->dp;
676     for (ix = 0; ix < pa; ix++) {
677       *tmpb++ = W[ix] & MP_MASK;
678     }
679
680     /* clear unused digits [that existed in the old copy of c] */
681     for (; ix < olduse; ix++) {
682       *tmpb++ = 0;
683     }
684   }
685   mp_clamp (b);
686   return MP_OKAY;
687 }
688 #endif
689
690 /* End: bn_fast_s_mp_sqr.c */
691
692 /* Start: bn_mp_2expt.c */
693 #include "tma.h"
694 #ifdef BN_MP_2EXPT_C
695 /* LibTomMath, multiple-precision integer library -- Tom St Denis
696  *
697  * LibTomMath is a library that provides multiple-precision
698  * integer arithmetic as well as number theoretic functionality.
699  *
700  * The library was designed directly after the MPI library by
701  * Michael Fromberger but has been written from scratch with
702  * additional optimizations in place.
703  *
704  * The library is free for all purposes without any express
705  * guarantee it works.
706  *
707  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
708  */
709
710 /* computes a = 2**b 
711  *
712  * Simple algorithm which zeroes the int, grows it then just sets one bit
713  * as required.
714  */
715 int
716 mp_2expt (mp_int * a, int b)
717 {
718   int     res;
719
720   /* zero a as per default */
721   mp_zero (a);
722
723   /* grow a to accomodate the single bit */
724   if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) {
725     return res;
726   }
727
728   /* set the used count of where the bit will go */
729   a->used = b / DIGIT_BIT + 1;
730
731   /* put the single bit in its place */
732   a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT);
733
734   return MP_OKAY;
735 }
736 #endif
737
738 /* End: bn_mp_2expt.c */
739
740 /* Start: bn_mp_abs.c */
741 #include "tma.h"
742 #ifdef BN_MP_ABS_C
743 /* LibTomMath, multiple-precision integer library -- Tom St Denis
744  *
745  * LibTomMath is a library that provides multiple-precision
746  * integer arithmetic as well as number theoretic functionality.
747  *
748  * The library was designed directly after the MPI library by
749  * Michael Fromberger but has been written from scratch with
750  * additional optimizations in place.
751  *
752  * The library is free for all purposes without any express
753  * guarantee it works.
754  *
755  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
756  */
757
758 /* b = |a| 
759  *
760  * Simple function copies the input and fixes the sign to positive
761  */
762 int
763 mp_abs (mp_int * a, mp_int * b)
764 {
765   int     res;
766
767   /* copy a to b */
768   if (a != b) {
769      if ((res = mp_copy (a, b)) != MP_OKAY) {
770        return res;
771      }
772   }
773
774   /* force the sign of b to positive */
775   b->sign = MP_ZPOS;
776
777   return MP_OKAY;
778 }
779 #endif
780
781 /* End: bn_mp_abs.c */
782
783 /* Start: bn_mp_add.c */
784 #include "tma.h"
785 #ifdef BN_MP_ADD_C
786 /* LibTomMath, multiple-precision integer library -- Tom St Denis
787  *
788  * LibTomMath is a library that provides multiple-precision
789  * integer arithmetic as well as number theoretic functionality.
790  *
791  * The library was designed directly after the MPI library by
792  * Michael Fromberger but has been written from scratch with
793  * additional optimizations in place.
794  *
795  * The library is free for all purposes without any express
796  * guarantee it works.
797  *
798  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
799  */
800
801 /* high level addition (handles signs) */
802 int mp_add (mp_int * a, mp_int * b, mp_int * c)
803 {
804   int     sa, sb, res;
805
806   /* get sign of both inputs */
807   sa = a->sign;
808   sb = b->sign;
809
810   /* handle two cases, not four */
811   if (sa == sb) {
812     /* both positive or both negative */
813     /* add their magnitudes, copy the sign */
814     c->sign = sa;
815     res = s_mp_add (a, b, c);
816   } else {
817     /* one positive, the other negative */
818     /* subtract the one with the greater magnitude from */
819     /* the one of the lesser magnitude.  The result gets */
820     /* the sign of the one with the greater magnitude. */
821     if (mp_cmp_mag (a, b) == MP_LT) {
822       c->sign = sb;
823       res = s_mp_sub (b, a, c);
824     } else {
825       c->sign = sa;
826       res = s_mp_sub (a, b, c);
827     }
828   }
829   return res;
830 }
831
832 #endif
833
834 /* End: bn_mp_add.c */
835
836 /* Start: bn_mp_add_d.c */
837 #include "tma.h"
838 #ifdef BN_MP_ADD_D_C
839 /* LibTomMath, multiple-precision integer library -- Tom St Denis
840  *
841  * LibTomMath is a library that provides multiple-precision
842  * integer arithmetic as well as number theoretic functionality.
843  *
844  * The library was designed directly after the MPI library by
845  * Michael Fromberger but has been written from scratch with
846  * additional optimizations in place.
847  *
848  * The library is free for all purposes without any express
849  * guarantee it works.
850  *
851  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
852  */
853
854 /* single digit addition */
855 int
856 mp_add_d (mp_int * a, mp_digit b, mp_int * c)
857 {
858   int     res, ix, oldused;
859   mp_digit *tmpa, *tmpc, mu;
860
861   /* grow c as required */
862   if (c->alloc < a->used + 1) {
863      if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
864         return res;
865      }
866   }
867
868   /* if a is negative and |a| >= b, call c = |a| - b */
869   if (a->sign == MP_NEG && (a->used > 1 || a->dp[0] >= b)) {
870      /* temporarily fix sign of a */
871      a->sign = MP_ZPOS;
872
873      /* c = |a| - b */
874      res = mp_sub_d(a, b, c);
875
876      /* fix sign  */
877      a->sign = c->sign = MP_NEG;
878
879      return res;
880   }
881
882   /* old number of used digits in c */
883   oldused = c->used;
884
885   /* sign always positive */
886   c->sign = MP_ZPOS;
887
888   /* source alias */
889   tmpa    = a->dp;
890
891   /* destination alias */
892   tmpc    = c->dp;
893
894   /* if a is positive */
895   if (a->sign == MP_ZPOS) {
896      /* add digit, after this we're propagating
897       * the carry.
898       */
899      *tmpc   = *tmpa++ + b;
900      mu      = *tmpc >> DIGIT_BIT;
901      *tmpc++ &= MP_MASK;
902
903      /* now handle rest of the digits */
904      for (ix = 1; ix < a->used; ix++) {
905         *tmpc   = *tmpa++ + mu;
906         mu      = *tmpc >> DIGIT_BIT;
907         *tmpc++ &= MP_MASK;
908      }
909      /* set final carry */
910      ix++;
911      *tmpc++  = mu;
912
913      /* setup size */
914      c->used = a->used + 1;
915   } else {
916      /* a was negative and |a| < b */
917      c->used  = 1;
918
919      /* the result is a single digit */
920      if (a->used == 1) {
921         *tmpc++  =  b - a->dp[0];
922      } else {
923         *tmpc++  =  b;
924      }
925
926      /* setup count so the clearing of oldused
927       * can fall through correctly
928       */
929      ix       = 1;
930   }
931
932   /* now zero to oldused */
933   while (ix++ < oldused) {
934      *tmpc++ = 0;
935   }
936   mp_clamp(c);
937
938   return MP_OKAY;
939 }
940
941 #endif
942
943 /* End: bn_mp_add_d.c */
944
945 /* Start: bn_mp_addmod.c */
946 #include "tma.h"
947 #ifdef BN_MP_ADDMOD_C
948 /* LibTomMath, multiple-precision integer library -- Tom St Denis
949  *
950  * LibTomMath is a library that provides multiple-precision
951  * integer arithmetic as well as number theoretic functionality.
952  *
953  * The library was designed directly after the MPI library by
954  * Michael Fromberger but has been written from scratch with
955  * additional optimizations in place.
956  *
957  * The library is free for all purposes without any express
958  * guarantee it works.
959  *
960  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
961  */
962
963 /* d = a + b (mod c) */
964 int
965 mp_addmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
966 {
967   int     res;
968   mp_int  t;
969
970   if ((res = mp_init (&t)) != MP_OKAY) {
971     return res;
972   }
973
974   if ((res = mp_add (a, b, &t)) != MP_OKAY) {
975     mp_clear (&t);
976     return res;
977   }
978   res = mp_mod (&t, c, d);
979   mp_clear (&t);
980   return res;
981 }
982 #endif
983
984 /* End: bn_mp_addmod.c */
985
986 /* Start: bn_mp_and.c */
987 #include "tma.h"
988 #ifdef BN_MP_AND_C
989 /* LibTomMath, multiple-precision integer library -- Tom St Denis
990  *
991  * LibTomMath is a library that provides multiple-precision
992  * integer arithmetic as well as number theoretic functionality.
993  *
994  * The library was designed directly after the MPI library by
995  * Michael Fromberger but has been written from scratch with
996  * additional optimizations in place.
997  *
998  * The library is free for all purposes without any express
999  * guarantee it works.
1000  *
1001  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
1002  */
1003
1004 /* AND two ints together */
1005 int
1006 mp_and (mp_int * a, mp_int * b, mp_int * c)
1007 {
1008   int     res, ix, px;
1009   mp_int  t, *x;
1010
1011   if (a->used > b->used) {
1012     if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
1013       return res;
1014     }
1015     px = b->used;
1016     x = b;
1017   } else {
1018     if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
1019       return res;
1020     }
1021     px = a->used;
1022     x = a;
1023   }
1024
1025   for (ix = 0; ix < px; ix++) {
1026     t.dp[ix] &= x->dp[ix];
1027   }
1028
1029   /* zero digits above the last from the smallest mp_int */
1030   for (; ix < t.used; ix++) {
1031     t.dp[ix] = 0;
1032   }
1033
1034   mp_clamp (&t);
1035   mp_exch (c, &t);
1036   mp_clear (&t);
1037   return MP_OKAY;
1038 }
1039 #endif
1040
1041 /* End: bn_mp_and.c */
1042
1043 /* Start: bn_mp_clamp.c */
1044 #include "tma.h"
1045 #ifdef BN_MP_CLAMP_C
1046 /* LibTomMath, multiple-precision integer library -- Tom St Denis
1047  *
1048  * LibTomMath is a library that provides multiple-precision
1049  * integer arithmetic as well as number theoretic functionality.
1050  *
1051  * The library was designed directly after the MPI library by
1052  * Michael Fromberger but has been written from scratch with
1053  * additional optimizations in place.
1054  *
1055  * The library is free for all purposes without any express
1056  * guarantee it works.
1057  *
1058  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
1059  */
1060
1061 /* trim unused digits 
1062  *
1063  * This is used to ensure that leading zero digits are
1064  * trimed and the leading "used" digit will be non-zero
1065  * Typically very fast.  Also fixes the sign if there
1066  * are no more leading digits
1067  */
1068 void
1069 mp_clamp (mp_int * a)
1070 {
1071   /* decrease used while the most significant digit is
1072    * zero.
1073    */
1074   while (a->used > 0 && a->dp[a->used - 1] == 0) {
1075     --(a->used);
1076   }
1077
1078   /* reset the sign flag if used == 0 */
1079   if (a->used == 0) {
1080     a->sign = MP_ZPOS;
1081   }
1082 }
1083 #endif
1084
1085 /* End: bn_mp_clamp.c */
1086
1087 /* Start: bn_mp_clear.c */
1088 #include "tma.h"
1089 #ifdef BN_MP_CLEAR_C
1090 /* LibTomMath, multiple-precision integer library -- Tom St Denis
1091  *
1092  * LibTomMath is a library that provides multiple-precision
1093  * integer arithmetic as well as number theoretic functionality.
1094  *
1095  * The library was designed directly after the MPI library by
1096  * Michael Fromberger but has been written from scratch with
1097  * additional optimizations in place.
1098  *
1099  * The library is free for all purposes without any express
1100  * guarantee it works.
1101  *
1102  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
1103  */
1104
1105 /* clear one (frees)  */
1106 void
1107 mp_clear (mp_int * a)
1108 {
1109   int i;
1110
1111   /* only do anything if a hasn't been freed previously */
1112   if (a->dp != NULL) {
1113     /* first zero the digits */
1114     for (i = 0; i < a->used; i++) {
1115         a->dp[i] = 0;
1116     }
1117
1118     /* free ram */
1119     XFREE(a->dp);
1120
1121     /* reset members to make debugging easier */
1122     a->dp    = NULL;
1123     a->alloc = a->used = 0;
1124     a->sign  = MP_ZPOS;
1125   }
1126 }
1127 #endif
1128
1129 /* End: bn_mp_clear.c */
1130
1131 /* Start: bn_mp_clear_multi.c */
1132 #include "tma.h"
1133 #ifdef BN_MP_CLEAR_MULTI_C
1134 /* LibTomMath, multiple-precision integer library -- Tom St Denis
1135  *
1136  * LibTomMath is a library that provides multiple-precision
1137  * integer arithmetic as well as number theoretic functionality.
1138  *
1139  * The library was designed directly after the MPI library by
1140  * Michael Fromberger but has been written from scratch with
1141  * additional optimizations in place.
1142  *
1143  * The library is free for all purposes without any express
1144  * guarantee it works.
1145  *
1146  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
1147  */
1148 #include <stdarg.h>
1149
1150 void mp_clear_multi(mp_int *mp, ...) 
1151 {
1152     mp_int* next_mp = mp;
1153     va_list args;
1154     va_start(args, mp);
1155     while (next_mp != NULL) {
1156         mp_clear(next_mp);
1157         next_mp = va_arg(args, mp_int*);
1158     }
1159     va_end(args);
1160 }
1161 #endif
1162
1163 /* End: bn_mp_clear_multi.c */
1164
1165 /* Start: bn_mp_cmp.c */
1166 #include "tma.h"
1167 #ifdef BN_MP_CMP_C
1168 /* LibTomMath, multiple-precision integer library -- Tom St Denis
1169  *
1170  * LibTomMath is a library that provides multiple-precision
1171  * integer arithmetic as well as number theoretic functionality.
1172  *
1173  * The library was designed directly after the MPI library by
1174  * Michael Fromberger but has been written from scratch with
1175  * additional optimizations in place.
1176  *
1177  * The library is free for all purposes without any express
1178  * guarantee it works.
1179  *
1180  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
1181  */
1182
1183 /* compare two ints (signed)*/
1184 int
1185 mp_cmp (mp_int * a, mp_int * b)
1186 {
1187   /* compare based on sign */
1188   if (a->sign != b->sign) {
1189      if (a->sign == MP_NEG) {
1190         return MP_LT;
1191      } else {
1192         return MP_GT;
1193      }
1194   }
1195   
1196   /* compare digits */
1197   if (a->sign == MP_NEG) {
1198      /* if negative compare opposite direction */
1199      return mp_cmp_mag(b, a);
1200   } else {
1201      return mp_cmp_mag(a, b);
1202   }
1203 }
1204 #endif
1205
1206 /* End: bn_mp_cmp.c */
1207
1208 /* Start: bn_mp_cmp_d.c */
1209 #include "tma.h"
1210 #ifdef BN_MP_CMP_D_C
1211 /* LibTomMath, multiple-precision integer library -- Tom St Denis
1212  *
1213  * LibTomMath is a library that provides multiple-precision
1214  * integer arithmetic as well as number theoretic functionality.
1215  *
1216  * The library was designed directly after the MPI library by
1217  * Michael Fromberger but has been written from scratch with
1218  * additional optimizations in place.
1219  *
1220  * The library is free for all purposes without any express
1221  * guarantee it works.
1222  *
1223  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
1224  */
1225
1226 /* compare a digit */
1227 int mp_cmp_d(mp_int * a, mp_digit b)
1228 {
1229   /* compare based on sign */
1230   if (a->sign == MP_NEG) {
1231     return MP_LT;
1232   }
1233
1234   /* compare based on magnitude */
1235   if (a->used > 1) {
1236     return MP_GT;
1237   }
1238
1239   /* compare the only digit of a to b */
1240   if (a->dp[0] > b) {
1241     return MP_GT;
1242   } else if (a->dp[0] < b) {
1243     return MP_LT;
1244   } else {
1245     return MP_EQ;
1246   }
1247 }
1248 #endif
1249
1250 /* End: bn_mp_cmp_d.c */
1251
1252 /* Start: bn_mp_cmp_mag.c */
1253 #include "tma.h"
1254 #ifdef BN_MP_CMP_MAG_C
1255 /* LibTomMath, multiple-precision integer library -- Tom St Denis
1256  *
1257  * LibTomMath is a library that provides multiple-precision
1258  * integer arithmetic as well as number theoretic functionality.
1259  *
1260  * The library was designed directly after the MPI library by
1261  * Michael Fromberger but has been written from scratch with
1262  * additional optimizations in place.
1263  *
1264  * The library is free for all purposes without any express
1265  * guarantee it works.
1266  *
1267  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
1268  */
1269
1270 /* compare maginitude of two ints (unsigned) */
1271 int mp_cmp_mag (mp_int * a, mp_int * b)
1272 {
1273   int     n;
1274   mp_digit *tmpa, *tmpb;
1275
1276   /* compare based on # of non-zero digits */
1277   if (a->used > b->used) {
1278     return MP_GT;
1279   }
1280   
1281   if (a->used < b->used) {
1282     return MP_LT;
1283   }
1284
1285   /* alias for a */
1286   tmpa = a->dp + (a->used - 1);
1287
1288   /* alias for b */
1289   tmpb = b->dp + (a->used - 1);
1290
1291   /* compare based on digits  */
1292   for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
1293     if (*tmpa > *tmpb) {
1294       return MP_GT;
1295     }
1296
1297     if (*tmpa < *tmpb) {
1298       return MP_LT;
1299     }
1300   }
1301   return MP_EQ;
1302 }
1303 #endif
1304
1305 /* End: bn_mp_cmp_mag.c */
1306
1307 /* Start: bn_mp_cnt_lsb.c */
1308 #include "tma.h"
1309 #ifdef BN_MP_CNT_LSB_C
1310 /* LibTomMath, multiple-precision integer library -- Tom St Denis
1311  *
1312  * LibTomMath is a library that provides multiple-precision
1313  * integer arithmetic as well as number theoretic functionality.
1314  *
1315  * The library was designed directly after the MPI library by
1316  * Michael Fromberger but has been written from scratch with
1317  * additional optimizations in place.
1318  *
1319  * The library is free for all purposes without any express
1320  * guarantee it works.
1321  *
1322  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
1323  */
1324
1325 static const int lnz[16] = { 
1326    4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
1327 };
1328
1329 /* Counts the number of lsbs which are zero before the first zero bit */
1330 int mp_cnt_lsb(mp_int *a)
1331 {
1332    int x;
1333    mp_digit q, qq;
1334
1335    /* easy out */
1336    if (mp_iszero(a) == 1) {
1337       return 0;
1338    }
1339
1340    /* scan lower digits until non-zero */
1341    for (x = 0; x < a->used && a->dp[x] == 0; x++);
1342    q = a->dp[x];
1343    x *= DIGIT_BIT;
1344
1345    /* now scan this digit until a 1 is found */
1346    if ((q & 1) == 0) {
1347       do {
1348          qq  = q & 15;
1349          x  += lnz[qq];
1350          q >>= 4;
1351       } while (qq == 0);
1352    }
1353    return x;
1354 }
1355
1356 #endif
1357
1358 /* End: bn_mp_cnt_lsb.c */
1359
1360 /* Start: bn_mp_copy.c */
1361 #include "tma.h"
1362 #ifdef BN_MP_COPY_C
1363 /* LibTomMath, multiple-precision integer library -- Tom St Denis
1364  *
1365  * LibTomMath is a library that provides multiple-precision
1366  * integer arithmetic as well as number theoretic functionality.
1367  *
1368  * The library was designed directly after the MPI library by
1369  * Michael Fromberger but has been written from scratch with
1370  * additional optimizations in place.
1371  *
1372  * The library is free for all purposes without any express
1373  * guarantee it works.
1374  *
1375  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
1376  */
1377
1378 /* copy, b = a */
1379 int
1380 mp_copy (mp_int * a, mp_int * b)
1381 {
1382   int     res, n;
1383
1384   /* if dst == src do nothing */
1385   if (a == b) {
1386     return MP_OKAY;
1387   }
1388
1389   /* grow dest */
1390   if (b->alloc < a->used) {
1391      if ((res = mp_grow (b, a->used)) != MP_OKAY) {
1392         return res;
1393      }
1394   }
1395
1396   /* zero b and copy the parameters over */
1397   {
1398     register mp_digit *tmpa, *tmpb;
1399
1400     /* pointer aliases */
1401
1402     /* source */
1403     tmpa = a->dp;
1404
1405     /* destination */
1406     tmpb = b->dp;
1407
1408     /* copy all the digits */
1409     for (n = 0; n < a->used; n++) {
1410       *tmpb++ = *tmpa++;
1411     }
1412
1413     /* clear high digits */
1414     for (; n < b->used; n++) {
1415       *tmpb++ = 0;
1416     }
1417   }
1418
1419   /* copy used count and sign */
1420   b->used = a->used;
1421   b->sign = a->sign;
1422   return MP_OKAY;
1423 }
1424 #endif
1425
1426 /* End: bn_mp_copy.c */
1427
1428 /* Start: bn_mp_count_bits.c */
1429 #include "tma.h"
1430 #ifdef BN_MP_COUNT_BITS_C
1431 /* LibTomMath, multiple-precision integer library -- Tom St Denis
1432  *
1433  * LibTomMath is a library that provides multiple-precision
1434  * integer arithmetic as well as number theoretic functionality.
1435  *
1436  * The library was designed directly after the MPI library by
1437  * Michael Fromberger but has been written from scratch with
1438  * additional optimizations in place.
1439  *
1440  * The library is free for all purposes without any express
1441  * guarantee it works.
1442  *
1443  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
1444  */
1445
1446 /* returns the number of bits in an int */
1447 int
1448 mp_count_bits (mp_int * a)
1449 {
1450   int     r;
1451   mp_digit q;
1452
1453   /* shortcut */
1454   if (a->used == 0) {
1455     return 0;
1456   }
1457
1458   /* get number of digits and add that */
1459   r = (a->used - 1) * DIGIT_BIT;
1460   
1461   /* take the last digit and count the bits in it */
1462   q = a->dp[a->used - 1];
1463   while (q > ((mp_digit) 0)) {
1464     ++r;
1465     q >>= ((mp_digit) 1);
1466   }
1467   return r;
1468 }
1469 #endif
1470
1471 /* End: bn_mp_count_bits.c */
1472
1473 /* Start: bn_mp_div.c */
1474 #include "tma.h"
1475 #ifdef BN_MP_DIV_C
1476 /* LibTomMath, multiple-precision integer library -- Tom St Denis
1477  *
1478  * LibTomMath is a library that provides multiple-precision
1479  * integer arithmetic as well as number theoretic functionality.
1480  *
1481  * The library was designed directly after the MPI library by
1482  * Michael Fromberger but has been written from scratch with
1483  * additional optimizations in place.
1484  *
1485  * The library is free for all purposes without any express
1486  * guarantee it works.
1487  *
1488  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
1489  */
1490
1491 #ifdef BN_MP_DIV_SMALL
1492
1493 /* slower bit-bang division... also smaller */
1494 int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d)
1495 {
1496    mp_int ta, tb, tq, q;
1497    int    res, n, n2;
1498
1499   /* is divisor zero ? */
1500   if (mp_iszero (b) == 1) {
1501     return MP_VAL;
1502   }
1503
1504   /* if a < b then q=0, r = a */
1505   if (mp_cmp_mag (a, b) == MP_LT) {
1506     if (d != NULL) {
1507       res = mp_copy (a, d);
1508     } else {
1509       res = MP_OKAY;
1510     }
1511     if (c != NULL) {
1512       mp_zero (c);
1513     }
1514     return res;
1515   }
1516         
1517   /* init our temps */
1518   if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) {
1519      return res;
1520   }
1521
1522
1523   mp_set(&tq, 1);
1524   n = mp_count_bits(a) - mp_count_bits(b);
1525   if (((res = mp_abs(a, &ta)) != MP_OKAY) ||
1526       ((res = mp_abs(b, &tb)) != MP_OKAY) || 
1527       ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) ||
1528       ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) {
1529       goto LBL_ERR;
1530   }
1531
1532   while (n-- >= 0) {
1533      if (mp_cmp(&tb, &ta) != MP_GT) {
1534         if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) ||
1535             ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) {
1536            goto LBL_ERR;
1537         }
1538      }
1539      if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) ||
1540          ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) {
1541            goto LBL_ERR;
1542      }
1543   }
1544
1545   /* now q == quotient and ta == remainder */
1546   n  = a->sign;
1547   n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG);
1548   if (c != NULL) {
1549      mp_exch(c, &q);
1550      c->sign  = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2;
1551   }
1552   if (d != NULL) {
1553      mp_exch(d, &ta);
1554      d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n;
1555   }
1556 LBL_ERR:
1557    mp_clear_multi(&ta, &tb, &tq, &q, NULL);
1558    return res;
1559 }
1560
1561 #else
1562
1563 /* integer signed division. 
1564  * c*b + d == a [e.g. a/b, c=quotient, d=remainder]
1565  * HAC pp.598 Algorithm 14.20
1566  *
1567  * Note that the description in HAC is horribly 
1568  * incomplete.  For example, it doesn't consider 
1569  * the case where digits are removed from 'x' in 
1570  * the inner loop.  It also doesn't consider the 
1571  * case that y has fewer than three digits, etc..
1572  *
1573  * The overall algorithm is as described as 
1574  * 14.20 from HAC but fixed to treat these cases.
1575 */
1576 int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
1577 {
1578   mp_int  q, x, y, t1, t2;
1579   int     res, n, t, i, norm, neg;
1580
1581   /* is divisor zero ? */
1582   if (mp_iszero (b) == 1) {
1583     return MP_VAL;
1584   }
1585
1586   /* if a < b then q=0, r = a */
1587   if (mp_cmp_mag (a, b) == MP_LT) {
1588     if (d != NULL) {
1589       res = mp_copy (a, d);
1590     } else {
1591       res = MP_OKAY;
1592     }
1593     if (c != NULL) {
1594       mp_zero (c);
1595     }
1596     return res;
1597   }
1598
1599   if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) {
1600     return res;
1601   }
1602   q.used = a->used + 2;
1603
1604   if ((res = mp_init (&t1)) != MP_OKAY) {
1605     goto LBL_Q;
1606   }
1607
1608   if ((res = mp_init (&t2)) != MP_OKAY) {
1609     goto LBL_T1;
1610   }
1611
1612   if ((res = mp_init_copy (&x, a)) != MP_OKAY) {
1613     goto LBL_T2;
1614   }
1615
1616   if ((res = mp_init_copy (&y, b)) != MP_OKAY) {
1617     goto LBL_X;
1618   }
1619
1620   /* fix the sign */
1621   neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
1622   x.sign = y.sign = MP_ZPOS;
1623
1624   /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
1625   norm = mp_count_bits(&y) % DIGIT_BIT;
1626   if (norm < (int)(DIGIT_BIT-1)) {
1627      norm = (DIGIT_BIT-1) - norm;
1628      if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) {
1629        goto LBL_Y;
1630      }
1631      if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) {
1632        goto LBL_Y;
1633      }
1634   } else {
1635      norm = 0;
1636   }
1637
1638   /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
1639   n = x.used - 1;
1640   t = y.used - 1;
1641
1642   /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
1643   if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */
1644     goto LBL_Y;
1645   }
1646
1647   while (mp_cmp (&x, &y) != MP_LT) {
1648     ++(q.dp[n - t]);
1649     if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) {
1650       goto LBL_Y;
1651     }
1652   }
1653
1654   /* reset y by shifting it back down */
1655   mp_rshd (&y, n - t);
1656
1657   /* step 3. for i from n down to (t + 1) */
1658   for (i = n; i >= (t + 1); i--) {
1659     if (i > x.used) {
1660       continue;
1661     }
1662
1663     /* step 3.1 if xi == yt then set q{i-t-1} to b-1, 
1664      * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
1665     if (x.dp[i] == y.dp[t]) {
1666       q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1);
1667     } else {
1668       mp_word tmp;
1669       tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT);
1670       tmp |= ((mp_word) x.dp[i - 1]);
1671       tmp /= ((mp_word) y.dp[t]);
1672       if (tmp > (mp_word) MP_MASK)
1673         tmp = MP_MASK;
1674       q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK));
1675     }
1676
1677     /* while (q{i-t-1} * (yt * b + y{t-1})) > 
1678              xi * b**2 + xi-1 * b + xi-2 
1679      
1680        do q{i-t-1} -= 1; 
1681     */
1682     q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK;
1683     do {
1684       q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK;
1685
1686       /* find left hand */
1687       mp_zero (&t1);
1688       t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
1689       t1.dp[1] = y.dp[t];
1690       t1.used = 2;
1691       if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) {
1692         goto LBL_Y;
1693       }
1694
1695       /* find right hand */
1696       t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];
1697       t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];
1698       t2.dp[2] = x.dp[i];
1699       t2.used = 3;
1700     } while (mp_cmp_mag(&t1, &t2) == MP_GT);
1701
1702     /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
1703     if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) {
1704       goto LBL_Y;
1705     }
1706
1707     if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
1708       goto LBL_Y;
1709     }
1710
1711     if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) {
1712       goto LBL_Y;
1713     }
1714
1715     /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
1716     if (x.sign == MP_NEG) {
1717       if ((res = mp_copy (&y, &t1)) != MP_OKAY) {
1718         goto LBL_Y;
1719       }
1720       if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
1721         goto LBL_Y;
1722       }
1723       if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) {
1724         goto LBL_Y;
1725       }
1726
1727       q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK;
1728     }
1729   }
1730
1731   /* now q is the quotient and x is the remainder 
1732    * [which we have to normalize] 
1733    */
1734   
1735   /* get sign before writing to c */
1736   x.sign = x.used == 0 ? MP_ZPOS : a->sign;
1737
1738   if (c != NULL) {
1739     mp_clamp (&q);
1740     mp_exch (&q, c);
1741     c->sign = neg;
1742   }
1743
1744   if (d != NULL) {
1745     mp_div_2d (&x, norm, &x, NULL);
1746     mp_exch (&x, d);
1747   }
1748
1749   res = MP_OKAY;
1750
1751 LBL_Y:mp_clear (&y);
1752 LBL_X:mp_clear (&x);
1753 LBL_T2:mp_clear (&t2);
1754 LBL_T1:mp_clear (&t1);
1755 LBL_Q:mp_clear (&q);
1756   return res;
1757 }
1758
1759 #endif
1760
1761 #endif
1762
1763 /* End: bn_mp_div.c */
1764
1765 /* Start: bn_mp_div_2.c */
1766 #include "tma.h"
1767 #ifdef BN_MP_DIV_2_C
1768 /* LibTomMath, multiple-precision integer library -- Tom St Denis
1769  *
1770  * LibTomMath is a library that provides multiple-precision
1771  * integer arithmetic as well as number theoretic functionality.
1772  *
1773  * The library was designed directly after the MPI library by
1774  * Michael Fromberger but has been written from scratch with
1775  * additional optimizations in place.
1776  *
1777  * The library is free for all purposes without any express
1778  * guarantee it works.
1779  *
1780  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
1781  */
1782
1783 /* b = a/2 */
1784 int mp_div_2(mp_int * a, mp_int * b)
1785 {
1786   int     x, res, oldused;
1787
1788   /* copy */
1789   if (b->alloc < a->used) {
1790     if ((res = mp_grow (b, a->used)) != MP_OKAY) {
1791       return res;
1792     }
1793   }
1794
1795   oldused = b->used;
1796   b->used = a->used;
1797   {
1798     register mp_digit r, rr, *tmpa, *tmpb;
1799
1800     /* source alias */
1801     tmpa = a->dp + b->used - 1;
1802
1803     /* dest alias */
1804     tmpb = b->dp + b->used - 1;
1805
1806     /* carry */
1807     r = 0;
1808     for (x = b->used - 1; x >= 0; x--) {
1809       /* get the carry for the next iteration */
1810       rr = *tmpa & 1;
1811
1812       /* shift the current digit, add in carry and store */
1813       *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
1814
1815       /* forward carry to next iteration */
1816       r = rr;
1817     }
1818
1819     /* zero excess digits */
1820     tmpb = b->dp + b->used;
1821     for (x = b->used; x < oldused; x++) {
1822       *tmpb++ = 0;
1823     }
1824   }
1825   b->sign = a->sign;
1826   mp_clamp (b);
1827   return MP_OKAY;
1828 }
1829 #endif
1830
1831 /* End: bn_mp_div_2.c */
1832
1833 /* Start: bn_mp_div_2d.c */
1834 #include "tma.h"
1835 #ifdef BN_MP_DIV_2D_C
1836 /* LibTomMath, multiple-precision integer library -- Tom St Denis
1837  *
1838  * LibTomMath is a library that provides multiple-precision
1839  * integer arithmetic as well as number theoretic functionality.
1840  *
1841  * The library was designed directly after the MPI library by
1842  * Michael Fromberger but has been written from scratch with
1843  * additional optimizations in place.
1844  *
1845  * The library is free for all purposes without any express
1846  * guarantee it works.
1847  *
1848  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
1849  */
1850
1851 /* shift right by a certain bit count (store quotient in c, optional remainder in d) */
1852 int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d)
1853 {
1854   mp_digit D, r, rr;
1855   int     x, res;
1856   mp_int  t;
1857
1858
1859   /* if the shift count is <= 0 then we do no work */
1860   if (b <= 0) {
1861     res = mp_copy (a, c);
1862     if (d != NULL) {
1863       mp_zero (d);
1864     }
1865     return res;
1866   }
1867
1868   if ((res = mp_init (&t)) != MP_OKAY) {
1869     return res;
1870   }
1871
1872   /* get the remainder */
1873   if (d != NULL) {
1874     if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) {
1875       mp_clear (&t);
1876       return res;
1877     }
1878   }
1879
1880   /* copy */
1881   if ((res = mp_copy (a, c)) != MP_OKAY) {
1882     mp_clear (&t);
1883     return res;
1884   }
1885
1886   /* shift by as many digits in the bit count */
1887   if (b >= (int)DIGIT_BIT) {
1888     mp_rshd (c, b / DIGIT_BIT);
1889   }
1890
1891   /* shift any bit count < DIGIT_BIT */
1892   D = (mp_digit) (b % DIGIT_BIT);
1893   if (D != 0) {
1894     register mp_digit *tmpc, mask, shift;
1895
1896     /* mask */
1897     mask = (((mp_digit)1) << D) - 1;
1898
1899     /* shift for lsb */
1900     shift = DIGIT_BIT - D;
1901
1902     /* alias */
1903     tmpc = c->dp + (c->used - 1);
1904
1905     /* carry */
1906     r = 0;
1907     for (x = c->used - 1; x >= 0; x--) {
1908       /* get the lower  bits of this word in a temp */
1909       rr = *tmpc & mask;
1910
1911       /* shift the current word and mix in the carry bits from the previous word */
1912       *tmpc = (*tmpc >> D) | (r << shift);
1913       --tmpc;
1914
1915       /* set the carry to the carry bits of the current word found above */
1916       r = rr;
1917     }
1918   }
1919   mp_clamp (c);
1920   if (d != NULL) {
1921     mp_exch (&t, d);
1922   }
1923   mp_clear (&t);
1924   return MP_OKAY;
1925 }
1926 #endif
1927
1928 /* End: bn_mp_div_2d.c */
1929
1930 /* Start: bn_mp_div_3.c */
1931 #include "tma.h"
1932 #ifdef BN_MP_DIV_3_C
1933 /* LibTomMath, multiple-precision integer library -- Tom St Denis
1934  *
1935  * LibTomMath is a library that provides multiple-precision
1936  * integer arithmetic as well as number theoretic functionality.
1937  *
1938  * The library was designed directly after the MPI library by
1939  * Michael Fromberger but has been written from scratch with
1940  * additional optimizations in place.
1941  *
1942  * The library is free for all purposes without any express
1943  * guarantee it works.
1944  *
1945  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
1946  */
1947
1948 /* divide by three (based on routine from MPI and the GMP manual) */
1949 int
1950 mp_div_3 (mp_int * a, mp_int *c, mp_digit * d)
1951 {
1952   mp_int   q;
1953   mp_word  w, t;
1954   mp_digit b;
1955   int      res, ix;
1956   
1957   /* b = 2**DIGIT_BIT / 3 */
1958   b = (((mp_word)1) << ((mp_word)DIGIT_BIT)) / ((mp_word)3);
1959
1960   if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
1961      return res;
1962   }
1963   
1964   q.used = a->used;
1965   q.sign = a->sign;
1966   w = 0;
1967   for (ix = a->used - 1; ix >= 0; ix--) {
1968      w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
1969
1970      if (w >= 3) {
1971         /* multiply w by [1/3] */
1972         t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT);
1973
1974         /* now subtract 3 * [w/3] from w, to get the remainder */
1975         w -= t+t+t;
1976
1977         /* fixup the remainder as required since
1978          * the optimization is not exact.
1979          */
1980         while (w >= 3) {
1981            t += 1;
1982            w -= 3;
1983         }
1984       } else {
1985         t = 0;
1986       }
1987       q.dp[ix] = (mp_digit)t;
1988   }
1989
1990   /* [optional] store the remainder */
1991   if (d != NULL) {
1992      *d = (mp_digit)w;
1993   }
1994
1995   /* [optional] store the quotient */
1996   if (c != NULL) {
1997      mp_clamp(&q);
1998      mp_exch(&q, c);
1999   }
2000   mp_clear(&q);
2001   
2002   return res;
2003 }
2004
2005 #endif
2006
2007 /* End: bn_mp_div_3.c */
2008
2009 /* Start: bn_mp_div_d.c */
2010 #include "tma.h"
2011 #ifdef BN_MP_DIV_D_C
2012 /* LibTomMath, multiple-precision integer library -- Tom St Denis
2013  *
2014  * LibTomMath is a library that provides multiple-precision
2015  * integer arithmetic as well as number theoretic functionality.
2016  *
2017  * The library was designed directly after the MPI library by
2018  * Michael Fromberger but has been written from scratch with
2019  * additional optimizations in place.
2020  *
2021  * The library is free for all purposes without any express
2022  * guarantee it works.
2023  *
2024  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
2025  */
2026
2027 static int s_is_power_of_two(mp_digit b, int *p)
2028 {
2029    int x;
2030
2031    for (x = 1; x < DIGIT_BIT; x++) {
2032       if (b == (((mp_digit)1)<<x)) {
2033          *p = x;
2034          return 1;
2035       }
2036    }
2037    return 0;
2038 }
2039
2040 /* single digit division (based on routine from MPI) */
2041 int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d)
2042 {
2043   mp_int  q;
2044   mp_word w;
2045   mp_digit t;
2046   int     res, ix;
2047
2048   /* cannot divide by zero */
2049   if (b == 0) {
2050      return MP_VAL;
2051   }
2052
2053   /* quick outs */
2054   if (b == 1 || mp_iszero(a) == 1) {
2055      if (d != NULL) {
2056         *d = 0;
2057      }
2058      if (c != NULL) {
2059         return mp_copy(a, c);
2060      }
2061      return MP_OKAY;
2062   }
2063
2064   /* power of two ? */
2065   if (s_is_power_of_two(b, &ix) == 1) {
2066      if (d != NULL) {
2067         *d = a->dp[0] & ((((mp_digit)1)<<ix) - 1);
2068      }
2069      if (c != NULL) {
2070         return mp_div_2d(a, ix, c, NULL);
2071      }
2072      return MP_OKAY;
2073   }
2074
2075 #ifdef BN_MP_DIV_3_C
2076   /* three? */
2077   if (b == 3) {
2078      return mp_div_3(a, c, d);
2079   }
2080 #endif
2081
2082   /* no easy answer [c'est la vie].  Just division */
2083   if ((res = mp_init_size(&q, a->used)) != MP_OKAY) {
2084      return res;
2085   }
2086   
2087   q.used = a->used;
2088   q.sign = a->sign;
2089   w = 0;
2090   for (ix = a->used - 1; ix >= 0; ix--) {
2091      w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]);
2092      
2093      if (w >= b) {
2094         t = (mp_digit)(w / b);
2095         w -= ((mp_word)t) * ((mp_word)b);
2096       } else {
2097         t = 0;
2098       }
2099       q.dp[ix] = (mp_digit)t;
2100   }
2101   
2102   if (d != NULL) {
2103      *d = (mp_digit)w;
2104   }
2105   
2106   if (c != NULL) {
2107      mp_clamp(&q);
2108      mp_exch(&q, c);
2109   }
2110   mp_clear(&q);
2111   
2112   return res;
2113 }
2114
2115 #endif
2116
2117 /* End: bn_mp_div_d.c */
2118
2119 /* Start: bn_mp_dr_is_modulus.c */
2120 #include "tma.h"
2121 #ifdef BN_MP_DR_IS_MODULUS_C
2122 /* LibTomMath, multiple-precision integer library -- Tom St Denis
2123  *
2124  * LibTomMath is a library that provides multiple-precision
2125  * integer arithmetic as well as number theoretic functionality.
2126  *
2127  * The library was designed directly after the MPI library by
2128  * Michael Fromberger but has been written from scratch with
2129  * additional optimizations in place.
2130  *
2131  * The library is free for all purposes without any express
2132  * guarantee it works.
2133  *
2134  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
2135  */
2136
2137 /* determines if a number is a valid DR modulus */
2138 int mp_dr_is_modulus(mp_int *a)
2139 {
2140    int ix;
2141
2142    /* must be at least two digits */
2143    if (a->used < 2) {
2144       return 0;
2145    }
2146
2147    /* must be of the form b**k - a [a <= b] so all
2148     * but the first digit must be equal to -1 (mod b).
2149     */
2150    for (ix = 1; ix < a->used; ix++) {
2151        if (a->dp[ix] != MP_MASK) {
2152           return 0;
2153        }
2154    }
2155    return 1;
2156 }
2157
2158 #endif
2159
2160 /* End: bn_mp_dr_is_modulus.c */
2161
2162 /* Start: bn_mp_dr_reduce.c */
2163 #include "tma.h"
2164 #ifdef BN_MP_DR_REDUCE_C
2165 /* LibTomMath, multiple-precision integer library -- Tom St Denis
2166  *
2167  * LibTomMath is a library that provides multiple-precision
2168  * integer arithmetic as well as number theoretic functionality.
2169  *
2170  * The library was designed directly after the MPI library by
2171  * Michael Fromberger but has been written from scratch with
2172  * additional optimizations in place.
2173  *
2174  * The library is free for all purposes without any express
2175  * guarantee it works.
2176  *
2177  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
2178  */
2179
2180 /* reduce "x" in place modulo "n" using the Diminished Radix algorithm.
2181  *
2182  * Based on algorithm from the paper
2183  *
2184  * "Generating Efficient Primes for Discrete Log Cryptosystems"
2185  *                 Chae Hoon Lim, Pil Joong Lee,
2186  *          POSTECH Information Research Laboratories
2187  *
2188  * The modulus must be of a special format [see manual]
2189  *
2190  * Has been modified to use algorithm 7.10 from the LTM book instead
2191  *
2192  * Input x must be in the range 0 <= x <= (n-1)**2
2193  */
2194 int
2195 mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k)
2196 {
2197   int      err, i, m;
2198   mp_word  r;
2199   mp_digit mu, *tmpx1, *tmpx2;
2200
2201   /* m = digits in modulus */
2202   m = n->used;
2203
2204   /* ensure that "x" has at least 2m digits */
2205   if (x->alloc < m + m) {
2206     if ((err = mp_grow (x, m + m)) != MP_OKAY) {
2207       return err;
2208     }
2209   }
2210
2211 /* top of loop, this is where the code resumes if
2212  * another reduction pass is required.
2213  */
2214 top:
2215   /* aliases for digits */
2216   /* alias for lower half of x */
2217   tmpx1 = x->dp;
2218
2219   /* alias for upper half of x, or x/B**m */
2220   tmpx2 = x->dp + m;
2221
2222   /* set carry to zero */
2223   mu = 0;
2224
2225   /* compute (x mod B**m) + k * [x/B**m] inline and inplace */
2226   for (i = 0; i < m; i++) {
2227       r         = ((mp_word)*tmpx2++) * ((mp_word)k) + *tmpx1 + mu;
2228       *tmpx1++  = (mp_digit)(r & MP_MASK);
2229       mu        = (mp_digit)(r >> ((mp_word)DIGIT_BIT));
2230   }
2231
2232   /* set final carry */
2233   *tmpx1++ = mu;
2234
2235   /* zero words above m */
2236   for (i = m + 1; i < x->used; i++) {
2237       *tmpx1++ = 0;
2238   }
2239
2240   /* clamp, sub and return */
2241   mp_clamp (x);
2242
2243   /* if x >= n then subtract and reduce again
2244    * Each successive "recursion" makes the input smaller and smaller.
2245    */
2246   if (mp_cmp_mag (x, n) != MP_LT) {
2247     s_mp_sub(x, n, x);
2248     goto top;
2249   }
2250   return MP_OKAY;
2251 }
2252 #endif
2253
2254 /* End: bn_mp_dr_reduce.c */
2255
2256 /* Start: bn_mp_dr_setup.c */
2257 #include "tma.h"
2258 #ifdef BN_MP_DR_SETUP_C
2259 /* LibTomMath, multiple-precision integer library -- Tom St Denis
2260  *
2261  * LibTomMath is a library that provides multiple-precision
2262  * integer arithmetic as well as number theoretic functionality.
2263  *
2264  * The library was designed directly after the MPI library by
2265  * Michael Fromberger but has been written from scratch with
2266  * additional optimizations in place.
2267  *
2268  * The library is free for all purposes without any express
2269  * guarantee it works.
2270  *
2271  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
2272  */
2273
2274 /* determines the setup value */
2275 void mp_dr_setup(mp_int *a, mp_digit *d)
2276 {
2277    /* the casts are required if DIGIT_BIT is one less than
2278     * the number of bits in a mp_digit [e.g. DIGIT_BIT==31]
2279     */
2280    *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) - 
2281         ((mp_word)a->dp[0]));
2282 }
2283
2284 #endif
2285
2286 /* End: bn_mp_dr_setup.c */
2287
2288 /* Start: bn_mp_exch.c */
2289 #include "tma.h"
2290 #ifdef BN_MP_EXCH_C
2291 /* LibTomMath, multiple-precision integer library -- Tom St Denis
2292  *
2293  * LibTomMath is a library that provides multiple-precision
2294  * integer arithmetic as well as number theoretic functionality.
2295  *
2296  * The library was designed directly after the MPI library by
2297  * Michael Fromberger but has been written from scratch with
2298  * additional optimizations in place.
2299  *
2300  * The library is free for all purposes without any express
2301  * guarantee it works.
2302  *
2303  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
2304  */
2305
2306 /* swap the elements of two integers, for cases where you can't simply swap the 
2307  * mp_int pointers around
2308  */
2309 void
2310 mp_exch (mp_int * a, mp_int * b)
2311 {
2312   mp_int  t;
2313
2314   t  = *a;
2315   *a = *b;
2316   *b = t;
2317 }
2318 #endif
2319
2320 /* End: bn_mp_exch.c */
2321
2322 /* Start: bn_mp_expt_d.c */
2323 #include "tma.h"
2324 #ifdef BN_MP_EXPT_D_C
2325 /* LibTomMath, multiple-precision integer library -- Tom St Denis
2326  *
2327  * LibTomMath is a library that provides multiple-precision
2328  * integer arithmetic as well as number theoretic functionality.
2329  *
2330  * The library was designed directly after the MPI library by
2331  * Michael Fromberger but has been written from scratch with
2332  * additional optimizations in place.
2333  *
2334  * The library is free for all purposes without any express
2335  * guarantee it works.
2336  *
2337  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
2338  */
2339
2340 /* calculate c = a**b  using a square-multiply algorithm */
2341 int mp_expt_d (mp_int * a, mp_digit b, mp_int * c)
2342 {
2343   int     res, x;
2344   mp_int  g;
2345
2346   if ((res = mp_init_copy (&g, a)) != MP_OKAY) {
2347     return res;
2348   }
2349
2350   /* set initial result */
2351   mp_set (c, 1);
2352
2353   for (x = 0; x < (int) DIGIT_BIT; x++) {
2354     /* square */
2355     if ((res = mp_sqr (c, c)) != MP_OKAY) {
2356       mp_clear (&g);
2357       return res;
2358     }
2359
2360     /* if the bit is set multiply */
2361     if ((b & (mp_digit) (((mp_digit)1) << (DIGIT_BIT - 1))) != 0) {
2362       if ((res = mp_mul (c, &g, c)) != MP_OKAY) {
2363          mp_clear (&g);
2364          return res;
2365       }
2366     }
2367
2368     /* shift to next bit */
2369     b <<= 1;
2370   }
2371
2372   mp_clear (&g);
2373   return MP_OKAY;
2374 }
2375 #endif
2376
2377 /* End: bn_mp_expt_d.c */
2378
2379 /* Start: bn_mp_exptmod.c */
2380 #include "tma.h"
2381 #ifdef BN_MP_EXPTMOD_C
2382 /* LibTomMath, multiple-precision integer library -- Tom St Denis
2383  *
2384  * LibTomMath is a library that provides multiple-precision
2385  * integer arithmetic as well as number theoretic functionality.
2386  *
2387  * The library was designed directly after the MPI library by
2388  * Michael Fromberger but has been written from scratch with
2389  * additional optimizations in place.
2390  *
2391  * The library is free for all purposes without any express
2392  * guarantee it works.
2393  *
2394  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
2395  */
2396
2397
2398 /* this is a shell function that calls either the normal or Montgomery
2399  * exptmod functions.  Originally the call to the montgomery code was
2400  * embedded in the normal function but that wasted alot of stack space
2401  * for nothing (since 99% of the time the Montgomery code would be called)
2402  */
2403 int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
2404 {
2405   int dr;
2406
2407   /* modulus P must be positive */
2408   if (P->sign == MP_NEG) {
2409      return MP_VAL;
2410   }
2411
2412   /* if exponent X is negative we have to recurse */
2413   if (X->sign == MP_NEG) {
2414 #ifdef BN_MP_INVMOD_C
2415      mp_int tmpG, tmpX;
2416      int err;
2417
2418      /* first compute 1/G mod P */
2419      if ((err = mp_init(&tmpG)) != MP_OKAY) {
2420         return err;
2421      }
2422      if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) {
2423         mp_clear(&tmpG);
2424         return err;
2425      }
2426
2427      /* now get |X| */
2428      if ((err = mp_init(&tmpX)) != MP_OKAY) {
2429         mp_clear(&tmpG);
2430         return err;
2431      }
2432      if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {
2433         mp_clear_multi(&tmpG, &tmpX, NULL);
2434         return err;
2435      }
2436
2437      /* and now compute (1/G)**|X| instead of G**X [X < 0] */
2438      err = mp_exptmod(&tmpG, &tmpX, P, Y);
2439      mp_clear_multi(&tmpG, &tmpX, NULL);
2440      return err;
2441 #else 
2442      /* no invmod */
2443      return MP_VAL;
2444 #endif
2445   }
2446
2447 /* modified diminished radix reduction */
2448 #if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C)
2449   if (mp_reduce_is_2k_l(P) == MP_YES) {
2450      return s_mp_exptmod(G, X, P, Y, 1);
2451   }
2452 #endif
2453
2454 #ifdef BN_MP_DR_IS_MODULUS_C
2455   /* is it a DR modulus? */
2456   dr = mp_dr_is_modulus(P);
2457 #else
2458   /* default to no */
2459   dr = 0;
2460 #endif
2461
2462 #ifdef BN_MP_REDUCE_IS_2K_C
2463   /* if not, is it a unrestricted DR modulus? */
2464   if (dr == 0) {
2465      dr = mp_reduce_is_2k(P) << 1;
2466   }
2467 #endif
2468     
2469   /* if the modulus is odd or dr != 0 use the montgomery method */
2470 #ifdef BN_MP_EXPTMOD_FAST_C
2471   if (mp_isodd (P) == 1 || dr !=  0) {
2472     return mp_exptmod_fast (G, X, P, Y, dr);
2473   } else {
2474 #endif
2475 #ifdef BN_S_MP_EXPTMOD_C
2476     /* otherwise use the generic Barrett reduction technique */
2477     return s_mp_exptmod (G, X, P, Y, 0);
2478 #else
2479     /* no exptmod for evens */
2480     return MP_VAL;
2481 #endif
2482 #ifdef BN_MP_EXPTMOD_FAST_C
2483   }
2484 #endif
2485 }
2486
2487 #endif
2488
2489 /* End: bn_mp_exptmod.c */
2490
2491 /* Start: bn_mp_exptmod_fast.c */
2492 #include "tma.h"
2493 #ifdef BN_MP_EXPTMOD_FAST_C
2494 /* LibTomMath, multiple-precision integer library -- Tom St Denis
2495  *
2496  * LibTomMath is a library that provides multiple-precision
2497  * integer arithmetic as well as number theoretic functionality.
2498  *
2499  * The library was designed directly after the MPI library by
2500  * Michael Fromberger but has been written from scratch with
2501  * additional optimizations in place.
2502  *
2503  * The library is free for all purposes without any express
2504  * guarantee it works.
2505  *
2506  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
2507  */
2508
2509 /* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85
2510  *
2511  * Uses a left-to-right k-ary sliding window to compute the modular exponentiation.
2512  * The value of k changes based on the size of the exponent.
2513  *
2514  * Uses Montgomery or Diminished Radix reduction [whichever appropriate]
2515  */
2516
2517 #ifdef MP_LOW_MEM
2518    #define TAB_SIZE 32
2519 #else
2520    #define TAB_SIZE 256
2521 #endif
2522
2523 int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
2524 {
2525   mp_int  M[TAB_SIZE], res;
2526   mp_digit buf, mp;
2527   int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
2528
2529   /* use a pointer to the reduction algorithm.  This allows us to use
2530    * one of many reduction algorithms without modding the guts of
2531    * the code with if statements everywhere.
2532    */
2533   int     (*redux)(mp_int*,mp_int*,mp_digit);
2534
2535   /* find window size */
2536   x = mp_count_bits (X);
2537   if (x <= 7) {
2538     winsize = 2;
2539   } else if (x <= 36) {
2540     winsize = 3;
2541   } else if (x <= 140) {
2542     winsize = 4;
2543   } else if (x <= 450) {
2544     winsize = 5;
2545   } else if (x <= 1303) {
2546     winsize = 6;
2547   } else if (x <= 3529) {
2548     winsize = 7;
2549   } else {
2550     winsize = 8;
2551   }
2552
2553 #ifdef MP_LOW_MEM
2554   if (winsize > 5) {
2555      winsize = 5;
2556   }
2557 #endif
2558
2559   /* init M array */
2560   /* init first cell */
2561   if ((err = mp_init(&M[1])) != MP_OKAY) {
2562      return err;
2563   }
2564
2565   /* now init the second half of the array */
2566   for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
2567     if ((err = mp_init(&M[x])) != MP_OKAY) {
2568       for (y = 1<<(winsize-1); y < x; y++) {
2569         mp_clear (&M[y]);
2570       }
2571       mp_clear(&M[1]);
2572       return err;
2573     }
2574   }
2575
2576   /* determine and setup reduction code */
2577   if (redmode == 0) {
2578 #ifdef BN_MP_MONTGOMERY_SETUP_C     
2579      /* now setup montgomery  */
2580      if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) {
2581         goto LBL_M;
2582      }
2583 #else
2584      err = MP_VAL;
2585      goto LBL_M;
2586 #endif
2587
2588      /* automatically pick the comba one if available (saves quite a few calls/ifs) */
2589 #ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
2590      if (((P->used * 2 + 1) < MP_WARRAY) &&
2591           P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
2592         redux = fast_mp_montgomery_reduce;
2593      } else 
2594 #endif
2595      {
2596 #ifdef BN_MP_MONTGOMERY_REDUCE_C
2597         /* use slower baseline Montgomery method */
2598         redux = mp_montgomery_reduce;
2599 #else
2600         err = MP_VAL;
2601         goto LBL_M;
2602 #endif
2603      }
2604   } else if (redmode == 1) {
2605 #if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C)
2606      /* setup DR reduction for moduli of the form B**k - b */
2607      mp_dr_setup(P, &mp);
2608      redux = mp_dr_reduce;
2609 #else
2610      err = MP_VAL;
2611      goto LBL_M;
2612 #endif
2613   } else {
2614 #if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C)
2615      /* setup DR reduction for moduli of the form 2**k - b */
2616      if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) {
2617         goto LBL_M;
2618      }
2619      redux = mp_reduce_2k;
2620 #else
2621      err = MP_VAL;
2622      goto LBL_M;
2623 #endif
2624   }
2625
2626   /* setup result */
2627   if ((err = mp_init (&res)) != MP_OKAY) {
2628     goto LBL_M;
2629   }
2630
2631   /* create M table
2632    *
2633
2634    *
2635    * The first half of the table is not computed though accept for M[0] and M[1]
2636    */
2637
2638   if (redmode == 0) {
2639 #ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
2640      /* now we need R mod m */
2641      if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) {
2642        goto LBL_RES;
2643      }
2644 #else 
2645      err = MP_VAL;
2646      goto LBL_RES;
2647 #endif
2648
2649      /* now set M[1] to G * R mod m */
2650      if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) {
2651        goto LBL_RES;
2652      }
2653   } else {
2654      mp_set(&res, 1);
2655      if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) {
2656         goto LBL_RES;
2657      }
2658   }
2659
2660   /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */
2661   if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
2662     goto LBL_RES;
2663   }
2664
2665   for (x = 0; x < (winsize - 1); x++) {
2666     if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) {
2667       goto LBL_RES;
2668     }
2669     if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) {
2670       goto LBL_RES;
2671     }
2672   }
2673
2674   /* create upper table */
2675   for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
2676     if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
2677       goto LBL_RES;
2678     }
2679     if ((err = redux (&M[x], P, mp)) != MP_OKAY) {
2680       goto LBL_RES;
2681     }
2682   }
2683
2684   /* set initial mode and bit cnt */
2685   mode   = 0;
2686   bitcnt = 1;
2687   buf    = 0;
2688   digidx = X->used - 1;
2689   bitcpy = 0;
2690   bitbuf = 0;
2691
2692   for (;;) {
2693     /* grab next digit as required */
2694     if (--bitcnt == 0) {
2695       /* if digidx == -1 we are out of digits so break */
2696       if (digidx == -1) {
2697         break;
2698       }
2699       /* read next digit and reset bitcnt */
2700       buf    = X->dp[digidx--];
2701       bitcnt = (int)DIGIT_BIT;
2702     }
2703
2704     /* grab the next msb from the exponent */
2705     y     = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1;
2706     buf <<= (mp_digit)1;
2707
2708     /* if the bit is zero and mode == 0 then we ignore it
2709      * These represent the leading zero bits before the first 1 bit
2710      * in the exponent.  Technically this opt is not required but it
2711      * does lower the # of trivial squaring/reductions used
2712      */
2713     if (mode == 0 && y == 0) {
2714       continue;
2715     }
2716
2717     /* if the bit is zero and mode == 1 then we square */
2718     if (mode == 1 && y == 0) {
2719       if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
2720         goto LBL_RES;
2721       }
2722       if ((err = redux (&res, P, mp)) != MP_OKAY) {
2723         goto LBL_RES;
2724       }
2725       continue;
2726     }
2727
2728     /* else we add it to the window */
2729     bitbuf |= (y << (winsize - ++bitcpy));
2730     mode    = 2;
2731
2732     if (bitcpy == winsize) {
2733       /* ok window is filled so square as required and multiply  */
2734       /* square first */
2735       for (x = 0; x < winsize; x++) {
2736         if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
2737           goto LBL_RES;
2738         }
2739         if ((err = redux (&res, P, mp)) != MP_OKAY) {
2740           goto LBL_RES;
2741         }
2742       }
2743
2744       /* then multiply */
2745       if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
2746         goto LBL_RES;
2747       }
2748       if ((err = redux (&res, P, mp)) != MP_OKAY) {
2749         goto LBL_RES;
2750       }
2751
2752       /* empty window and reset */
2753       bitcpy = 0;
2754       bitbuf = 0;
2755       mode   = 1;
2756     }
2757   }
2758
2759   /* if bits remain then square/multiply */
2760   if (mode == 2 && bitcpy > 0) {
2761     /* square then multiply if the bit is set */
2762     for (x = 0; x < bitcpy; x++) {
2763       if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
2764         goto LBL_RES;
2765       }
2766       if ((err = redux (&res, P, mp)) != MP_OKAY) {
2767         goto LBL_RES;
2768       }
2769
2770       /* get next bit of the window */
2771       bitbuf <<= 1;
2772       if ((bitbuf & (1 << winsize)) != 0) {
2773         /* then multiply */
2774         if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
2775           goto LBL_RES;
2776         }
2777         if ((err = redux (&res, P, mp)) != MP_OKAY) {
2778           goto LBL_RES;
2779         }
2780       }
2781     }
2782   }
2783
2784   if (redmode == 0) {
2785      /* fixup result if Montgomery reduction is used
2786       * recall that any value in a Montgomery system is
2787       * actually multiplied by R mod n.  So we have
2788       * to reduce one more time to cancel out the factor
2789       * of R.
2790       */
2791      if ((err = redux(&res, P, mp)) != MP_OKAY) {
2792        goto LBL_RES;
2793      }
2794   }
2795
2796   /* swap res with Y */
2797   mp_exch (&res, Y);
2798   err = MP_OKAY;
2799 LBL_RES:mp_clear (&res);
2800 LBL_M:
2801   mp_clear(&M[1]);
2802   for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
2803     mp_clear (&M[x]);
2804   }
2805   return err;
2806 }
2807 #endif
2808
2809
2810 /* End: bn_mp_exptmod_fast.c */
2811
2812 /* Start: bn_mp_exteuclid.c */
2813 #include "tma.h"
2814 #ifdef BN_MP_EXTEUCLID_C
2815 /* LibTomMath, multiple-precision integer library -- Tom St Denis
2816  *
2817  * LibTomMath is a library that provides multiple-precision
2818  * integer arithmetic as well as number theoretic functionality.
2819  *
2820  * The library was designed directly after the MPI library by
2821  * Michael Fromberger but has been written from scratch with
2822  * additional optimizations in place.
2823  *
2824  * The library is free for all purposes without any express
2825  * guarantee it works.
2826  *
2827  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
2828  */
2829
2830 /* Extended euclidean algorithm of (a, b) produces 
2831    a*u1 + b*u2 = u3
2832  */
2833 int mp_exteuclid(mp_int *a, mp_int *b, mp_int *U1, mp_int *U2, mp_int *U3)
2834 {
2835    mp_int u1,u2,u3,v1,v2,v3,t1,t2,t3,q,tmp;
2836    int err;
2837
2838    if ((err = mp_init_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL)) != MP_OKAY) {
2839       return err;
2840    }
2841
2842    /* initialize, (u1,u2,u3) = (1,0,a) */
2843    mp_set(&u1, 1);
2844    if ((err = mp_copy(a, &u3)) != MP_OKAY)                                        { goto _ERR; }
2845
2846    /* initialize, (v1,v2,v3) = (0,1,b) */
2847    mp_set(&v2, 1);
2848    if ((err = mp_copy(b, &v3)) != MP_OKAY)                                        { goto _ERR; }
2849
2850    /* loop while v3 != 0 */
2851    while (mp_iszero(&v3) == MP_NO) {
2852        /* q = u3/v3 */
2853        if ((err = mp_div(&u3, &v3, &q, NULL)) != MP_OKAY)                         { goto _ERR; }
2854
2855        /* (t1,t2,t3) = (u1,u2,u3) - (v1,v2,v3)q */
2856        if ((err = mp_mul(&v1, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
2857        if ((err = mp_sub(&u1, &tmp, &t1)) != MP_OKAY)                             { goto _ERR; }
2858        if ((err = mp_mul(&v2, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
2859        if ((err = mp_sub(&u2, &tmp, &t2)) != MP_OKAY)                             { goto _ERR; }
2860        if ((err = mp_mul(&v3, &q, &tmp)) != MP_OKAY)                              { goto _ERR; }
2861        if ((err = mp_sub(&u3, &tmp, &t3)) != MP_OKAY)                             { goto _ERR; }
2862
2863        /* (u1,u2,u3) = (v1,v2,v3) */
2864        if ((err = mp_copy(&v1, &u1)) != MP_OKAY)                                  { goto _ERR; }
2865        if ((err = mp_copy(&v2, &u2)) != MP_OKAY)                                  { goto _ERR; }
2866        if ((err = mp_copy(&v3, &u3)) != MP_OKAY)                                  { goto _ERR; }
2867
2868        /* (v1,v2,v3) = (t1,t2,t3) */
2869        if ((err = mp_copy(&t1, &v1)) != MP_OKAY)                                  { goto _ERR; }
2870        if ((err = mp_copy(&t2, &v2)) != MP_OKAY)                                  { goto _ERR; }
2871        if ((err = mp_copy(&t3, &v3)) != MP_OKAY)                                  { goto _ERR; }
2872    }
2873
2874    /* make sure U3 >= 0 */
2875    if (u3.sign == MP_NEG) {
2876       mp_neg(&u1, &u1);
2877       mp_neg(&u2, &u2);
2878       mp_neg(&u3, &u3);
2879    }
2880
2881    /* copy result out */
2882    if (U1 != NULL) { mp_exch(U1, &u1); }
2883    if (U2 != NULL) { mp_exch(U2, &u2); }
2884    if (U3 != NULL) { mp_exch(U3, &u3); }
2885
2886    err = MP_OKAY;
2887 _ERR: mp_clear_multi(&u1, &u2, &u3, &v1, &v2, &v3, &t1, &t2, &t3, &q, &tmp, NULL);
2888    return err;
2889 }
2890 #endif
2891
2892 /* End: bn_mp_exteuclid.c */
2893
2894 /* Start: bn_mp_fread.c */
2895 #include "tma.h"
2896 #ifdef BN_MP_FREAD_C
2897 /* LibTomMath, multiple-precision integer library -- Tom St Denis
2898  *
2899  * LibTomMath is a library that provides multiple-precision
2900  * integer arithmetic as well as number theoretic functionality.
2901  *
2902  * The library was designed directly after the MPI library by
2903  * Michael Fromberger but has been written from scratch with
2904  * additional optimizations in place.
2905  *
2906  * The library is free for all purposes without any express
2907  * guarantee it works.
2908  *
2909  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
2910  */
2911
2912 /* read a bigint from a file stream in ASCII */
2913 int mp_fread(mp_int *a, int radix, FILE *stream)
2914 {
2915    int err, ch, neg, y;
2916    
2917    /* clear a */
2918    mp_zero(a);
2919    
2920    /* if first digit is - then set negative */
2921    ch = fgetc(stream);
2922    if (ch == '-') {
2923       neg = MP_NEG;
2924       ch = fgetc(stream);
2925    } else {
2926       neg = MP_ZPOS;
2927    }
2928    
2929    for (;;) {
2930       /* find y in the radix map */
2931       for (y = 0; y < radix; y++) {
2932           if (mp_s_rmap[y] == ch) {
2933              break;
2934           }
2935       }
2936       if (y == radix) {
2937          break;
2938       }
2939       
2940       /* shift up and add */
2941       if ((err = mp_mul_d(a, radix, a)) != MP_OKAY) {
2942          return err;
2943       }
2944       if ((err = mp_add_d(a, y, a)) != MP_OKAY) {
2945          return err;
2946       }
2947       
2948       ch = fgetc(stream);
2949    }
2950    if (mp_cmp_d(a, 0) != MP_EQ) {
2951       a->sign = neg;
2952    }
2953    
2954    return MP_OKAY;
2955 }
2956
2957 #endif
2958
2959 /* End: bn_mp_fread.c */
2960
2961 /* Start: bn_mp_fwrite.c */
2962 #include "tma.h"
2963 #ifdef BN_MP_FWRITE_C
2964 /* LibTomMath, multiple-precision integer library -- Tom St Denis
2965  *
2966  * LibTomMath is a library that provides multiple-precision
2967  * integer arithmetic as well as number theoretic functionality.
2968  *
2969  * The library was designed directly after the MPI library by
2970  * Michael Fromberger but has been written from scratch with
2971  * additional optimizations in place.
2972  *
2973  * The library is free for all purposes without any express
2974  * guarantee it works.
2975  *
2976  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
2977  */
2978
2979 int mp_fwrite(mp_int *a, int radix, FILE *stream)
2980 {
2981    char *buf;
2982    int err, len, x;
2983    
2984    if ((err = mp_radix_size(a, radix, &len)) != MP_OKAY) {
2985       return err;
2986    }
2987
2988    buf = OPT_CAST(char) XMALLOC (len);
2989    if (buf == NULL) {
2990       return MP_MEM;
2991    }
2992    
2993    if ((err = mp_toradix(a, buf, radix)) != MP_OKAY) {
2994       XFREE (buf);
2995       return err;
2996    }
2997    
2998    for (x = 0; x < len; x++) {
2999        if (fputc(buf[x], stream) == EOF) {
3000           XFREE (buf);
3001           return MP_VAL;
3002        }
3003    }
3004    
3005    XFREE (buf);
3006    return MP_OKAY;
3007 }
3008
3009 #endif
3010
3011 /* End: bn_mp_fwrite.c */
3012
3013 /* Start: bn_mp_gcd.c */
3014 #include "tma.h"
3015 #ifdef BN_MP_GCD_C
3016 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3017  *
3018  * LibTomMath is a library that provides multiple-precision
3019  * integer arithmetic as well as number theoretic functionality.
3020  *
3021  * The library was designed directly after the MPI library by
3022  * Michael Fromberger but has been written from scratch with
3023  * additional optimizations in place.
3024  *
3025  * The library is free for all purposes without any express
3026  * guarantee it works.
3027  *
3028  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
3029  */
3030
3031 /* Greatest Common Divisor using the binary method */
3032 int mp_gcd (mp_int * a, mp_int * b, mp_int * c)
3033 {
3034   mp_int  u, v;
3035   int     k, u_lsb, v_lsb, res;
3036
3037   /* either zero than gcd is the largest */
3038   if (mp_iszero (a) == 1 && mp_iszero (b) == 0) {
3039     return mp_abs (b, c);
3040   }
3041   if (mp_iszero (a) == 0 && mp_iszero (b) == 1) {
3042     return mp_abs (a, c);
3043   }
3044
3045   /* optimized.  At this point if a == 0 then
3046    * b must equal zero too
3047    */
3048   if (mp_iszero (a) == 1) {
3049     mp_zero(c);
3050     return MP_OKAY;
3051   }
3052
3053   /* get copies of a and b we can modify */
3054   if ((res = mp_init_copy (&u, a)) != MP_OKAY) {
3055     return res;
3056   }
3057
3058   if ((res = mp_init_copy (&v, b)) != MP_OKAY) {
3059     goto LBL_U;
3060   }
3061
3062   /* must be positive for the remainder of the algorithm */
3063   u.sign = v.sign = MP_ZPOS;
3064
3065   /* B1.  Find the common power of two for u and v */
3066   u_lsb = mp_cnt_lsb(&u);
3067   v_lsb = mp_cnt_lsb(&v);
3068   k     = MIN(u_lsb, v_lsb);
3069
3070   if (k > 0) {
3071      /* divide the power of two out */
3072      if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) {
3073         goto LBL_V;
3074      }
3075
3076      if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) {
3077         goto LBL_V;
3078      }
3079   }
3080
3081   /* divide any remaining factors of two out */
3082   if (u_lsb != k) {
3083      if ((res = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) {
3084         goto LBL_V;
3085      }
3086   }
3087
3088   if (v_lsb != k) {
3089      if ((res = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) {
3090         goto LBL_V;
3091      }
3092   }
3093
3094   while (mp_iszero(&v) == 0) {
3095      /* make sure v is the largest */
3096      if (mp_cmp_mag(&u, &v) == MP_GT) {
3097         /* swap u and v to make sure v is >= u */
3098         mp_exch(&u, &v);
3099      }
3100      
3101      /* subtract smallest from largest */
3102      if ((res = s_mp_sub(&v, &u, &v)) != MP_OKAY) {
3103         goto LBL_V;
3104      }
3105      
3106      /* Divide out all factors of two */
3107      if ((res = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) {
3108         goto LBL_V;
3109      } 
3110   } 
3111
3112   /* multiply by 2**k which we divided out at the beginning */
3113   if ((res = mp_mul_2d (&u, k, c)) != MP_OKAY) {
3114      goto LBL_V;
3115   }
3116   c->sign = MP_ZPOS;
3117   res = MP_OKAY;
3118 LBL_V:mp_clear (&u);
3119 LBL_U:mp_clear (&v);
3120   return res;
3121 }
3122 #endif
3123
3124 /* End: bn_mp_gcd.c */
3125
3126 /* Start: bn_mp_get_int.c */
3127 #include "tma.h"
3128 #ifdef BN_MP_GET_INT_C
3129 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3130  *
3131  * LibTomMath is a library that provides multiple-precision
3132  * integer arithmetic as well as number theoretic functionality.
3133  *
3134  * The library was designed directly after the MPI library by
3135  * Michael Fromberger but has been written from scratch with
3136  * additional optimizations in place.
3137  *
3138  * The library is free for all purposes without any express
3139  * guarantee it works.
3140  *
3141  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
3142  */
3143
3144 /* get the lower 32-bits of an mp_int */
3145 unsigned long mp_get_int(mp_int * a) 
3146 {
3147   int i;
3148   unsigned long res;
3149
3150   if (a->used == 0) {
3151      return 0;
3152   }
3153
3154   /* get number of digits of the lsb we have to read */
3155   i = MIN(a->used,(int)((sizeof(unsigned long)*CHAR_BIT+DIGIT_BIT-1)/DIGIT_BIT))-1;
3156
3157   /* get most significant digit of result */
3158   res = DIGIT(a,i);
3159    
3160   while (--i >= 0) {
3161     res = (res << DIGIT_BIT) | DIGIT(a,i);
3162   }
3163
3164   /* force result to 32-bits always so it is consistent on non 32-bit platforms */
3165   return res & 0xFFFFFFFFUL;
3166 }
3167 #endif
3168
3169 /* End: bn_mp_get_int.c */
3170
3171 /* Start: bn_mp_grow.c */
3172 #include "tma.h"
3173 #ifdef BN_MP_GROW_C
3174 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3175  *
3176  * LibTomMath is a library that provides multiple-precision
3177  * integer arithmetic as well as number theoretic functionality.
3178  *
3179  * The library was designed directly after the MPI library by
3180  * Michael Fromberger but has been written from scratch with
3181  * additional optimizations in place.
3182  *
3183  * The library is free for all purposes without any express
3184  * guarantee it works.
3185  *
3186  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
3187  */
3188
3189 /* grow as required */
3190 int mp_grow (mp_int * a, int size)
3191 {
3192   int     i;
3193   mp_digit *tmp;
3194
3195   /* if the alloc size is smaller alloc more ram */
3196   if (a->alloc < size) {
3197     /* ensure there are always at least MP_PREC digits extra on top */
3198     size += (MP_PREC * 2) - (size % MP_PREC);
3199
3200     /* reallocate the array a->dp
3201      *
3202      * We store the return in a temporary variable
3203      * in case the operation failed we don't want
3204      * to overwrite the dp member of a.
3205      */
3206     tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size);
3207     if (tmp == NULL) {
3208       /* reallocation failed but "a" is still valid [can be freed] */
3209       return MP_MEM;
3210     }
3211
3212     /* reallocation succeeded so set a->dp */
3213     a->dp = tmp;
3214
3215     /* zero excess digits */
3216     i        = a->alloc;
3217     a->alloc = size;
3218     for (; i < a->alloc; i++) {
3219       a->dp[i] = 0;
3220     }
3221   }
3222   return MP_OKAY;
3223 }
3224 #endif
3225
3226 /* End: bn_mp_grow.c */
3227
3228 /* Start: bn_mp_init.c */
3229 #include "tma.h"
3230 #ifdef BN_MP_INIT_C
3231 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3232  *
3233  * LibTomMath is a library that provides multiple-precision
3234  * integer arithmetic as well as number theoretic functionality.
3235  *
3236  * The library was designed directly after the MPI library by
3237  * Michael Fromberger but has been written from scratch with
3238  * additional optimizations in place.
3239  *
3240  * The library is free for all purposes without any express
3241  * guarantee it works.
3242  *
3243  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
3244  */
3245
3246 /* init a new mp_int */
3247 int mp_init (mp_int * a)
3248 {
3249   int i;
3250
3251   /* allocate memory required and clear it */
3252   a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC);
3253   if (a->dp == NULL) {
3254     return MP_MEM;
3255   }
3256
3257   /* set the digits to zero */
3258   for (i = 0; i < MP_PREC; i++) {
3259       a->dp[i] = 0;
3260   }
3261
3262   /* set the used to zero, allocated digits to the default precision
3263    * and sign to positive */
3264   a->used  = 0;
3265   a->alloc = MP_PREC;
3266   a->sign  = MP_ZPOS;
3267
3268   return MP_OKAY;
3269 }
3270 #endif
3271
3272 /* End: bn_mp_init.c */
3273
3274 /* Start: bn_mp_init_copy.c */
3275 #include "tma.h"
3276 #ifdef BN_MP_INIT_COPY_C
3277 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3278  *
3279  * LibTomMath is a library that provides multiple-precision
3280  * integer arithmetic as well as number theoretic functionality.
3281  *
3282  * The library was designed directly after the MPI library by
3283  * Michael Fromberger but has been written from scratch with
3284  * additional optimizations in place.
3285  *
3286  * The library is free for all purposes without any express
3287  * guarantee it works.
3288  *
3289  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
3290  */
3291
3292 /* creates "a" then copies b into it */
3293 int mp_init_copy (mp_int * a, mp_int * b)
3294 {
3295   int     res;
3296
3297   if ((res = mp_init (a)) != MP_OKAY) {
3298     return res;
3299   }
3300   return mp_copy (b, a);
3301 }
3302 #endif
3303
3304 /* End: bn_mp_init_copy.c */
3305
3306 /* Start: bn_mp_init_multi.c */
3307 #include "tma.h"
3308 #ifdef BN_MP_INIT_MULTI_C
3309 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3310  *
3311  * LibTomMath is a library that provides multiple-precision
3312  * integer arithmetic as well as number theoretic functionality.
3313  *
3314  * The library was designed directly after the MPI library by
3315  * Michael Fromberger but has been written from scratch with
3316  * additional optimizations in place.
3317  *
3318  * The library is free for all purposes without any express
3319  * guarantee it works.
3320  *
3321  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
3322  */
3323 #include <stdarg.h>
3324
3325 int mp_init_multi(mp_int *mp, ...) 
3326 {
3327     mp_err res = MP_OKAY;      /* Assume ok until proven otherwise */
3328     int n = 0;                 /* Number of ok inits */
3329     mp_int* cur_arg = mp;
3330     va_list args;
3331
3332     va_start(args, mp);        /* init args to next argument from caller */
3333     while (cur_arg != NULL) {
3334         if (mp_init(cur_arg) != MP_OKAY) {
3335             /* Oops - error! Back-track and mp_clear what we already
3336                succeeded in init-ing, then return error.
3337             */
3338             va_list clean_args;
3339             
3340             /* end the current list */
3341             va_end(args);
3342             
3343             /* now start cleaning up */            
3344             cur_arg = mp;
3345             va_start(clean_args, mp);
3346             while (n--) {
3347                 mp_clear(cur_arg);
3348                 cur_arg = va_arg(clean_args, mp_int*);
3349             }
3350             va_end(clean_args);
3351             res = MP_MEM;
3352             break;
3353         }
3354         n++;
3355         cur_arg = va_arg(args, mp_int*);
3356     }
3357     va_end(args);
3358     return res;                /* Assumed ok, if error flagged above. */
3359 }
3360
3361 #endif
3362
3363 /* End: bn_mp_init_multi.c */
3364
3365 /* Start: bn_mp_init_set.c */
3366 #include "tma.h"
3367 #ifdef BN_MP_INIT_SET_C
3368 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3369  *
3370  * LibTomMath is a library that provides multiple-precision
3371  * integer arithmetic as well as number theoretic functionality.
3372  *
3373  * The library was designed directly after the MPI library by
3374  * Michael Fromberger but has been written from scratch with
3375  * additional optimizations in place.
3376  *
3377  * The library is free for all purposes without any express
3378  * guarantee it works.
3379  *
3380  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
3381  */
3382
3383 /* initialize and set a digit */
3384 int mp_init_set (mp_int * a, mp_digit b)
3385 {
3386   int err;
3387   if ((err = mp_init(a)) != MP_OKAY) {
3388      return err;
3389   }
3390   mp_set(a, b);
3391   return err;
3392 }
3393 #endif
3394
3395 /* End: bn_mp_init_set.c */
3396
3397 /* Start: bn_mp_init_set_int.c */
3398 #include "tma.h"
3399 #ifdef BN_MP_INIT_SET_INT_C
3400 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3401  *
3402  * LibTomMath is a library that provides multiple-precision
3403  * integer arithmetic as well as number theoretic functionality.
3404  *
3405  * The library was designed directly after the MPI library by
3406  * Michael Fromberger but has been written from scratch with
3407  * additional optimizations in place.
3408  *
3409  * The library is free for all purposes without any express
3410  * guarantee it works.
3411  *
3412  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
3413  */
3414
3415 /* initialize and set a digit */
3416 int mp_init_set_int (mp_int * a, unsigned long b)
3417 {
3418   int err;
3419   if ((err = mp_init(a)) != MP_OKAY) {
3420      return err;
3421   }
3422   return mp_set_int(a, b);
3423 }
3424 #endif
3425
3426 /* End: bn_mp_init_set_int.c */
3427
3428 /* Start: bn_mp_init_size.c */
3429 #include "tma.h"
3430 #ifdef BN_MP_INIT_SIZE_C
3431 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3432  *
3433  * LibTomMath is a library that provides multiple-precision
3434  * integer arithmetic as well as number theoretic functionality.
3435  *
3436  * The library was designed directly after the MPI library by
3437  * Michael Fromberger but has been written from scratch with
3438  * additional optimizations in place.
3439  *
3440  * The library is free for all purposes without any express
3441  * guarantee it works.
3442  *
3443  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
3444  */
3445
3446 /* init an mp_init for a given size */
3447 int mp_init_size (mp_int * a, int size)
3448 {
3449   int x;
3450
3451   /* pad size so there are always extra digits */
3452   size += (MP_PREC * 2) - (size % MP_PREC);     
3453   
3454   /* alloc mem */
3455   a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size);
3456   if (a->dp == NULL) {
3457     return MP_MEM;
3458   }
3459
3460   /* set the members */
3461   a->used  = 0;
3462   a->alloc = size;
3463   a->sign  = MP_ZPOS;
3464
3465   /* zero the digits */
3466   for (x = 0; x < size; x++) {
3467       a->dp[x] = 0;
3468   }
3469
3470   return MP_OKAY;
3471 }
3472 #endif
3473
3474 /* End: bn_mp_init_size.c */
3475
3476 /* Start: bn_mp_invmod.c */
3477 #include "tma.h"
3478 #ifdef BN_MP_INVMOD_C
3479 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3480  *
3481  * LibTomMath is a library that provides multiple-precision
3482  * integer arithmetic as well as number theoretic functionality.
3483  *
3484  * The library was designed directly after the MPI library by
3485  * Michael Fromberger but has been written from scratch with
3486  * additional optimizations in place.
3487  *
3488  * The library is free for all purposes without any express
3489  * guarantee it works.
3490  *
3491  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
3492  */
3493
3494 /* hac 14.61, pp608 */
3495 int mp_invmod (mp_int * a, mp_int * b, mp_int * c)
3496 {
3497   /* b cannot be negative */
3498   if (b->sign == MP_NEG || mp_iszero(b) == 1) {
3499     return MP_VAL;
3500   }
3501
3502 #ifdef BN_FAST_MP_INVMOD_C
3503   /* if the modulus is odd we can use a faster routine instead */
3504   if (mp_isodd (b) == 1) {
3505     return fast_mp_invmod (a, b, c);
3506   }
3507 #endif
3508
3509 #ifdef BN_MP_INVMOD_SLOW_C
3510   return mp_invmod_slow(a, b, c);
3511 #endif
3512
3513   return MP_VAL;
3514 }
3515 #endif
3516
3517 /* End: bn_mp_invmod.c */
3518
3519 /* Start: bn_mp_invmod_slow.c */
3520 #include "tma.h"
3521 #ifdef BN_MP_INVMOD_SLOW_C
3522 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3523  *
3524  * LibTomMath is a library that provides multiple-precision
3525  * integer arithmetic as well as number theoretic functionality.
3526  *
3527  * The library was designed directly after the MPI library by
3528  * Michael Fromberger but has been written from scratch with
3529  * additional optimizations in place.
3530  *
3531  * The library is free for all purposes without any express
3532  * guarantee it works.
3533  *
3534  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
3535  */
3536
3537 /* hac 14.61, pp608 */
3538 int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c)
3539 {
3540   mp_int  x, y, u, v, A, B, C, D;
3541   int     res;
3542
3543   /* b cannot be negative */
3544   if (b->sign == MP_NEG || mp_iszero(b) == 1) {
3545     return MP_VAL;
3546   }
3547
3548   /* init temps */
3549   if ((res = mp_init_multi(&x, &y, &u, &v, 
3550                            &A, &B, &C, &D, NULL)) != MP_OKAY) {
3551      return res;
3552   }
3553
3554   /* x = a, y = b */
3555   if ((res = mp_mod(a, b, &x)) != MP_OKAY) {
3556       goto LBL_ERR;
3557   }
3558   if ((res = mp_copy (b, &y)) != MP_OKAY) {
3559     goto LBL_ERR;
3560   }
3561
3562   /* 2. [modified] if x,y are both even then return an error! */
3563   if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) {
3564     res = MP_VAL;
3565     goto LBL_ERR;
3566   }
3567
3568   /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
3569   if ((res = mp_copy (&x, &u)) != MP_OKAY) {
3570     goto LBL_ERR;
3571   }
3572   if ((res = mp_copy (&y, &v)) != MP_OKAY) {
3573     goto LBL_ERR;
3574   }
3575   mp_set (&A, 1);
3576   mp_set (&D, 1);
3577
3578 top:
3579   /* 4.  while u is even do */
3580   while (mp_iseven (&u) == 1) {
3581     /* 4.1 u = u/2 */
3582     if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
3583       goto LBL_ERR;
3584     }
3585     /* 4.2 if A or B is odd then */
3586     if (mp_isodd (&A) == 1 || mp_isodd (&B) == 1) {
3587       /* A = (A+y)/2, B = (B-x)/2 */
3588       if ((res = mp_add (&A, &y, &A)) != MP_OKAY) {
3589          goto LBL_ERR;
3590       }
3591       if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
3592          goto LBL_ERR;
3593       }
3594     }
3595     /* A = A/2, B = B/2 */
3596     if ((res = mp_div_2 (&A, &A)) != MP_OKAY) {
3597       goto LBL_ERR;
3598     }
3599     if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
3600       goto LBL_ERR;
3601     }
3602   }
3603
3604   /* 5.  while v is even do */
3605   while (mp_iseven (&v) == 1) {
3606     /* 5.1 v = v/2 */
3607     if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
3608       goto LBL_ERR;
3609     }
3610     /* 5.2 if C or D is odd then */
3611     if (mp_isodd (&C) == 1 || mp_isodd (&D) == 1) {
3612       /* C = (C+y)/2, D = (D-x)/2 */
3613       if ((res = mp_add (&C, &y, &C)) != MP_OKAY) {
3614          goto LBL_ERR;
3615       }
3616       if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
3617          goto LBL_ERR;
3618       }
3619     }
3620     /* C = C/2, D = D/2 */
3621     if ((res = mp_div_2 (&C, &C)) != MP_OKAY) {
3622       goto LBL_ERR;
3623     }
3624     if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
3625       goto LBL_ERR;
3626     }
3627   }
3628
3629   /* 6.  if u >= v then */
3630   if (mp_cmp (&u, &v) != MP_LT) {
3631     /* u = u - v, A = A - C, B = B - D */
3632     if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
3633       goto LBL_ERR;
3634     }
3635
3636     if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) {
3637       goto LBL_ERR;
3638     }
3639
3640     if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
3641       goto LBL_ERR;
3642     }
3643   } else {
3644     /* v - v - u, C = C - A, D = D - B */
3645     if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
3646       goto LBL_ERR;
3647     }
3648
3649     if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) {
3650       goto LBL_ERR;
3651     }
3652
3653     if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
3654       goto LBL_ERR;
3655     }
3656   }
3657
3658   /* if not zero goto step 4 */
3659   if (mp_iszero (&u) == 0)
3660     goto top;
3661
3662   /* now a = C, b = D, gcd == g*v */
3663
3664   /* if v != 1 then there is no inverse */
3665   if (mp_cmp_d (&v, 1) != MP_EQ) {
3666     res = MP_VAL;
3667     goto LBL_ERR;
3668   }
3669
3670   /* if its too low */
3671   while (mp_cmp_d(&C, 0) == MP_LT) {
3672       if ((res = mp_add(&C, b, &C)) != MP_OKAY) {
3673          goto LBL_ERR;
3674       }
3675   }
3676   
3677   /* too big */
3678   while (mp_cmp_mag(&C, b) != MP_LT) {
3679       if ((res = mp_sub(&C, b, &C)) != MP_OKAY) {
3680          goto LBL_ERR;
3681       }
3682   }
3683   
3684   /* C is now the inverse */
3685   mp_exch (&C, c);
3686   res = MP_OKAY;
3687 LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL);
3688   return res;
3689 }
3690 #endif
3691
3692 /* End: bn_mp_invmod_slow.c */
3693
3694 /* Start: bn_mp_is_square.c */
3695 #include "tma.h"
3696 #ifdef BN_MP_IS_SQUARE_C
3697 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3698  *
3699  * LibTomMath is a library that provides multiple-precision
3700  * integer arithmetic as well as number theoretic functionality.
3701  *
3702  * The library was designed directly after the MPI library by
3703  * Michael Fromberger but has been written from scratch with
3704  * additional optimizations in place.
3705  *
3706  * The library is free for all purposes without any express
3707  * guarantee it works.
3708  *
3709  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
3710  */
3711
3712 /* Check if remainders are possible squares - fast exclude non-squares */
3713 static const char rem_128[128] = {
3714  0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
3715  0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
3716  1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
3717  1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
3718  0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
3719  1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
3720  1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
3721  1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1
3722 };
3723
3724 static const char rem_105[105] = {
3725  0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
3726  0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1,
3727  0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1,
3728  1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
3729  0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
3730  1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1,
3731  1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1
3732 };
3733
3734 /* Store non-zero to ret if arg is square, and zero if not */
3735 int mp_is_square(mp_int *arg,int *ret) 
3736 {
3737   int           res;
3738   mp_digit      c;
3739   mp_int        t;
3740   unsigned long r;
3741
3742   /* Default to Non-square :) */
3743   *ret = MP_NO; 
3744
3745   if (arg->sign == MP_NEG) {
3746     return MP_VAL;
3747   }
3748
3749   /* digits used?  (TSD) */
3750   if (arg->used == 0) {
3751      return MP_OKAY;
3752   }
3753
3754   /* First check mod 128 (suppose that DIGIT_BIT is at least 7) */
3755   if (rem_128[127 & DIGIT(arg,0)] == 1) {
3756      return MP_OKAY;
3757   }
3758
3759   /* Next check mod 105 (3*5*7) */
3760   if ((res = mp_mod_d(arg,105,&c)) != MP_OKAY) {
3761      return res;
3762   }
3763   if (rem_105[c] == 1) {
3764      return MP_OKAY;
3765   }
3766
3767
3768   if ((res = mp_init_set_int(&t,11L*13L*17L*19L*23L*29L*31L)) != MP_OKAY) {
3769      return res;
3770   }
3771   if ((res = mp_mod(arg,&t,&t)) != MP_OKAY) {
3772      goto ERR;
3773   }
3774   r = mp_get_int(&t);
3775   /* Check for other prime modules, note it's not an ERROR but we must
3776    * free "t" so the easiest way is to goto ERR.  We know that res
3777    * is already equal to MP_OKAY from the mp_mod call 
3778    */ 
3779   if ( (1L<<(r%11)) & 0x5C4L )             goto ERR;
3780   if ( (1L<<(r%13)) & 0x9E4L )             goto ERR;
3781   if ( (1L<<(r%17)) & 0x5CE8L )            goto ERR;
3782   if ( (1L<<(r%19)) & 0x4F50CL )           goto ERR;
3783   if ( (1L<<(r%23)) & 0x7ACCA0L )          goto ERR;
3784   if ( (1L<<(r%29)) & 0xC2EDD0CL )         goto ERR;
3785   if ( (1L<<(r%31)) & 0x6DE2B848L )        goto ERR;
3786
3787   /* Final check - is sqr(sqrt(arg)) == arg ? */
3788   if ((res = mp_sqrt(arg,&t)) != MP_OKAY) {
3789      goto ERR;
3790   }
3791   if ((res = mp_sqr(&t,&t)) != MP_OKAY) {
3792      goto ERR;
3793   }
3794
3795   *ret = (mp_cmp_mag(&t,arg) == MP_EQ) ? MP_YES : MP_NO;
3796 ERR:mp_clear(&t);
3797   return res;
3798 }
3799 #endif
3800
3801 /* End: bn_mp_is_square.c */
3802
3803 /* Start: bn_mp_jacobi.c */
3804 #include "tma.h"
3805 #ifdef BN_MP_JACOBI_C
3806 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3807  *
3808  * LibTomMath is a library that provides multiple-precision
3809  * integer arithmetic as well as number theoretic functionality.
3810  *
3811  * The library was designed directly after the MPI library by
3812  * Michael Fromberger but has been written from scratch with
3813  * additional optimizations in place.
3814  *
3815  * The library is free for all purposes without any express
3816  * guarantee it works.
3817  *
3818  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
3819  */
3820
3821 /* computes the jacobi c = (a | n) (or Legendre if n is prime)
3822  * HAC pp. 73 Algorithm 2.149
3823  */
3824 int mp_jacobi (mp_int * a, mp_int * p, int *c)
3825 {
3826   mp_int  a1, p1;
3827   int     k, s, r, res;
3828   mp_digit residue;
3829
3830   /* if p <= 0 return MP_VAL */
3831   if (mp_cmp_d(p, 0) != MP_GT) {
3832      return MP_VAL;
3833   }
3834
3835   /* step 1.  if a == 0, return 0 */
3836   if (mp_iszero (a) == 1) {
3837     *c = 0;
3838     return MP_OKAY;
3839   }
3840
3841   /* step 2.  if a == 1, return 1 */
3842   if (mp_cmp_d (a, 1) == MP_EQ) {
3843     *c = 1;
3844     return MP_OKAY;
3845   }
3846
3847   /* default */
3848   s = 0;
3849
3850   /* step 3.  write a = a1 * 2**k  */
3851   if ((res = mp_init_copy (&a1, a)) != MP_OKAY) {
3852     return res;
3853   }
3854
3855   if ((res = mp_init (&p1)) != MP_OKAY) {
3856     goto LBL_A1;
3857   }
3858
3859   /* divide out larger power of two */
3860   k = mp_cnt_lsb(&a1);
3861   if ((res = mp_div_2d(&a1, k, &a1, NULL)) != MP_OKAY) {
3862      goto LBL_P1;
3863   }
3864
3865   /* step 4.  if e is even set s=1 */
3866   if ((k & 1) == 0) {
3867     s = 1;
3868   } else {
3869     /* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */
3870     residue = p->dp[0] & 7;
3871
3872     if (residue == 1 || residue == 7) {
3873       s = 1;
3874     } else if (residue == 3 || residue == 5) {
3875       s = -1;
3876     }
3877   }
3878
3879   /* step 5.  if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */
3880   if ( ((p->dp[0] & 3) == 3) && ((a1.dp[0] & 3) == 3)) {
3881     s = -s;
3882   }
3883
3884   /* if a1 == 1 we're done */
3885   if (mp_cmp_d (&a1, 1) == MP_EQ) {
3886     *c = s;
3887   } else {
3888     /* n1 = n mod a1 */
3889     if ((res = mp_mod (p, &a1, &p1)) != MP_OKAY) {
3890       goto LBL_P1;
3891     }
3892     if ((res = mp_jacobi (&p1, &a1, &r)) != MP_OKAY) {
3893       goto LBL_P1;
3894     }
3895     *c = s * r;
3896   }
3897
3898   /* done */
3899   res = MP_OKAY;
3900 LBL_P1:mp_clear (&p1);
3901 LBL_A1:mp_clear (&a1);
3902   return res;
3903 }
3904 #endif
3905
3906 /* End: bn_mp_jacobi.c */
3907
3908 /* Start: bn_mp_karatsuba_mul.c */
3909 #include "tma.h"
3910 #ifdef BN_MP_KARATSUBA_MUL_C
3911 /* LibTomMath, multiple-precision integer library -- Tom St Denis
3912  *
3913  * LibTomMath is a library that provides multiple-precision
3914  * integer arithmetic as well as number theoretic functionality.
3915  *
3916  * The library was designed directly after the MPI library by
3917  * Michael Fromberger but has been written from scratch with
3918  * additional optimizations in place.
3919  *
3920  * The library is free for all purposes without any express
3921  * guarantee it works.
3922  *
3923  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
3924  */
3925
3926 /* c = |a| * |b| using Karatsuba Multiplication using 
3927  * three half size multiplications
3928  *
3929  * Let B represent the radix [e.g. 2**DIGIT_BIT] and 
3930  * let n represent half of the number of digits in 
3931  * the min(a,b)
3932  *
3933  * a = a1 * B**n + a0
3934  * b = b1 * B**n + b0
3935  *
3936  * Then, a * b => 
3937    a1b1 * B**2n + ((a1 - a0)(b1 - b0) + a0b0 + a1b1) * B + a0b0
3938  *
3939  * Note that a1b1 and a0b0 are used twice and only need to be 
3940  * computed once.  So in total three half size (half # of 
3941  * digit) multiplications are performed, a0b0, a1b1 and 
3942  * (a1-b1)(a0-b0)
3943  *
3944  * Note that a multiplication of half the digits requires
3945  * 1/4th the number of single precision multiplications so in 
3946  * total after one call 25% of the single precision multiplications 
3947  * are saved.  Note also that the call to mp_mul can end up back 
3948  * in this function if the a0, a1, b0, or b1 are above the threshold.  
3949  * This is known as divide-and-conquer and leads to the famous 
3950  * O(N**lg(3)) or O(N**1.584) work which is asymptopically lower than 
3951  * the standard O(N**2) that the baseline/comba methods use.  
3952  * Generally though the overhead of this method doesn't pay off 
3953  * until a certain size (N ~ 80) is reached.
3954  */
3955 int mp_karatsuba_mul (mp_int * a, mp_int * b, mp_int * c)
3956 {
3957   mp_int  x0, x1, y0, y1, t1, x0y0, x1y1;
3958   int     B, err;
3959
3960   /* default the return code to an error */
3961   err = MP_MEM;
3962
3963   /* min # of digits */
3964   B = MIN (a->used, b->used);
3965
3966   /* now divide in two */
3967   B = B >> 1;
3968
3969   /* init copy all the temps */
3970   if (mp_init_size (&x0, B) != MP_OKAY)
3971     goto ERR;
3972   if (mp_init_size (&x1, a->used - B) != MP_OKAY)
3973     goto X0;
3974   if (mp_init_size (&y0, B) != MP_OKAY)
3975     goto X1;
3976   if (mp_init_size (&y1, b->used - B) != MP_OKAY)
3977     goto Y0;
3978
3979   /* init temps */
3980   if (mp_init_size (&t1, B * 2) != MP_OKAY)
3981     goto Y1;
3982   if (mp_init_size (&x0y0, B * 2) != MP_OKAY)
3983     goto T1;
3984   if (mp_init_size (&x1y1, B * 2) != MP_OKAY)
3985     goto X0Y0;
3986
3987   /* now shift the digits */
3988   x0.used = y0.used = B;
3989   x1.used = a->used - B;
3990   y1.used = b->used - B;
3991
3992   {
3993     register int x;
3994     register mp_digit *tmpa, *tmpb, *tmpx, *tmpy;
3995
3996     /* we copy the digits directly instead of using higher level functions
3997      * since we also need to shift the digits
3998      */
3999     tmpa = a->dp;
4000     tmpb = b->dp;
4001
4002     tmpx = x0.dp;
4003     tmpy = y0.dp;
4004     for (x = 0; x < B; x++) {
4005       *tmpx++ = *tmpa++;
4006       *tmpy++ = *tmpb++;
4007     }
4008
4009     tmpx = x1.dp;
4010     for (x = B; x < a->used; x++) {
4011       *tmpx++ = *tmpa++;
4012     }
4013
4014     tmpy = y1.dp;
4015     for (x = B; x < b->used; x++) {
4016       *tmpy++ = *tmpb++;
4017     }
4018   }
4019
4020   /* only need to clamp the lower words since by definition the 
4021    * upper words x1/y1 must have a known number of digits
4022    */
4023   mp_clamp (&x0);
4024   mp_clamp (&y0);
4025
4026   /* now calc the products x0y0 and x1y1 */
4027   /* after this x0 is no longer required, free temp [x0==t2]! */
4028   if (mp_mul (&x0, &y0, &x0y0) != MP_OKAY)  
4029     goto X1Y1;          /* x0y0 = x0*y0 */
4030   if (mp_mul (&x1, &y1, &x1y1) != MP_OKAY)
4031     goto X1Y1;          /* x1y1 = x1*y1 */
4032
4033   /* now calc x1-x0 and y1-y0 */
4034   if (mp_sub (&x1, &x0, &t1) != MP_OKAY)
4035     goto X1Y1;          /* t1 = x1 - x0 */
4036   if (mp_sub (&y1, &y0, &x0) != MP_OKAY)
4037     goto X1Y1;          /* t2 = y1 - y0 */
4038   if (mp_mul (&t1, &x0, &t1) != MP_OKAY)
4039     goto X1Y1;          /* t1 = (x1 - x0) * (y1 - y0) */
4040
4041   /* add x0y0 */
4042   if (mp_add (&x0y0, &x1y1, &x0) != MP_OKAY)
4043     goto X1Y1;          /* t2 = x0y0 + x1y1 */
4044   if (mp_sub (&x0, &t1, &t1) != MP_OKAY)
4045     goto X1Y1;          /* t1 = x0y0 + x1y1 - (x1-x0)*(y1-y0) */
4046
4047   /* shift by B */
4048   if (mp_lshd (&t1, B) != MP_OKAY)
4049     goto X1Y1;          /* t1 = (x0y0 + x1y1 - (x1-x0)*(y1-y0))<<B */
4050   if (mp_lshd (&x1y1, B * 2) != MP_OKAY)
4051     goto X1Y1;          /* x1y1 = x1y1 << 2*B */
4052
4053   if (mp_add (&x0y0, &t1, &t1) != MP_OKAY)
4054     goto X1Y1;          /* t1 = x0y0 + t1 */
4055   if (mp_add (&t1, &x1y1, c) != MP_OKAY)
4056     goto X1Y1;          /* t1 = x0y0 + t1 + x1y1 */
4057
4058   /* Algorithm succeeded set the return code to MP_OKAY */
4059   err = MP_OKAY;
4060
4061 X1Y1:mp_clear (&x1y1);
4062 X0Y0:mp_clear (&x0y0);
4063 T1:mp_clear (&t1);
4064 Y1:mp_clear (&y1);
4065 Y0:mp_clear (&y0);
4066 X1:mp_clear (&x1);
4067 X0:mp_clear (&x0);
4068 ERR:
4069   return err;
4070 }
4071 #endif
4072
4073 /* End: bn_mp_karatsuba_mul.c */
4074
4075 /* Start: bn_mp_karatsuba_sqr.c */
4076 #include "tma.h"
4077 #ifdef BN_MP_KARATSUBA_SQR_C
4078 /* LibTomMath, multiple-precision integer library -- Tom St Denis
4079  *
4080  * LibTomMath is a library that provides multiple-precision
4081  * integer arithmetic as well as number theoretic functionality.
4082  *
4083  * The library was designed directly after the MPI library by
4084  * Michael Fromberger but has been written from scratch with
4085  * additional optimizations in place.
4086  *
4087  * The library is free for all purposes without any express
4088  * guarantee it works.
4089  *
4090  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
4091  */
4092
4093 /* Karatsuba squaring, computes b = a*a using three 
4094  * half size squarings
4095  *
4096  * See comments of karatsuba_mul for details.  It 
4097  * is essentially the same algorithm but merely 
4098  * tuned to perform recursive squarings.
4099  */
4100 int mp_karatsuba_sqr (mp_int * a, mp_int * b)
4101 {
4102   mp_int  x0, x1, t1, t2, x0x0, x1x1;
4103   int     B, err;
4104
4105   err = MP_MEM;
4106
4107   /* min # of digits */
4108   B = a->used;
4109
4110   /* now divide in two */
4111   B = B >> 1;
4112
4113   /* init copy all the temps */
4114   if (mp_init_size (&x0, B) != MP_OKAY)
4115     goto ERR;
4116   if (mp_init_size (&x1, a->used - B) != MP_OKAY)
4117     goto X0;
4118
4119   /* init temps */
4120   if (mp_init_size (&t1, a->used * 2) != MP_OKAY)
4121     goto X1;
4122   if (mp_init_size (&t2, a->used * 2) != MP_OKAY)
4123     goto T1;
4124   if (mp_init_size (&x0x0, B * 2) != MP_OKAY)
4125     goto T2;
4126   if (mp_init_size (&x1x1, (a->used - B) * 2) != MP_OKAY)
4127     goto X0X0;
4128
4129   {
4130     register int x;
4131     register mp_digit *dst, *src;
4132
4133     src = a->dp;
4134
4135     /* now shift the digits */
4136     dst = x0.dp;
4137     for (x = 0; x < B; x++) {
4138       *dst++ = *src++;
4139     }
4140
4141     dst = x1.dp;
4142     for (x = B; x < a->used; x++) {
4143       *dst++ = *src++;
4144     }
4145   }
4146
4147   x0.used = B;
4148   x1.used = a->used - B;
4149
4150   mp_clamp (&x0);
4151
4152   /* now calc the products x0*x0 and x1*x1 */
4153   if (mp_sqr (&x0, &x0x0) != MP_OKAY)
4154     goto X1X1;           /* x0x0 = x0*x0 */
4155   if (mp_sqr (&x1, &x1x1) != MP_OKAY)
4156     goto X1X1;           /* x1x1 = x1*x1 */
4157
4158   /* now calc (x1-x0)**2 */
4159   if (mp_sub (&x1, &x0, &t1) != MP_OKAY)
4160     goto X1X1;           /* t1 = x1 - x0 */
4161   if (mp_sqr (&t1, &t1) != MP_OKAY)
4162     goto X1X1;           /* t1 = (x1 - x0) * (x1 - x0) */
4163
4164   /* add x0y0 */
4165   if (s_mp_add (&x0x0, &x1x1, &t2) != MP_OKAY)
4166     goto X1X1;           /* t2 = x0x0 + x1x1 */
4167   if (mp_sub (&t2, &t1, &t1) != MP_OKAY)
4168     goto X1X1;           /* t1 = x0x0 + x1x1 - (x1-x0)*(x1-x0) */
4169
4170   /* shift by B */
4171   if (mp_lshd (&t1, B) != MP_OKAY)
4172     goto X1X1;           /* t1 = (x0x0 + x1x1 - (x1-x0)*(x1-x0))<<B */
4173   if (mp_lshd (&x1x1, B * 2) != MP_OKAY)
4174     goto X1X1;           /* x1x1 = x1x1 << 2*B */
4175
4176   if (mp_add (&x0x0, &t1, &t1) != MP_OKAY)
4177     goto X1X1;           /* t1 = x0x0 + t1 */
4178   if (mp_add (&t1, &x1x1, b) != MP_OKAY)
4179     goto X1X1;           /* t1 = x0x0 + t1 + x1x1 */
4180
4181   err = MP_OKAY;
4182
4183 X1X1:mp_clear (&x1x1);
4184 X0X0:mp_clear (&x0x0);
4185 T2:mp_clear (&t2);
4186 T1:mp_clear (&t1);
4187 X1:mp_clear (&x1);
4188 X0:mp_clear (&x0);
4189 ERR:
4190   return err;
4191 }
4192 #endif
4193
4194 /* End: bn_mp_karatsuba_sqr.c */
4195
4196 /* Start: bn_mp_lcm.c */
4197 #include "tma.h"
4198 #ifdef BN_MP_LCM_C
4199 /* LibTomMath, multiple-precision integer library -- Tom St Denis
4200  *
4201  * LibTomMath is a library that provides multiple-precision
4202  * integer arithmetic as well as number theoretic functionality.
4203  *
4204  * The library was designed directly after the MPI library by
4205  * Michael Fromberger but has been written from scratch with
4206  * additional optimizations in place.
4207  *
4208  * The library is free for all purposes without any express
4209  * guarantee it works.
4210  *
4211  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
4212  */
4213
4214 /* computes least common multiple as |a*b|/(a, b) */
4215 int mp_lcm (mp_int * a, mp_int * b, mp_int * c)
4216 {
4217   int     res;
4218   mp_int  t1, t2;
4219
4220
4221   if ((res = mp_init_multi (&t1, &t2, NULL)) != MP_OKAY) {
4222     return res;
4223   }
4224
4225   /* t1 = get the GCD of the two inputs */
4226   if ((res = mp_gcd (a, b, &t1)) != MP_OKAY) {
4227     goto LBL_T;
4228   }
4229
4230   /* divide the smallest by the GCD */
4231   if (mp_cmp_mag(a, b) == MP_LT) {
4232      /* store quotient in t2 such that t2 * b is the LCM */
4233      if ((res = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) {
4234         goto LBL_T;
4235      }
4236      res = mp_mul(b, &t2, c);
4237   } else {
4238      /* store quotient in t2 such that t2 * a is the LCM */
4239      if ((res = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) {
4240         goto LBL_T;
4241      }
4242      res = mp_mul(a, &t2, c);
4243   }
4244
4245   /* fix the sign to positive */
4246   c->sign = MP_ZPOS;
4247
4248 LBL_T:
4249   mp_clear_multi (&t1, &t2, NULL);
4250   return res;
4251 }
4252 #endif
4253
4254 /* End: bn_mp_lcm.c */
4255
4256 /* Start: bn_mp_lshd.c */
4257 #include "tma.h"
4258 #ifdef BN_MP_LSHD_C
4259 /* LibTomMath, multiple-precision integer library -- Tom St Denis
4260  *
4261  * LibTomMath is a library that provides multiple-precision
4262  * integer arithmetic as well as number theoretic functionality.
4263  *
4264  * The library was designed directly after the MPI library by
4265  * Michael Fromberger but has been written from scratch with
4266  * additional optimizations in place.
4267  *
4268  * The library is free for all purposes without any express
4269  * guarantee it works.
4270  *
4271  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
4272  */
4273
4274 /* shift left a certain amount of digits */
4275 int mp_lshd (mp_int * a, int b)
4276 {
4277   int     x, res;
4278
4279   /* if its less than zero return */
4280   if (b <= 0) {
4281     return MP_OKAY;
4282   }
4283
4284   /* grow to fit the new digits */
4285   if (a->alloc < a->used + b) {
4286      if ((res = mp_grow (a, a->used + b)) != MP_OKAY) {
4287        return res;
4288      }
4289   }
4290
4291   {
4292     register mp_digit *top, *bottom;
4293
4294     /* increment the used by the shift amount then copy upwards */
4295     a->used += b;
4296
4297     /* top */
4298     top = a->dp + a->used - 1;
4299
4300     /* base */
4301     bottom = a->dp + a->used - 1 - b;
4302
4303     /* much like mp_rshd this is implemented using a sliding window
4304      * except the window goes the otherway around.  Copying from
4305      * the bottom to the top.  see bn_mp_rshd.c for more info.
4306      */
4307     for (x = a->used - 1; x >= b; x--) {
4308       *top-- = *bottom--;
4309     }
4310
4311     /* zero the lower digits */
4312     top = a->dp;
4313     for (x = 0; x < b; x++) {
4314       *top++ = 0;
4315     }
4316   }
4317   return MP_OKAY;
4318 }
4319 #endif
4320
4321 /* End: bn_mp_lshd.c */
4322
4323 /* Start: bn_mp_mod.c */
4324 #include "tma.h"
4325 #ifdef BN_MP_MOD_C
4326 /* LibTomMath, multiple-precision integer library -- Tom St Denis
4327  *
4328  * LibTomMath is a library that provides multiple-precision
4329  * integer arithmetic as well as number theoretic functionality.
4330  *
4331  * The library was designed directly after the MPI library by
4332  * Michael Fromberger but has been written from scratch with
4333  * additional optimizations in place.
4334  *
4335  * The library is free for all purposes without any express
4336  * guarantee it works.
4337  *
4338  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
4339  */
4340
4341 /* c = a mod b, 0 <= c < b */
4342 int
4343 mp_mod (mp_int * a, mp_int * b, mp_int * c)
4344 {
4345   mp_int  t;
4346   int     res;
4347
4348   if ((res = mp_init (&t)) != MP_OKAY) {
4349     return res;
4350   }
4351
4352   if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) {
4353     mp_clear (&t);
4354     return res;
4355   }
4356
4357   if (t.sign != b->sign) {
4358     res = mp_add (b, &t, c);
4359   } else {
4360     res = MP_OKAY;
4361     mp_exch (&t, c);
4362   }
4363
4364   mp_clear (&t);
4365   return res;
4366 }
4367 #endif
4368
4369 /* End: bn_mp_mod.c */
4370
4371 /* Start: bn_mp_mod_2d.c */
4372 #include "tma.h"
4373 #ifdef BN_MP_MOD_2D_C
4374 /* LibTomMath, multiple-precision integer library -- Tom St Denis
4375  *
4376  * LibTomMath is a library that provides multiple-precision
4377  * integer arithmetic as well as number theoretic functionality.
4378  *
4379  * The library was designed directly after the MPI library by
4380  * Michael Fromberger but has been written from scratch with
4381  * additional optimizations in place.
4382  *
4383  * The library is free for all purposes without any express
4384  * guarantee it works.
4385  *
4386  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
4387  */
4388
4389 /* calc a value mod 2**b */
4390 int
4391 mp_mod_2d (mp_int * a, int b, mp_int * c)
4392 {
4393   int     x, res;
4394
4395   /* if b is <= 0 then zero the int */
4396   if (b <= 0) {
4397     mp_zero (c);
4398     return MP_OKAY;
4399   }
4400
4401   /* if the modulus is larger than the value than return */
4402   if (b >= (int) (a->used * DIGIT_BIT)) {
4403     res = mp_copy (a, c);
4404     return res;
4405   }
4406
4407   /* copy */
4408   if ((res = mp_copy (a, c)) != MP_OKAY) {
4409     return res;
4410   }
4411
4412   /* zero digits above the last digit of the modulus */
4413   for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) {
4414     c->dp[x] = 0;
4415   }
4416   /* clear the digit that is not completely outside/inside the modulus */
4417   c->dp[b / DIGIT_BIT] &=
4418     (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1));
4419   mp_clamp (c);
4420   return MP_OKAY;
4421 }
4422 #endif
4423
4424 /* End: bn_mp_mod_2d.c */
4425
4426 /* Start: bn_mp_mod_d.c */
4427 #include "tma.h"
4428 #ifdef BN_MP_MOD_D_C
4429 /* LibTomMath, multiple-precision integer library -- Tom St Denis
4430  *
4431  * LibTomMath is a library that provides multiple-precision
4432  * integer arithmetic as well as number theoretic functionality.
4433  *
4434  * The library was designed directly after the MPI library by
4435  * Michael Fromberger but has been written from scratch with
4436  * additional optimizations in place.
4437  *
4438  * The library is free for all purposes without any express
4439  * guarantee it works.
4440  *
4441  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
4442  */
4443
4444 int
4445 mp_mod_d (mp_int * a, mp_digit b, mp_digit * c)
4446 {
4447   return mp_div_d(a, b, NULL, c);
4448 }
4449 #endif
4450
4451 /* End: bn_mp_mod_d.c */
4452
4453 /* Start: bn_mp_montgomery_calc_normalization.c */
4454 #include "tma.h"
4455 #ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
4456 /* LibTomMath, multiple-precision integer library -- Tom St Denis
4457  *
4458  * LibTomMath is a library that provides multiple-precision
4459  * integer arithmetic as well as number theoretic functionality.
4460  *
4461  * The library was designed directly after the MPI library by
4462  * Michael Fromberger but has been written from scratch with
4463  * additional optimizations in place.
4464  *
4465  * The library is free for all purposes without any express
4466  * guarantee it works.
4467  *
4468  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
4469  */
4470
4471 /*
4472  * shifts with subtractions when the result is greater than b.
4473  *
4474  * The method is slightly modified to shift B unconditionally upto just under
4475  * the leading bit of b.  This saves alot of multiple precision shifting.
4476  */
4477 int mp_montgomery_calc_normalization (mp_int * a, mp_int * b)
4478 {
4479   int     x, bits, res;
4480
4481   /* how many bits of last digit does b use */
4482   bits = mp_count_bits (b) % DIGIT_BIT;
4483
4484   if (b->used > 1) {
4485      if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) {
4486         return res;
4487      }
4488   } else {
4489      mp_set(a, 1);
4490      bits = 1;
4491   }
4492
4493
4494   /* now compute C = A * B mod b */
4495   for (x = bits - 1; x < (int)DIGIT_BIT; x++) {
4496     if ((res = mp_mul_2 (a, a)) != MP_OKAY) {
4497       return res;
4498     }
4499     if (mp_cmp_mag (a, b) != MP_LT) {
4500       if ((res = s_mp_sub (a, b, a)) != MP_OKAY) {
4501         return res;
4502       }
4503     }
4504   }
4505
4506   return MP_OKAY;
4507 }
4508 #endif
4509
4510 /* End: bn_mp_montgomery_calc_normalization.c */
4511
4512 /* Start: bn_mp_montgomery_reduce.c */
4513 #include "tma.h"
4514 #ifdef BN_MP_MONTGOMERY_REDUCE_C
4515 /* LibTomMath, multiple-precision integer library -- Tom St Denis
4516  *
4517  * LibTomMath is a library that provides multiple-precision
4518  * integer arithmetic as well as number theoretic functionality.
4519  *
4520  * The library was designed directly after the MPI library by
4521  * Michael Fromberger but has been written from scratch with
4522  * additional optimizations in place.
4523  *
4524  * The library is free for all purposes without any express
4525  * guarantee it works.
4526  *
4527  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
4528  */
4529
4530 /* computes xR**-1 == x (mod N) via Montgomery Reduction */
4531 int
4532 mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
4533 {
4534   int     ix, res, digs;
4535   mp_digit mu;
4536
4537   /* can the fast reduction [comba] method be used?
4538    *
4539    * Note that unlike in mul you're safely allowed *less*
4540    * than the available columns [255 per default] since carries
4541    * are fixed up in the inner loop.
4542    */
4543   digs = n->used * 2 + 1;
4544   if ((digs < MP_WARRAY) &&
4545       n->used <
4546       (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
4547     return fast_mp_montgomery_reduce (x, n, rho);
4548   }
4549
4550   /* grow the input as required */
4551   if (x->alloc < digs) {
4552     if ((res = mp_grow (x, digs)) != MP_OKAY) {
4553       return res;
4554     }
4555   }
4556   x->used = digs;
4557
4558   for (ix = 0; ix < n->used; ix++) {
4559     /* mu = ai * rho mod b
4560      *
4561      * The value of rho must be precalculated via
4562      * montgomery_setup() such that
4563      * it equals -1/n0 mod b this allows the
4564      * following inner loop to reduce the
4565      * input one digit at a time
4566      */
4567     mu = (mp_digit) (((mp_word)x->dp[ix]) * ((mp_word)rho) & MP_MASK);
4568
4569     /* a = a + mu * m * b**i */
4570     {
4571       register int iy;
4572       register mp_digit *tmpn, *tmpx, u;
4573       register mp_word r;
4574
4575       /* alias for digits of the modulus */
4576       tmpn = n->dp;
4577
4578       /* alias for the digits of x [the input] */
4579       tmpx = x->dp + ix;
4580
4581       /* set the carry to zero */
4582       u = 0;
4583
4584       /* Multiply and add in place */
4585       for (iy = 0; iy < n->used; iy++) {
4586         /* compute product and sum */
4587         r       = ((mp_word)mu) * ((mp_word)*tmpn++) +
4588                   ((mp_word) u) + ((mp_word) * tmpx);
4589
4590         /* get carry */
4591         u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
4592
4593         /* fix digit */
4594         *tmpx++ = (mp_digit)(r & ((mp_word) MP_MASK));
4595       }
4596       /* At this point the ix'th digit of x should be zero */
4597
4598
4599       /* propagate carries upwards as required*/
4600       while (u) {
4601         *tmpx   += u;
4602         u        = *tmpx >> DIGIT_BIT;
4603         *tmpx++ &= MP_MASK;
4604       }
4605     }
4606   }
4607
4608   /* at this point the n.used'th least
4609    * significant digits of x are all zero
4610    * which means we can shift x to the
4611    * right by n.used digits and the
4612    * residue is unchanged.
4613    */
4614
4615   /* x = x/b**n.used */
4616   mp_clamp(x);
4617   mp_rshd (x, n->used);
4618
4619   /* if x >= n then x = x - n */
4620   if (mp_cmp_mag (x, n) != MP_LT) {
4621     return s_mp_sub (x, n, x);
4622   }
4623
4624   return MP_OKAY;
4625 }
4626 #endif
4627
4628 /* End: bn_mp_montgomery_reduce.c */
4629
4630 /* Start: bn_mp_montgomery_setup.c */
4631 #include "tma.h"
4632 #ifdef BN_MP_MONTGOMERY_SETUP_C
4633 /* LibTomMath, multiple-precision integer library -- Tom St Denis
4634  *
4635  * LibTomMath is a library that provides multiple-precision
4636  * integer arithmetic as well as number theoretic functionality.
4637  *
4638  * The library was designed directly after the MPI library by
4639  * Michael Fromberger but has been written from scratch with
4640  * additional optimizations in place.
4641  *
4642  * The library is free for all purposes without any express
4643  * guarantee it works.
4644  *
4645  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
4646  */
4647
4648 /* setups the montgomery reduction stuff */
4649 int
4650 mp_montgomery_setup (mp_int * n, mp_digit * rho)
4651 {
4652   mp_digit x, b;
4653
4654 /* fast inversion mod 2**k
4655  *
4656  * Based on the fact that
4657  *
4658  * XA = 1 (mod 2**n)  =>  (X(2-XA)) A = 1 (mod 2**2n)
4659  *                    =>  2*X*A - X*X*A*A = 1
4660  *                    =>  2*(1) - (1)     = 1
4661  */
4662   b = n->dp[0];
4663
4664   if ((b & 1) == 0) {
4665     return MP_VAL;
4666   }
4667
4668   x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
4669   x *= 2 - b * x;               /* here x*a==1 mod 2**8 */
4670 #if !defined(MP_8BIT)
4671   x *= 2 - b * x;               /* here x*a==1 mod 2**16 */
4672 #endif
4673 #if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT))
4674   x *= 2 - b * x;               /* here x*a==1 mod 2**32 */
4675 #endif
4676 #ifdef MP_64BIT
4677   x *= 2 - b * x;               /* here x*a==1 mod 2**64 */
4678 #endif
4679
4680   /* rho = -1/m mod b */
4681   *rho = (((mp_word)1 << ((mp_word) DIGIT_BIT)) - x) & MP_MASK;
4682
4683   return MP_OKAY;
4684 }
4685 #endif
4686
4687 /* End: bn_mp_montgomery_setup.c */
4688
4689 /* Start: bn_mp_mul.c */
4690 #include "tma.h"
4691 #ifdef BN_MP_MUL_C
4692 /* LibTomMath, multiple-precision integer library -- Tom St Denis
4693  *
4694  * LibTomMath is a library that provides multiple-precision
4695  * integer arithmetic as well as number theoretic functionality.
4696  *
4697  * The library was designed directly after the MPI library by
4698  * Michael Fromberger but has been written from scratch with
4699  * additional optimizations in place.
4700  *
4701  * The library is free for all purposes without any express
4702  * guarantee it works.
4703  *
4704  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
4705  */
4706
4707 /* high level multiplication (handles sign) */
4708 int mp_mul (mp_int * a, mp_int * b, mp_int * c)
4709 {
4710   int     res, neg;
4711   neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
4712
4713   /* use Toom-Cook? */
4714 #ifdef BN_MP_TOOM_MUL_C
4715   if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) {
4716     res = mp_toom_mul(a, b, c);
4717   } else 
4718 #endif
4719 #ifdef BN_MP_KARATSUBA_MUL_C
4720   /* use Karatsuba? */
4721   if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) {
4722     res = mp_karatsuba_mul (a, b, c);
4723   } else 
4724 #endif
4725   {
4726     /* can we use the fast multiplier?
4727      *
4728      * The fast multiplier can be used if the output will 
4729      * have less than MP_WARRAY digits and the number of 
4730      * digits won't affect carry propagation
4731      */
4732     int     digs = a->used + b->used + 1;
4733
4734 #ifdef BN_FAST_S_MP_MUL_DIGS_C
4735     if ((digs < MP_WARRAY) &&
4736         MIN(a->used, b->used) <= 
4737         (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
4738       res = fast_s_mp_mul_digs (a, b, c, digs);
4739     } else 
4740 #endif
4741 #ifdef BN_S_MP_MUL_DIGS_C
4742       res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */
4743 #else
4744       res = MP_VAL;
4745 #endif
4746
4747   }
4748   c->sign = (c->used > 0) ? neg : MP_ZPOS;
4749   return res;
4750 }
4751 #endif
4752
4753 /* End: bn_mp_mul.c */
4754
4755 /* Start: bn_mp_mul_2.c */
4756 #include "tma.h"
4757 #ifdef BN_MP_MUL_2_C
4758 /* LibTomMath, multiple-precision integer library -- Tom St Denis
4759  *
4760  * LibTomMath is a library that provides multiple-precision
4761  * integer arithmetic as well as number theoretic functionality.
4762  *
4763  * The library was designed directly after the MPI library by
4764  * Michael Fromberger but has been written from scratch with
4765  * additional optimizations in place.
4766  *
4767  * The library is free for all purposes without any express
4768  * guarantee it works.
4769  *
4770  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
4771  */
4772
4773 /* b = a*2 */
4774 int mp_mul_2(mp_int * a, mp_int * b)
4775 {
4776   int     x, res, oldused;
4777
4778   /* grow to accomodate result */
4779   if (b->alloc < a->used + 1) {
4780     if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) {
4781       return res;
4782     }
4783   }
4784
4785   oldused = b->used;
4786   b->used = a->used;
4787
4788   {
4789     register mp_digit r, rr, *tmpa, *tmpb;
4790
4791     /* alias for source */
4792     tmpa = a->dp;
4793     
4794     /* alias for dest */
4795     tmpb = b->dp;
4796
4797     /* carry */
4798     r = 0;
4799     for (x = 0; x < a->used; x++) {
4800     
4801       /* get what will be the *next* carry bit from the 
4802        * MSB of the current digit 
4803        */
4804       rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1));
4805       
4806       /* now shift up this digit, add in the carry [from the previous] */
4807       *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK;
4808       
4809       /* copy the carry that would be from the source 
4810        * digit into the next iteration 
4811        */
4812       r = rr;
4813     }
4814
4815     /* new leading digit? */
4816     if (r != 0) {
4817       /* add a MSB which is always 1 at this point */
4818       *tmpb = 1;
4819       ++(b->used);
4820     }
4821
4822     /* now zero any excess digits on the destination 
4823      * that we didn't write to 
4824      */
4825     tmpb = b->dp + b->used;
4826     for (x = b->used; x < oldused; x++) {
4827       *tmpb++ = 0;
4828     }
4829   }
4830   b->sign = a->sign;
4831   return MP_OKAY;
4832 }
4833 #endif
4834
4835 /* End: bn_mp_mul_2.c */
4836
4837 /* Start: bn_mp_mul_2d.c */
4838 #include "tma.h"
4839 #ifdef BN_MP_MUL_2D_C
4840 /* LibTomMath, multiple-precision integer library -- Tom St Denis
4841  *
4842  * LibTomMath is a library that provides multiple-precision
4843  * integer arithmetic as well as number theoretic functionality.
4844  *
4845  * The library was designed directly after the MPI library by
4846  * Michael Fromberger but has been written from scratch with
4847  * additional optimizations in place.
4848  *
4849  * The library is free for all purposes without any express
4850  * guarantee it works.
4851  *
4852  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
4853  */
4854
4855 /* shift left by a certain bit count */
4856 int mp_mul_2d (mp_int * a, int b, mp_int * c)
4857 {
4858   mp_digit d;
4859   int      res;
4860
4861   /* copy */
4862   if (a != c) {
4863      if ((res = mp_copy (a, c)) != MP_OKAY) {
4864        return res;
4865      }
4866   }
4867
4868   if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) {
4869      if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) {
4870        return res;
4871      }
4872   }
4873
4874   /* shift by as many digits in the bit count */
4875   if (b >= (int)DIGIT_BIT) {
4876     if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) {
4877       return res;
4878     }
4879   }
4880
4881   /* shift any bit count < DIGIT_BIT */
4882   d = (mp_digit) (b % DIGIT_BIT);
4883   if (d != 0) {
4884     register mp_digit *tmpc, shift, mask, r, rr;
4885     register int x;
4886
4887     /* bitmask for carries */
4888     mask = (((mp_digit)1) << d) - 1;
4889
4890     /* shift for msbs */
4891     shift = DIGIT_BIT - d;
4892
4893     /* alias */
4894     tmpc = c->dp;
4895
4896     /* carry */
4897     r    = 0;
4898     for (x = 0; x < c->used; x++) {
4899       /* get the higher bits of the current word */
4900       rr = (*tmpc >> shift) & mask;
4901
4902       /* shift the current word and OR in the carry */
4903       *tmpc = ((*tmpc << d) | r) & MP_MASK;
4904       ++tmpc;
4905
4906       /* set the carry to the carry bits of the current word */
4907       r = rr;
4908     }
4909     
4910     /* set final carry */
4911     if (r != 0) {
4912        c->dp[(c->used)++] = r;
4913     }
4914   }
4915   mp_clamp (c);
4916   return MP_OKAY;
4917 }
4918 #endif
4919
4920 /* End: bn_mp_mul_2d.c */
4921
4922 /* Start: bn_mp_mul_d.c */
4923 #include "tma.h"
4924 #ifdef BN_MP_MUL_D_C
4925 /* LibTomMath, multiple-precision integer library -- Tom St Denis
4926  *
4927  * LibTomMath is a library that provides multiple-precision
4928  * integer arithmetic as well as number theoretic functionality.
4929  *
4930  * The library was designed directly after the MPI library by
4931  * Michael Fromberger but has been written from scratch with
4932  * additional optimizations in place.
4933  *
4934  * The library is free for all purposes without any express
4935  * guarantee it works.
4936  *
4937  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
4938  */
4939
4940 /* multiply by a digit */
4941 int
4942 mp_mul_d (mp_int * a, mp_digit b, mp_int * c)
4943 {
4944   mp_digit u, *tmpa, *tmpc;
4945   mp_word  r;
4946   int      ix, res, olduse;
4947
4948   /* make sure c is big enough to hold a*b */
4949   if (c->alloc < a->used + 1) {
4950     if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) {
4951       return res;
4952     }
4953   }
4954
4955   /* get the original destinations used count */
4956   olduse = c->used;
4957
4958   /* set the sign */
4959   c->sign = a->sign;
4960
4961   /* alias for a->dp [source] */
4962   tmpa = a->dp;
4963
4964   /* alias for c->dp [dest] */
4965   tmpc = c->dp;
4966
4967   /* zero carry */
4968   u = 0;
4969
4970   /* compute columns */
4971   for (ix = 0; ix < a->used; ix++) {
4972     /* compute product and carry sum for this term */
4973     r       = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b);
4974
4975     /* mask off higher bits to get a single digit */
4976     *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK));
4977
4978     /* send carry into next iteration */
4979     u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
4980   }
4981
4982   /* store final carry [if any] and increment ix offset  */
4983   *tmpc++ = u;
4984   ++ix;
4985
4986   /* now zero digits above the top */
4987   while (ix++ < olduse) {
4988      *tmpc++ = 0;
4989   }
4990
4991   /* set used count */
4992   c->used = a->used + 1;
4993   mp_clamp(c);
4994
4995   return MP_OKAY;
4996 }
4997 #endif
4998
4999 /* End: bn_mp_mul_d.c */
5000
5001 /* Start: bn_mp_mulmod.c */
5002 #include "tma.h"
5003 #ifdef BN_MP_MULMOD_C
5004 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5005  *
5006  * LibTomMath is a library that provides multiple-precision
5007  * integer arithmetic as well as number theoretic functionality.
5008  *
5009  * The library was designed directly after the MPI library by
5010  * Michael Fromberger but has been written from scratch with
5011  * additional optimizations in place.
5012  *
5013  * The library is free for all purposes without any express
5014  * guarantee it works.
5015  *
5016  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
5017  */
5018
5019 /* d = a * b (mod c) */
5020 int
5021 mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
5022 {
5023   int     res;
5024   mp_int  t;
5025
5026   if ((res = mp_init (&t)) != MP_OKAY) {
5027     return res;
5028   }
5029
5030   if ((res = mp_mul (a, b, &t)) != MP_OKAY) {
5031     mp_clear (&t);
5032     return res;
5033   }
5034   res = mp_mod (&t, c, d);
5035   mp_clear (&t);
5036   return res;
5037 }
5038 #endif
5039
5040 /* End: bn_mp_mulmod.c */
5041
5042 /* Start: bn_mp_n_root.c */
5043 #include "tma.h"
5044 #ifdef BN_MP_N_ROOT_C
5045 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5046  *
5047  * LibTomMath is a library that provides multiple-precision
5048  * integer arithmetic as well as number theoretic functionality.
5049  *
5050  * The library was designed directly after the MPI library by
5051  * Michael Fromberger but has been written from scratch with
5052  * additional optimizations in place.
5053  *
5054  * The library is free for all purposes without any express
5055  * guarantee it works.
5056  *
5057  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
5058  */
5059
5060 /* find the n'th root of an integer 
5061  *
5062  * Result found such that (c)**b <= a and (c+1)**b > a 
5063  *
5064  * This algorithm uses Newton's approximation 
5065  * x[i+1] = x[i] - f(x[i])/f'(x[i]) 
5066  * which will find the root in log(N) time where 
5067  * each step involves a fair bit.  This is not meant to 
5068  * find huge roots [square and cube, etc].
5069  */
5070 int mp_n_root (mp_int * a, mp_digit b, mp_int * c)
5071 {
5072   mp_int  t1, t2, t3;
5073   int     res, neg;
5074
5075   /* input must be positive if b is even */
5076   if ((b & 1) == 0 && a->sign == MP_NEG) {
5077     return MP_VAL;
5078   }
5079
5080   if ((res = mp_init (&t1)) != MP_OKAY) {
5081     return res;
5082   }
5083
5084   if ((res = mp_init (&t2)) != MP_OKAY) {
5085     goto LBL_T1;
5086   }
5087
5088   if ((res = mp_init (&t3)) != MP_OKAY) {
5089     goto LBL_T2;
5090   }
5091
5092   /* if a is negative fudge the sign but keep track */
5093   neg     = a->sign;
5094   a->sign = MP_ZPOS;
5095
5096   /* t2 = 2 */
5097   mp_set (&t2, 2);
5098
5099   do {
5100     /* t1 = t2 */
5101     if ((res = mp_copy (&t2, &t1)) != MP_OKAY) {
5102       goto LBL_T3;
5103     }
5104
5105     /* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */
5106     
5107     /* t3 = t1**(b-1) */
5108     if ((res = mp_expt_d (&t1, b - 1, &t3)) != MP_OKAY) {   
5109       goto LBL_T3;
5110     }
5111
5112     /* numerator */
5113     /* t2 = t1**b */
5114     if ((res = mp_mul (&t3, &t1, &t2)) != MP_OKAY) {    
5115       goto LBL_T3;
5116     }
5117
5118     /* t2 = t1**b - a */
5119     if ((res = mp_sub (&t2, a, &t2)) != MP_OKAY) {  
5120       goto LBL_T3;
5121     }
5122
5123     /* denominator */
5124     /* t3 = t1**(b-1) * b  */
5125     if ((res = mp_mul_d (&t3, b, &t3)) != MP_OKAY) {    
5126       goto LBL_T3;
5127     }
5128
5129     /* t3 = (t1**b - a)/(b * t1**(b-1)) */
5130     if ((res = mp_div (&t2, &t3, &t3, NULL)) != MP_OKAY) {  
5131       goto LBL_T3;
5132     }
5133
5134     if ((res = mp_sub (&t1, &t3, &t2)) != MP_OKAY) {
5135       goto LBL_T3;
5136     }
5137   }  while (mp_cmp (&t1, &t2) != MP_EQ);
5138
5139   /* result can be off by a few so check */
5140   for (;;) {
5141     if ((res = mp_expt_d (&t1, b, &t2)) != MP_OKAY) {
5142       goto LBL_T3;
5143     }
5144
5145     if (mp_cmp (&t2, a) == MP_GT) {
5146       if ((res = mp_sub_d (&t1, 1, &t1)) != MP_OKAY) {
5147          goto LBL_T3;
5148       }
5149     } else {
5150       break;
5151     }
5152   }
5153
5154   /* reset the sign of a first */
5155   a->sign = neg;
5156
5157   /* set the result */
5158   mp_exch (&t1, c);
5159
5160   /* set the sign of the result */
5161   c->sign = neg;
5162
5163   res = MP_OKAY;
5164
5165 LBL_T3:mp_clear (&t3);
5166 LBL_T2:mp_clear (&t2);
5167 LBL_T1:mp_clear (&t1);
5168   return res;
5169 }
5170 #endif
5171
5172 /* End: bn_mp_n_root.c */
5173
5174 /* Start: bn_mp_neg.c */
5175 #include "tma.h"
5176 #ifdef BN_MP_NEG_C
5177 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5178  *
5179  * LibTomMath is a library that provides multiple-precision
5180  * integer arithmetic as well as number theoretic functionality.
5181  *
5182  * The library was designed directly after the MPI library by
5183  * Michael Fromberger but has been written from scratch with
5184  * additional optimizations in place.
5185  *
5186  * The library is free for all purposes without any express
5187  * guarantee it works.
5188  *
5189  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
5190  */
5191
5192 /* b = -a */
5193 int mp_neg (mp_int * a, mp_int * b)
5194 {
5195   int     res;
5196   if (a != b) {
5197      if ((res = mp_copy (a, b)) != MP_OKAY) {
5198         return res;
5199      }
5200   }
5201
5202   if (mp_iszero(b) != MP_YES) {
5203      b->sign = (a->sign == MP_ZPOS) ? MP_NEG : MP_ZPOS;
5204   } else {
5205      b->sign = MP_ZPOS;
5206   }
5207
5208   return MP_OKAY;
5209 }
5210 #endif
5211
5212 /* End: bn_mp_neg.c */
5213
5214 /* Start: bn_mp_or.c */
5215 #include "tma.h"
5216 #ifdef BN_MP_OR_C
5217 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5218  *
5219  * LibTomMath is a library that provides multiple-precision
5220  * integer arithmetic as well as number theoretic functionality.
5221  *
5222  * The library was designed directly after the MPI library by
5223  * Michael Fromberger but has been written from scratch with
5224  * additional optimizations in place.
5225  *
5226  * The library is free for all purposes without any express
5227  * guarantee it works.
5228  *
5229  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
5230  */
5231
5232 /* OR two ints together */
5233 int mp_or (mp_int * a, mp_int * b, mp_int * c)
5234 {
5235   int     res, ix, px;
5236   mp_int  t, *x;
5237
5238   if (a->used > b->used) {
5239     if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
5240       return res;
5241     }
5242     px = b->used;
5243     x = b;
5244   } else {
5245     if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
5246       return res;
5247     }
5248     px = a->used;
5249     x = a;
5250   }
5251
5252   for (ix = 0; ix < px; ix++) {
5253     t.dp[ix] |= x->dp[ix];
5254   }
5255   mp_clamp (&t);
5256   mp_exch (c, &t);
5257   mp_clear (&t);
5258   return MP_OKAY;
5259 }
5260 #endif
5261
5262 /* End: bn_mp_or.c */
5263
5264 /* Start: bn_mp_prime_fermat.c */
5265 #include "tma.h"
5266 #ifdef BN_MP_PRIME_FERMAT_C
5267 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5268  *
5269  * LibTomMath is a library that provides multiple-precision
5270  * integer arithmetic as well as number theoretic functionality.
5271  *
5272  * The library was designed directly after the MPI library by
5273  * Michael Fromberger but has been written from scratch with
5274  * additional optimizations in place.
5275  *
5276  * The library is free for all purposes without any express
5277  * guarantee it works.
5278  *
5279  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
5280  */
5281
5282 /* performs one Fermat test.
5283  * 
5284  * If "a" were prime then b**a == b (mod a) since the order of
5285  * the multiplicative sub-group would be phi(a) = a-1.  That means
5286  * it would be the same as b**(a mod (a-1)) == b**1 == b (mod a).
5287  *
5288  * Sets result to 1 if the congruence holds, or zero otherwise.
5289  */
5290 int mp_prime_fermat (mp_int * a, mp_int * b, int *result)
5291 {
5292   mp_int  t;
5293   int     err;
5294
5295   /* default to composite  */
5296   *result = MP_NO;
5297
5298   /* ensure b > 1 */
5299   if (mp_cmp_d(b, 1) != MP_GT) {
5300      return MP_VAL;
5301   }
5302
5303   /* init t */
5304   if ((err = mp_init (&t)) != MP_OKAY) {
5305     return err;
5306   }
5307
5308   /* compute t = b**a mod a */
5309   if ((err = mp_exptmod (b, a, a, &t)) != MP_OKAY) {
5310     goto LBL_T;
5311   }
5312
5313   /* is it equal to b? */
5314   if (mp_cmp (&t, b) == MP_EQ) {
5315     *result = MP_YES;
5316   }
5317
5318   err = MP_OKAY;
5319 LBL_T:mp_clear (&t);
5320   return err;
5321 }
5322 #endif
5323
5324 /* End: bn_mp_prime_fermat.c */
5325
5326 /* Start: bn_mp_prime_is_divisible.c */
5327 #include "tma.h"
5328 #ifdef BN_MP_PRIME_IS_DIVISIBLE_C
5329 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5330  *
5331  * LibTomMath is a library that provides multiple-precision
5332  * integer arithmetic as well as number theoretic functionality.
5333  *
5334  * The library was designed directly after the MPI library by
5335  * Michael Fromberger but has been written from scratch with
5336  * additional optimizations in place.
5337  *
5338  * The library is free for all purposes without any express
5339  * guarantee it works.
5340  *
5341  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
5342  */
5343
5344 /* determines if an integers is divisible by one 
5345  * of the first PRIME_SIZE primes or not
5346  *
5347  * sets result to 0 if not, 1 if yes
5348  */
5349 int mp_prime_is_divisible (mp_int * a, int *result)
5350 {
5351   int     err, ix;
5352   mp_digit res;
5353
5354   /* default to not */
5355   *result = MP_NO;
5356
5357   for (ix = 0; ix < PRIME_SIZE; ix++) {
5358     /* what is a mod LBL_prime_tab[ix] */
5359     if ((err = mp_mod_d (a, ltm_prime_tab[ix], &res)) != MP_OKAY) {
5360       return err;
5361     }
5362
5363     /* is the residue zero? */
5364     if (res == 0) {
5365       *result = MP_YES;
5366       return MP_OKAY;
5367     }
5368   }
5369
5370   return MP_OKAY;
5371 }
5372 #endif
5373
5374 /* End: bn_mp_prime_is_divisible.c */
5375
5376 /* Start: bn_mp_prime_is_prime.c */
5377 #include "tma.h"
5378 #ifdef BN_MP_PRIME_IS_PRIME_C
5379 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5380  *
5381  * LibTomMath is a library that provides multiple-precision
5382  * integer arithmetic as well as number theoretic functionality.
5383  *
5384  * The library was designed directly after the MPI library by
5385  * Michael Fromberger but has been written from scratch with
5386  * additional optimizations in place.
5387  *
5388  * The library is free for all purposes without any express
5389  * guarantee it works.
5390  *
5391  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
5392  */
5393
5394 /* performs a variable number of rounds of Miller-Rabin
5395  *
5396  * Probability of error after t rounds is no more than
5397
5398  *
5399  * Sets result to 1 if probably prime, 0 otherwise
5400  */
5401 int mp_prime_is_prime (mp_int * a, int t, int *result)
5402 {
5403   mp_int  b;
5404   int     ix, err, res;
5405
5406   /* default to no */
5407   *result = MP_NO;
5408
5409   /* valid value of t? */
5410   if (t <= 0 || t > PRIME_SIZE) {
5411     return MP_VAL;
5412   }
5413
5414   /* is the input equal to one of the primes in the table? */
5415   for (ix = 0; ix < PRIME_SIZE; ix++) {
5416       if (mp_cmp_d(a, ltm_prime_tab[ix]) == MP_EQ) {
5417          *result = 1;
5418          return MP_OKAY;
5419       }
5420   }
5421
5422   /* first perform trial division */
5423   if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) {
5424     return err;
5425   }
5426
5427   /* return if it was trivially divisible */
5428   if (res == MP_YES) {
5429     return MP_OKAY;
5430   }
5431
5432   /* now perform the miller-rabin rounds */
5433   if ((err = mp_init (&b)) != MP_OKAY) {
5434     return err;
5435   }
5436
5437   for (ix = 0; ix < t; ix++) {
5438     /* set the prime */
5439     mp_set (&b, ltm_prime_tab[ix]);
5440
5441     if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) {
5442       goto LBL_B;
5443     }
5444
5445     if (res == MP_NO) {
5446       goto LBL_B;
5447     }
5448   }
5449
5450   /* passed the test */
5451   *result = MP_YES;
5452 LBL_B:mp_clear (&b);
5453   return err;
5454 }
5455 #endif
5456
5457 /* End: bn_mp_prime_is_prime.c */
5458
5459 /* Start: bn_mp_prime_miller_rabin.c */
5460 #include "tma.h"
5461 #ifdef BN_MP_PRIME_MILLER_RABIN_C
5462 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5463  *
5464  * LibTomMath is a library that provides multiple-precision
5465  * integer arithmetic as well as number theoretic functionality.
5466  *
5467  * The library was designed directly after the MPI library by
5468  * Michael Fromberger but has been written from scratch with
5469  * additional optimizations in place.
5470  *
5471  * The library is free for all purposes without any express
5472  * guarantee it works.
5473  *
5474  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
5475  */
5476
5477 /* Miller-Rabin test of "a" to the base of "b" as described in 
5478  * HAC pp. 139 Algorithm 4.24
5479  *
5480  * Sets result to 0 if definitely composite or 1 if probably prime.
5481  * Randomly the chance of error is no more than 1/4 and often 
5482  * very much lower.
5483  */
5484 int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result)
5485 {
5486   mp_int  n1, y, r;
5487   int     s, j, err;
5488
5489   /* default */
5490   *result = MP_NO;
5491
5492   /* ensure b > 1 */
5493   if (mp_cmp_d(b, 1) != MP_GT) {
5494      return MP_VAL;
5495   }     
5496
5497   /* get n1 = a - 1 */
5498   if ((err = mp_init_copy (&n1, a)) != MP_OKAY) {
5499     return err;
5500   }
5501   if ((err = mp_sub_d (&n1, 1, &n1)) != MP_OKAY) {
5502     goto LBL_N1;
5503   }
5504
5505   /* set 2**s * r = n1 */
5506   if ((err = mp_init_copy (&r, &n1)) != MP_OKAY) {
5507     goto LBL_N1;
5508   }
5509
5510   /* count the number of least significant bits
5511    * which are zero
5512    */
5513   s = mp_cnt_lsb(&r);
5514
5515   /* now divide n - 1 by 2**s */
5516   if ((err = mp_div_2d (&r, s, &r, NULL)) != MP_OKAY) {
5517     goto LBL_R;
5518   }
5519
5520   /* compute y = b**r mod a */
5521   if ((err = mp_init (&y)) != MP_OKAY) {
5522     goto LBL_R;
5523   }
5524   if ((err = mp_exptmod (b, &r, a, &y)) != MP_OKAY) {
5525     goto LBL_Y;
5526   }
5527
5528   /* if y != 1 and y != n1 do */
5529   if (mp_cmp_d (&y, 1) != MP_EQ && mp_cmp (&y, &n1) != MP_EQ) {
5530     j = 1;
5531     /* while j <= s-1 and y != n1 */
5532     while ((j <= (s - 1)) && mp_cmp (&y, &n1) != MP_EQ) {
5533       if ((err = mp_sqrmod (&y, a, &y)) != MP_OKAY) {
5534          goto LBL_Y;
5535       }
5536
5537       /* if y == 1 then composite */
5538       if (mp_cmp_d (&y, 1) == MP_EQ) {
5539          goto LBL_Y;
5540       }
5541
5542       ++j;
5543     }
5544
5545     /* if y != n1 then composite */
5546     if (mp_cmp (&y, &n1) != MP_EQ) {
5547       goto LBL_Y;
5548     }
5549   }
5550
5551   /* probably prime now */
5552   *result = MP_YES;
5553 LBL_Y:mp_clear (&y);
5554 LBL_R:mp_clear (&r);
5555 LBL_N1:mp_clear (&n1);
5556   return err;
5557 }
5558 #endif
5559
5560 /* End: bn_mp_prime_miller_rabin.c */
5561
5562 /* Start: bn_mp_prime_next_prime.c */
5563 #include "tma.h"
5564 #ifdef BN_MP_PRIME_NEXT_PRIME_C
5565 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5566  *
5567  * LibTomMath is a library that provides multiple-precision
5568  * integer arithmetic as well as number theoretic functionality.
5569  *
5570  * The library was designed directly after the MPI library by
5571  * Michael Fromberger but has been written from scratch with
5572  * additional optimizations in place.
5573  *
5574  * The library is free for all purposes without any express
5575  * guarantee it works.
5576  *
5577  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
5578  */
5579
5580 /* finds the next prime after the number "a" using "t" trials
5581  * of Miller-Rabin.
5582  *
5583  * bbs_style = 1 means the prime must be congruent to 3 mod 4
5584  */
5585 int mp_prime_next_prime(mp_int *a, int t, int bbs_style)
5586 {
5587    int      err, res, x, y;
5588    mp_digit res_tab[PRIME_SIZE], step, kstep;
5589    mp_int   b;
5590
5591    /* ensure t is valid */
5592    if (t <= 0 || t > PRIME_SIZE) {
5593       return MP_VAL;
5594    }
5595
5596    /* force positive */
5597    a->sign = MP_ZPOS;
5598
5599    /* simple algo if a is less than the largest prime in the table */
5600    if (mp_cmp_d(a, ltm_prime_tab[PRIME_SIZE-1]) == MP_LT) {
5601       /* find which prime it is bigger than */
5602       for (x = PRIME_SIZE - 2; x >= 0; x--) {
5603           if (mp_cmp_d(a, ltm_prime_tab[x]) != MP_LT) {
5604              if (bbs_style == 1) {
5605                 /* ok we found a prime smaller or
5606                  * equal [so the next is larger]
5607                  *
5608                  * however, the prime must be
5609                  * congruent to 3 mod 4
5610                  */
5611                 if ((ltm_prime_tab[x + 1] & 3) != 3) {
5612                    /* scan upwards for a prime congruent to 3 mod 4 */
5613                    for (y = x + 1; y < PRIME_SIZE; y++) {
5614                        if ((ltm_prime_tab[y] & 3) == 3) {
5615                           mp_set(a, ltm_prime_tab[y]);
5616                           return MP_OKAY;
5617                        }
5618                    }
5619                 }
5620              } else {
5621                 mp_set(a, ltm_prime_tab[x + 1]);
5622                 return MP_OKAY;
5623              }
5624           }
5625       }
5626       /* at this point a maybe 1 */
5627       if (mp_cmp_d(a, 1) == MP_EQ) {
5628          mp_set(a, 2);
5629          return MP_OKAY;
5630       }
5631       /* fall through to the sieve */
5632    }
5633
5634    /* generate a prime congruent to 3 mod 4 or 1/3 mod 4? */
5635    if (bbs_style == 1) {
5636       kstep   = 4;
5637    } else {
5638       kstep   = 2;
5639    }
5640
5641    /* at this point we will use a combination of a sieve and Miller-Rabin */
5642
5643    if (bbs_style == 1) {
5644       /* if a mod 4 != 3 subtract the correct value to make it so */
5645       if ((a->dp[0] & 3) != 3) {
5646          if ((err = mp_sub_d(a, (a->dp[0] & 3) + 1, a)) != MP_OKAY) { return err; };
5647       }
5648    } else {
5649       if (mp_iseven(a) == 1) {
5650          /* force odd */
5651          if ((err = mp_sub_d(a, 1, a)) != MP_OKAY) {
5652             return err;
5653          }
5654       }
5655    }
5656
5657    /* generate the restable */
5658    for (x = 1; x < PRIME_SIZE; x++) {
5659       if ((err = mp_mod_d(a, ltm_prime_tab[x], res_tab + x)) != MP_OKAY) {
5660          return err;
5661       }
5662    }
5663
5664    /* init temp used for Miller-Rabin Testing */
5665    if ((err = mp_init(&b)) != MP_OKAY) {
5666       return err;
5667    }
5668
5669    for (;;) {
5670       /* skip to the next non-trivially divisible candidate */
5671       step = 0;
5672       do {
5673          /* y == 1 if any residue was zero [e.g. cannot be prime] */
5674          y     =  0;
5675
5676          /* increase step to next candidate */
5677          step += kstep;
5678
5679          /* compute the new residue without using division */
5680          for (x = 1; x < PRIME_SIZE; x++) {
5681              /* add the step to each residue */
5682              res_tab[x] += kstep;
5683
5684              /* subtract the modulus [instead of using division] */
5685              if (res_tab[x] >= ltm_prime_tab[x]) {
5686                 res_tab[x]  -= ltm_prime_tab[x];
5687              }
5688
5689              /* set flag if zero */
5690              if (res_tab[x] == 0) {
5691                 y = 1;
5692              }
5693          }
5694       } while (y == 1 && step < ((((mp_digit)1)<<DIGIT_BIT) - kstep));
5695
5696       /* add the step */
5697       if ((err = mp_add_d(a, step, a)) != MP_OKAY) {
5698          goto LBL_ERR;
5699       }
5700
5701       /* if didn't pass sieve and step == MAX then skip test */
5702       if (y == 1 && step >= ((((mp_digit)1)<<DIGIT_BIT) - kstep)) {
5703          continue;
5704       }
5705
5706       /* is this prime? */
5707       for (x = 0; x < t; x++) {
5708           mp_set(&b, ltm_prime_tab[t]);
5709           if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) {
5710              goto LBL_ERR;
5711           }
5712           if (res == MP_NO) {
5713              break;
5714           }
5715       }
5716
5717       if (res == MP_YES) {
5718          break;
5719       }
5720    }
5721
5722    err = MP_OKAY;
5723 LBL_ERR:
5724    mp_clear(&b);
5725    return err;
5726 }
5727
5728 #endif
5729
5730 /* End: bn_mp_prime_next_prime.c */
5731
5732 /* Start: bn_mp_prime_rabin_miller_trials.c */
5733 #include "tma.h"
5734 #ifdef BN_MP_PRIME_RABIN_MILLER_TRIALS_C
5735 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5736  *
5737  * LibTomMath is a library that provides multiple-precision
5738  * integer arithmetic as well as number theoretic functionality.
5739  *
5740  * The library was designed directly after the MPI library by
5741  * Michael Fromberger but has been written from scratch with
5742  * additional optimizations in place.
5743  *
5744  * The library is free for all purposes without any express
5745  * guarantee it works.
5746  *
5747  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
5748  */
5749
5750
5751 static const struct {
5752    int k, t;
5753 } sizes[] = {
5754 {   128,    28 },
5755 {   256,    16 },
5756 {   384,    10 },
5757 {   512,     7 },
5758 {   640,     6 },
5759 {   768,     5 },
5760 {   896,     4 },
5761 {  1024,     4 }
5762 };
5763
5764 /* returns # of RM trials required for a given bit size */
5765 int mp_prime_rabin_miller_trials(int size)
5766 {
5767    int x;
5768
5769    for (x = 0; x < (int)(sizeof(sizes)/(sizeof(sizes[0]))); x++) {
5770        if (sizes[x].k == size) {
5771           return sizes[x].t;
5772        } else if (sizes[x].k > size) {
5773           return (x == 0) ? sizes[0].t : sizes[x - 1].t;
5774        }
5775    }
5776    return sizes[x-1].t + 1;
5777 }
5778
5779
5780 #endif
5781
5782 /* End: bn_mp_prime_rabin_miller_trials.c */
5783
5784 /* Start: bn_mp_prime_random_ex.c */
5785 #include "tma.h"
5786 #ifdef BN_MP_PRIME_RANDOM_EX_C
5787 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5788  *
5789  * LibTomMath is a library that provides multiple-precision
5790  * integer arithmetic as well as number theoretic functionality.
5791  *
5792  * The library was designed directly after the MPI library by
5793  * Michael Fromberger but has been written from scratch with
5794  * additional optimizations in place.
5795  *
5796  * The library is free for all purposes without any express
5797  * guarantee it works.
5798  *
5799  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
5800  */
5801
5802 /* makes a truly random prime of a given size (bits),
5803  *
5804  * Flags are as follows:
5805  * 
5806  *   LTM_PRIME_BBS      - make prime congruent to 3 mod 4
5807  *   LTM_PRIME_SAFE     - make sure (p-1)/2 is prime as well (implies LTM_PRIME_BBS)
5808  *   LTM_PRIME_2MSB_OFF - make the 2nd highest bit zero
5809  *   LTM_PRIME_2MSB_ON  - make the 2nd highest bit one
5810  *
5811  * You have to supply a callback which fills in a buffer with random bytes.  "dat" is a parameter you can
5812  * have passed to the callback (e.g. a state or something).  This function doesn't use "dat" itself
5813  * so it can be NULL
5814  *
5815  */
5816
5817 /* This is possibly the mother of all prime generation functions, muahahahahaha! */
5818 int mp_prime_random_ex(mp_int *a, int t, int size, int flags, ltm_prime_callback cb, void *dat)
5819 {
5820    unsigned char *tmp, maskAND, maskOR_msb, maskOR_lsb;
5821    int res, err, bsize, maskOR_msb_offset;
5822
5823    /* sanity check the input */
5824    if (size <= 1 || t <= 0) {
5825       return MP_VAL;
5826    }
5827
5828    /* LTM_PRIME_SAFE implies LTM_PRIME_BBS */
5829    if (flags & LTM_PRIME_SAFE) {
5830       flags |= LTM_PRIME_BBS;
5831    }
5832
5833    /* calc the byte size */
5834    bsize = (size>>3) + ((size&7)?1:0);
5835
5836    /* we need a buffer of bsize bytes */
5837    tmp = OPT_CAST(unsigned char) XMALLOC(bsize);
5838    if (tmp == NULL) {
5839       return MP_MEM;
5840    }
5841
5842    /* calc the maskAND value for the MSbyte*/
5843    maskAND = ((size&7) == 0) ? 0xFF : (0xFF >> (8 - (size & 7)));
5844
5845    /* calc the maskOR_msb */
5846    maskOR_msb        = 0;
5847    maskOR_msb_offset = ((size & 7) == 1) ? 1 : 0;
5848    if (flags & LTM_PRIME_2MSB_ON) {
5849       maskOR_msb     |= 1 << ((size - 2) & 7);
5850    } else if (flags & LTM_PRIME_2MSB_OFF) {
5851       maskAND        &= ~(1 << ((size - 2) & 7));
5852    } 
5853
5854    /* get the maskOR_lsb */
5855    maskOR_lsb         = 1;
5856    if (flags & LTM_PRIME_BBS) {
5857       maskOR_lsb     |= 3;
5858    }
5859
5860    do {
5861       /* read the bytes */
5862       if (cb(tmp, bsize, dat) != bsize) {
5863          err = MP_VAL;
5864          goto error;
5865       }
5866  
5867       /* work over the MSbyte */
5868       tmp[0]    &= maskAND;
5869       tmp[0]    |= 1 << ((size - 1) & 7);
5870
5871       /* mix in the maskORs */
5872       tmp[maskOR_msb_offset]   |= maskOR_msb;
5873       tmp[bsize-1]             |= maskOR_lsb;
5874
5875       /* read it in */
5876       if ((err = mp_read_unsigned_bin(a, tmp, bsize)) != MP_OKAY)     { goto error; }
5877
5878       /* is it prime? */
5879       if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY)           { goto error; }
5880       if (res == MP_NO) {  
5881          continue;
5882       }
5883
5884       if (flags & LTM_PRIME_SAFE) {
5885          /* see if (a-1)/2 is prime */
5886          if ((err = mp_sub_d(a, 1, a)) != MP_OKAY)                    { goto error; }
5887          if ((err = mp_div_2(a, a)) != MP_OKAY)                       { goto error; }
5888  
5889          /* is it prime? */
5890          if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY)        { goto error; }
5891       }
5892    } while (res == MP_NO);
5893
5894    if (flags & LTM_PRIME_SAFE) {
5895       /* restore a to the original value */
5896       if ((err = mp_mul_2(a, a)) != MP_OKAY)                          { goto error; }
5897       if ((err = mp_add_d(a, 1, a)) != MP_OKAY)                       { goto error; }
5898    }
5899
5900    err = MP_OKAY;
5901 error:
5902    XFREE(tmp);
5903    return err;
5904 }
5905
5906
5907 #endif
5908
5909 /* End: bn_mp_prime_random_ex.c */
5910
5911 /* Start: bn_mp_radix_size.c */
5912 #include "tma.h"
5913 #ifdef BN_MP_RADIX_SIZE_C
5914 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5915  *
5916  * LibTomMath is a library that provides multiple-precision
5917  * integer arithmetic as well as number theoretic functionality.
5918  *
5919  * The library was designed directly after the MPI library by
5920  * Michael Fromberger but has been written from scratch with
5921  * additional optimizations in place.
5922  *
5923  * The library is free for all purposes without any express
5924  * guarantee it works.
5925  *
5926  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
5927  */
5928
5929 /* returns size of ASCII reprensentation */
5930 int mp_radix_size (mp_int * a, int radix, int *size)
5931 {
5932   int     res, digs;
5933   mp_int  t;
5934   mp_digit d;
5935
5936   *size = 0;
5937
5938   /* special case for binary */
5939   if (radix == 2) {
5940     *size = mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1;
5941     return MP_OKAY;
5942   }
5943
5944   /* make sure the radix is in range */
5945   if (radix < 2 || radix > 64) {
5946     return MP_VAL;
5947   }
5948
5949   if (mp_iszero(a) == MP_YES) {
5950      *size = 2;
5951     return MP_OKAY;
5952   }
5953
5954   /* digs is the digit count */
5955   digs = 0;
5956
5957   /* if it's negative add one for the sign */
5958   if (a->sign == MP_NEG) {
5959     ++digs;
5960   }
5961
5962   /* init a copy of the input */
5963   if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
5964     return res;
5965   }
5966
5967   /* force temp to positive */
5968   t.sign = MP_ZPOS; 
5969
5970   /* fetch out all of the digits */
5971   while (mp_iszero (&t) == MP_NO) {
5972     if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
5973       mp_clear (&t);
5974       return res;
5975     }
5976     ++digs;
5977   }
5978   mp_clear (&t);
5979
5980   /* return digs + 1, the 1 is for the NULL byte that would be required. */
5981   *size = digs + 1;
5982   return MP_OKAY;
5983 }
5984
5985 #endif
5986
5987 /* End: bn_mp_radix_size.c */
5988
5989 /* Start: bn_mp_radix_smap.c */
5990 #include "tma.h"
5991 #ifdef BN_MP_RADIX_SMAP_C
5992 /* LibTomMath, multiple-precision integer library -- Tom St Denis
5993  *
5994  * LibTomMath is a library that provides multiple-precision
5995  * integer arithmetic as well as number theoretic functionality.
5996  *
5997  * The library was designed directly after the MPI library by
5998  * Michael Fromberger but has been written from scratch with
5999  * additional optimizations in place.
6000  *
6001  * The library is free for all purposes without any express
6002  * guarantee it works.
6003  *
6004  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
6005  */
6006
6007 /* chars used in radix conversions */
6008 const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";
6009 #endif
6010
6011 /* End: bn_mp_radix_smap.c */
6012
6013 /* Start: bn_mp_rand.c */
6014 #include "tma.h"
6015 #ifdef BN_MP_RAND_C
6016 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6017  *
6018  * LibTomMath is a library that provides multiple-precision
6019  * integer arithmetic as well as number theoretic functionality.
6020  *
6021  * The library was designed directly after the MPI library by
6022  * Michael Fromberger but has been written from scratch with
6023  * additional optimizations in place.
6024  *
6025  * The library is free for all purposes without any express
6026  * guarantee it works.
6027  *
6028  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
6029  */
6030
6031 /* makes a pseudo-random int of a given size */
6032 int
6033 mp_rand (mp_int * a, int digits)
6034 {
6035   int     res;
6036   mp_digit d;
6037
6038   mp_zero (a);
6039   if (digits <= 0) {
6040     return MP_OKAY;
6041   }
6042
6043   /* first place a random non-zero digit */
6044   do {
6045     d = ((mp_digit) abs (rand ())) & MP_MASK;
6046   } while (d == 0);
6047
6048   if ((res = mp_add_d (a, d, a)) != MP_OKAY) {
6049     return res;
6050   }
6051
6052   while (--digits > 0) {
6053     if ((res = mp_lshd (a, 1)) != MP_OKAY) {
6054       return res;
6055     }
6056
6057     if ((res = mp_add_d (a, ((mp_digit) abs (rand ())), a)) != MP_OKAY) {
6058       return res;
6059     }
6060   }
6061
6062   return MP_OKAY;
6063 }
6064 #endif
6065
6066 /* End: bn_mp_rand.c */
6067
6068 /* Start: bn_mp_read_radix.c */
6069 #include "tma.h"
6070 #ifdef BN_MP_READ_RADIX_C
6071 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6072  *
6073  * LibTomMath is a library that provides multiple-precision
6074  * integer arithmetic as well as number theoretic functionality.
6075  *
6076  * The library was designed directly after the MPI library by
6077  * Michael Fromberger but has been written from scratch with
6078  * additional optimizations in place.
6079  *
6080  * The library is free for all purposes without any express
6081  * guarantee it works.
6082  *
6083  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
6084  */
6085
6086 /* read a string [ASCII] in a given radix */
6087 int mp_read_radix (mp_int * a, const char *str, int radix)
6088 {
6089   int     y, res, neg;
6090   char    ch;
6091
6092   /* make sure the radix is ok */
6093   if (radix < 2 || radix > 64) {
6094     return MP_VAL;
6095   }
6096
6097   /* if the leading digit is a 
6098    * minus set the sign to negative. 
6099    */
6100   if (*str == '-') {
6101     ++str;
6102     neg = MP_NEG;
6103   } else {
6104     neg = MP_ZPOS;
6105   }
6106
6107   /* set the integer to the default of zero */
6108   mp_zero (a);
6109   
6110   /* process each digit of the string */
6111   while (*str) {
6112     /* if the radix < 36 the conversion is case insensitive
6113      * this allows numbers like 1AB and 1ab to represent the same  value
6114      * [e.g. in hex]
6115      */
6116     ch = (char) ((radix < 36) ? toupper (*str) : *str);
6117     for (y = 0; y < 64; y++) {
6118       if (ch == mp_s_rmap[y]) {
6119          break;
6120       }
6121     }
6122
6123     /* if the char was found in the map 
6124      * and is less than the given radix add it
6125      * to the number, otherwise exit the loop. 
6126      */
6127     if (y < radix) {
6128       if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) {
6129          return res;
6130       }
6131       if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) {
6132          return res;
6133       }
6134     } else {
6135       break;
6136     }
6137     ++str;
6138   }
6139   
6140   /* set the sign only if a != 0 */
6141   if (mp_iszero(a) != 1) {
6142      a->sign = neg;
6143   }
6144   return MP_OKAY;
6145 }
6146 #endif
6147
6148 /* End: bn_mp_read_radix.c */
6149
6150 /* Start: bn_mp_read_signed_bin.c */
6151 #include "tma.h"
6152 #ifdef BN_MP_READ_SIGNED_BIN_C
6153 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6154  *
6155  * LibTomMath is a library that provides multiple-precision
6156  * integer arithmetic as well as number theoretic functionality.
6157  *
6158  * The library was designed directly after the MPI library by
6159  * Michael Fromberger but has been written from scratch with
6160  * additional optimizations in place.
6161  *
6162  * The library is free for all purposes without any express
6163  * guarantee it works.
6164  *
6165  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
6166  */
6167
6168 /* read signed bin, big endian, first byte is 0==positive or 1==negative */
6169 int
6170 mp_read_signed_bin (mp_int * a, unsigned char *b, int c)
6171 {
6172   int     res;
6173
6174   /* read magnitude */
6175   if ((res = mp_read_unsigned_bin (a, b + 1, c - 1)) != MP_OKAY) {
6176     return res;
6177   }
6178
6179   /* first byte is 0 for positive, non-zero for negative */
6180   if (b[0] == 0) {
6181      a->sign = MP_ZPOS;
6182   } else {
6183      a->sign = MP_NEG;
6184   }
6185
6186   return MP_OKAY;
6187 }
6188 #endif
6189
6190 /* End: bn_mp_read_signed_bin.c */
6191
6192 /* Start: bn_mp_read_unsigned_bin.c */
6193 #include "tma.h"
6194 #ifdef BN_MP_READ_UNSIGNED_BIN_C
6195 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6196  *
6197  * LibTomMath is a library that provides multiple-precision
6198  * integer arithmetic as well as number theoretic functionality.
6199  *
6200  * The library was designed directly after the MPI library by
6201  * Michael Fromberger but has been written from scratch with
6202  * additional optimizations in place.
6203  *
6204  * The library is free for all purposes without any express
6205  * guarantee it works.
6206  *
6207  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
6208  */
6209
6210 /* reads a unsigned char array, assumes the msb is stored first [big endian] */
6211 int
6212 mp_read_unsigned_bin (mp_int * a, unsigned char *b, int c)
6213 {
6214   int     res;
6215
6216   /* make sure there are at least two digits */
6217   if (a->alloc < 2) {
6218      if ((res = mp_grow(a, 2)) != MP_OKAY) {
6219         return res;
6220      }
6221   }
6222
6223   /* zero the int */
6224   mp_zero (a);
6225
6226   /* read the bytes in */
6227   while (c-- > 0) {
6228     if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) {
6229       return res;
6230     }
6231
6232 #ifndef MP_8BIT
6233       a->dp[0] |= *b++;
6234       a->used += 1;
6235 #else
6236       a->dp[0] = (*b & MP_MASK);
6237       a->dp[1] |= ((*b++ >> 7U) & 1);
6238       a->used += 2;
6239 #endif
6240   }
6241   mp_clamp (a);
6242   return MP_OKAY;
6243 }
6244 #endif
6245
6246 /* End: bn_mp_read_unsigned_bin.c */
6247
6248 /* Start: bn_mp_reduce.c */
6249 #include "tma.h"
6250 #ifdef BN_MP_REDUCE_C
6251 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6252  *
6253  * LibTomMath is a library that provides multiple-precision
6254  * integer arithmetic as well as number theoretic functionality.
6255  *
6256  * The library was designed directly after the MPI library by
6257  * Michael Fromberger but has been written from scratch with
6258  * additional optimizations in place.
6259  *
6260  * The library is free for all purposes without any express
6261  * guarantee it works.
6262  *
6263  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
6264  */
6265
6266 /* reduces x mod m, assumes 0 < x < m**2, mu is 
6267  * precomputed via mp_reduce_setup.
6268  * From HAC pp.604 Algorithm 14.42
6269  */
6270 int mp_reduce (mp_int * x, mp_int * m, mp_int * mu)
6271 {
6272   mp_int  q;
6273   int     res, um = m->used;
6274
6275   /* q = x */
6276   if ((res = mp_init_copy (&q, x)) != MP_OKAY) {
6277     return res;
6278   }
6279
6280   /* q1 = x / b**(k-1)  */
6281   mp_rshd (&q, um - 1);         
6282
6283   /* according to HAC this optimization is ok */
6284   if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) {
6285     if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) {
6286       goto CLEANUP;
6287     }
6288   } else {
6289 #ifdef BN_S_MP_MUL_HIGH_DIGS_C
6290     if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
6291       goto CLEANUP;
6292     }
6293 #elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
6294     if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
6295       goto CLEANUP;
6296     }
6297 #else 
6298     { 
6299       res = MP_VAL;
6300       goto CLEANUP;
6301     }
6302 #endif
6303   }
6304
6305   /* q3 = q2 / b**(k+1) */
6306   mp_rshd (&q, um + 1);         
6307
6308   /* x = x mod b**(k+1), quick (no division) */
6309   if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) {
6310     goto CLEANUP;
6311   }
6312
6313   /* q = q * m mod b**(k+1), quick (no division) */
6314   if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) {
6315     goto CLEANUP;
6316   }
6317
6318   /* x = x - q */
6319   if ((res = mp_sub (x, &q, x)) != MP_OKAY) {
6320     goto CLEANUP;
6321   }
6322
6323   /* If x < 0, add b**(k+1) to it */
6324   if (mp_cmp_d (x, 0) == MP_LT) {
6325     mp_set (&q, 1);
6326     if ((res = mp_lshd (&q, um + 1)) != MP_OKAY)
6327       goto CLEANUP;
6328     if ((res = mp_add (x, &q, x)) != MP_OKAY)
6329       goto CLEANUP;
6330   }
6331
6332   /* Back off if it's too big */
6333   while (mp_cmp (x, m) != MP_LT) {
6334     if ((res = s_mp_sub (x, m, x)) != MP_OKAY) {
6335       goto CLEANUP;
6336     }
6337   }
6338   
6339 CLEANUP:
6340   mp_clear (&q);
6341
6342   return res;
6343 }
6344 #endif
6345
6346 /* End: bn_mp_reduce.c */
6347
6348 /* Start: bn_mp_reduce_2k.c */
6349 #include "tma.h"
6350 #ifdef BN_MP_REDUCE_2K_C
6351 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6352  *
6353  * LibTomMath is a library that provides multiple-precision
6354  * integer arithmetic as well as number theoretic functionality.
6355  *
6356  * The library was designed directly after the MPI library by
6357  * Michael Fromberger but has been written from scratch with
6358  * additional optimizations in place.
6359  *
6360  * The library is free for all purposes without any express
6361  * guarantee it works.
6362  *
6363  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
6364  */
6365
6366 /* reduces a modulo n where n is of the form 2**p - d */
6367 int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d)
6368 {
6369    mp_int q;
6370    int    p, res;
6371    
6372    if ((res = mp_init(&q)) != MP_OKAY) {
6373       return res;
6374    }
6375    
6376    p = mp_count_bits(n);    
6377 top:
6378    /* q = a/2**p, a = a mod 2**p */
6379    if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
6380       goto ERR;
6381    }
6382    
6383    if (d != 1) {
6384       /* q = q * d */
6385       if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) { 
6386          goto ERR;
6387       }
6388    }
6389    
6390    /* a = a + q */
6391    if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
6392       goto ERR;
6393    }
6394    
6395    if (mp_cmp_mag(a, n) != MP_LT) {
6396       s_mp_sub(a, n, a);
6397       goto top;
6398    }
6399    
6400 ERR:
6401    mp_clear(&q);
6402    return res;
6403 }
6404
6405 #endif
6406
6407 /* End: bn_mp_reduce_2k.c */
6408
6409 /* Start: bn_mp_reduce_2k_l.c */
6410 #include "tma.h"
6411 #ifdef BN_MP_REDUCE_2K_L_C
6412 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6413  *
6414  * LibTomMath is a library that provides multiple-precision
6415  * integer arithmetic as well as number theoretic functionality.
6416  *
6417  * The library was designed directly after the MPI library by
6418  * Michael Fromberger but has been written from scratch with
6419  * additional optimizations in place.
6420  *
6421  * The library is free for all purposes without any express
6422  * guarantee it works.
6423  *
6424  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
6425  */
6426
6427 /* reduces a modulo n where n is of the form 2**p - d 
6428    This differs from reduce_2k since "d" can be larger
6429    than a single digit.
6430 */
6431 int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d)
6432 {
6433    mp_int q;
6434    int    p, res;
6435    
6436    if ((res = mp_init(&q)) != MP_OKAY) {
6437       return res;
6438    }
6439    
6440    p = mp_count_bits(n);    
6441 top:
6442    /* q = a/2**p, a = a mod 2**p */
6443    if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
6444       goto ERR;
6445    }
6446    
6447    /* q = q * d */
6448    if ((res = mp_mul(&q, d, &q)) != MP_OKAY) { 
6449       goto ERR;
6450    }
6451    
6452    /* a = a + q */
6453    if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
6454       goto ERR;
6455    }
6456    
6457    if (mp_cmp_mag(a, n) != MP_LT) {
6458       s_mp_sub(a, n, a);
6459       goto top;
6460    }
6461    
6462 ERR:
6463    mp_clear(&q);
6464    return res;
6465 }
6466
6467 #endif
6468
6469 /* End: bn_mp_reduce_2k_l.c */
6470
6471 /* Start: bn_mp_reduce_2k_setup.c */
6472 #include "tma.h"
6473 #ifdef BN_MP_REDUCE_2K_SETUP_C
6474 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6475  *
6476  * LibTomMath is a library that provides multiple-precision
6477  * integer arithmetic as well as number theoretic functionality.
6478  *
6479  * The library was designed directly after the MPI library by
6480  * Michael Fromberger but has been written from scratch with
6481  * additional optimizations in place.
6482  *
6483  * The library is free for all purposes without any express
6484  * guarantee it works.
6485  *
6486  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
6487  */
6488
6489 /* determines the setup value */
6490 int mp_reduce_2k_setup(mp_int *a, mp_digit *d)
6491 {
6492    int res, p;
6493    mp_int tmp;
6494    
6495    if ((res = mp_init(&tmp)) != MP_OKAY) {
6496       return res;
6497    }
6498    
6499    p = mp_count_bits(a);
6500    if ((res = mp_2expt(&tmp, p)) != MP_OKAY) {
6501       mp_clear(&tmp);
6502       return res;
6503    }
6504    
6505    if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) {
6506       mp_clear(&tmp);
6507       return res;
6508    }
6509    
6510    *d = tmp.dp[0];
6511    mp_clear(&tmp);
6512    return MP_OKAY;
6513 }
6514 #endif
6515
6516 /* End: bn_mp_reduce_2k_setup.c */
6517
6518 /* Start: bn_mp_reduce_2k_setup_l.c */
6519 #include "tma.h"
6520 #ifdef BN_MP_REDUCE_2K_SETUP_L_C
6521 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6522  *
6523  * LibTomMath is a library that provides multiple-precision
6524  * integer arithmetic as well as number theoretic functionality.
6525  *
6526  * The library was designed directly after the MPI library by
6527  * Michael Fromberger but has been written from scratch with
6528  * additional optimizations in place.
6529  *
6530  * The library is free for all purposes without any express
6531  * guarantee it works.
6532  *
6533  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
6534  */
6535
6536 /* determines the setup value */
6537 int mp_reduce_2k_setup_l(mp_int *a, mp_int *d)
6538 {
6539    int    res;
6540    mp_int tmp;
6541    
6542    if ((res = mp_init(&tmp)) != MP_OKAY) {
6543       return res;
6544    }
6545    
6546    if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) {
6547       goto ERR;
6548    }
6549    
6550    if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) {
6551       goto ERR;
6552    }
6553    
6554 ERR:
6555    mp_clear(&tmp);
6556    return res;
6557 }
6558 #endif
6559
6560 /* End: bn_mp_reduce_2k_setup_l.c */
6561
6562 /* Start: bn_mp_reduce_is_2k.c */
6563 #include "tma.h"
6564 #ifdef BN_MP_REDUCE_IS_2K_C
6565 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6566  *
6567  * LibTomMath is a library that provides multiple-precision
6568  * integer arithmetic as well as number theoretic functionality.
6569  *
6570  * The library was designed directly after the MPI library by
6571  * Michael Fromberger but has been written from scratch with
6572  * additional optimizations in place.
6573  *
6574  * The library is free for all purposes without any express
6575  * guarantee it works.
6576  *
6577  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
6578  */
6579
6580 /* determines if mp_reduce_2k can be used */
6581 int mp_reduce_is_2k(mp_int *a)
6582 {
6583    int ix, iy, iw;
6584    mp_digit iz;
6585    
6586    if (a->used == 0) {
6587       return MP_NO;
6588    } else if (a->used == 1) {
6589       return MP_YES;
6590    } else if (a->used > 1) {
6591       iy = mp_count_bits(a);
6592       iz = 1;
6593       iw = 1;
6594     
6595       /* Test every bit from the second digit up, must be 1 */
6596       for (ix = DIGIT_BIT; ix < iy; ix++) {
6597           if ((a->dp[iw] & iz) == 0) {
6598              return MP_NO;
6599           }
6600           iz <<= 1;
6601           if (iz > (mp_digit)MP_MASK) {
6602              ++iw;
6603              iz = 1;
6604           }
6605       }
6606    }
6607    return MP_YES;
6608 }
6609
6610 #endif
6611
6612 /* End: bn_mp_reduce_is_2k.c */
6613
6614 /* Start: bn_mp_reduce_is_2k_l.c */
6615 #include "tma.h"
6616 #ifdef BN_MP_REDUCE_IS_2K_L_C
6617 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6618  *
6619  * LibTomMath is a library that provides multiple-precision
6620  * integer arithmetic as well as number theoretic functionality.
6621  *
6622  * The library was designed directly after the MPI library by
6623  * Michael Fromberger but has been written from scratch with
6624  * additional optimizations in place.
6625  *
6626  * The library is free for all purposes without any express
6627  * guarantee it works.
6628  *
6629  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
6630  */
6631
6632 /* determines if reduce_2k_l can be used */
6633 int mp_reduce_is_2k_l(mp_int *a)
6634 {
6635    int ix, iy;
6636    
6637    if (a->used == 0) {
6638       return MP_NO;
6639    } else if (a->used == 1) {
6640       return MP_YES;
6641    } else if (a->used > 1) {
6642       /* if more than half of the digits are -1 we're sold */
6643       for (iy = ix = 0; ix < a->used; ix++) {
6644           if (a->dp[ix] == MP_MASK) {
6645               ++iy;
6646           }
6647       }
6648       return (iy >= (a->used/2)) ? MP_YES : MP_NO;
6649       
6650    }
6651    return MP_NO;
6652 }
6653
6654 #endif
6655
6656 /* End: bn_mp_reduce_is_2k_l.c */
6657
6658 /* Start: bn_mp_reduce_setup.c */
6659 #include "tma.h"
6660 #ifdef BN_MP_REDUCE_SETUP_C
6661 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6662  *
6663  * LibTomMath is a library that provides multiple-precision
6664  * integer arithmetic as well as number theoretic functionality.
6665  *
6666  * The library was designed directly after the MPI library by
6667  * Michael Fromberger but has been written from scratch with
6668  * additional optimizations in place.
6669  *
6670  * The library is free for all purposes without any express
6671  * guarantee it works.
6672  *
6673  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
6674  */
6675
6676 /* pre-calculate the value required for Barrett reduction
6677  * For a given modulus "b" it calulates the value required in "a"
6678  */
6679 int mp_reduce_setup (mp_int * a, mp_int * b)
6680 {
6681   int     res;
6682   
6683   if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) {
6684     return res;
6685   }
6686   return mp_div (a, b, a, NULL);
6687 }
6688 #endif
6689
6690 /* End: bn_mp_reduce_setup.c */
6691
6692 /* Start: bn_mp_rshd.c */
6693 #include "tma.h"
6694 #ifdef BN_MP_RSHD_C
6695 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6696  *
6697  * LibTomMath is a library that provides multiple-precision
6698  * integer arithmetic as well as number theoretic functionality.
6699  *
6700  * The library was designed directly after the MPI library by
6701  * Michael Fromberger but has been written from scratch with
6702  * additional optimizations in place.
6703  *
6704  * The library is free for all purposes without any express
6705  * guarantee it works.
6706  *
6707  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
6708  */
6709
6710 /* shift right a certain amount of digits */
6711 void mp_rshd (mp_int * a, int b)
6712 {
6713   int     x;
6714
6715   /* if b <= 0 then ignore it */
6716   if (b <= 0) {
6717     return;
6718   }
6719
6720   /* if b > used then simply zero it and return */
6721   if (a->used <= b) {
6722     mp_zero (a);
6723     return;
6724   }
6725
6726   {
6727     register mp_digit *bottom, *top;
6728
6729     /* shift the digits down */
6730
6731     /* bottom */
6732     bottom = a->dp;
6733
6734     /* top [offset into digits] */
6735     top = a->dp + b;
6736
6737     /* this is implemented as a sliding window where 
6738      * the window is b-digits long and digits from 
6739      * the top of the window are copied to the bottom
6740      *
6741      * e.g.
6742
6743      b-2 | b-1 | b0 | b1 | b2 | ... | bb |   ---->
6744                  /\                   |      ---->
6745                   \-------------------/      ---->
6746      */
6747     for (x = 0; x < (a->used - b); x++) {
6748       *bottom++ = *top++;
6749     }
6750
6751     /* zero the top digits */
6752     for (; x < a->used; x++) {
6753       *bottom++ = 0;
6754     }
6755   }
6756   
6757   /* remove excess digits */
6758   a->used -= b;
6759 }
6760 #endif
6761
6762 /* End: bn_mp_rshd.c */
6763
6764 /* Start: bn_mp_set.c */
6765 #include "tma.h"
6766 #ifdef BN_MP_SET_C
6767 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6768  *
6769  * LibTomMath is a library that provides multiple-precision
6770  * integer arithmetic as well as number theoretic functionality.
6771  *
6772  * The library was designed directly after the MPI library by
6773  * Michael Fromberger but has been written from scratch with
6774  * additional optimizations in place.
6775  *
6776  * The library is free for all purposes without any express
6777  * guarantee it works.
6778  *
6779  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
6780  */
6781
6782 /* set to a digit */
6783 void mp_set (mp_int * a, mp_digit b)
6784 {
6785   mp_zero (a);
6786   a->dp[0] = b & MP_MASK;
6787   a->used  = (a->dp[0] != 0) ? 1 : 0;
6788 }
6789 #endif
6790
6791 /* End: bn_mp_set.c */
6792
6793 /* Start: bn_mp_set_int.c */
6794 #include "tma.h"
6795 #ifdef BN_MP_SET_INT_C
6796 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6797  *
6798  * LibTomMath is a library that provides multiple-precision
6799  * integer arithmetic as well as number theoretic functionality.
6800  *
6801  * The library was designed directly after the MPI library by
6802  * Michael Fromberger but has been written from scratch with
6803  * additional optimizations in place.
6804  *
6805  * The library is free for all purposes without any express
6806  * guarantee it works.
6807  *
6808  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
6809  */
6810
6811 /* set a 32-bit const */
6812 int mp_set_int (mp_int * a, unsigned long b)
6813 {
6814   int     x, res;
6815
6816   mp_zero (a);
6817   
6818   /* set four bits at a time */
6819   for (x = 0; x < 8; x++) {
6820     /* shift the number up four bits */
6821     if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) {
6822       return res;
6823     }
6824
6825     /* OR in the top four bits of the source */
6826     a->dp[0] |= (b >> 28) & 15;
6827
6828     /* shift the source up to the next four bits */
6829     b <<= 4;
6830
6831     /* ensure that digits are not clamped off */
6832     a->used += 1;
6833   }
6834   mp_clamp (a);
6835   return MP_OKAY;
6836 }
6837 #endif
6838
6839 /* End: bn_mp_set_int.c */
6840
6841 /* Start: bn_mp_shrink.c */
6842 #include "tma.h"
6843 #ifdef BN_MP_SHRINK_C
6844 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6845  *
6846  * LibTomMath is a library that provides multiple-precision
6847  * integer arithmetic as well as number theoretic functionality.
6848  *
6849  * The library was designed directly after the MPI library by
6850  * Michael Fromberger but has been written from scratch with
6851  * additional optimizations in place.
6852  *
6853  * The library is free for all purposes without any express
6854  * guarantee it works.
6855  *
6856  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
6857  */
6858
6859 /* shrink a bignum */
6860 int mp_shrink (mp_int * a)
6861 {
6862   mp_digit *tmp;
6863   if (a->alloc != a->used && a->used > 0) {
6864     if ((tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * a->used)) == NULL) {
6865       return MP_MEM;
6866     }
6867     a->dp    = tmp;
6868     a->alloc = a->used;
6869   }
6870   return MP_OKAY;
6871 }
6872 #endif
6873
6874 /* End: bn_mp_shrink.c */
6875
6876 /* Start: bn_mp_signed_bin_size.c */
6877 #include "tma.h"
6878 #ifdef BN_MP_SIGNED_BIN_SIZE_C
6879 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6880  *
6881  * LibTomMath is a library that provides multiple-precision
6882  * integer arithmetic as well as number theoretic functionality.
6883  *
6884  * The library was designed directly after the MPI library by
6885  * Michael Fromberger but has been written from scratch with
6886  * additional optimizations in place.
6887  *
6888  * The library is free for all purposes without any express
6889  * guarantee it works.
6890  *
6891  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
6892  */
6893
6894 /* get the size for an signed equivalent */
6895 int mp_signed_bin_size (mp_int * a)
6896 {
6897   return 1 + mp_unsigned_bin_size (a);
6898 }
6899 #endif
6900
6901 /* End: bn_mp_signed_bin_size.c */
6902
6903 /* Start: bn_mp_sqr.c */
6904 #include "tma.h"
6905 #ifdef BN_MP_SQR_C
6906 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6907  *
6908  * LibTomMath is a library that provides multiple-precision
6909  * integer arithmetic as well as number theoretic functionality.
6910  *
6911  * The library was designed directly after the MPI library by
6912  * Michael Fromberger but has been written from scratch with
6913  * additional optimizations in place.
6914  *
6915  * The library is free for all purposes without any express
6916  * guarantee it works.
6917  *
6918  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
6919  */
6920
6921 /* computes b = a*a */
6922 int
6923 mp_sqr (mp_int * a, mp_int * b)
6924 {
6925   int     res;
6926
6927 #ifdef BN_MP_TOOM_SQR_C
6928   /* use Toom-Cook? */
6929   if (a->used >= TOOM_SQR_CUTOFF) {
6930     res = mp_toom_sqr(a, b);
6931   /* Karatsuba? */
6932   } else 
6933 #endif
6934 #ifdef BN_MP_KARATSUBA_SQR_C
6935 if (a->used >= KARATSUBA_SQR_CUTOFF) {
6936     res = mp_karatsuba_sqr (a, b);
6937   } else 
6938 #endif
6939   {
6940 #ifdef BN_FAST_S_MP_SQR_C
6941     /* can we use the fast comba multiplier? */
6942     if ((a->used * 2 + 1) < MP_WARRAY && 
6943          a->used < 
6944          (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) {
6945       res = fast_s_mp_sqr (a, b);
6946     } else
6947 #endif
6948 #ifdef BN_S_MP_SQR_C
6949       res = s_mp_sqr (a, b);
6950 #else
6951       res = MP_VAL;
6952 #endif
6953   }
6954   b->sign = MP_ZPOS;
6955   return res;
6956 }
6957 #endif
6958
6959 /* End: bn_mp_sqr.c */
6960
6961 /* Start: bn_mp_sqrmod.c */
6962 #include "tma.h"
6963 #ifdef BN_MP_SQRMOD_C
6964 /* LibTomMath, multiple-precision integer library -- Tom St Denis
6965  *
6966  * LibTomMath is a library that provides multiple-precision
6967  * integer arithmetic as well as number theoretic functionality.
6968  *
6969  * The library was designed directly after the MPI library by
6970  * Michael Fromberger but has been written from scratch with
6971  * additional optimizations in place.
6972  *
6973  * The library is free for all purposes without any express
6974  * guarantee it works.
6975  *
6976  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
6977  */
6978
6979 /* c = a * a (mod b) */
6980 int
6981 mp_sqrmod (mp_int * a, mp_int * b, mp_int * c)
6982 {
6983   int     res;
6984   mp_int  t;
6985
6986   if ((res = mp_init (&t)) != MP_OKAY) {
6987     return res;
6988   }
6989
6990   if ((res = mp_sqr (a, &t)) != MP_OKAY) {
6991     mp_clear (&t);
6992     return res;
6993   }
6994   res = mp_mod (&t, b, c);
6995   mp_clear (&t);
6996   return res;
6997 }
6998 #endif
6999
7000 /* End: bn_mp_sqrmod.c */
7001
7002 /* Start: bn_mp_sqrt.c */
7003 #include "tma.h"
7004 #ifdef BN_MP_SQRT_C
7005 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7006  *
7007  * LibTomMath is a library that provides multiple-precision
7008  * integer arithmetic as well as number theoretic functionality.
7009  *
7010  * The library was designed directly after the MPI library by
7011  * Michael Fromberger but has been written from scratch with
7012  * additional optimizations in place.
7013  *
7014  * The library is free for all purposes without any express
7015  * guarantee it works.
7016  *
7017  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
7018  */
7019
7020 /* this function is less generic than mp_n_root, simpler and faster */
7021 int mp_sqrt(mp_int *arg, mp_int *ret) 
7022 {
7023   int res;
7024   mp_int t1,t2;
7025
7026   /* must be positive */
7027   if (arg->sign == MP_NEG) {
7028     return MP_VAL;
7029   }
7030
7031   /* easy out */
7032   if (mp_iszero(arg) == MP_YES) {
7033     mp_zero(ret);
7034     return MP_OKAY;
7035   }
7036
7037   if ((res = mp_init_copy(&t1, arg)) != MP_OKAY) {
7038     return res;
7039   }
7040
7041   if ((res = mp_init(&t2)) != MP_OKAY) {
7042     goto E2;
7043   }
7044
7045   /* First approx. (not very bad for large arg) */
7046   mp_rshd (&t1,t1.used/2);
7047
7048   /* t1 > 0  */ 
7049   if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) {
7050     goto E1;
7051   }
7052   if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) {
7053     goto E1;
7054   }
7055   if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) {
7056     goto E1;
7057   }
7058   /* And now t1 > sqrt(arg) */
7059   do { 
7060     if ((res = mp_div(arg,&t1,&t2,NULL)) != MP_OKAY) {
7061       goto E1;
7062     }
7063     if ((res = mp_add(&t1,&t2,&t1)) != MP_OKAY) {
7064       goto E1;
7065     }
7066     if ((res = mp_div_2(&t1,&t1)) != MP_OKAY) {
7067       goto E1;
7068     }
7069     /* t1 >= sqrt(arg) >= t2 at this point */
7070   } while (mp_cmp_mag(&t1,&t2) == MP_GT);
7071
7072   mp_exch(&t1,ret);
7073
7074 E1: mp_clear(&t2);
7075 E2: mp_clear(&t1);
7076   return res;
7077 }
7078
7079 #endif
7080
7081 /* End: bn_mp_sqrt.c */
7082
7083 /* Start: bn_mp_sub.c */
7084 #include "tma.h"
7085 #ifdef BN_MP_SUB_C
7086 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7087  *
7088  * LibTomMath is a library that provides multiple-precision
7089  * integer arithmetic as well as number theoretic functionality.
7090  *
7091  * The library was designed directly after the MPI library by
7092  * Michael Fromberger but has been written from scratch with
7093  * additional optimizations in place.
7094  *
7095  * The library is free for all purposes without any express
7096  * guarantee it works.
7097  *
7098  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
7099  */
7100
7101 /* high level subtraction (handles signs) */
7102 int
7103 mp_sub (mp_int * a, mp_int * b, mp_int * c)
7104 {
7105   int     sa, sb, res;
7106
7107   sa = a->sign;
7108   sb = b->sign;
7109
7110   if (sa != sb) {
7111     /* subtract a negative from a positive, OR */
7112     /* subtract a positive from a negative. */
7113     /* In either case, ADD their magnitudes, */
7114     /* and use the sign of the first number. */
7115     c->sign = sa;
7116     res = s_mp_add (a, b, c);
7117   } else {
7118     /* subtract a positive from a positive, OR */
7119     /* subtract a negative from a negative. */
7120     /* First, take the difference between their */
7121     /* magnitudes, then... */
7122     if (mp_cmp_mag (a, b) != MP_LT) {
7123       /* Copy the sign from the first */
7124       c->sign = sa;
7125       /* The first has a larger or equal magnitude */
7126       res = s_mp_sub (a, b, c);
7127     } else {
7128       /* The result has the *opposite* sign from */
7129       /* the first number. */
7130       c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS;
7131       /* The second has a larger magnitude */
7132       res = s_mp_sub (b, a, c);
7133     }
7134   }
7135   return res;
7136 }
7137
7138 #endif
7139
7140 /* End: bn_mp_sub.c */
7141
7142 /* Start: bn_mp_sub_d.c */
7143 #include "tma.h"
7144 #ifdef BN_MP_SUB_D_C
7145 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7146  *
7147  * LibTomMath is a library that provides multiple-precision
7148  * integer arithmetic as well as number theoretic functionality.
7149  *
7150  * The library was designed directly after the MPI library by
7151  * Michael Fromberger but has been written from scratch with
7152  * additional optimizations in place.
7153  *
7154  * The library is free for all purposes without any express
7155  * guarantee it works.
7156  *
7157  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
7158  */
7159
7160 /* single digit subtraction */
7161 int
7162 mp_sub_d (mp_int * a, mp_digit b, mp_int * c)
7163 {
7164   mp_digit *tmpa, *tmpc, mu;
7165   int       res, ix, oldused;
7166
7167   /* grow c as required */
7168   if (c->alloc < a->used + 1) {
7169      if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) {
7170         return res;
7171      }
7172   }
7173
7174   /* if a is negative just do an unsigned
7175    * addition [with fudged signs]
7176    */
7177   if (a->sign == MP_NEG) {
7178      a->sign = MP_ZPOS;
7179      res     = mp_add_d(a, b, c);
7180      a->sign = c->sign = MP_NEG;
7181      return res;
7182   }
7183
7184   /* setup regs */
7185   oldused = c->used;
7186   tmpa    = a->dp;
7187   tmpc    = c->dp;
7188
7189   /* if a <= b simply fix the single digit */
7190   if ((a->used == 1 && a->dp[0] <= b) || a->used == 0) {
7191      if (a->used == 1) {
7192         *tmpc++ = b - *tmpa;
7193      } else {
7194         *tmpc++ = b;
7195      }
7196      ix      = 1;
7197
7198      /* negative/1digit */
7199      c->sign = MP_NEG;
7200      c->used = 1;
7201   } else {
7202      /* positive/size */
7203      c->sign = MP_ZPOS;
7204      c->used = a->used;
7205
7206      /* subtract first digit */
7207      *tmpc    = *tmpa++ - b;
7208      mu       = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
7209      *tmpc++ &= MP_MASK;
7210
7211      /* handle rest of the digits */
7212      for (ix = 1; ix < a->used; ix++) {
7213         *tmpc    = *tmpa++ - mu;
7214         mu       = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1);
7215         *tmpc++ &= MP_MASK;
7216      }
7217   }
7218
7219   /* zero excess digits */
7220   while (ix++ < oldused) {
7221      *tmpc++ = 0;
7222   }
7223   mp_clamp(c);
7224   return MP_OKAY;
7225 }
7226
7227 #endif
7228
7229 /* End: bn_mp_sub_d.c */
7230
7231 /* Start: bn_mp_submod.c */
7232 #include "tma.h"
7233 #ifdef BN_MP_SUBMOD_C
7234 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7235  *
7236  * LibTomMath is a library that provides multiple-precision
7237  * integer arithmetic as well as number theoretic functionality.
7238  *
7239  * The library was designed directly after the MPI library by
7240  * Michael Fromberger but has been written from scratch with
7241  * additional optimizations in place.
7242  *
7243  * The library is free for all purposes without any express
7244  * guarantee it works.
7245  *
7246  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
7247  */
7248
7249 /* d = a - b (mod c) */
7250 int
7251 mp_submod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
7252 {
7253   int     res;
7254   mp_int  t;
7255
7256
7257   if ((res = mp_init (&t)) != MP_OKAY) {
7258     return res;
7259   }
7260
7261   if ((res = mp_sub (a, b, &t)) != MP_OKAY) {
7262     mp_clear (&t);
7263     return res;
7264   }
7265   res = mp_mod (&t, c, d);
7266   mp_clear (&t);
7267   return res;
7268 }
7269 #endif
7270
7271 /* End: bn_mp_submod.c */
7272
7273 /* Start: bn_mp_to_signed_bin.c */
7274 #include "tma.h"
7275 #ifdef BN_MP_TO_SIGNED_BIN_C
7276 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7277  *
7278  * LibTomMath is a library that provides multiple-precision
7279  * integer arithmetic as well as number theoretic functionality.
7280  *
7281  * The library was designed directly after the MPI library by
7282  * Michael Fromberger but has been written from scratch with
7283  * additional optimizations in place.
7284  *
7285  * The library is free for all purposes without any express
7286  * guarantee it works.
7287  *
7288  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
7289  */
7290
7291 /* store in signed [big endian] format */
7292 int mp_to_signed_bin (mp_int * a, unsigned char *b)
7293 {
7294   int     res;
7295
7296   if ((res = mp_to_unsigned_bin (a, b + 1)) != MP_OKAY) {
7297     return res;
7298   }
7299   b[0] = (unsigned char) ((a->sign == MP_ZPOS) ? 0 : 1);
7300   return MP_OKAY;
7301 }
7302 #endif
7303
7304 /* End: bn_mp_to_signed_bin.c */
7305
7306 /* Start: bn_mp_to_signed_bin_n.c */
7307 #include "tma.h"
7308 #ifdef BN_MP_TO_SIGNED_BIN_N_C
7309 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7310  *
7311  * LibTomMath is a library that provides multiple-precision
7312  * integer arithmetic as well as number theoretic functionality.
7313  *
7314  * The library was designed directly after the MPI library by
7315  * Michael Fromberger but has been written from scratch with
7316  * additional optimizations in place.
7317  *
7318  * The library is free for all purposes without any express
7319  * guarantee it works.
7320  *
7321  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
7322  */
7323
7324 /* store in signed [big endian] format */
7325 int mp_to_signed_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen)
7326 {
7327    if (*outlen < (unsigned long)mp_signed_bin_size(a)) {
7328       return MP_VAL;
7329    }
7330    *outlen = mp_signed_bin_size(a);
7331    return mp_to_signed_bin(a, b);
7332 }
7333 #endif
7334
7335 /* End: bn_mp_to_signed_bin_n.c */
7336
7337 /* Start: bn_mp_to_unsigned_bin.c */
7338 #include "tma.h"
7339 #ifdef BN_MP_TO_UNSIGNED_BIN_C
7340 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7341  *
7342  * LibTomMath is a library that provides multiple-precision
7343  * integer arithmetic as well as number theoretic functionality.
7344  *
7345  * The library was designed directly after the MPI library by
7346  * Michael Fromberger but has been written from scratch with
7347  * additional optimizations in place.
7348  *
7349  * The library is free for all purposes without any express
7350  * guarantee it works.
7351  *
7352  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
7353  */
7354
7355 /* store in unsigned [big endian] format */
7356 int mp_to_unsigned_bin (mp_int * a, unsigned char *b)
7357 {
7358   int     x, res;
7359   mp_int  t;
7360
7361   if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
7362     return res;
7363   }
7364
7365   x = 0;
7366   while (mp_iszero (&t) == 0) {
7367 #ifndef MP_8BIT
7368       b[x++] = (unsigned char) (t.dp[0] & 255);
7369 #else
7370       b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7));
7371 #endif
7372     if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) {
7373       mp_clear (&t);
7374       return res;
7375     }
7376   }
7377   bn_reverse (b, x);
7378   mp_clear (&t);
7379   return MP_OKAY;
7380 }
7381 #endif
7382
7383 /* End: bn_mp_to_unsigned_bin.c */
7384
7385 /* Start: bn_mp_to_unsigned_bin_n.c */
7386 #include "tma.h"
7387 #ifdef BN_MP_TO_UNSIGNED_BIN_N_C
7388 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7389  *
7390  * LibTomMath is a library that provides multiple-precision
7391  * integer arithmetic as well as number theoretic functionality.
7392  *
7393  * The library was designed directly after the MPI library by
7394  * Michael Fromberger but has been written from scratch with
7395  * additional optimizations in place.
7396  *
7397  * The library is free for all purposes without any express
7398  * guarantee it works.
7399  *
7400  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
7401  */
7402
7403 /* store in unsigned [big endian] format */
7404 int mp_to_unsigned_bin_n (mp_int * a, unsigned char *b, unsigned long *outlen)
7405 {
7406    if (*outlen < (unsigned long)mp_unsigned_bin_size(a)) {
7407       return MP_VAL;
7408    }
7409    *outlen = mp_unsigned_bin_size(a);
7410    return mp_to_unsigned_bin(a, b);
7411 }
7412 #endif
7413
7414 /* End: bn_mp_to_unsigned_bin_n.c */
7415
7416 /* Start: bn_mp_toom_mul.c */
7417 #include "tma.h"
7418 #ifdef BN_MP_TOOM_MUL_C
7419 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7420  *
7421  * LibTomMath is a library that provides multiple-precision
7422  * integer arithmetic as well as number theoretic functionality.
7423  *
7424  * The library was designed directly after the MPI library by
7425  * Michael Fromberger but has been written from scratch with
7426  * additional optimizations in place.
7427  *
7428  * The library is free for all purposes without any express
7429  * guarantee it works.
7430  *
7431  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
7432  */
7433
7434 /* multiplication using the Toom-Cook 3-way algorithm 
7435  *
7436  * Much more complicated than Karatsuba but has a lower 
7437  * asymptotic running time of O(N**1.464).  This algorithm is 
7438  * only particularly useful on VERY large inputs 
7439  * (we're talking 1000s of digits here...).
7440 */
7441 int mp_toom_mul(mp_int *a, mp_int *b, mp_int *c)
7442 {
7443     mp_int w0, w1, w2, w3, w4, tmp1, tmp2, a0, a1, a2, b0, b1, b2;
7444     int res, B;
7445         
7446     /* init temps */
7447     if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, 
7448                              &a0, &a1, &a2, &b0, &b1, 
7449                              &b2, &tmp1, &tmp2, NULL)) != MP_OKAY) {
7450        return res;
7451     }
7452     
7453     /* B */
7454     B = MIN(a->used, b->used) / 3;
7455     
7456     /* a = a2 * B**2 + a1 * B + a0 */
7457     if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
7458        goto ERR;
7459     }
7460
7461     if ((res = mp_copy(a, &a1)) != MP_OKAY) {
7462        goto ERR;
7463     }
7464     mp_rshd(&a1, B);
7465     mp_mod_2d(&a1, DIGIT_BIT * B, &a1);
7466
7467     if ((res = mp_copy(a, &a2)) != MP_OKAY) {
7468        goto ERR;
7469     }
7470     mp_rshd(&a2, B*2);
7471     
7472     /* b = b2 * B**2 + b1 * B + b0 */
7473     if ((res = mp_mod_2d(b, DIGIT_BIT * B, &b0)) != MP_OKAY) {
7474        goto ERR;
7475     }
7476
7477     if ((res = mp_copy(b, &b1)) != MP_OKAY) {
7478        goto ERR;
7479     }
7480     mp_rshd(&b1, B);
7481     mp_mod_2d(&b1, DIGIT_BIT * B, &b1);
7482
7483     if ((res = mp_copy(b, &b2)) != MP_OKAY) {
7484        goto ERR;
7485     }
7486     mp_rshd(&b2, B*2);
7487     
7488     /* w0 = a0*b0 */
7489     if ((res = mp_mul(&a0, &b0, &w0)) != MP_OKAY) {
7490        goto ERR;
7491     }
7492     
7493     /* w4 = a2 * b2 */
7494     if ((res = mp_mul(&a2, &b2, &w4)) != MP_OKAY) {
7495        goto ERR;
7496     }
7497     
7498     /* w1 = (a2 + 2(a1 + 2a0))(b2 + 2(b1 + 2b0)) */
7499     if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
7500        goto ERR;
7501     }
7502     if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
7503        goto ERR;
7504     }
7505     if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
7506        goto ERR;
7507     }
7508     if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
7509        goto ERR;
7510     }
7511     
7512     if ((res = mp_mul_2(&b0, &tmp2)) != MP_OKAY) {
7513        goto ERR;
7514     }
7515     if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
7516        goto ERR;
7517     }
7518     if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
7519        goto ERR;
7520     }
7521     if ((res = mp_add(&tmp2, &b2, &tmp2)) != MP_OKAY) {
7522        goto ERR;
7523     }
7524     
7525     if ((res = mp_mul(&tmp1, &tmp2, &w1)) != MP_OKAY) {
7526        goto ERR;
7527     }
7528     
7529     /* w3 = (a0 + 2(a1 + 2a2))(b0 + 2(b1 + 2b2)) */
7530     if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
7531        goto ERR;
7532     }
7533     if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
7534        goto ERR;
7535     }
7536     if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
7537        goto ERR;
7538     }
7539     if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
7540        goto ERR;
7541     }
7542     
7543     if ((res = mp_mul_2(&b2, &tmp2)) != MP_OKAY) {
7544        goto ERR;
7545     }
7546     if ((res = mp_add(&tmp2, &b1, &tmp2)) != MP_OKAY) {
7547        goto ERR;
7548     }
7549     if ((res = mp_mul_2(&tmp2, &tmp2)) != MP_OKAY) {
7550        goto ERR;
7551     }
7552     if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
7553        goto ERR;
7554     }
7555     
7556     if ((res = mp_mul(&tmp1, &tmp2, &w3)) != MP_OKAY) {
7557        goto ERR;
7558     }
7559     
7560
7561     /* w2 = (a2 + a1 + a0)(b2 + b1 + b0) */
7562     if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
7563        goto ERR;
7564     }
7565     if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
7566        goto ERR;
7567     }
7568     if ((res = mp_add(&b2, &b1, &tmp2)) != MP_OKAY) {
7569        goto ERR;
7570     }
7571     if ((res = mp_add(&tmp2, &b0, &tmp2)) != MP_OKAY) {
7572        goto ERR;
7573     }
7574     if ((res = mp_mul(&tmp1, &tmp2, &w2)) != MP_OKAY) {
7575        goto ERR;
7576     }
7577     
7578     /* now solve the matrix 
7579     
7580        0  0  0  0  1
7581        1  2  4  8  16
7582        1  1  1  1  1
7583        16 8  4  2  1
7584        1  0  0  0  0
7585        
7586        using 12 subtractions, 4 shifts, 
7587               2 small divisions and 1 small multiplication 
7588      */
7589      
7590      /* r1 - r4 */
7591      if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
7592         goto ERR;
7593      }
7594      /* r3 - r0 */
7595      if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
7596         goto ERR;
7597      }
7598      /* r1/2 */
7599      if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
7600         goto ERR;
7601      }
7602      /* r3/2 */
7603      if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
7604         goto ERR;
7605      }
7606      /* r2 - r0 - r4 */
7607      if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
7608         goto ERR;
7609      }
7610      if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
7611         goto ERR;
7612      }
7613      /* r1 - r2 */
7614      if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
7615         goto ERR;
7616      }
7617      /* r3 - r2 */
7618      if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
7619         goto ERR;
7620      }
7621      /* r1 - 8r0 */
7622      if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
7623         goto ERR;
7624      }
7625      if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
7626         goto ERR;
7627      }
7628      /* r3 - 8r4 */
7629      if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
7630         goto ERR;
7631      }
7632      if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
7633         goto ERR;
7634      }
7635      /* 3r2 - r1 - r3 */
7636      if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
7637         goto ERR;
7638      }
7639      if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
7640         goto ERR;
7641      }
7642      if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
7643         goto ERR;
7644      }
7645      /* r1 - r2 */
7646      if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
7647         goto ERR;
7648      }
7649      /* r3 - r2 */
7650      if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
7651         goto ERR;
7652      }
7653      /* r1/3 */
7654      if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
7655         goto ERR;
7656      }
7657      /* r3/3 */
7658      if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
7659         goto ERR;
7660      }
7661      
7662      /* at this point shift W[n] by B*n */
7663      if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
7664         goto ERR;
7665      }
7666      if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
7667         goto ERR;
7668      }
7669      if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
7670         goto ERR;
7671      }
7672      if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
7673         goto ERR;
7674      }     
7675      
7676      if ((res = mp_add(&w0, &w1, c)) != MP_OKAY) {
7677         goto ERR;
7678      }
7679      if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
7680         goto ERR;
7681      }
7682      if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
7683         goto ERR;
7684      }
7685      if ((res = mp_add(&tmp1, c, c)) != MP_OKAY) {
7686         goto ERR;
7687      }     
7688      
7689 ERR:
7690      mp_clear_multi(&w0, &w1, &w2, &w3, &w4, 
7691                     &a0, &a1, &a2, &b0, &b1, 
7692                     &b2, &tmp1, &tmp2, NULL);
7693      return res;
7694 }     
7695      
7696 #endif
7697
7698 /* End: bn_mp_toom_mul.c */
7699
7700 /* Start: bn_mp_toom_sqr.c */
7701 #include "tma.h"
7702 #ifdef BN_MP_TOOM_SQR_C
7703 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7704  *
7705  * LibTomMath is a library that provides multiple-precision
7706  * integer arithmetic as well as number theoretic functionality.
7707  *
7708  * The library was designed directly after the MPI library by
7709  * Michael Fromberger but has been written from scratch with
7710  * additional optimizations in place.
7711  *
7712  * The library is free for all purposes without any express
7713  * guarantee it works.
7714  *
7715  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
7716  */
7717
7718 /* squaring using Toom-Cook 3-way algorithm */
7719 int
7720 mp_toom_sqr(mp_int *a, mp_int *b)
7721 {
7722     mp_int w0, w1, w2, w3, w4, tmp1, a0, a1, a2;
7723     int res, B;
7724
7725     /* init temps */
7726     if ((res = mp_init_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL)) != MP_OKAY) {
7727        return res;
7728     }
7729
7730     /* B */
7731     B = a->used / 3;
7732
7733     /* a = a2 * B**2 + a1 * B + a0 */
7734     if ((res = mp_mod_2d(a, DIGIT_BIT * B, &a0)) != MP_OKAY) {
7735        goto ERR;
7736     }
7737
7738     if ((res = mp_copy(a, &a1)) != MP_OKAY) {
7739        goto ERR;
7740     }
7741     mp_rshd(&a1, B);
7742     mp_mod_2d(&a1, DIGIT_BIT * B, &a1);
7743
7744     if ((res = mp_copy(a, &a2)) != MP_OKAY) {
7745        goto ERR;
7746     }
7747     mp_rshd(&a2, B*2);
7748
7749     /* w0 = a0*a0 */
7750     if ((res = mp_sqr(&a0, &w0)) != MP_OKAY) {
7751        goto ERR;
7752     }
7753
7754     /* w4 = a2 * a2 */
7755     if ((res = mp_sqr(&a2, &w4)) != MP_OKAY) {
7756        goto ERR;
7757     }
7758
7759     /* w1 = (a2 + 2(a1 + 2a0))**2 */
7760     if ((res = mp_mul_2(&a0, &tmp1)) != MP_OKAY) {
7761        goto ERR;
7762     }
7763     if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
7764        goto ERR;
7765     }
7766     if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
7767        goto ERR;
7768     }
7769     if ((res = mp_add(&tmp1, &a2, &tmp1)) != MP_OKAY) {
7770        goto ERR;
7771     }
7772
7773     if ((res = mp_sqr(&tmp1, &w1)) != MP_OKAY) {
7774        goto ERR;
7775     }
7776
7777     /* w3 = (a0 + 2(a1 + 2a2))**2 */
7778     if ((res = mp_mul_2(&a2, &tmp1)) != MP_OKAY) {
7779        goto ERR;
7780     }
7781     if ((res = mp_add(&tmp1, &a1, &tmp1)) != MP_OKAY) {
7782        goto ERR;
7783     }
7784     if ((res = mp_mul_2(&tmp1, &tmp1)) != MP_OKAY) {
7785        goto ERR;
7786     }
7787     if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
7788        goto ERR;
7789     }
7790
7791     if ((res = mp_sqr(&tmp1, &w3)) != MP_OKAY) {
7792        goto ERR;
7793     }
7794
7795
7796     /* w2 = (a2 + a1 + a0)**2 */
7797     if ((res = mp_add(&a2, &a1, &tmp1)) != MP_OKAY) {
7798        goto ERR;
7799     }
7800     if ((res = mp_add(&tmp1, &a0, &tmp1)) != MP_OKAY) {
7801        goto ERR;
7802     }
7803     if ((res = mp_sqr(&tmp1, &w2)) != MP_OKAY) {
7804        goto ERR;
7805     }
7806
7807     /* now solve the matrix
7808
7809        0  0  0  0  1
7810        1  2  4  8  16
7811        1  1  1  1  1
7812        16 8  4  2  1
7813        1  0  0  0  0
7814
7815        using 12 subtractions, 4 shifts, 2 small divisions and 1 small multiplication.
7816      */
7817
7818      /* r1 - r4 */
7819      if ((res = mp_sub(&w1, &w4, &w1)) != MP_OKAY) {
7820         goto ERR;
7821      }
7822      /* r3 - r0 */
7823      if ((res = mp_sub(&w3, &w0, &w3)) != MP_OKAY) {
7824         goto ERR;
7825      }
7826      /* r1/2 */
7827      if ((res = mp_div_2(&w1, &w1)) != MP_OKAY) {
7828         goto ERR;
7829      }
7830      /* r3/2 */
7831      if ((res = mp_div_2(&w3, &w3)) != MP_OKAY) {
7832         goto ERR;
7833      }
7834      /* r2 - r0 - r4 */
7835      if ((res = mp_sub(&w2, &w0, &w2)) != MP_OKAY) {
7836         goto ERR;
7837      }
7838      if ((res = mp_sub(&w2, &w4, &w2)) != MP_OKAY) {
7839         goto ERR;
7840      }
7841      /* r1 - r2 */
7842      if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
7843         goto ERR;
7844      }
7845      /* r3 - r2 */
7846      if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
7847         goto ERR;
7848      }
7849      /* r1 - 8r0 */
7850      if ((res = mp_mul_2d(&w0, 3, &tmp1)) != MP_OKAY) {
7851         goto ERR;
7852      }
7853      if ((res = mp_sub(&w1, &tmp1, &w1)) != MP_OKAY) {
7854         goto ERR;
7855      }
7856      /* r3 - 8r4 */
7857      if ((res = mp_mul_2d(&w4, 3, &tmp1)) != MP_OKAY) {
7858         goto ERR;
7859      }
7860      if ((res = mp_sub(&w3, &tmp1, &w3)) != MP_OKAY) {
7861         goto ERR;
7862      }
7863      /* 3r2 - r1 - r3 */
7864      if ((res = mp_mul_d(&w2, 3, &w2)) != MP_OKAY) {
7865         goto ERR;
7866      }
7867      if ((res = mp_sub(&w2, &w1, &w2)) != MP_OKAY) {
7868         goto ERR;
7869      }
7870      if ((res = mp_sub(&w2, &w3, &w2)) != MP_OKAY) {
7871         goto ERR;
7872      }
7873      /* r1 - r2 */
7874      if ((res = mp_sub(&w1, &w2, &w1)) != MP_OKAY) {
7875         goto ERR;
7876      }
7877      /* r3 - r2 */
7878      if ((res = mp_sub(&w3, &w2, &w3)) != MP_OKAY) {
7879         goto ERR;
7880      }
7881      /* r1/3 */
7882      if ((res = mp_div_3(&w1, &w1, NULL)) != MP_OKAY) {
7883         goto ERR;
7884      }
7885      /* r3/3 */
7886      if ((res = mp_div_3(&w3, &w3, NULL)) != MP_OKAY) {
7887         goto ERR;
7888      }
7889
7890      /* at this point shift W[n] by B*n */
7891      if ((res = mp_lshd(&w1, 1*B)) != MP_OKAY) {
7892         goto ERR;
7893      }
7894      if ((res = mp_lshd(&w2, 2*B)) != MP_OKAY) {
7895         goto ERR;
7896      }
7897      if ((res = mp_lshd(&w3, 3*B)) != MP_OKAY) {
7898         goto ERR;
7899      }
7900      if ((res = mp_lshd(&w4, 4*B)) != MP_OKAY) {
7901         goto ERR;
7902      }
7903
7904      if ((res = mp_add(&w0, &w1, b)) != MP_OKAY) {
7905         goto ERR;
7906      }
7907      if ((res = mp_add(&w2, &w3, &tmp1)) != MP_OKAY) {
7908         goto ERR;
7909      }
7910      if ((res = mp_add(&w4, &tmp1, &tmp1)) != MP_OKAY) {
7911         goto ERR;
7912      }
7913      if ((res = mp_add(&tmp1, b, b)) != MP_OKAY) {
7914         goto ERR;
7915      }
7916
7917 ERR:
7918      mp_clear_multi(&w0, &w1, &w2, &w3, &w4, &a0, &a1, &a2, &tmp1, NULL);
7919      return res;
7920 }
7921
7922 #endif
7923
7924 /* End: bn_mp_toom_sqr.c */
7925
7926 /* Start: bn_mp_toradix.c */
7927 #include "tma.h"
7928 #ifdef BN_MP_TORADIX_C
7929 /* LibTomMath, multiple-precision integer library -- Tom St Denis
7930  *
7931  * LibTomMath is a library that provides multiple-precision
7932  * integer arithmetic as well as number theoretic functionality.
7933  *
7934  * The library was designed directly after the MPI library by
7935  * Michael Fromberger but has been written from scratch with
7936  * additional optimizations in place.
7937  *
7938  * The library is free for all purposes without any express
7939  * guarantee it works.
7940  *
7941  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
7942  */
7943
7944 /* stores a bignum as a ASCII string in a given radix (2..64) */
7945 int mp_toradix (mp_int * a, char *str, int radix)
7946 {
7947   int     res, digs;
7948   mp_int  t;
7949   mp_digit d;
7950   char   *_s = str;
7951
7952   /* check range of the radix */
7953   if (radix < 2 || radix > 64) {
7954     return MP_VAL;
7955   }
7956
7957   /* quick out if its zero */
7958   if (mp_iszero(a) == 1) {
7959      *str++ = '0';
7960      *str = '\0';
7961      return MP_OKAY;
7962   }
7963
7964   if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
7965     return res;
7966   }
7967
7968   /* if it is negative output a - */
7969   if (t.sign == MP_NEG) {
7970     ++_s;
7971     *str++ = '-';
7972     t.sign = MP_ZPOS;
7973   }
7974
7975   digs = 0;
7976   while (mp_iszero (&t) == 0) {
7977     if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
7978       mp_clear (&t);
7979       return res;
7980     }
7981     *str++ = mp_s_rmap[d];
7982     ++digs;
7983   }
7984
7985   /* reverse the digits of the string.  In this case _s points
7986    * to the first digit [exluding the sign] of the number]
7987    */
7988   bn_reverse ((unsigned char *)_s, digs);
7989
7990   /* append a NULL so the string is properly terminated */
7991   *str = '\0';
7992
7993   mp_clear (&t);
7994   return MP_OKAY;
7995 }
7996
7997 #endif
7998
7999 /* End: bn_mp_toradix.c */
8000
8001 /* Start: bn_mp_toradix_n.c */
8002 #include "tma.h"
8003 #ifdef BN_MP_TORADIX_N_C
8004 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8005  *
8006  * LibTomMath is a library that provides multiple-precision
8007  * integer arithmetic as well as number theoretic functionality.
8008  *
8009  * The library was designed directly after the MPI library by
8010  * Michael Fromberger but has been written from scratch with
8011  * additional optimizations in place.
8012  *
8013  * The library is free for all purposes without any express
8014  * guarantee it works.
8015  *
8016  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
8017  */
8018
8019 /* stores a bignum as a ASCII string in a given radix (2..64) 
8020  *
8021  * Stores upto maxlen-1 chars and always a NULL byte 
8022  */
8023 int mp_toradix_n(mp_int * a, char *str, int radix, int maxlen)
8024 {
8025   int     res, digs;
8026   mp_int  t;
8027   mp_digit d;
8028   char   *_s = str;
8029
8030   /* check range of the maxlen, radix */
8031   if (maxlen < 3 || radix < 2 || radix > 64) {
8032     return MP_VAL;
8033   }
8034
8035   /* quick out if its zero */
8036   if (mp_iszero(a) == 1) {
8037      *str++ = '0';
8038      *str = '\0';
8039      return MP_OKAY;
8040   }
8041
8042   if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
8043     return res;
8044   }
8045
8046   /* if it is negative output a - */
8047   if (t.sign == MP_NEG) {
8048     /* we have to reverse our digits later... but not the - sign!! */
8049     ++_s;
8050
8051     /* store the flag and mark the number as positive */
8052     *str++ = '-';
8053     t.sign = MP_ZPOS;
8054  
8055     /* subtract a char */
8056     --maxlen;
8057   }
8058
8059   digs = 0;
8060   while (mp_iszero (&t) == 0) {
8061     if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
8062       mp_clear (&t);
8063       return res;
8064     }
8065     *str++ = mp_s_rmap[d];
8066     ++digs;
8067
8068     if (--maxlen == 1) {
8069        /* no more room */
8070        break;
8071     }
8072   }
8073
8074   /* reverse the digits of the string.  In this case _s points
8075    * to the first digit [exluding the sign] of the number]
8076    */
8077   bn_reverse ((unsigned char *)_s, digs);
8078
8079   /* append a NULL so the string is properly terminated */
8080   *str = '\0';
8081
8082   mp_clear (&t);
8083   return MP_OKAY;
8084 }
8085
8086 #endif
8087
8088 /* End: bn_mp_toradix_n.c */
8089
8090 /* Start: bn_mp_unsigned_bin_size.c */
8091 #include "tma.h"
8092 #ifdef BN_MP_UNSIGNED_BIN_SIZE_C
8093 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8094  *
8095  * LibTomMath is a library that provides multiple-precision
8096  * integer arithmetic as well as number theoretic functionality.
8097  *
8098  * The library was designed directly after the MPI library by
8099  * Michael Fromberger but has been written from scratch with
8100  * additional optimizations in place.
8101  *
8102  * The library is free for all purposes without any express
8103  * guarantee it works.
8104  *
8105  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
8106  */
8107
8108 /* get the size for an unsigned equivalent */
8109 int mp_unsigned_bin_size (mp_int * a)
8110 {
8111   int     size = mp_count_bits (a);
8112   return (size / 8 + ((size & 7) != 0 ? 1 : 0));
8113 }
8114 #endif
8115
8116 /* End: bn_mp_unsigned_bin_size.c */
8117
8118 /* Start: bn_mp_xor.c */
8119 #include "tma.h"
8120 #ifdef BN_MP_XOR_C
8121 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8122  *
8123  * LibTomMath is a library that provides multiple-precision
8124  * integer arithmetic as well as number theoretic functionality.
8125  *
8126  * The library was designed directly after the MPI library by
8127  * Michael Fromberger but has been written from scratch with
8128  * additional optimizations in place.
8129  *
8130  * The library is free for all purposes without any express
8131  * guarantee it works.
8132  *
8133  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
8134  */
8135
8136 /* XOR two ints together */
8137 int
8138 mp_xor (mp_int * a, mp_int * b, mp_int * c)
8139 {
8140   int     res, ix, px;
8141   mp_int  t, *x;
8142
8143   if (a->used > b->used) {
8144     if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
8145       return res;
8146     }
8147     px = b->used;
8148     x = b;
8149   } else {
8150     if ((res = mp_init_copy (&t, b)) != MP_OKAY) {
8151       return res;
8152     }
8153     px = a->used;
8154     x = a;
8155   }
8156
8157   for (ix = 0; ix < px; ix++) {
8158      t.dp[ix] ^= x->dp[ix];
8159   }
8160   mp_clamp (&t);
8161   mp_exch (c, &t);
8162   mp_clear (&t);
8163   return MP_OKAY;
8164 }
8165 #endif
8166
8167 /* End: bn_mp_xor.c */
8168
8169 /* Start: bn_mp_zero.c */
8170 #include "tma.h"
8171 #ifdef BN_MP_ZERO_C
8172 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8173  *
8174  * LibTomMath is a library that provides multiple-precision
8175  * integer arithmetic as well as number theoretic functionality.
8176  *
8177  * The library was designed directly after the MPI library by
8178  * Michael Fromberger but has been written from scratch with
8179  * additional optimizations in place.
8180  *
8181  * The library is free for all purposes without any express
8182  * guarantee it works.
8183  *
8184  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
8185  */
8186
8187 /* set to zero */
8188 void mp_zero (mp_int * a)
8189 {
8190   int       n;
8191   mp_digit *tmp;
8192
8193   a->sign = MP_ZPOS;
8194   a->used = 0;
8195
8196   tmp = a->dp;
8197   for (n = 0; n < a->alloc; n++) {
8198      *tmp++ = 0;
8199   }
8200 }
8201 #endif
8202
8203 /* End: bn_mp_zero.c */
8204
8205 /* Start: bn_prime_tab.c */
8206 #include "tma.h"
8207 #ifdef BN_PRIME_TAB_C
8208 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8209  *
8210  * LibTomMath is a library that provides multiple-precision
8211  * integer arithmetic as well as number theoretic functionality.
8212  *
8213  * The library was designed directly after the MPI library by
8214  * Michael Fromberger but has been written from scratch with
8215  * additional optimizations in place.
8216  *
8217  * The library is free for all purposes without any express
8218  * guarantee it works.
8219  *
8220  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
8221  */
8222 const mp_digit ltm_prime_tab[] = {
8223   0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
8224   0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035,
8225   0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059,
8226   0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F,
8227 #ifndef MP_8BIT
8228   0x0083,
8229   0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD,
8230   0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF,
8231   0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107,
8232   0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137,
8233
8234   0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167,
8235   0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199,
8236   0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9,
8237   0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7,
8238   0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239,
8239   0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265,
8240   0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293,
8241   0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF,
8242
8243   0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301,
8244   0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B,
8245   0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371,
8246   0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD,
8247   0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5,
8248   0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419,
8249   0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449,
8250   0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B,
8251
8252   0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7,
8253   0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503,
8254   0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529,
8255   0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F,
8256   0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3,
8257   0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7,
8258   0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623,
8259   0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653
8260 #endif
8261 };
8262 #endif
8263
8264 /* End: bn_prime_tab.c */
8265
8266 /* Start: bn_reverse.c */
8267 #include "tma.h"
8268 #ifdef BN_REVERSE_C
8269 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8270  *
8271  * LibTomMath is a library that provides multiple-precision
8272  * integer arithmetic as well as number theoretic functionality.
8273  *
8274  * The library was designed directly after the MPI library by
8275  * Michael Fromberger but has been written from scratch with
8276  * additional optimizations in place.
8277  *
8278  * The library is free for all purposes without any express
8279  * guarantee it works.
8280  *
8281  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
8282  */
8283
8284 /* reverse an array, used for radix code */
8285 void
8286 bn_reverse (unsigned char *s, int len)
8287 {
8288   int     ix, iy;
8289   unsigned char t;
8290
8291   ix = 0;
8292   iy = len - 1;
8293   while (ix < iy) {
8294     t     = s[ix];
8295     s[ix] = s[iy];
8296     s[iy] = t;
8297     ++ix;
8298     --iy;
8299   }
8300 }
8301 #endif
8302
8303 /* End: bn_reverse.c */
8304
8305 /* Start: bn_s_mp_add.c */
8306 #include "tma.h"
8307 #ifdef BN_S_MP_ADD_C
8308 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8309  *
8310  * LibTomMath is a library that provides multiple-precision
8311  * integer arithmetic as well as number theoretic functionality.
8312  *
8313  * The library was designed directly after the MPI library by
8314  * Michael Fromberger but has been written from scratch with
8315  * additional optimizations in place.
8316  *
8317  * The library is free for all purposes without any express
8318  * guarantee it works.
8319  *
8320  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
8321  */
8322
8323 /* low level addition, based on HAC pp.594, Algorithm 14.7 */
8324 int
8325 s_mp_add (mp_int * a, mp_int * b, mp_int * c)
8326 {
8327   mp_int *x;
8328   int     olduse, res, min, max;
8329
8330   /* find sizes, we let |a| <= |b| which means we have to sort
8331    * them.  "x" will point to the input with the most digits
8332    */
8333   if (a->used > b->used) {
8334     min = b->used;
8335     max = a->used;
8336     x = a;
8337   } else {
8338     min = a->used;
8339     max = b->used;
8340     x = b;
8341   }
8342
8343   /* init result */
8344   if (c->alloc < max + 1) {
8345     if ((res = mp_grow (c, max + 1)) != MP_OKAY) {
8346       return res;
8347     }
8348   }
8349
8350   /* get old used digit count and set new one */
8351   olduse = c->used;
8352   c->used = max + 1;
8353
8354   {
8355     register mp_digit u, *tmpa, *tmpb, *tmpc;
8356     register int i;
8357
8358     /* alias for digit pointers */
8359
8360     /* first input */
8361     tmpa = a->dp;
8362
8363     /* second input */
8364     tmpb = b->dp;
8365
8366     /* destination */
8367     tmpc = c->dp;
8368
8369     /* zero the carry */
8370     u = 0;
8371     for (i = 0; i < min; i++) {
8372       /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */
8373       *tmpc = *tmpa++ + *tmpb++ + u;
8374
8375       /* U = carry bit of T[i] */
8376       u = *tmpc >> ((mp_digit)DIGIT_BIT);
8377
8378       /* take away carry bit from T[i] */
8379       *tmpc++ &= MP_MASK;
8380     }
8381
8382     /* now copy higher words if any, that is in A+B 
8383      * if A or B has more digits add those in 
8384      */
8385     if (min != max) {
8386       for (; i < max; i++) {
8387         /* T[i] = X[i] + U */
8388         *tmpc = x->dp[i] + u;
8389
8390         /* U = carry bit of T[i] */
8391         u = *tmpc >> ((mp_digit)DIGIT_BIT);
8392
8393         /* take away carry bit from T[i] */
8394         *tmpc++ &= MP_MASK;
8395       }
8396     }
8397
8398     /* add carry */
8399     *tmpc++ = u;
8400
8401     /* clear digits above oldused */
8402     for (i = c->used; i < olduse; i++) {
8403       *tmpc++ = 0;
8404     }
8405   }
8406
8407   mp_clamp (c);
8408   return MP_OKAY;
8409 }
8410 #endif
8411
8412 /* End: bn_s_mp_add.c */
8413
8414 /* Start: bn_s_mp_exptmod.c */
8415 #include "tma.h"
8416 #ifdef BN_S_MP_EXPTMOD_C
8417 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8418  *
8419  * LibTomMath is a library that provides multiple-precision
8420  * integer arithmetic as well as number theoretic functionality.
8421  *
8422  * The library was designed directly after the MPI library by
8423  * Michael Fromberger but has been written from scratch with
8424  * additional optimizations in place.
8425  *
8426  * The library is free for all purposes without any express
8427  * guarantee it works.
8428  *
8429  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
8430  */
8431
8432 #ifdef MP_LOW_MEM
8433    #define TAB_SIZE 32
8434 #else
8435    #define TAB_SIZE 256
8436 #endif
8437
8438 int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
8439 {
8440   mp_int  M[TAB_SIZE], res, mu;
8441   mp_digit buf;
8442   int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
8443   int (*redux)(mp_int*,mp_int*,mp_int*);
8444
8445   /* find window size */
8446   x = mp_count_bits (X);
8447   if (x <= 7) {
8448     winsize = 2;
8449   } else if (x <= 36) {
8450     winsize = 3;
8451   } else if (x <= 140) {
8452     winsize = 4;
8453   } else if (x <= 450) {
8454     winsize = 5;
8455   } else if (x <= 1303) {
8456     winsize = 6;
8457   } else if (x <= 3529) {
8458     winsize = 7;
8459   } else {
8460     winsize = 8;
8461   }
8462
8463 #ifdef MP_LOW_MEM
8464     if (winsize > 5) {
8465        winsize = 5;
8466     }
8467 #endif
8468
8469   /* init M array */
8470   /* init first cell */
8471   if ((err = mp_init(&M[1])) != MP_OKAY) {
8472      return err; 
8473   }
8474
8475   /* now init the second half of the array */
8476   for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
8477     if ((err = mp_init(&M[x])) != MP_OKAY) {
8478       for (y = 1<<(winsize-1); y < x; y++) {
8479         mp_clear (&M[y]);
8480       }
8481       mp_clear(&M[1]);
8482       return err;
8483     }
8484   }
8485
8486   /* create mu, used for Barrett reduction */
8487   if ((err = mp_init (&mu)) != MP_OKAY) {
8488     goto LBL_M;
8489   }
8490   
8491   if (redmode == 0) {
8492      if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) {
8493         goto LBL_MU;
8494      }
8495      redux = mp_reduce;
8496   } else {
8497      if ((err = mp_reduce_2k_setup_l (P, &mu)) != MP_OKAY) {
8498         goto LBL_MU;
8499      }
8500      redux = mp_reduce_2k_l;
8501   }    
8502
8503   /* create M table
8504    *
8505    * The M table contains powers of the base, 
8506    * e.g. M[x] = G**x mod P
8507    *
8508    * The first half of the table is not 
8509    * computed though accept for M[0] and M[1]
8510    */
8511   if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) {
8512     goto LBL_MU;
8513   }
8514
8515   /* compute the value at M[1<<(winsize-1)] by squaring 
8516    * M[1] (winsize-1) times 
8517    */
8518   if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
8519     goto LBL_MU;
8520   }
8521
8522   for (x = 0; x < (winsize - 1); x++) {
8523     /* square it */
8524     if ((err = mp_sqr (&M[1 << (winsize - 1)], 
8525                        &M[1 << (winsize - 1)])) != MP_OKAY) {
8526       goto LBL_MU;
8527     }
8528
8529     /* reduce modulo P */
8530     if ((err = redux (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) {
8531       goto LBL_MU;
8532     }
8533   }
8534
8535   /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
8536    * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
8537    */
8538   for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
8539     if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
8540       goto LBL_MU;
8541     }
8542     if ((err = redux (&M[x], P, &mu)) != MP_OKAY) {
8543       goto LBL_MU;
8544     }
8545   }
8546
8547   /* setup result */
8548   if ((err = mp_init (&res)) != MP_OKAY) {
8549     goto LBL_MU;
8550   }
8551   mp_set (&res, 1);
8552
8553   /* set initial mode and bit cnt */
8554   mode   = 0;
8555   bitcnt = 1;
8556   buf    = 0;
8557   digidx = X->used - 1;
8558   bitcpy = 0;
8559   bitbuf = 0;
8560
8561   for (;;) {
8562     /* grab next digit as required */
8563     if (--bitcnt == 0) {
8564       /* if digidx == -1 we are out of digits */
8565       if (digidx == -1) {
8566         break;
8567       }
8568       /* read next digit and reset the bitcnt */
8569       buf    = X->dp[digidx--];
8570       bitcnt = (int) DIGIT_BIT;
8571     }
8572
8573     /* grab the next msb from the exponent */
8574     y     = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1;
8575     buf <<= (mp_digit)1;
8576
8577     /* if the bit is zero and mode == 0 then we ignore it
8578      * These represent the leading zero bits before the first 1 bit
8579      * in the exponent.  Technically this opt is not required but it
8580      * does lower the # of trivial squaring/reductions used
8581      */
8582     if (mode == 0 && y == 0) {
8583       continue;
8584     }
8585
8586     /* if the bit is zero and mode == 1 then we square */
8587     if (mode == 1 && y == 0) {
8588       if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
8589         goto LBL_RES;
8590       }
8591       if ((err = redux (&res, P, &mu)) != MP_OKAY) {
8592         goto LBL_RES;
8593       }
8594       continue;
8595     }
8596
8597     /* else we add it to the window */
8598     bitbuf |= (y << (winsize - ++bitcpy));
8599     mode    = 2;
8600
8601     if (bitcpy == winsize) {
8602       /* ok window is filled so square as required and multiply  */
8603       /* square first */
8604       for (x = 0; x < winsize; x++) {
8605         if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
8606           goto LBL_RES;
8607         }
8608         if ((err = redux (&res, P, &mu)) != MP_OKAY) {
8609           goto LBL_RES;
8610         }
8611       }
8612
8613       /* then multiply */
8614       if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
8615         goto LBL_RES;
8616       }
8617       if ((err = redux (&res, P, &mu)) != MP_OKAY) {
8618         goto LBL_RES;
8619       }
8620
8621       /* empty window and reset */
8622       bitcpy = 0;
8623       bitbuf = 0;
8624       mode   = 1;
8625     }
8626   }
8627
8628   /* if bits remain then square/multiply */
8629   if (mode == 2 && bitcpy > 0) {
8630     /* square then multiply if the bit is set */
8631     for (x = 0; x < bitcpy; x++) {
8632       if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
8633         goto LBL_RES;
8634       }
8635       if ((err = redux (&res, P, &mu)) != MP_OKAY) {
8636         goto LBL_RES;
8637       }
8638
8639       bitbuf <<= 1;
8640       if ((bitbuf & (1 << winsize)) != 0) {
8641         /* then multiply */
8642         if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
8643           goto LBL_RES;
8644         }
8645         if ((err = redux (&res, P, &mu)) != MP_OKAY) {
8646           goto LBL_RES;
8647         }
8648       }
8649     }
8650   }
8651
8652   mp_exch (&res, Y);
8653   err = MP_OKAY;
8654 LBL_RES:mp_clear (&res);
8655 LBL_MU:mp_clear (&mu);
8656 LBL_M:
8657   mp_clear(&M[1]);
8658   for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
8659     mp_clear (&M[x]);
8660   }
8661   return err;
8662 }
8663 #endif
8664
8665 /* End: bn_s_mp_exptmod.c */
8666
8667 /* Start: bn_s_mp_mul_digs.c */
8668 #include "tma.h"
8669 #ifdef BN_S_MP_MUL_DIGS_C
8670 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8671  *
8672  * LibTomMath is a library that provides multiple-precision
8673  * integer arithmetic as well as number theoretic functionality.
8674  *
8675  * The library was designed directly after the MPI library by
8676  * Michael Fromberger but has been written from scratch with
8677  * additional optimizations in place.
8678  *
8679  * The library is free for all purposes without any express
8680  * guarantee it works.
8681  *
8682  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
8683  */
8684
8685 /* multiplies |a| * |b| and only computes upto digs digits of result
8686  * HAC pp. 595, Algorithm 14.12  Modified so you can control how 
8687  * many digits of output are created.
8688  */
8689 int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
8690 {
8691   mp_int  t;
8692   int     res, pa, pb, ix, iy;
8693   mp_digit u;
8694   mp_word r;
8695   mp_digit tmpx, *tmpt, *tmpy;
8696
8697   /* can we use the fast multiplier? */
8698   if (((digs) < MP_WARRAY) &&
8699       MIN (a->used, b->used) < 
8700           (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
8701     return fast_s_mp_mul_digs (a, b, c, digs);
8702   }
8703
8704   if ((res = mp_init_size (&t, digs)) != MP_OKAY) {
8705     return res;
8706   }
8707   t.used = digs;
8708
8709   /* compute the digits of the product directly */
8710   pa = a->used;
8711   for (ix = 0; ix < pa; ix++) {
8712     /* set the carry to zero */
8713     u = 0;
8714
8715     /* limit ourselves to making digs digits of output */
8716     pb = MIN (b->used, digs - ix);
8717
8718     /* setup some aliases */
8719     /* copy of the digit from a used within the nested loop */
8720     tmpx = a->dp[ix];
8721     
8722     /* an alias for the destination shifted ix places */
8723     tmpt = t.dp + ix;
8724     
8725     /* an alias for the digits of b */
8726     tmpy = b->dp;
8727
8728     /* compute the columns of the output and propagate the carry */
8729     for (iy = 0; iy < pb; iy++) {
8730       /* compute the column as a mp_word */
8731       r       = ((mp_word)*tmpt) +
8732                 ((mp_word)tmpx) * ((mp_word)*tmpy++) +
8733                 ((mp_word) u);
8734
8735       /* the new column is the lower part of the result */
8736       *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
8737
8738       /* get the carry word from the result */
8739       u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
8740     }
8741     /* set carry if it is placed below digs */
8742     if (ix + iy < digs) {
8743       *tmpt = u;
8744     }
8745   }
8746
8747   mp_clamp (&t);
8748   mp_exch (&t, c);
8749
8750   mp_clear (&t);
8751   return MP_OKAY;
8752 }
8753 #endif
8754
8755 /* End: bn_s_mp_mul_digs.c */
8756
8757 /* Start: bn_s_mp_mul_high_digs.c */
8758 #include "tma.h"
8759 #ifdef BN_S_MP_MUL_HIGH_DIGS_C
8760 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8761  *
8762  * LibTomMath is a library that provides multiple-precision
8763  * integer arithmetic as well as number theoretic functionality.
8764  *
8765  * The library was designed directly after the MPI library by
8766  * Michael Fromberger but has been written from scratch with
8767  * additional optimizations in place.
8768  *
8769  * The library is free for all purposes without any express
8770  * guarantee it works.
8771  *
8772  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
8773  */
8774
8775 /* multiplies |a| * |b| and does not compute the lower digs digits
8776  * [meant to get the higher part of the product]
8777  */
8778 int
8779 s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
8780 {
8781   mp_int  t;
8782   int     res, pa, pb, ix, iy;
8783   mp_digit u;
8784   mp_word r;
8785   mp_digit tmpx, *tmpt, *tmpy;
8786
8787   /* can we use the fast multiplier? */
8788 #ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
8789   if (((a->used + b->used + 1) < MP_WARRAY)
8790       && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
8791     return fast_s_mp_mul_high_digs (a, b, c, digs);
8792   }
8793 #endif
8794
8795   if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) {
8796     return res;
8797   }
8798   t.used = a->used + b->used + 1;
8799
8800   pa = a->used;
8801   pb = b->used;
8802   for (ix = 0; ix < pa; ix++) {
8803     /* clear the carry */
8804     u = 0;
8805
8806     /* left hand side of A[ix] * B[iy] */
8807     tmpx = a->dp[ix];
8808
8809     /* alias to the address of where the digits will be stored */
8810     tmpt = &(t.dp[digs]);
8811
8812     /* alias for where to read the right hand side from */
8813     tmpy = b->dp + (digs - ix);
8814
8815     for (iy = digs - ix; iy < pb; iy++) {
8816       /* calculate the double precision result */
8817       r       = ((mp_word)*tmpt) +
8818                 ((mp_word)tmpx) * ((mp_word)*tmpy++) +
8819                 ((mp_word) u);
8820
8821       /* get the lower part */
8822       *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
8823
8824       /* carry the carry */
8825       u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
8826     }
8827     *tmpt = u;
8828   }
8829   mp_clamp (&t);
8830   mp_exch (&t, c);
8831   mp_clear (&t);
8832   return MP_OKAY;
8833 }
8834 #endif
8835
8836 /* End: bn_s_mp_mul_high_digs.c */
8837
8838 /* Start: bn_s_mp_sqr.c */
8839 #include "tma.h"
8840 #ifdef BN_S_MP_SQR_C
8841 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8842  *
8843  * LibTomMath is a library that provides multiple-precision
8844  * integer arithmetic as well as number theoretic functionality.
8845  *
8846  * The library was designed directly after the MPI library by
8847  * Michael Fromberger but has been written from scratch with
8848  * additional optimizations in place.
8849  *
8850  * The library is free for all purposes without any express
8851  * guarantee it works.
8852  *
8853  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
8854  */
8855
8856 /* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */
8857 int s_mp_sqr (mp_int * a, mp_int * b)
8858 {
8859   mp_int  t;
8860   int     res, ix, iy, pa;
8861   mp_word r;
8862   mp_digit u, tmpx, *tmpt;
8863
8864   pa = a->used;
8865   if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) {
8866     return res;
8867   }
8868
8869   /* default used is maximum possible size */
8870   t.used = 2*pa + 1;
8871
8872   for (ix = 0; ix < pa; ix++) {
8873     /* first calculate the digit at 2*ix */
8874     /* calculate double precision result */
8875     r = ((mp_word) t.dp[2*ix]) +
8876         ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]);
8877
8878     /* store lower part in result */
8879     t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK));
8880
8881     /* get the carry */
8882     u           = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
8883
8884     /* left hand side of A[ix] * A[iy] */
8885     tmpx        = a->dp[ix];
8886
8887     /* alias for where to store the results */
8888     tmpt        = t.dp + (2*ix + 1);
8889     
8890     for (iy = ix + 1; iy < pa; iy++) {
8891       /* first calculate the product */
8892       r       = ((mp_word)tmpx) * ((mp_word)a->dp[iy]);
8893
8894       /* now calculate the double precision result, note we use
8895        * addition instead of *2 since it's easier to optimize
8896        */
8897       r       = ((mp_word) *tmpt) + r + r + ((mp_word) u);
8898
8899       /* store lower part */
8900       *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
8901
8902       /* get carry */
8903       u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
8904     }
8905     /* propagate upwards */
8906     while (u != ((mp_digit) 0)) {
8907       r       = ((mp_word) *tmpt) + ((mp_word) u);
8908       *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
8909       u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
8910     }
8911   }
8912
8913   mp_clamp (&t);
8914   mp_exch (&t, b);
8915   mp_clear (&t);
8916   return MP_OKAY;
8917 }
8918 #endif
8919
8920 /* End: bn_s_mp_sqr.c */
8921
8922 /* Start: bn_s_mp_sub.c */
8923 #include "tma.h"
8924 #ifdef BN_S_MP_SUB_C
8925 /* LibTomMath, multiple-precision integer library -- Tom St Denis
8926  *
8927  * LibTomMath is a library that provides multiple-precision
8928  * integer arithmetic as well as number theoretic functionality.
8929  *
8930  * The library was designed directly after the MPI library by
8931  * Michael Fromberger but has been written from scratch with
8932  * additional optimizations in place.
8933  *
8934  * The library is free for all purposes without any express
8935  * guarantee it works.
8936  *
8937  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
8938  */
8939
8940 /* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
8941 int
8942 s_mp_sub (mp_int * a, mp_int * b, mp_int * c)
8943 {
8944   int     olduse, res, min, max;
8945
8946   /* find sizes */
8947   min = b->used;
8948   max = a->used;
8949
8950   /* init result */
8951   if (c->alloc < max) {
8952     if ((res = mp_grow (c, max)) != MP_OKAY) {
8953       return res;
8954     }
8955   }
8956   olduse = c->used;
8957   c->used = max;
8958
8959   {
8960     register mp_digit u, *tmpa, *tmpb, *tmpc;
8961     register int i;
8962
8963     /* alias for digit pointers */
8964     tmpa = a->dp;
8965     tmpb = b->dp;
8966     tmpc = c->dp;
8967
8968     /* set carry to zero */
8969     u = 0;
8970     for (i = 0; i < min; i++) {
8971       /* T[i] = A[i] - B[i] - U */
8972       *tmpc = *tmpa++ - *tmpb++ - u;
8973
8974       /* U = carry bit of T[i]
8975        * Note this saves performing an AND operation since
8976        * if a carry does occur it will propagate all the way to the
8977        * MSB.  As a result a single shift is enough to get the carry
8978        */
8979       u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
8980
8981       /* Clear carry from T[i] */
8982       *tmpc++ &= MP_MASK;
8983     }
8984
8985     /* now copy higher words if any, e.g. if A has more digits than B  */
8986     for (; i < max; i++) {
8987       /* T[i] = A[i] - U */
8988       *tmpc = *tmpa++ - u;
8989
8990       /* U = carry bit of T[i] */
8991       u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
8992
8993       /* Clear carry from T[i] */
8994       *tmpc++ &= MP_MASK;
8995     }
8996
8997     /* clear digits above used (since we may not have grown result above) */
8998     for (i = c->used; i < olduse; i++) {
8999       *tmpc++ = 0;
9000     }
9001   }
9002
9003   mp_clamp (c);
9004   return MP_OKAY;
9005 }
9006
9007 #endif
9008
9009 /* End: bn_s_mp_sub.c */
9010
9011 /* Start: bncore.c */
9012 #include "tma.h"
9013 #ifdef BNCORE_C
9014 /* LibTomMath, multiple-precision integer library -- Tom St Denis
9015  *
9016  * LibTomMath is a library that provides multiple-precision
9017  * integer arithmetic as well as number theoretic functionality.
9018  *
9019  * The library was designed directly after the MPI library by
9020  * Michael Fromberger but has been written from scratch with
9021  * additional optimizations in place.
9022  *
9023  * The library is free for all purposes without any express
9024  * guarantee it works.
9025  *
9026  * Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
9027  */
9028
9029 /* Known optimal configurations
9030
9031  CPU                    /Compiler     /MUL CUTOFF/SQR CUTOFF
9032 -------------------------------------------------------------
9033  Intel P4 Northwood     /GCC v3.4.1   /        88/       128/LTM 0.32 ;-)
9034  AMD Athlon64           /GCC v3.4.4   /        74/       124/LTM 0.34
9035  
9036 */
9037
9038 int     KARATSUBA_MUL_CUTOFF = 74,      /* Min. number of digits before Karatsuba multiplication is used. */
9039         KARATSUBA_SQR_CUTOFF = 124,     /* Min. number of digits before Karatsuba squaring is used. */
9040         
9041         TOOM_MUL_CUTOFF      = 350,      /* no optimal values of these are known yet so set em high */
9042         TOOM_SQR_CUTOFF      = 400; 
9043 #endif
9044
9045 /* End: bncore.c */
9046
9047
9048 /* EOF */