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