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 */
tma_mp_error_to_string(int 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  */
fast_tma_mp_invmod(tma_mp_int * a,tma_mp_int * b,tma_mp_int * c)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 */
fast_tma_mp_montgomery_reduce(tma_mp_int * x,tma_mp_int * n,tma_mp_digit rho)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  */
fast_s_tma_mp_mul_digs(tma_mp_int * a,tma_mp_int * b,tma_mp_int * c,int digs)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  */
fast_s_tma_mp_mul_high_digs(tma_mp_int * a,tma_mp_int * b,tma_mp_int * c,int digs)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 
fast_s_tma_mp_sqr(tma_mp_int * a,tma_mp_int * b)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
tma_mp_2expt(tma_mp_int * a,int b)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
tma_mp_abs(tma_mp_int * a,tma_mp_int * b)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) */
tma_mp_add(tma_mp_int * a,tma_mp_int * b,tma_mp_int * c)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
tma_mp_add_d(tma_mp_int * a,tma_mp_digit b,tma_mp_int * c)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
tma_mp_addmod(tma_mp_int * a,tma_mp_int * b,tma_mp_int * c,tma_mp_int * d)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
tma_mp_and(tma_mp_int * a,tma_mp_int * b,tma_mp_int * c)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
tma_mp_clamp(tma_mp_int * a)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
tma_mp_clear(tma_mp_int * a)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 
tma_mp_clear_multi(tma_mp_int * mp,...)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
tma_mp_cmp(tma_mp_int * a,tma_mp_int * b)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 */
tma_mp_cmp_d(tma_mp_int * a,tma_mp_digit b)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) */
tma_mp_cmp_mag(tma_mp_int * a,tma_mp_int * b)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 */
tma_mp_cnt_lsb(tma_mp_int * a)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
tma_mp_copy(tma_mp_int * a,tma_mp_int * b)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
tma_mp_count_bits(tma_mp_int * a)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 */
tma_mp_div(tma_mp_int * a,tma_mp_int * b,tma_mp_int * c,tma_mp_int * d)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 */
tma_mp_div(tma_mp_int * a,tma_mp_int * b,tma_mp_int * c,tma_mp_int * d)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 */
tma_mp_div_2(tma_mp_int * a,tma_mp_int * b)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) */
tma_mp_div_2d(tma_mp_int * a,int b,tma_mp_int * c,tma_mp_int * 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
tma_mp_div_3(tma_mp_int * a,tma_mp_int * c,tma_mp_digit * d)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 
s_is_power_of_two(tma_mp_digit b,int * p)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) */
tma_mp_div_d(tma_mp_int * a,tma_mp_digit b,tma_mp_int * c,tma_mp_digit * d)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 */
tma_mp_dr_is_modulus(tma_mp_int * a)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
tma_mp_dr_reduce(tma_mp_int * x,tma_mp_int * n,tma_mp_digit k)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 */
tma_mp_dr_setup(tma_mp_int * a,tma_mp_digit * d)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
tma_mp_exch(tma_mp_int * a,tma_mp_int * b)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 */
tma_mp_expt_d(tma_mp_int * a,tma_mp_digit b,tma_mp_int * c)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  */
tma_mp_exptmod(tma_mp_int * G,tma_mp_int * X,tma_mp_int * P,tma_mp_int * Y)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 
tma_mp_exptmod_fast(tma_mp_int * G,tma_mp_int * X,tma_mp_int * P,tma_mp_int * Y,int redmode)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  */
tma_mp_exteuclid(tma_mp_int * a,tma_mp_int * b,tma_mp_int * U1,tma_mp_int * U2,tma_mp_int * U3)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 */
tma_mp_fread(tma_mp_int * a,int radix,FILE * stream)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 
tma_mp_fwrite(tma_mp_int * a,int radix,FILE * stream)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 */
tma_mp_gcd(tma_mp_int * a,tma_mp_int * b,tma_mp_int * c)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 */
tma_mp_get_int(tma_mp_int * a)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 */
tma_mp_grow(tma_mp_int * a,int size)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 */
tma_mp_init(tma_mp_int * a)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 */
tma_mp_init_copy(tma_mp_int * a,tma_mp_int * b)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 
tma_mp_init_multi(tma_mp_int * mp,...)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 */
tma_mp_init_set(tma_mp_int * a,tma_mp_digit b)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 */
tma_mp_init_set_int(tma_mp_int * a,unsigned long b)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 */
tma_mp_init_size(tma_mp_int * a,int 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 */
tma_mp_invmod(tma_mp_int * a,tma_mp_int * b,tma_mp_int * c)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 */
tma_mp_invmod_slow(tma_mp_int * a,tma_mp_int * b,tma_mp_int * c)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 */
tma_mp_is_square(tma_mp_int * arg,int * ret)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  */
tma_mp_jacobi(tma_mp_int * a,tma_mp_int * p,int * c)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  */
tma_mp_karatsuba_mul(tma_mp_int * a,tma_mp_int * b,tma_mp_int * c)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  */
tma_mp_karatsuba_sqr(tma_mp_int * a,tma_mp_int * b)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) */
tma_mp_lcm(tma_mp_int * a,tma_mp_int * b,tma_mp_int * c)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 */
tma_mp_lshd(tma_mp_int * a,int b)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
tma_mp_mod(tma_mp_int * a,tma_mp_int * b,tma_mp_int * c)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
tma_mp_mod_2d(tma_mp_int * a,int b,tma_mp_int * c)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
tma_mp_mod_d(tma_mp_int * a,tma_mp_digit b,tma_mp_digit * c)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  */
tma_mp_montgomery_calc_normalization(tma_mp_int * a,tma_mp_int * b)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
tma_mp_montgomery_reduce(tma_mp_int * x,tma_mp_int * n,tma_mp_digit rho)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
tma_mp_montgomery_setup(tma_mp_int * n,tma_mp_digit * rho)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) */
tma_mp_mul(tma_mp_int * a,tma_mp_int * b,tma_mp_int * c)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 */
tma_mp_mul_2(tma_mp_int * a,tma_mp_int * b)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 */
tma_mp_mul_2d(tma_mp_int * a,int b,tma_mp_int * c)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
tma_mp_mul_d(tma_mp_int * a,tma_mp_digit b,tma_mp_int * c)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) */
tma_mp_mulmod(tma_mp_int * a,tma_mp_int * b,tma_mp_int * c,tma_mp_int * d)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  */
tma_mp_n_root(tma_mp_int * a,tma_mp_digit b,tma_mp_int * c)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 */
tma_mp_neg(tma_mp_int * a,tma_mp_int * b)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 */
tma_mp_or(tma_mp_int * a,tma_mp_int * b,tma_mp_int * c)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  */
tma_mp_prime_fermat(tma_mp_int * a,tma_mp_int * b,int * result)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  */
tma_mp_prime_is_divisible(tma_mp_int * a,int * result)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  */
tma_mp_prime_is_prime(tma_mp_int * a,int t,int * result)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  */
tma_mp_prime_miller_rabin(tma_mp_int * a,tma_mp_int * b,int * result)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  */
tma_mp_prime_next_prime(tma_mp_int * a,int t,int bbs_style)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 */
tma_mp_prime_rabin_miller_trials(int 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! */
tma_mp_prime_random_ex(tma_mp_int * a,int t,int size,int flags,ltm_prime_callback cb,void * dat)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 */
tma_mp_radix_size(tma_mp_int * a,int radix,int * size)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
tma_mp_rand(tma_mp_int * a,int digits)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 */
tma_mp_read_radix(tma_mp_int * a,const char * str,int 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 */
tma_mp_read_signed_bin(tma_mp_int * a,const unsigned char * b,int c)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] */
tma_mp_read_unsigned_bin(tma_mp_int * a,const unsigned char * b,int c)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  */
tma_mp_reduce(tma_mp_int * x,tma_mp_int * m,tma_mp_int * mu)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 */
tma_mp_reduce_2k(tma_mp_int * a,tma_mp_int * n,tma_mp_digit 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 */
tma_mp_reduce_2k_l(tma_mp_int * a,tma_mp_int * n,tma_mp_int * d)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 */
tma_mp_reduce_2k_setup(tma_mp_int * a,tma_mp_digit * d)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 */
tma_mp_reduce_2k_setup_l(tma_mp_int * a,tma_mp_int * d)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 */
tma_mp_reduce_is_2k(tma_mp_int * a)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 */
tma_mp_reduce_is_2k_l(tma_mp_int * a)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  */
tma_mp_reduce_setup(tma_mp_int * a,tma_mp_int * b)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 */
tma_mp_rshd(tma_mp_int * a,int b)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 */
tma_mp_set(tma_mp_int * a,tma_mp_digit b)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 */
tma_mp_set_int(tma_mp_int * a,unsigned long b)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 */
tma_mp_shrink(tma_mp_int * a)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 */
tma_mp_signed_bin_size(tma_mp_int * a)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
tma_mp_sqr(tma_mp_int * a,tma_mp_int * b)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
tma_mp_sqrmod(tma_mp_int * a,tma_mp_int * b,tma_mp_int * c)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 */
tma_mp_sqrt(tma_mp_int * arg,tma_mp_int * ret)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
tma_mp_sub(tma_mp_int * a,tma_mp_int * b,tma_mp_int * c)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
tma_mp_sub_d(tma_mp_int * a,tma_mp_digit b,tma_mp_int * c)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
tma_mp_submod(tma_mp_int * a,tma_mp_int * b,tma_mp_int * c,tma_mp_int * d)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 */
tma_mp_to_signed_bin(tma_mp_int * a,unsigned char * b)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 */
tma_mp_to_signed_bin_n(tma_mp_int * a,unsigned char * b,unsigned long * outlen)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 */
tma_mp_to_unsigned_bin(tma_mp_int * a,unsigned char * b)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 */
tma_mp_to_unsigned_bin_n(tma_mp_int * a,unsigned char * b,unsigned long * outlen)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 */
tma_mp_toom_mul(tma_mp_int * a,tma_mp_int * b,tma_mp_int * c)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
tma_mp_toom_sqr(tma_mp_int * a,tma_mp_int * b)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) */
tma_mp_toradix(tma_mp_int * a,char * str,int radix)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  */
tma_mp_toradix_n(tma_mp_int * a,char * str,int radix,int maxlen)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 */
tma_mp_unsigned_bin_size(tma_mp_int * a)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
tma_mp_xor(tma_mp_int * a,tma_mp_int * b,tma_mp_int * c)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 */
tma_mp_zero(tma_mp_int * a)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
bn_reverse(unsigned char * s,int len)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
s_tma_mp_add(tma_mp_int * a,tma_mp_int * b,tma_mp_int * c)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 
s_tma_mp_exptmod(tma_mp_int * G,tma_mp_int * X,tma_mp_int * P,tma_mp_int * Y,int redmode)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  */
s_tma_mp_mul_digs(tma_mp_int * a,tma_mp_int * b,tma_mp_int * c,int digs)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
s_tma_mp_mul_high_digs(tma_mp_int * a,tma_mp_int * b,tma_mp_int * c,int digs)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 */
s_tma_mp_sqr(tma_mp_int * a,tma_mp_int * b)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
s_tma_mp_sub(tma_mp_int * a,tma_mp_int * b,tma_mp_int * c)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 */
9525