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