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