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