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
19static 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 */
29char *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 */
76int 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
110top:
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
193LBL_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*/
230int 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 */
414int 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 */
518int 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
618After that loop you do the squares and add them in.
619*/
620
621int 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 */
734int
735mp_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 */
785int
786mp_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) */
829int 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 */
886int
887mp_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) */
1002int
1003mp_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 */
1047int
1048mp_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 */
1114void
1115mp_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)  */
1156void
1157mp_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
1204void 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)*/
1242int
1243mp_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 */
1289int 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) */
1337int 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
1395static 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 */
1400int 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 */
1453int
1454mp_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 */
1525int
1526mp_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 */
1576int 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  }
1638LBL_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*/
1658int 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
1833LBL_Y:mp_clear (&y);
1834LBL_X:mp_clear (&x);
1835LBL_T2:mp_clear (&t2);
1836LBL_T1:mp_clear (&t1);
1837LBL_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 */
1870int 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) */
1942int 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) */
2043int
2044mp_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
2125static 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) */
2139int 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 */
2240int 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 */
2300int
2301mp_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 */
2320top:
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 */
2385void 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 */
2423void
2424mp_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 */
2459int 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 */
2525int 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
2649int 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;
2925LBL_RES:mp_clear (&res);
2926LBL_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 */
2963int 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 */
3047int 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
3117int 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 */
3174int 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;
3252LBL_V:mp_clear (&u);
3253LBL_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 */
3283unsigned 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 */
3332int 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 */
3393int 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 */
3443int 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
3479int 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 */
3542int 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 */
3578int 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 */
3613int 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 */
3665int 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 */
3712int 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
3752top:
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;
3861LBL_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 */
3891static 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
3902static 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 */
3913int 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;
3974ERR: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 */
4006int 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;
4082LBL_P1:mp_clear (&p1);
4083LBL_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 */
4141int 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
4247X1Y1:mp_clear (&x1y1);
4248X0Y0:mp_clear (&x0y0);
4249T1:mp_clear (&t1);
4250Y1:mp_clear (&y1);
4251Y0:mp_clear (&y0);
4252X1:mp_clear (&x1);
4253X0:mp_clear (&x0);
4254ERR:
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 */
4290int 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
4373X1X1:mp_clear (&x1x1);
4374X0X0:mp_clear (&x0x0);
4375T2:mp_clear (&t2);
4376T1:mp_clear (&t1);
4377X1:mp_clear (&x1);
4378X0:mp_clear (&x0);
4379ERR:
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) */
4409int 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
4442LBL_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 */
4473int 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 */
4544int
4545mp_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 */
4596int
4597mp_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
4654int
4655mp_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 */
4691int 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 */
4749int
4750mp_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 */
4871int
4872mp_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) */
4934int 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 */
5004int 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 */
5090int 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 */
5179int
5180mp_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) */
5262int 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 */
5315int 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
5410LBL_T3:mp_clear (&t3);
5411LBL_T2:mp_clear (&t2);
5412LBL_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 */
5442int 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 */
5486int 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 */
5547int 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;
5576LBL_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 */
5610int 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 */
5666int 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;
5717LBL_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 */
5753int 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;
5822LBL_Y:mp_clear (&y);
5823LBL_R:mp_clear (&r);
5824LBL_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 */
5858int 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;
5996LBL_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
6028static 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 */
6042int 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! */
6099int 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;
6180error:
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 */
6213int 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 */
6295const 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 */
6323int
6324mp_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 */
6382int 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 */
6471int 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] */
6516int 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 */
6578int 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
6647CLEANUP:
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 */
6679int 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);
6689top:
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
6712ERR:
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*/
6747int 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);
6757top:
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
6778ERR:
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 */
6810int 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 */
6861int 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
6878ERR:
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 */
6909int 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 */
6965int 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 */
7015int 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 */
7051void 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 */
7127void 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 */
7160int 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 */
7212int 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 */
7251int 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 */
7282int
7283mp_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
7295if (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) */
7344int
7345mp_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 */
7389int 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
7442E1: mp_clear(&t2);
7443E2: 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) */
7474int
7475mp_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 */
7537int
7538mp_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) */
7634int
7635mp_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 */
7680int 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 */
7717int 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 */
7752int 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 */
7804int 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*/
7845int 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
8093ERR:
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 */
8127int
8128mp_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
8325ERR:
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) */
8357int 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 */
8439int 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 */
8528int 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 */
8560int
8561mp_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 */
8615void 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 */
8653const 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 */
8720void
8721bn_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 */
8763int
8764s_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
8880int 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;
9096LBL_RES:mp_clear (&res);
9097LBL_MU:mp_clear (&mu);
9098LBL_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 */
9135int 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 */
9228int
9229s_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 */
9311int 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 */
9399int
9400s_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
9500int     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