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