added libtommath-0.28

This commit is contained in:
Tom St Denis 2003-12-24 18:59:22 +00:00 committed by Steffen Jaeckel
parent c343371bb2
commit 455bb4db20
83 changed files with 40276 additions and 1428 deletions

6
bn.ilg Normal file
View File

@ -0,0 +1,6 @@
This is makeindex, version 2.14 [02-Oct-2002] (kpathsea + Thai support).
Scanning input file bn.idx....done (53 entries accepted, 0 rejected).
Sorting entries....done (317 comparisons).
Generating output file bn.ind....done (56 lines written, 0 warnings).
Output written in bn.ind.
Transcript written in bn.ilg.

56
bn.ind Normal file
View File

@ -0,0 +1,56 @@
\begin{theindex}
\item mp\_add, \hyperpage{23}
\item mp\_and, \hyperpage{23}
\item mp\_clear, \hyperpage{7}
\item mp\_clear\_multi, \hyperpage{8}
\item mp\_cmp, \hyperpage{18}
\item mp\_cmp\_d, \hyperpage{20}
\item mp\_cmp\_mag, \hyperpage{17}
\item mp\_div, \hyperpage{29}
\item mp\_div\_2, \hyperpage{21}
\item mp\_div\_2d, \hyperpage{22}
\item MP\_EQ, \hyperpage{17}
\item mp\_error\_to\_string, \hyperpage{6}
\item mp\_expt\_d, \hyperpage{31}
\item mp\_exptmod, \hyperpage{31}
\item mp\_gcd, \hyperpage{39}
\item mp\_grow, \hyperpage{12}
\item MP\_GT, \hyperpage{17}
\item mp\_init, \hyperpage{7}
\item mp\_init\_copy, \hyperpage{9}
\item mp\_init\_multi, \hyperpage{8}
\item mp\_init\_size, \hyperpage{10}
\item mp\_int, \hyperpage{6}
\item mp\_invmod, \hyperpage{40}
\item mp\_jacobi, \hyperpage{39}
\item mp\_lcm, \hyperpage{39}
\item mp\_lshd, \hyperpage{23}
\item MP\_LT, \hyperpage{17}
\item MP\_MEM, \hyperpage{5}
\item mp\_mul, \hyperpage{25}
\item mp\_mul\_2, \hyperpage{21}
\item mp\_mul\_2d, \hyperpage{22}
\item mp\_n\_root, \hyperpage{31}
\item mp\_neg, \hyperpage{24}
\item MP\_NO, \hyperpage{5}
\item MP\_OKAY, \hyperpage{5}
\item mp\_or, \hyperpage{23}
\item mp\_prime\_fermat, \hyperpage{33}
\item mp\_prime\_is\_divisible, \hyperpage{33}
\item mp\_prime\_is\_prime, \hyperpage{34}
\item mp\_prime\_miller\_rabin, \hyperpage{33}
\item mp\_prime\_next\_prime, \hyperpage{34}
\item mp\_prime\_rabin\_miller\_trials, \hyperpage{34}
\item mp\_prime\_random, \hyperpage{35}
\item mp\_rshd, \hyperpage{23}
\item mp\_set, \hyperpage{15}
\item mp\_set\_int, \hyperpage{16}
\item mp\_shrink, \hyperpage{11}
\item mp\_sqr, \hyperpage{25}
\item mp\_sub, \hyperpage{23}
\item MP\_VAL, \hyperpage{5}
\item mp\_xor, \hyperpage{23}
\item MP\_YES, \hyperpage{5}
\end{theindex}

BIN
bn.pdf

Binary file not shown.

2076
bn.tex

File diff suppressed because it is too large Load Diff

View File

@ -26,11 +26,8 @@ fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c)
mp_int x, y, u, v, B, D; mp_int x, y, u, v, B, D;
int res, neg; int res, neg;
/* 2. [modified] if a,b are both even then return an error! /* 2. [modified] b must be odd */
* if (mp_iseven (b) == 1) {
* That is if gcd(a,b) = 2**k * q then obviously there is no inverse.
*/
if (mp_iseven (a) == 1 && mp_iseven (b) == 1) {
return MP_VAL; return MP_VAL;
} }

View File

@ -73,7 +73,7 @@ fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
* that W[ix-1] have the carry cleared (see after the inner loop) * that W[ix-1] have the carry cleared (see after the inner loop)
*/ */
register mp_digit mu; register mp_digit mu;
mu = ((W[ix] & MP_MASK) * rho) & MP_MASK; mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK);
/* a = a + mu * m * b**i /* a = a + mu * m * b**i
* *

View File

@ -15,8 +15,7 @@
#include <tommath.h> #include <tommath.h>
/* high level addition (handles signs) */ /* high level addition (handles signs) */
int int mp_add (mp_int * a, mp_int * b, mp_int * c)
mp_add (mp_int * a, mp_int * b, mp_int * c)
{ {
int sa, sb, res; int sa, sb, res;

View File

@ -24,7 +24,7 @@ mp_clear (mp_int * a)
memset (a->dp, 0, sizeof (mp_digit) * a->used); memset (a->dp, 0, sizeof (mp_digit) * a->used);
/* free ram */ /* free ram */
free (a->dp); XFREE(a->dp);
/* reset members to make debugging easier */ /* reset members to make debugging easier */
a->dp = NULL; a->dp = NULL;

View File

@ -15,8 +15,7 @@
#include <tommath.h> #include <tommath.h>
/* compare a digit */ /* compare a digit */
int int mp_cmp_d(mp_int * a, mp_digit b)
mp_cmp_d (mp_int * a, mp_digit b)
{ {
/* compare based on sign */ /* compare based on sign */
if (a->sign == MP_NEG) { if (a->sign == MP_NEG) {

View File

@ -15,8 +15,7 @@
#include <tommath.h> #include <tommath.h>
/* compare maginitude of two ints (unsigned) */ /* compare maginitude of two ints (unsigned) */
int int mp_cmp_mag (mp_int * a, mp_int * b)
mp_cmp_mag (mp_int * a, mp_int * b)
{ {
int n; int n;
mp_digit *tmpa, *tmpb; mp_digit *tmpa, *tmpb;

View File

@ -27,8 +27,7 @@
* The overall algorithm is as described as * The overall algorithm is as described as
* 14.20 from HAC but fixed to treat these cases. * 14.20 from HAC but fixed to treat these cases.
*/ */
int int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
{ {
mp_int q, x, y, t1, t2; mp_int q, x, y, t1, t2;
int res, n, t, i, norm, neg; int res, n, t, i, norm, neg;

View File

@ -15,8 +15,7 @@
#include <tommath.h> #include <tommath.h>
/* b = a/2 */ /* b = a/2 */
int int mp_div_2(mp_int * a, mp_int * b)
mp_div_2 (mp_int * a, mp_int * b)
{ {
int x, res, oldused; int x, res, oldused;

View File

@ -15,8 +15,7 @@
#include <tommath.h> #include <tommath.h>
/* shift right by a certain bit count (store quotient in c, optional remainder in d) */ /* shift right by a certain bit count (store quotient in c, optional remainder in d) */
int int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d)
mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d)
{ {
mp_digit D, r, rr; mp_digit D, r, rr;
int x, res; int x, res;

View File

@ -81,7 +81,7 @@ mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d)
if (w >= b) { if (w >= b) {
t = (mp_digit)(w / b); t = (mp_digit)(w / b);
w = w % b; w -= ((mp_word)t) * ((mp_word)b);
} else { } else {
t = 0; t = 0;
} }

View File

@ -15,8 +15,7 @@
#include <tommath.h> #include <tommath.h>
/* calculate c = a**b using a square-multiply algorithm */ /* calculate c = a**b using a square-multiply algorithm */
int int mp_expt_d (mp_int * a, mp_digit b, mp_int * c)
mp_expt_d (mp_int * a, mp_digit b, mp_int * c)
{ {
int res, x; int res, x;
mp_int g; mp_int g;

View File

@ -20,8 +20,7 @@
* embedded in the normal function but that wasted alot of stack space * embedded in the normal function but that wasted alot of stack space
* for nothing (since 99% of the time the Montgomery code would be called) * for nothing (since 99% of the time the Montgomery code would be called)
*/ */
int int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
{ {
int dr; int dr;

View File

@ -24,24 +24,24 @@ int mp_fwrite(mp_int *a, int radix, FILE *stream)
return MP_VAL; return MP_VAL;
} }
buf = malloc(len); buf = XMALLOC (len);
if (buf == NULL) { if (buf == NULL) {
return MP_MEM; return MP_MEM;
} }
if ((err = mp_toradix(a, buf, radix)) != MP_OKAY) { if ((err = mp_toradix(a, buf, radix)) != MP_OKAY) {
free(buf); XFREE (buf);
return err; return err;
} }
for (x = 0; x < len; x++) { for (x = 0; x < len; x++) {
if (fputc(buf[x], stream) == EOF) { if (fputc(buf[x], stream) == EOF) {
free(buf); XFREE (buf);
return MP_VAL; return MP_VAL;
} }
} }
free(buf); XFREE (buf);
return MP_OKAY; return MP_OKAY;
} }

View File

@ -15,8 +15,7 @@
#include <tommath.h> #include <tommath.h>
/* Greatest Common Divisor using the binary method */ /* Greatest Common Divisor using the binary method */
int int mp_gcd (mp_int * a, mp_int * b, mp_int * c)
mp_gcd (mp_int * a, mp_int * b, mp_int * c)
{ {
mp_int u, v; mp_int u, v;
int k, u_lsb, v_lsb, res; int k, u_lsb, v_lsb, res;

View File

@ -15,13 +15,11 @@
#include <tommath.h> #include <tommath.h>
/* grow as required */ /* grow as required */
int int mp_grow (mp_int * a, int size)
mp_grow (mp_int * a, int size)
{ {
int i; int i;
mp_digit *tmp; mp_digit *tmp;
/* if the alloc size is smaller alloc more ram */ /* if the alloc size is smaller alloc more ram */
if (a->alloc < size) { if (a->alloc < size) {
/* ensure there are always at least MP_PREC digits extra on top */ /* ensure there are always at least MP_PREC digits extra on top */
@ -33,7 +31,7 @@ mp_grow (mp_int * a, int size)
* in case the operation failed we don't want * in case the operation failed we don't want
* to overwrite the dp member of a. * to overwrite the dp member of a.
*/ */
tmp = OPT_CAST realloc (a->dp, sizeof (mp_digit) * size); tmp = OPT_CAST XREALLOC (a->dp, sizeof (mp_digit) * size);
if (tmp == NULL) { if (tmp == NULL) {
/* reallocation failed but "a" is still valid [can be freed] */ /* reallocation failed but "a" is still valid [can be freed] */
return MP_MEM; return MP_MEM;

View File

@ -15,11 +15,10 @@
#include <tommath.h> #include <tommath.h>
/* init a new bigint */ /* init a new bigint */
int int mp_init (mp_int * a)
mp_init (mp_int * a)
{ {
/* allocate memory required and clear it */ /* allocate memory required and clear it */
a->dp = OPT_CAST calloc (sizeof (mp_digit), MP_PREC); a->dp = OPT_CAST XCALLOC (sizeof (mp_digit), MP_PREC);
if (a->dp == NULL) { if (a->dp == NULL) {
return MP_MEM; return MP_MEM;
} }

View File

@ -15,8 +15,7 @@
#include <tommath.h> #include <tommath.h>
/* creates "a" then copies b into it */ /* creates "a" then copies b into it */
int int mp_init_copy (mp_int * a, mp_int * b)
mp_init_copy (mp_int * a, mp_int * b)
{ {
int res; int res;

View File

@ -15,14 +15,13 @@
#include <tommath.h> #include <tommath.h>
/* init an mp_init for a given size */ /* init an mp_init for a given size */
int int mp_init_size (mp_int * a, int size)
mp_init_size (mp_int * a, int size)
{ {
/* pad size so there are always extra digits */ /* pad size so there are always extra digits */
size += (MP_PREC * 2) - (size % MP_PREC); size += (MP_PREC * 2) - (size % MP_PREC);
/* alloc mem */ /* alloc mem */
a->dp = OPT_CAST calloc (sizeof (mp_digit), size); a->dp = OPT_CAST XCALLOC (sizeof (mp_digit), size);
if (a->dp == NULL) { if (a->dp == NULL) {
return MP_MEM; return MP_MEM;
} }

View File

@ -15,8 +15,7 @@
#include <tommath.h> #include <tommath.h>
/* hac 14.61, pp608 */ /* hac 14.61, pp608 */
int int mp_invmod (mp_int * a, mp_int * b, mp_int * c)
mp_invmod (mp_int * a, mp_int * b, mp_int * c)
{ {
mp_int x, y, u, v, A, B, C, D; mp_int x, y, u, v, A, B, C, D;
int res; int res;

View File

@ -17,8 +17,7 @@
/* computes the jacobi c = (a | n) (or Legendre if n is prime) /* computes the jacobi c = (a | n) (or Legendre if n is prime)
* HAC pp. 73 Algorithm 2.149 * HAC pp. 73 Algorithm 2.149
*/ */
int int mp_jacobi (mp_int * a, mp_int * p, int *c)
mp_jacobi (mp_int * a, mp_int * p, int *c)
{ {
mp_int a1, p1; mp_int a1, p1;
int k, s, r, res; int k, s, r, res;

View File

@ -15,8 +15,7 @@
#include <tommath.h> #include <tommath.h>
/* computes least common multiple as |a*b|/(a, b) */ /* computes least common multiple as |a*b|/(a, b) */
int int mp_lcm (mp_int * a, mp_int * b, mp_int * c)
mp_lcm (mp_int * a, mp_int * b, mp_int * c)
{ {
int res; int res;
mp_int t1, t2; mp_int t1, t2;

View File

@ -15,8 +15,7 @@
#include <tommath.h> #include <tommath.h>
/* shift left a certain amount of digits */ /* shift left a certain amount of digits */
int int mp_lshd (mp_int * a, int b)
mp_lshd (mp_int * a, int b)
{ {
int x, res; int x, res;

View File

@ -51,7 +51,7 @@ mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
* following inner loop to reduce the * following inner loop to reduce the
* input one digit at a time * input one digit at a time
*/ */
mu = ((mp_word)x->dp[ix]) * ((mp_word)rho) & MP_MASK; mu = (mp_digit) (((mp_word)x->dp[ix]) * ((mp_word)rho) & MP_MASK);
/* a = a + mu * m * b**i */ /* a = a + mu * m * b**i */
{ {

View File

@ -15,8 +15,7 @@
#include <tommath.h> #include <tommath.h>
/* high level multiplication (handles sign) */ /* high level multiplication (handles sign) */
int int mp_mul (mp_int * a, mp_int * b, mp_int * c)
mp_mul (mp_int * a, mp_int * b, mp_int * c)
{ {
int res, neg; int res, neg;
neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;

View File

@ -15,8 +15,7 @@
#include <tommath.h> #include <tommath.h>
/* b = a*2 */ /* b = a*2 */
int int mp_mul_2(mp_int * a, mp_int * b)
mp_mul_2 (mp_int * a, mp_int * b)
{ {
int x, res, oldused; int x, res, oldused;

View File

@ -15,8 +15,7 @@
#include <tommath.h> #include <tommath.h>
/* shift left by a certain bit count */ /* shift left by a certain bit count */
int int mp_mul_2d (mp_int * a, int b, mp_int * c)
mp_mul_2d (mp_int * a, int b, mp_int * c)
{ {
mp_digit d; mp_digit d;
int res; int res;

View File

@ -21,7 +21,6 @@ mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
int res; int res;
mp_int t; mp_int t;
if ((res = mp_init (&t)) != MP_OKAY) { if ((res = mp_init (&t)) != MP_OKAY) {
return res; return res;
} }

View File

@ -24,8 +24,7 @@
* each step involves a fair bit. This is not meant to * each step involves a fair bit. This is not meant to
* find huge roots [square and cube, etc]. * find huge roots [square and cube, etc].
*/ */
int int mp_n_root (mp_int * a, mp_digit b, mp_int * c)
mp_n_root (mp_int * a, mp_digit b, mp_int * c)
{ {
mp_int t1, t2, t3; mp_int t1, t2, t3;
int res, neg; int res, neg;

View File

@ -15,8 +15,7 @@
#include <tommath.h> #include <tommath.h>
/* b = -a */ /* b = -a */
int int mp_neg (mp_int * a, mp_int * b)
mp_neg (mp_int * a, mp_int * b)
{ {
int res; int res;
if ((res = mp_copy (a, b)) != MP_OKAY) { if ((res = mp_copy (a, b)) != MP_OKAY) {

View File

@ -15,8 +15,7 @@
#include <tommath.h> #include <tommath.h>
/* OR two ints together */ /* OR two ints together */
int int mp_or (mp_int * a, mp_int * b, mp_int * c)
mp_or (mp_int * a, mp_int * b, mp_int * c)
{ {
int res, ix, px; int res, ix, px;
mp_int t, *x; mp_int t, *x;

View File

@ -22,14 +22,13 @@
* *
* Sets result to 1 if the congruence holds, or zero otherwise. * Sets result to 1 if the congruence holds, or zero otherwise.
*/ */
int int mp_prime_fermat (mp_int * a, mp_int * b, int *result)
mp_prime_fermat (mp_int * a, mp_int * b, int *result)
{ {
mp_int t; mp_int t;
int err; int err;
/* default to composite */ /* default to composite */
*result = 0; *result = MP_NO;
/* ensure b > 1 */ /* ensure b > 1 */
if (mp_cmp_d(b, 1) != MP_GT) { if (mp_cmp_d(b, 1) != MP_GT) {
@ -48,7 +47,7 @@ mp_prime_fermat (mp_int * a, mp_int * b, int *result)
/* is it equal to b? */ /* is it equal to b? */
if (mp_cmp (&t, b) == MP_EQ) { if (mp_cmp (&t, b) == MP_EQ) {
*result = 1; *result = MP_YES;
} }
err = MP_OKAY; err = MP_OKAY;

View File

@ -19,14 +19,13 @@
* *
* sets result to 0 if not, 1 if yes * sets result to 0 if not, 1 if yes
*/ */
int int mp_prime_is_divisible (mp_int * a, int *result)
mp_prime_is_divisible (mp_int * a, int *result)
{ {
int err, ix; int err, ix;
mp_digit res; mp_digit res;
/* default to not */ /* default to not */
*result = 0; *result = MP_NO;
for (ix = 0; ix < PRIME_SIZE; ix++) { for (ix = 0; ix < PRIME_SIZE; ix++) {
/* what is a mod __prime_tab[ix] */ /* what is a mod __prime_tab[ix] */
@ -36,7 +35,7 @@ mp_prime_is_divisible (mp_int * a, int *result)
/* is the residue zero? */ /* is the residue zero? */
if (res == 0) { if (res == 0) {
*result = 1; *result = MP_YES;
return MP_OKAY; return MP_OKAY;
} }
} }

View File

@ -21,14 +21,13 @@
* *
* Sets result to 1 if probably prime, 0 otherwise * Sets result to 1 if probably prime, 0 otherwise
*/ */
int int mp_prime_is_prime (mp_int * a, int t, int *result)
mp_prime_is_prime (mp_int * a, int t, int *result)
{ {
mp_int b; mp_int b;
int ix, err, res; int ix, err, res;
/* default to no */ /* default to no */
*result = 0; *result = MP_NO;
/* valid value of t? */ /* valid value of t? */
if (t <= 0 || t > PRIME_SIZE) { if (t <= 0 || t > PRIME_SIZE) {
@ -49,7 +48,7 @@ mp_prime_is_prime (mp_int * a, int t, int *result)
} }
/* return if it was trivially divisible */ /* return if it was trivially divisible */
if (res == 1) { if (res == MP_YES) {
return MP_OKAY; return MP_OKAY;
} }
@ -66,13 +65,13 @@ mp_prime_is_prime (mp_int * a, int t, int *result)
goto __B; goto __B;
} }
if (res == 0) { if (res == MP_NO) {
goto __B; goto __B;
} }
} }
/* passed the test */ /* passed the test */
*result = 1; *result = MP_YES;
__B:mp_clear (&b); __B:mp_clear (&b);
return err; return err;
} }

View File

@ -21,14 +21,13 @@
* Randomly the chance of error is no more than 1/4 and often * Randomly the chance of error is no more than 1/4 and often
* very much lower. * very much lower.
*/ */
int int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result)
mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result)
{ {
mp_int n1, y, r; mp_int n1, y, r;
int s, j, err; int s, j, err;
/* default */ /* default */
*result = 0; *result = MP_NO;
/* ensure b > 1 */ /* ensure b > 1 */
if (mp_cmp_d(b, 1) != MP_GT) { if (mp_cmp_d(b, 1) != MP_GT) {
@ -90,7 +89,7 @@ mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result)
} }
/* probably prime now */ /* probably prime now */
*result = 1; *result = MP_YES;
__Y:mp_clear (&y); __Y:mp_clear (&y);
__R:mp_clear (&r); __R:mp_clear (&r);
__N1:mp_clear (&n1); __N1:mp_clear (&n1);

View File

@ -146,12 +146,12 @@ int mp_prime_next_prime(mp_int *a, int t, int bbs_style)
if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) { if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) {
goto __ERR; goto __ERR;
} }
if (res == 0) { if (res == MP_NO) {
break; break;
} }
} }
if (res == 1) { if (res == MP_YES) {
break; break;
} }
} }

74
bn_mp_prime_random.c Normal file
View File

@ -0,0 +1,74 @@
/* LibTomMath, multiple-precision integer library -- Tom St Denis
*
* LibTomMath is a library that provides multiple-precision
* integer arithmetic as well as number theoretic functionality.
*
* The library was designed directly after the MPI library by
* Michael Fromberger but has been written from scratch with
* additional optimizations in place.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
*/
#include <tommath.h>
/* makes a truly random prime of a given size (bytes),
* call with bbs = 1 if you want it to be congruent to 3 mod 4
*
* You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can
* have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself
* so it can be NULL
*
* The prime generated will be larger than 2^(8*size).
*/
/* this sole function may hold the key to enslaving all mankind! */
int mp_prime_random(mp_int *a, int t, int size, int bbs, ltm_prime_callback cb, void *dat)
{
unsigned char *tmp;
int res, err;
/* sanity check the input */
if (size <= 0) {
return MP_VAL;
}
/* we need a buffer of size+1 bytes */
tmp = XMALLOC(size+1);
if (tmp == NULL) {
return MP_MEM;
}
/* fix MSB */
tmp[0] = 1;
do {
/* read the bytes */
if (cb(tmp+1, size, dat) != size) {
err = MP_VAL;
goto error;
}
/* fix the LSB */
tmp[size] |= (bbs ? 3 : 1);
/* read it in */
if ((err = mp_read_unsigned_bin(a, tmp, size+1)) != MP_OKAY) {
goto error;
}
/* is it prime? */
if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) {
goto error;
}
} while (res == MP_NO);
err = MP_OKAY;
error:
XFREE(tmp);
return err;
}

View File

@ -27,28 +27,36 @@ mp_radix_size (mp_int * a, int radix)
return mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1; return mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1;
} }
/* make sure the radix is in range */
if (radix < 2 || radix > 64) { if (radix < 2 || radix > 64) {
return 0; return 0;
} }
/* init a copy of the input */
if ((res = mp_init_copy (&t, a)) != MP_OKAY) { if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
return 0; return 0;
} }
/* digs is the digit count */
digs = 0; digs = 0;
/* if it's negative add one for the sign */
if (t.sign == MP_NEG) { if (t.sign == MP_NEG) {
++digs; ++digs;
t.sign = MP_ZPOS; t.sign = MP_ZPOS;
} }
/* fetch out all of the digits */
while (mp_iszero (&t) == 0) { while (mp_iszero (&t) == 0) {
if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
mp_clear (&t); mp_clear (&t);
return 0; return res;
} }
++digs; ++digs;
} }
mp_clear (&t); mp_clear (&t);
/* return digs + 1, the 1 is for the NULL byte that would be required. */
return digs + 1; return digs + 1;
} }

View File

@ -15,10 +15,9 @@
#include <tommath.h> #include <tommath.h>
/* determines if mp_reduce_2k can be used */ /* determines if mp_reduce_2k can be used */
int int mp_reduce_is_2k(mp_int *a)
mp_reduce_is_2k(mp_int *a)
{ {
int ix, iy; int ix, iy, iz, iw;
if (a->used == 0) { if (a->used == 0) {
return 0; return 0;
@ -26,11 +25,19 @@ mp_reduce_is_2k(mp_int *a)
return 1; return 1;
} else if (a->used > 1) { } else if (a->used > 1) {
iy = mp_count_bits(a); iy = mp_count_bits(a);
iz = 1;
iw = 1;
/* Test every bit from the second digit up, must be 1 */
for (ix = DIGIT_BIT; ix < iy; ix++) { for (ix = DIGIT_BIT; ix < iy; ix++) {
if ((a->dp[ix/DIGIT_BIT] & if ((a->dp[iw] & iz) == 0) {
((mp_digit)1 << (mp_digit)(ix % DIGIT_BIT))) == 0) {
return 0; return 0;
} }
iz <<= 1;
if (iz > (int)MP_MASK) {
++iw;
iz = 1;
}
} }
} }
return 1; return 1;

View File

@ -15,8 +15,7 @@
#include <tommath.h> #include <tommath.h>
/* shift right a certain amount of digits */ /* shift right a certain amount of digits */
void void mp_rshd (mp_int * a, int b)
mp_rshd (mp_int * a, int b)
{ {
int x; int x;

View File

@ -15,8 +15,7 @@
#include <tommath.h> #include <tommath.h>
/* set to a digit */ /* set to a digit */
void void mp_set (mp_int * a, mp_digit b)
mp_set (mp_int * a, mp_digit b)
{ {
mp_zero (a); mp_zero (a);
a->dp[0] = b & MP_MASK; a->dp[0] = b & MP_MASK;

View File

@ -15,8 +15,7 @@
#include <tommath.h> #include <tommath.h>
/* set a 32-bit const */ /* set a 32-bit const */
int int mp_set_int (mp_int * a, unsigned long b)
mp_set_int (mp_int * a, unsigned int b)
{ {
int x, res; int x, res;

View File

@ -15,13 +15,14 @@
#include <tommath.h> #include <tommath.h>
/* shrink a bignum */ /* shrink a bignum */
int int mp_shrink (mp_int * a)
mp_shrink (mp_int * a)
{ {
mp_digit *tmp;
if (a->alloc != a->used) { if (a->alloc != a->used) {
if ((a->dp = OPT_CAST realloc (a->dp, sizeof (mp_digit) * a->used)) == NULL) { if ((tmp = OPT_CAST XREALLOC (a->dp, sizeof (mp_digit) * a->used)) == NULL) {
return MP_MEM; return MP_MEM;
} }
a->dp = tmp;
a->alloc = a->used; a->alloc = a->used;
} }
return MP_OKAY; return MP_OKAY;

View File

@ -23,6 +23,7 @@ mp_toradix (mp_int * a, char *str, int radix)
mp_digit d; mp_digit d;
char *_s = str; char *_s = str;
/* check range of the radix */
if (radix < 2 || radix > 64) { if (radix < 2 || radix > 64) {
return MP_VAL; return MP_VAL;
} }
@ -61,8 +62,7 @@ mp_toradix (mp_int * a, char *str, int radix)
bn_reverse ((unsigned char *)_s, digs); bn_reverse ((unsigned char *)_s, digs);
/* append a NULL so the string is properly terminated */ /* append a NULL so the string is properly terminated */
*str++ = '\0'; *str = '\0';
mp_clear (&t); mp_clear (&t);
return MP_OKAY; return MP_OKAY;

69
bn_prime_sizes_tab.c Normal file
View File

@ -0,0 +1,69 @@
/* LibTomMath, multiple-precision integer library -- Tom St Denis
*
* LibTomMath is a library that provides multiple-precision
* integer arithmetic as well as number theoretic functionality.
*
* The library was designed directly after the MPI library by
* Michael Fromberger but has been written from scratch with
* additional optimizations in place.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
*/
#include <tommath.h>
/* this table gives the # of rabin miller trials for a prob of failure lower than 2^-96 */
static const struct {
int k, t;
} sizes[] = {
{ 128, 28 },
{ 256, 16 },
{ 384, 10 },
{ 512, 7 },
{ 640, 6 },
{ 768, 5 },
{ 896, 4 },
{ 1024, 4 },
{ 1152, 3 },
{ 1280, 3 },
{ 1408, 3 },
{ 1536, 3 },
{ 1664, 3 },
{ 1792, 2 },
{ 1920, 2 },
{ 2048, 2 },
{ 2176, 2 },
{ 2304, 2 },
{ 2432, 2 },
{ 2560, 2 },
{ 2688, 2 },
{ 2816, 2 },
{ 2944, 2 },
{ 3072, 2 },
{ 3200, 2 },
{ 3328, 2 },
{ 3456, 2 },
{ 3584, 2 },
{ 3712, 2 },
{ 3840, 1 },
{ 3968, 1 },
{ 4096, 1 } };
/* returns # of RM trials required for a given bit size */
int mp_prime_rabin_miller_trials(int size)
{
int x;
for (x = 0; x < (int)(sizeof(sizes)/(sizeof(sizes[0]))); x++) {
if (sizes[x].k == size) {
return sizes[x].t;
} else if (sizes[x].k > size) {
return (x == 0) ? sizes[0].t : sizes[x - 1].t;
}
}
return 1;
}

View File

@ -27,6 +27,8 @@ s_mp_sqr (mp_int * a, mp_int * b)
if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) { if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) {
return res; return res;
} }
/* default used is maximum possible size */
t.used = 2*pa + 1; t.used = 2*pa + 1;
for (ix = 0; ix < pa; ix++) { for (ix = 0; ix < pa; ix++) {
@ -36,20 +38,20 @@ s_mp_sqr (mp_int * a, mp_int * b)
((mp_word)a->dp[ix])*((mp_word)a->dp[ix]); ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]);
/* store lower part in result */ /* store lower part in result */
t.dp[2*ix] = (mp_digit) (r & ((mp_word) MP_MASK)); t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK));
/* get the carry */ /* get the carry */
u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
/* left hand side of A[ix] * A[iy] */ /* left hand side of A[ix] * A[iy] */
tmpx = a->dp[ix]; tmpx = a->dp[ix];
/* alias for where to store the results */ /* alias for where to store the results */
tmpt = t.dp + (2*ix + 1); tmpt = t.dp + (2*ix + 1);
for (iy = ix + 1; iy < pa; iy++) { for (iy = ix + 1; iy < pa; iy++) {
/* first calculate the product */ /* first calculate the product */
r = ((mp_word)tmpx) * ((mp_word)a->dp[iy]); r = ((mp_word)tmpx) * ((mp_word)a->dp[iy]);
/* now calculate the double precision result, note we use /* now calculate the double precision result, note we use
* addition instead of *2 since it's easier to optimize * addition instead of *2 since it's easier to optimize

View File

@ -1,3 +1,24 @@
Dec 24th, 2003
v0.28 -- Henrik suggested I add casts to the montomgery code [stores into mu...] so compilers wouldn't
spew [erroneous] diagnostics... fixed.
-- Henrik also spotted two typos. One in mp_radix_size() and another in mp_toradix().
-- Added fix to mp_shrink() to avoid a memory leak.
-- Added mp_prime_random() which requires a callback to make truly random primes of a given nature
(idea from chat with Niels Ferguson at Crypto'03)
-- Picked up a second wind. I'm filled with Gooo. Mission Gooo!
-- Removed divisions from mp_reduce_is_2k()
-- Sped up mp_div_d() [general case] to use only one division per digit instead of two.
-- Added the heap macros from LTC to LTM. Now you can easily [by editing four lines of tommath.h]
change the name of the heap functions used in LTM [also compatible with LTC via MPI mode]
-- Added bn_prime_rabin_miller_trials() which gives the number of Rabin-Miller trials to achieve
a failure rate of less than 2^-96
-- fixed bug in fast_mp_invmod(). The initial testing logic was wrong. An invalid input is not when
"a" and "b" are even it's when "b" is even [the algo is for odd moduli only].
-- Started a new manual [finally]. It is incomplete and will be finished as time goes on. I had to stop
adding full demos around half way in chapter three so I could at least get a good portion of the
manual done. If you really need help using the library you can always email me!
-- My Textbook is now included as part of the package [all Public Domain]
Sept 19th, 2003 Sept 19th, 2003
v0.27 -- Removed changes.txt~ which was made by accident since "kate" decided it was v0.27 -- Removed changes.txt~ which was made by accident since "kate" decided it was
a good time to re-enable backups... [kde is fun!] a good time to re-enable backups... [kde is fun!]

View File

@ -111,10 +111,10 @@ int main(void)
/* test mp_reduce_2k */ /* test mp_reduce_2k */
#if 0 #if 0
for (cnt = 3; cnt <= 256; ++cnt) { for (cnt = 3; cnt <= 384; ++cnt) {
mp_digit tmp; mp_digit tmp;
mp_2expt(&a, cnt); mp_2expt(&a, cnt);
mp_sub_d(&a, 1, &a); /* a = 2**cnt - 1 */ mp_sub_d(&a, 2, &a); /* a = 2**cnt - 2 */
printf("\nTesting %4d bits", cnt); printf("\nTesting %4d bits", cnt);
@ -138,11 +138,11 @@ int main(void)
/* test mp_div_3 */ /* test mp_div_3 */
#if 0 #if 0
for (cnt = 0; cnt < 10000; ) { for (cnt = 0; cnt < 1000000; ) {
mp_digit r1, r2; mp_digit r1, r2;
if (!(++cnt & 127)) printf("%9d\r", cnt); if (!(++cnt & 127)) printf("%9d\r", cnt);
mp_rand(&a, abs(rand()) % 32 + 1); mp_rand(&a, abs(rand()) % 128 + 1);
mp_div_d(&a, 3, &b, &r1); mp_div_d(&a, 3, &b, &r1);
mp_div_3(&a, &c, &r2); mp_div_3(&a, &c, &r2);
@ -155,7 +155,7 @@ int main(void)
/* test the DR reduction */ /* test the DR reduction */
#if 0 #if 0
for (cnt = 2; cnt < 32; cnt++) { for (cnt = 2; cnt < 128; cnt++) {
printf("%d digit modulus\n", cnt); printf("%d digit modulus\n", cnt);
mp_grow(&a, cnt); mp_grow(&a, cnt);
mp_zero(&a); mp_zero(&a);
@ -181,7 +181,7 @@ int main(void)
printf("Failed on trial %lu\n", rr); exit(-1); printf("Failed on trial %lu\n", rr); exit(-1);
} }
} while (++rr < 10000); } while (++rr < 100000);
printf("Passed DR test for %d digits\n", cnt); printf("Passed DR test for %d digits\n", cnt);
} }
#endif #endif
@ -203,8 +203,8 @@ int main(void)
rr += 16; rr += 16;
} while (rdtsc() < (CLOCKS_PER_SEC * 2)); } while (rdtsc() < (CLOCKS_PER_SEC * 2));
tt = rdtsc(); tt = rdtsc();
printf("Adding\t\t%4d-bit => %9llu/sec, %9llu ticks\n", mp_count_bits(&a), (((unsigned long long)rr)*CLOCKS_PER_SEC)/tt, tt); printf("Adding\t\t%4d-bit => %9llu/sec, %9llu ticks\n", mp_count_bits(&a), (((ulong64)rr)*CLOCKS_PER_SEC)/tt, tt);
fprintf(log, "%d %9llu\n", cnt*DIGIT_BIT, (((unsigned long long)rr)*CLOCKS_PER_SEC)/tt); fprintf(log, "%d %9llu\n", cnt*DIGIT_BIT, (((ulong64)rr)*CLOCKS_PER_SEC)/tt);
} }
fclose(log); fclose(log);
@ -220,12 +220,13 @@ int main(void)
rr += 16; rr += 16;
} while (rdtsc() < (CLOCKS_PER_SEC * 2)); } while (rdtsc() < (CLOCKS_PER_SEC * 2));
tt = rdtsc(); tt = rdtsc();
printf("Subtracting\t\t%4d-bit => %9llu/sec, %9llu ticks\n", mp_count_bits(&a), (((unsigned long long)rr)*CLOCKS_PER_SEC)/tt, tt); printf("Subtracting\t\t%4d-bit => %9llu/sec, %9llu ticks\n", mp_count_bits(&a), (((ulong64)rr)*CLOCKS_PER_SEC)/tt, tt);
fprintf(log, "%d %9llu\n", cnt*DIGIT_BIT, (((unsigned long long)rr)*CLOCKS_PER_SEC)/tt); fprintf(log, "%d %9llu\n", cnt*DIGIT_BIT, (((ulong64)rr)*CLOCKS_PER_SEC)/tt);
} }
fclose(log); fclose(log);
/* do mult/square twice, first without karatsuba and second with */ /* do mult/square twice, first without karatsuba and second with */
mult_test:
old_kara_m = KARATSUBA_MUL_CUTOFF; old_kara_m = KARATSUBA_MUL_CUTOFF;
old_kara_s = KARATSUBA_SQR_CUTOFF; old_kara_s = KARATSUBA_SQR_CUTOFF;
for (ix = 0; ix < 2; ix++) { for (ix = 0; ix < 2; ix++) {
@ -246,8 +247,8 @@ int main(void)
rr += 16; rr += 16;
} while (rdtsc() < (CLOCKS_PER_SEC * 2)); } while (rdtsc() < (CLOCKS_PER_SEC * 2));
tt = rdtsc(); tt = rdtsc();
printf("Multiplying\t%4d-bit => %9llu/sec, %9llu ticks\n", mp_count_bits(&a), (((unsigned long long)rr)*CLOCKS_PER_SEC)/tt, tt); printf("Multiplying\t%4d-bit => %9llu/sec, %9llu ticks\n", mp_count_bits(&a), (((ulong64)rr)*CLOCKS_PER_SEC)/tt, tt);
fprintf(log, "%d %9llu\n", cnt*DIGIT_BIT, (((unsigned long long)rr)*CLOCKS_PER_SEC)/tt); fprintf(log, "%d %9llu\n", mp_count_bits(&a), (((ulong64)rr)*CLOCKS_PER_SEC)/tt);
} }
fclose(log); fclose(log);
@ -262,8 +263,8 @@ int main(void)
rr += 16; rr += 16;
} while (rdtsc() < (CLOCKS_PER_SEC * 2)); } while (rdtsc() < (CLOCKS_PER_SEC * 2));
tt = rdtsc(); tt = rdtsc();
printf("Squaring\t%4d-bit => %9llu/sec, %9llu ticks\n", mp_count_bits(&a), (((unsigned long long)rr)*CLOCKS_PER_SEC)/tt, tt); printf("Squaring\t%4d-bit => %9llu/sec, %9llu ticks\n", mp_count_bits(&a), (((ulong64)rr)*CLOCKS_PER_SEC)/tt, tt);
fprintf(log, "%d %9llu\n", cnt*DIGIT_BIT, (((unsigned long long)rr)*CLOCKS_PER_SEC)/tt); fprintf(log, "%d %9llu\n", mp_count_bits(&a), (((ulong64)rr)*CLOCKS_PER_SEC)/tt);
} }
fclose(log); fclose(log);
@ -297,12 +298,14 @@ int main(void)
"1214855636816562637502584060163403830270705000634713483015101384881871978446801224798536155406895823305035467591632531067547890948695117172076954220727075688048751022421198712032848890056357845974246560748347918630050853933697792254955890439720297560693579400297062396904306270145886830719309296352765295712183040773146419022875165382778007040109957609739589875590885701126197906063620133954893216612678838507540777138437797705602453719559017633986486649523611975865005712371194067612263330335590526176087004421363598470302731349138773205901447704682181517904064735636518462452242791676541725292378925568296858010151852326316777511935037531017413910506921922450666933202278489024521263798482237150056835746454842662048692127173834433089016107854491097456725016327709663199738238442164843147132789153725513257167915555162094970853584447993125488607696008169807374736711297007473812256272245489405898470297178738029484459690836250560495461579533254473316340608217876781986188705928270735695752830825527963838355419762516246028680280988020401914551825487349990306976304093109384451438813251211051597392127491464898797406789175453067960072008590614886532333015881171367104445044718144312416815712216611576221546455968770801413440778423979", "1214855636816562637502584060163403830270705000634713483015101384881871978446801224798536155406895823305035467591632531067547890948695117172076954220727075688048751022421198712032848890056357845974246560748347918630050853933697792254955890439720297560693579400297062396904306270145886830719309296352765295712183040773146419022875165382778007040109957609739589875590885701126197906063620133954893216612678838507540777138437797705602453719559017633986486649523611975865005712371194067612263330335590526176087004421363598470302731349138773205901447704682181517904064735636518462452242791676541725292378925568296858010151852326316777511935037531017413910506921922450666933202278489024521263798482237150056835746454842662048692127173834433089016107854491097456725016327709663199738238442164843147132789153725513257167915555162094970853584447993125488607696008169807374736711297007473812256272245489405898470297178738029484459690836250560495461579533254473316340608217876781986188705928270735695752830825527963838355419762516246028680280988020401914551825487349990306976304093109384451438813251211051597392127491464898797406789175453067960072008590614886532333015881171367104445044718144312416815712216611576221546455968770801413440778423979",
NULL NULL
}; };
expt_test:
log = fopen("logs/expt.log", "w"); log = fopen("logs/expt.log", "w");
logb = fopen("logs/expt_dr.log", "w"); logb = fopen("logs/expt_dr.log", "w");
logc = fopen("logs/expt_2k.log", "w"); logc = fopen("logs/expt_2k.log", "w");
for (n = 0; primes[n]; n++) { for (n = 0; primes[n]; n++) {
SLEEP; SLEEP;
mp_read_radix(&a, primes[n], 10); mp_read_radix(&a, primes[n], 10);
printf("Different (%d)!!!\n", mp_count_bits(&a));
mp_zero(&b); mp_zero(&b);
for (rr = 0; rr < mp_count_bits(&a); rr++) { for (rr = 0; rr < mp_count_bits(&a); rr++) {
mp_mul_2(&b, &b); mp_mul_2(&b, &b);
@ -328,8 +331,8 @@ int main(void)
draw(&d); draw(&d);
exit(0); exit(0);
} }
printf("Exponentiating\t%4d-bit => %9llu/sec, %9llu ticks\n", mp_count_bits(&a), (((unsigned long long)rr)*CLOCKS_PER_SEC)/tt, tt); printf("Exponentiating\t%4d-bit => %9llu/sec, %9llu ticks\n", mp_count_bits(&a), (((ulong64)rr)*CLOCKS_PER_SEC)/tt, tt);
fprintf((n < 6) ? logc : (n < 13) ? logb : log, "%d %9llu\n", mp_count_bits(&a), (((unsigned long long)rr)*CLOCKS_PER_SEC)/tt); fprintf((n < 6) ? logc : (n < 13) ? logb : log, "%d %9llu\n", mp_count_bits(&a), (((ulong64)rr)*CLOCKS_PER_SEC)/tt);
} }
} }
fclose(log); fclose(log);
@ -359,8 +362,8 @@ int main(void)
printf("Failed to invert\n"); printf("Failed to invert\n");
return 0; return 0;
} }
printf("Inverting mod\t%4d-bit => %9llu/sec, %9llu ticks\n", mp_count_bits(&a), (((unsigned long long)rr)*CLOCKS_PER_SEC)/tt, tt); printf("Inverting mod\t%4d-bit => %9llu/sec, %9llu ticks\n", mp_count_bits(&a), (((ulong64)rr)*CLOCKS_PER_SEC)/tt, tt);
fprintf(log, "%d %9llu\n", cnt*DIGIT_BIT, (((unsigned long long)rr)*CLOCKS_PER_SEC)/tt); fprintf(log, "%d %9llu\n", cnt*DIGIT_BIT, (((ulong64)rr)*CLOCKS_PER_SEC)/tt);
} }
fclose(log); fclose(log);

View File

@ -0,0 +1,2 @@
256-bits (k = 36113) = 115792089237316195423570985008687907853269984665640564039457584007913129603823
512-bits (k = 38117) = 13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006045979

View File

@ -1,3 +1,6 @@
280-bit prime: 280-bit prime:
p == 1942668892225729070919461906823518906642406839052139521251812409738904285204940164839 p == 1942668892225729070919461906823518906642406839052139521251812409738904285204940164839
532-bit prime:
p == 14059105607947488696282932836518693308967803494693489478439861164411992439598399594747002144074658928593502845729752797260025831423419686528151609940203368691747

View File

@ -19,6 +19,11 @@ tune86: tune.c
nasm -f coff timer.asm nasm -f coff timer.asm
$(CC) -DX86_TIMER $(CFLAGS) tune.c timer.o $(LIBNAME) -o tune86 $(CC) -DX86_TIMER $(CFLAGS) tune.c timer.o $(LIBNAME) -o tune86
# for cygwin
tune86c: tune.c
nasm -f gnuwin32 timer.asm
$(CC) -DX86_TIMER $(CFLAGS) tune.c timer.o $(LIBNAME) -o tune86
#make tune86 for linux or any ELF format #make tune86 for linux or any ELF format
tune86l: tune.c tune86l: tune.c
nasm -f elf -DUSE_ELF timer.asm nasm -f elf -DUSE_ELF timer.asm

View File

@ -1,16 +1,16 @@
224 12849536 224 8622881
448 9956080 448 7241417
672 8372000 672 5844712
896 7065464 896 4938016
1120 5824864 1120 4256543
1344 5141728 1344 3728000
1568 4511808 1568 3328263
1792 4170480 1792 3012161
2016 3802536 2016 2743688
2240 3500936 2240 2512095
2464 3193352 2464 2234464
2688 2991976 2688 1960139
2912 2818672 2912 2013395
3136 2661448 3136 1879636
3360 2506560 3360 1756301
3584 2343304 3584 1680982

View File

@ -1,7 +0,0 @@
513 600
769 221
1025 103
2049 15
2561 8
3073 4
4097 2

View File

@ -1,6 +0,0 @@
521 728
607 549
1279 100
2203 29
3217 11
4253 5

View File

@ -1,7 +0,0 @@
532 1032
784 424
1036 214
1540 81
2072 38
3080 13
4116 5

View File

@ -1,17 +1,17 @@
896 301008 896 348504
1344 141872 1344 165040
1792 84424 1792 98696
2240 55864 2240 65400
2688 39784 2688 46672
3136 29624 3136 34968
3584 22952 3584 27144
4032 18304 4032 21648
4480 14944 4480 17672
4928 12432 4928 14768
5376 10496 5376 12416
5824 8976 5824 10696
6272 7776 6272 9184
6720 6792 6720 8064
7168 1656 7168 1896
7616 1472 7616 1680
8064 1312 8064 1504

View File

@ -1,17 +1,17 @@
896 371856 911 167013
1344 196352 1359 83796
1792 122312 1807 50308
2240 83144 2254 33637
2688 60304 2703 24067
3136 45832 3151 17997
3584 12760 3599 5751
4032 10160 4047 4561
4480 8352 4490 3714
4928 6944 4943 3067
5376 5824 5391 2597
5824 5008 5839 2204
6272 4336 6286 1909
6720 3768 6735 1637
7168 3280 7183 1461
7616 2952 7631 1302
8064 2640 8078 1158

17
logs/sqr.old Normal file
View File

@ -0,0 +1,17 @@
896 382617
1344 207161
1792 131522
2240 90775
2688 66652
3136 50955
3584 11678
4032 9342
4480 7684
4928 6382
5376 5399
5824 4545
6272 3994
6720 3490
7168 3075
7616 2733
8064 2428

View File

@ -1,17 +1,17 @@
896 372256 910 165312
1344 196368 1358 84355
1792 122272 1806 50316
2240 82976 2255 33661
2688 60480 2702 24027
3136 45808 3151 18068
3584 33296 3599 14721
4032 27888 4046 12101
4480 23608 4493 10112
4928 20296 4942 8591
5376 17576 5390 7364
5824 15416 5839 6398
6272 13600 6285 5607
6720 12104 6735 4952
7168 10080 7182 4625
7616 9232 7631 4193
8064 8008 8079 3810

View File

@ -1,16 +1,16 @@
224 9325944 224 10295756
448 8075808 448 7577910
672 7054912 672 6279588
896 5757992 896 5345182
1120 5081768 1120 4646989
1344 4669384 1344 4101759
1568 4422384 1568 3685447
1792 3900416 1792 3337497
2016 3548872 2016 3051095
2240 3428912 2240 2811900
2464 3216968 2464 2605371
2688 2905280 2688 2420561
2912 2782664 2912 2273174
3136 2591440 3136 2134662
3360 2475728 3360 2014354
3584 2282216 3584 1901723

View File

@ -6,7 +6,7 @@ CFLAGS += -I./ -Wall -W -Wshadow -O3 -funroll-loops
#x86 optimizations [should be valid for any GCC install though] #x86 optimizations [should be valid for any GCC install though]
CFLAGS += -fomit-frame-pointer CFLAGS += -fomit-frame-pointer
VERSION=0.27 VERSION=0.28
default: libtommath.a default: libtommath.a
@ -44,7 +44,7 @@ bn_mp_toom_mul.o bn_mp_toom_sqr.o bn_mp_div_3.o bn_s_mp_exptmod.o \
bn_mp_reduce_2k.o bn_mp_reduce_is_2k.o bn_mp_reduce_2k_setup.o \ bn_mp_reduce_2k.o bn_mp_reduce_is_2k.o bn_mp_reduce_2k_setup.o \
bn_mp_radix_smap.o bn_mp_read_radix.o bn_mp_toradix.o bn_mp_radix_size.o \ bn_mp_radix_smap.o bn_mp_read_radix.o bn_mp_toradix.o bn_mp_radix_size.o \
bn_mp_fread.o bn_mp_fwrite.o bn_mp_cnt_lsb.o bn_error.o \ bn_mp_fread.o bn_mp_fwrite.o bn_mp_cnt_lsb.o bn_error.o \
bn_mp_init_multi.o bn_mp_clear_multi.o bn_mp_init_multi.o bn_mp_clear_multi.o bn_mp_prime_random.o bn_prime_sizes_tab.o
libtommath.a: $(OBJECTS) libtommath.a: $(OBJECTS)
$(AR) $(ARFLAGS) libtommath.a $(OBJECTS) $(AR) $(ARFLAGS) libtommath.a $(OBJECTS)
@ -87,23 +87,29 @@ docs:
latex tommath > /dev/null latex tommath > /dev/null
pdflatex tommath pdflatex tommath
rm -f tommath.log tommath.aux tommath.dvi tommath.idx tommath.toc tommath.lof tommath.ind tommath.ilg rm -f tommath.log tommath.aux tommath.dvi tommath.idx tommath.toc tommath.lof tommath.ind tommath.ilg
cd pics ; make clean
#the old manual being phased out #LTM user manual
manual: mandvi: bn.tex
latex bn echo "hello" > bn.ind
pdflatex bn latex bn > /dev/null
rm -f bn.aux bn.dvi bn.log makeindex bn
latex bn > /dev/null
#LTM user manual [pdf]
manual: mandvi
pdflatex bn >/dev/null
rm -f bn.aux bn.dvi bn.log bn.idx bn.lof bn.out bn.toc
clean: clean:
rm -f *.bat *.pdf *.o *.a *.obj *.lib *.exe etclib/*.o demo/demo.o test ltmtest mpitest mtest/mtest mtest/mtest.exe \ rm -f *.bat *.pdf *.o *.a *.obj *.lib *.exe *.dll etclib/*.o demo/demo.o test ltmtest mpitest mtest/mtest mtest/mtest.exe \
tommath.idx tommath.toc tommath.log tommath.aux tommath.dvi tommath.lof tommath.ind tommath.ilg *.ps *.pdf *.log *.s mpi.c \ *.idx *.toc *.log *.aux *.dvi *.lof *.ind *.ilg *.ps *.log *.s mpi.c
poster.aux poster.dvi poster.log
cd etc ; make clean cd etc ; make clean
cd pics ; make clean cd pics ; make clean
zipup: clean manual poster zipup: clean manual poster docs
perl gen.pl ; mv mpi.c pre_gen/ ; \ perl gen.pl ; mv mpi.c pre_gen/ ; \
cd .. ; rm -rf ltm* libtommath-$(VERSION) ; mkdir libtommath-$(VERSION) ; \ cd .. ; rm -rf ltm* libtommath-$(VERSION) ; mkdir libtommath-$(VERSION) ; \
cp -R ./libtommath/* ./libtommath-$(VERSION)/ ; cd ./libtommath-$(VERSION) ; rm -f tommath.src tommath.tex tommath.out ; cd pics ; rm -f *.tif *.ps *.pdf ; cd .. ; cd .. ; ls ; \ cp -R ./libtommath/* ./libtommath-$(VERSION)/ ; \
tar -c libtommath-$(VERSION)/* > ltm-$(VERSION).tar ; \ tar -c libtommath-$(VERSION)/* | bzip2 -9vvc > ltm-$(VERSION).tar.bz2 ; \
bzip2 -9vv ltm-$(VERSION).tar ; zip -9 -r ltm-$(VERSION).zip libtommath-$(VERSION)/* zip -9 -r ltm-$(VERSION).zip libtommath-$(VERSION)/*

View File

@ -29,7 +29,7 @@ bn_mp_toom_mul.obj bn_mp_toom_sqr.obj bn_mp_div_3.obj bn_s_mp_exptmod.obj \
bn_mp_reduce_2k.obj bn_mp_reduce_is_2k.obj bn_mp_reduce_2k_setup.obj \ bn_mp_reduce_2k.obj bn_mp_reduce_is_2k.obj bn_mp_reduce_2k_setup.obj \
bn_mp_radix_smap.obj bn_mp_read_radix.obj bn_mp_toradix.obj bn_mp_radix_size.obj \ bn_mp_radix_smap.obj bn_mp_read_radix.obj bn_mp_toradix.obj bn_mp_radix_size.obj \
bn_mp_fread.obj bn_mp_fwrite.obj bn_mp_cnt_lsb.obj bn_error.obj \ bn_mp_fread.obj bn_mp_fwrite.obj bn_mp_cnt_lsb.obj bn_error.obj \
bn_mp_init_multi.obj bn_mp_clear_multi.obj bn_mp_init_multi.obj bn_mp_clear_multi.obj bn_mp_prime_random.obj bn_prime_sizes_tab.obj
TARGET = libtommath.lib TARGET = libtommath.lib

47
makefile.cygwin_dll Normal file
View File

@ -0,0 +1,47 @@
#Makefile for Cygwin-GCC
#
#This makefile will build a Windows DLL [doesn't require cygwin to run] in the file
#libtommath.dll. The import library is in libtommath.dll.a. Remember to add
#"-Wl,--enable-auto-import" to your client build to avoid the auto-import warnings
#
#Tom St Denis
CFLAGS += -I./ -Wall -W -Wshadow -O3 -funroll-loops -mno-cygwin
#x86 optimizations [should be valid for any GCC install though]
CFLAGS += -fomit-frame-pointer
default: windll
OBJECTS=bncore.o bn_mp_init.o bn_mp_clear.o bn_mp_exch.o bn_mp_grow.o bn_mp_shrink.o \
bn_mp_clamp.o bn_mp_zero.o bn_mp_set.o bn_mp_set_int.o bn_mp_init_size.o bn_mp_copy.o \
bn_mp_init_copy.o bn_mp_abs.o bn_mp_neg.o bn_mp_cmp_mag.o bn_mp_cmp.o bn_mp_cmp_d.o \
bn_mp_rshd.o bn_mp_lshd.o bn_mp_mod_2d.o bn_mp_div_2d.o bn_mp_mul_2d.o bn_mp_div_2.o \
bn_mp_mul_2.o bn_s_mp_add.o bn_s_mp_sub.o bn_fast_s_mp_mul_digs.o bn_s_mp_mul_digs.o \
bn_fast_s_mp_mul_high_digs.o bn_s_mp_mul_high_digs.o bn_fast_s_mp_sqr.o bn_s_mp_sqr.o \
bn_mp_add.o bn_mp_sub.o bn_mp_karatsuba_mul.o bn_mp_mul.o bn_mp_karatsuba_sqr.o \
bn_mp_sqr.o bn_mp_div.o bn_mp_mod.o bn_mp_add_d.o bn_mp_sub_d.o bn_mp_mul_d.o \
bn_mp_div_d.o bn_mp_mod_d.o bn_mp_expt_d.o bn_mp_addmod.o bn_mp_submod.o \
bn_mp_mulmod.o bn_mp_sqrmod.o bn_mp_gcd.o bn_mp_lcm.o bn_fast_mp_invmod.o bn_mp_invmod.o \
bn_mp_reduce.o bn_mp_montgomery_setup.o bn_fast_mp_montgomery_reduce.o bn_mp_montgomery_reduce.o \
bn_mp_exptmod_fast.o bn_mp_exptmod.o bn_mp_2expt.o bn_mp_n_root.o bn_mp_jacobi.o bn_reverse.o \
bn_mp_count_bits.o bn_mp_read_unsigned_bin.o bn_mp_read_signed_bin.o bn_mp_to_unsigned_bin.o \
bn_mp_to_signed_bin.o bn_mp_unsigned_bin_size.o bn_mp_signed_bin_size.o \
bn_mp_xor.o bn_mp_and.o bn_mp_or.o bn_mp_rand.o bn_mp_montgomery_calc_normalization.o \
bn_mp_prime_is_divisible.o bn_prime_tab.o bn_mp_prime_fermat.o bn_mp_prime_miller_rabin.o \
bn_mp_prime_is_prime.o bn_mp_prime_next_prime.o bn_mp_dr_reduce.o \
bn_mp_dr_is_modulus.o bn_mp_dr_setup.o bn_mp_reduce_setup.o \
bn_mp_toom_mul.o bn_mp_toom_sqr.o bn_mp_div_3.o bn_s_mp_exptmod.o \
bn_mp_reduce_2k.o bn_mp_reduce_is_2k.o bn_mp_reduce_2k_setup.o \
bn_mp_radix_smap.o bn_mp_read_radix.o bn_mp_toradix.o bn_mp_radix_size.o \
bn_mp_fread.o bn_mp_fwrite.o bn_mp_cnt_lsb.o bn_error.o \
bn_mp_init_multi.o bn_mp_clear_multi.o bn_mp_prime_random.o bn_prime_sizes_tab.o
# make a Windows DLL via Cygwin
windll: $(OBJECTS)
gcc -mno-cygwin -mdll -o libtommath.dll -Wl,--out-implib=libtommath.dll.a -Wl,--export-all-symbols *.o
ranlib libtommath.dll.a
# build the test program using the windows DLL
test: $(OBJECTS) windll
gcc $(CFLAGS) demo/demo.c libtommath.dll.a -Wl,--enable-auto-import -o test -s
cd mtest ; $(CC) -O3 -fomit-frame-pointer -funroll-loops mtest.c -o mtest -s

View File

@ -2,7 +2,7 @@
# #
#Tom St Denis #Tom St Denis
CFLAGS = /I. /Ox /DWIN32 /W3 CFLAGS = /I. /Ox /DWIN32 /W4
default: library default: library
@ -28,7 +28,7 @@ bn_mp_toom_mul.obj bn_mp_toom_sqr.obj bn_mp_div_3.obj bn_s_mp_exptmod.obj \
bn_mp_reduce_2k.obj bn_mp_reduce_is_2k.obj bn_mp_reduce_2k_setup.obj \ bn_mp_reduce_2k.obj bn_mp_reduce_is_2k.obj bn_mp_reduce_2k_setup.obj \
bn_mp_radix_smap.obj bn_mp_read_radix.obj bn_mp_toradix.obj bn_mp_radix_size.obj \ bn_mp_radix_smap.obj bn_mp_read_radix.obj bn_mp_toradix.obj bn_mp_radix_size.obj \
bn_mp_fread.obj bn_mp_fwrite.obj bn_mp_cnt_lsb.obj bn_error.obj \ bn_mp_fread.obj bn_mp_fwrite.obj bn_mp_cnt_lsb.obj bn_error.obj \
bn_mp_init_multi.obj bn_mp_clear_multi.obj bn_mp_init_multi.obj bn_mp_clear_multi.obj bn_mp_prime_random.obj bn_prime_sizes_tab.obj
library: $(OBJECTS) library: $(OBJECTS)
lib /out:tommath.lib $(OBJECTS) lib /out:tommath.lib $(OBJECTS)

View File

@ -1,23 +0,0 @@
#include <stdio.h>
#include "mpi.c"
int main(void)
{
mp_int a, b;
int ix;
char buf[1024];
mp_init(&a);
mp_init(&b);
mp_set(&a, 0x1B);
mp_neg(&a, &a);
ix = 0;
mp_add_d(&a, ix, &b);
mp_toradix(&b, buf, 64);
printf("b == %s\n", buf);
return 0;
}

BIN
pics/design_process.tif Normal file

Binary file not shown.

BIN
pics/expt_state.tif Normal file

Binary file not shown.

BIN
pics/primality.tif Normal file

Binary file not shown.

BIN
pics/radix.sxd Normal file

Binary file not shown.

BIN
pics/sliding_window.tif Normal file

Binary file not shown.

Binary file not shown.

View File

@ -2,7 +2,6 @@
\usepackage{amsmath, amssymb} \usepackage{amsmath, amssymb}
\usepackage{hyperref} \usepackage{hyperref}
\begin{document} \begin{document}
\hspace*{-3in} \hspace*{-3in}
\begin{tabular}{llllll} \begin{tabular}{llllll}
$c = a + b$ & {\tt mp\_add(\&a, \&b, \&c)} & $b = 2a$ & {\tt mp\_mul\_2(\&a, \&b)} & \\ $c = a + b$ & {\tt mp\_add(\&a, \&b, \&c)} & $b = 2a$ & {\tt mp\_mul\_2(\&a, \&b)} & \\

View File

@ -72,11 +72,8 @@ fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c)
mp_int x, y, u, v, B, D; mp_int x, y, u, v, B, D;
int res, neg; int res, neg;
/* 2. [modified] if a,b are both even then return an error! /* 2. [modified] b must be odd */
* if (mp_iseven (b) == 1) {
* That is if gcd(a,b) = 2**k * q then obviously there is no inverse.
*/
if (mp_iseven (a) == 1 && mp_iseven (b) == 1) {
return MP_VAL; return MP_VAL;
} }
@ -269,7 +266,7 @@ fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
* that W[ix-1] have the carry cleared (see after the inner loop) * that W[ix-1] have the carry cleared (see after the inner loop)
*/ */
register mp_digit mu; register mp_digit mu;
mu = ((W[ix] & MP_MASK) * rho) & MP_MASK; mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK);
/* a = a + mu * m * b**i /* a = a + mu * m * b**i
* *
@ -849,8 +846,7 @@ mp_abs (mp_int * a, mp_int * b)
#include <tommath.h> #include <tommath.h>
/* high level addition (handles signs) */ /* high level addition (handles signs) */
int int mp_add (mp_int * a, mp_int * b, mp_int * c)
mp_add (mp_int * a, mp_int * b, mp_int * c)
{ {
int sa, sb, res; int sa, sb, res;
@ -1153,7 +1149,7 @@ mp_clear (mp_int * a)
memset (a->dp, 0, sizeof (mp_digit) * a->used); memset (a->dp, 0, sizeof (mp_digit) * a->used);
/* free ram */ /* free ram */
free (a->dp); XFREE(a->dp);
/* reset members to make debugging easier */ /* reset members to make debugging easier */
a->dp = NULL; a->dp = NULL;
@ -1255,8 +1251,7 @@ mp_cmp (mp_int * a, mp_int * b)
#include <tommath.h> #include <tommath.h>
/* compare a digit */ /* compare a digit */
int int mp_cmp_d(mp_int * a, mp_digit b)
mp_cmp_d (mp_int * a, mp_digit b)
{ {
/* compare based on sign */ /* compare based on sign */
if (a->sign == MP_NEG) { if (a->sign == MP_NEG) {
@ -1298,8 +1293,7 @@ mp_cmp_d (mp_int * a, mp_digit b)
#include <tommath.h> #include <tommath.h>
/* compare maginitude of two ints (unsigned) */ /* compare maginitude of two ints (unsigned) */
int int mp_cmp_mag (mp_int * a, mp_int * b)
mp_cmp_mag (mp_int * a, mp_int * b)
{ {
int n; int n;
mp_digit *tmpa, *tmpb; mp_digit *tmpa, *tmpb;
@ -1518,8 +1512,7 @@ mp_count_bits (mp_int * a)
* The overall algorithm is as described as * The overall algorithm is as described as
* 14.20 from HAC but fixed to treat these cases. * 14.20 from HAC but fixed to treat these cases.
*/ */
int int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
{ {
mp_int q, x, y, t1, t2; mp_int q, x, y, t1, t2;
int res, n, t, i, norm, neg; int res, n, t, i, norm, neg;
@ -1722,8 +1715,7 @@ __Q:mp_clear (&q);
#include <tommath.h> #include <tommath.h>
/* b = a/2 */ /* b = a/2 */
int int mp_div_2(mp_int * a, mp_int * b)
mp_div_2 (mp_int * a, mp_int * b)
{ {
int x, res, oldused; int x, res, oldused;
@ -1789,8 +1781,7 @@ mp_div_2 (mp_int * a, mp_int * b)
#include <tommath.h> #include <tommath.h>
/* shift right by a certain bit count (store quotient in c, optional remainder in d) */ /* shift right by a certain bit count (store quotient in c, optional remainder in d) */
int int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d)
mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d)
{ {
mp_digit D, r, rr; mp_digit D, r, rr;
int x, res; int x, res;
@ -2028,7 +2019,7 @@ mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d)
if (w >= b) { if (w >= b) {
t = (mp_digit)(w / b); t = (mp_digit)(w / b);
w = w % b; w -= ((mp_word)t) * ((mp_word)b);
} else { } else {
t = 0; t = 0;
} }
@ -2264,8 +2255,7 @@ mp_exch (mp_int * a, mp_int * b)
#include <tommath.h> #include <tommath.h>
/* calculate c = a**b using a square-multiply algorithm */ /* calculate c = a**b using a square-multiply algorithm */
int int mp_expt_d (mp_int * a, mp_digit b, mp_int * c)
mp_expt_d (mp_int * a, mp_digit b, mp_int * c)
{ {
int res, x; int res, x;
mp_int g; mp_int g;
@ -2325,8 +2315,7 @@ mp_expt_d (mp_int * a, mp_digit b, mp_int * c)
* embedded in the normal function but that wasted alot of stack space * embedded in the normal function but that wasted alot of stack space
* for nothing (since 99% of the time the Montgomery code would be called) * for nothing (since 99% of the time the Montgomery code would be called)
*/ */
int int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
{ {
int dr; int dr;
@ -2768,24 +2757,24 @@ int mp_fwrite(mp_int *a, int radix, FILE *stream)
return MP_VAL; return MP_VAL;
} }
buf = malloc(len); buf = XMALLOC (len);
if (buf == NULL) { if (buf == NULL) {
return MP_MEM; return MP_MEM;
} }
if ((err = mp_toradix(a, buf, radix)) != MP_OKAY) { if ((err = mp_toradix(a, buf, radix)) != MP_OKAY) {
free(buf); XFREE (buf);
return err; return err;
} }
for (x = 0; x < len; x++) { for (x = 0; x < len; x++) {
if (fputc(buf[x], stream) == EOF) { if (fputc(buf[x], stream) == EOF) {
free(buf); XFREE (buf);
return MP_VAL; return MP_VAL;
} }
} }
free(buf); XFREE (buf);
return MP_OKAY; return MP_OKAY;
} }
@ -2810,8 +2799,7 @@ int mp_fwrite(mp_int *a, int radix, FILE *stream)
#include <tommath.h> #include <tommath.h>
/* Greatest Common Divisor using the binary method */ /* Greatest Common Divisor using the binary method */
int int mp_gcd (mp_int * a, mp_int * b, mp_int * c)
mp_gcd (mp_int * a, mp_int * b, mp_int * c)
{ {
mp_int u, v; mp_int u, v;
int k, u_lsb, v_lsb, res; int k, u_lsb, v_lsb, res;
@ -2922,13 +2910,11 @@ __U:mp_clear (&v);
#include <tommath.h> #include <tommath.h>
/* grow as required */ /* grow as required */
int int mp_grow (mp_int * a, int size)
mp_grow (mp_int * a, int size)
{ {
int i; int i;
mp_digit *tmp; mp_digit *tmp;
/* if the alloc size is smaller alloc more ram */ /* if the alloc size is smaller alloc more ram */
if (a->alloc < size) { if (a->alloc < size) {
/* ensure there are always at least MP_PREC digits extra on top */ /* ensure there are always at least MP_PREC digits extra on top */
@ -2940,7 +2926,7 @@ mp_grow (mp_int * a, int size)
* in case the operation failed we don't want * in case the operation failed we don't want
* to overwrite the dp member of a. * to overwrite the dp member of a.
*/ */
tmp = OPT_CAST realloc (a->dp, sizeof (mp_digit) * size); tmp = OPT_CAST XREALLOC (a->dp, sizeof (mp_digit) * size);
if (tmp == NULL) { if (tmp == NULL) {
/* reallocation failed but "a" is still valid [can be freed] */ /* reallocation failed but "a" is still valid [can be freed] */
return MP_MEM; return MP_MEM;
@ -2979,11 +2965,10 @@ mp_grow (mp_int * a, int size)
#include <tommath.h> #include <tommath.h>
/* init a new bigint */ /* init a new bigint */
int int mp_init (mp_int * a)
mp_init (mp_int * a)
{ {
/* allocate memory required and clear it */ /* allocate memory required and clear it */
a->dp = OPT_CAST calloc (sizeof (mp_digit), MP_PREC); a->dp = OPT_CAST XCALLOC (sizeof (mp_digit), MP_PREC);
if (a->dp == NULL) { if (a->dp == NULL) {
return MP_MEM; return MP_MEM;
} }
@ -3017,8 +3002,7 @@ mp_init (mp_int * a)
#include <tommath.h> #include <tommath.h>
/* creates "a" then copies b into it */ /* creates "a" then copies b into it */
int int mp_init_copy (mp_int * a, mp_int * b)
mp_init_copy (mp_int * a, mp_int * b)
{ {
int res; int res;
@ -3105,14 +3089,13 @@ int mp_init_multi(mp_int *mp, ...)
#include <tommath.h> #include <tommath.h>
/* init an mp_init for a given size */ /* init an mp_init for a given size */
int int mp_init_size (mp_int * a, int size)
mp_init_size (mp_int * a, int size)
{ {
/* pad size so there are always extra digits */ /* pad size so there are always extra digits */
size += (MP_PREC * 2) - (size % MP_PREC); size += (MP_PREC * 2) - (size % MP_PREC);
/* alloc mem */ /* alloc mem */
a->dp = OPT_CAST calloc (sizeof (mp_digit), size); a->dp = OPT_CAST XCALLOC (sizeof (mp_digit), size);
if (a->dp == NULL) { if (a->dp == NULL) {
return MP_MEM; return MP_MEM;
} }
@ -3143,8 +3126,7 @@ mp_init_size (mp_int * a, int size)
#include <tommath.h> #include <tommath.h>
/* hac 14.61, pp608 */ /* hac 14.61, pp608 */
int int mp_invmod (mp_int * a, mp_int * b, mp_int * c)
mp_invmod (mp_int * a, mp_int * b, mp_int * c)
{ {
mp_int x, y, u, v, A, B, C, D; mp_int x, y, u, v, A, B, C, D;
int res; int res;
@ -3324,8 +3306,7 @@ __ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL);
/* computes the jacobi c = (a | n) (or Legendre if n is prime) /* computes the jacobi c = (a | n) (or Legendre if n is prime)
* HAC pp. 73 Algorithm 2.149 * HAC pp. 73 Algorithm 2.149
*/ */
int int mp_jacobi (mp_int * a, mp_int * p, int *c)
mp_jacobi (mp_int * a, mp_int * p, int *c)
{ {
mp_int a1, p1; mp_int a1, p1;
int k, s, r, res; int k, s, r, res;
@ -3715,8 +3696,7 @@ ERR:
#include <tommath.h> #include <tommath.h>
/* computes least common multiple as |a*b|/(a, b) */ /* computes least common multiple as |a*b|/(a, b) */
int int mp_lcm (mp_int * a, mp_int * b, mp_int * c)
mp_lcm (mp_int * a, mp_int * b, mp_int * c)
{ {
int res; int res;
mp_int t1, t2; mp_int t1, t2;
@ -3774,8 +3754,7 @@ __T:
#include <tommath.h> #include <tommath.h>
/* shift left a certain amount of digits */ /* shift left a certain amount of digits */
int int mp_lshd (mp_int * a, int b)
mp_lshd (mp_int * a, int b)
{ {
int x, res; int x, res;
@ -4058,7 +4037,7 @@ mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
* following inner loop to reduce the * following inner loop to reduce the
* input one digit at a time * input one digit at a time
*/ */
mu = ((mp_word)x->dp[ix]) * ((mp_word)rho) & MP_MASK; mu = (mp_digit) (((mp_word)x->dp[ix]) * ((mp_word)rho) & MP_MASK);
/* a = a + mu * m * b**i */ /* a = a + mu * m * b**i */
{ {
@ -4195,8 +4174,7 @@ mp_montgomery_setup (mp_int * n, mp_digit * rho)
#include <tommath.h> #include <tommath.h>
/* high level multiplication (handles sign) */ /* high level multiplication (handles sign) */
int int mp_mul (mp_int * a, mp_int * b, mp_int * c)
mp_mul (mp_int * a, mp_int * b, mp_int * c)
{ {
int res, neg; int res, neg;
neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
@ -4249,8 +4227,7 @@ mp_mul (mp_int * a, mp_int * b, mp_int * c)
#include <tommath.h> #include <tommath.h>
/* b = a*2 */ /* b = a*2 */
int int mp_mul_2(mp_int * a, mp_int * b)
mp_mul_2 (mp_int * a, mp_int * b)
{ {
int x, res, oldused; int x, res, oldused;
@ -4330,8 +4307,7 @@ mp_mul_2 (mp_int * a, mp_int * b)
#include <tommath.h> #include <tommath.h>
/* shift left by a certain bit count */ /* shift left by a certain bit count */
int int mp_mul_2d (mp_int * a, int b, mp_int * c)
mp_mul_2d (mp_int * a, int b, mp_int * c)
{ {
mp_digit d; mp_digit d;
int res; int res;
@ -4496,7 +4472,6 @@ mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
int res; int res;
mp_int t; mp_int t;
if ((res = mp_init (&t)) != MP_OKAY) { if ((res = mp_init (&t)) != MP_OKAY) {
return res; return res;
} }
@ -4539,8 +4514,7 @@ mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
* each step involves a fair bit. This is not meant to * each step involves a fair bit. This is not meant to
* find huge roots [square and cube, etc]. * find huge roots [square and cube, etc].
*/ */
int int mp_n_root (mp_int * a, mp_digit b, mp_int * c)
mp_n_root (mp_int * a, mp_digit b, mp_int * c)
{ {
mp_int t1, t2, t3; mp_int t1, t2, t3;
int res, neg; int res, neg;
@ -4661,8 +4635,7 @@ __T1:mp_clear (&t1);
#include <tommath.h> #include <tommath.h>
/* b = -a */ /* b = -a */
int int mp_neg (mp_int * a, mp_int * b)
mp_neg (mp_int * a, mp_int * b)
{ {
int res; int res;
if ((res = mp_copy (a, b)) != MP_OKAY) { if ((res = mp_copy (a, b)) != MP_OKAY) {
@ -4694,8 +4667,7 @@ mp_neg (mp_int * a, mp_int * b)
#include <tommath.h> #include <tommath.h>
/* OR two ints together */ /* OR two ints together */
int int mp_or (mp_int * a, mp_int * b, mp_int * c)
mp_or (mp_int * a, mp_int * b, mp_int * c)
{ {
int res, ix, px; int res, ix, px;
mp_int t, *x; mp_int t, *x;
@ -4750,14 +4722,13 @@ mp_or (mp_int * a, mp_int * b, mp_int * c)
* *
* Sets result to 1 if the congruence holds, or zero otherwise. * Sets result to 1 if the congruence holds, or zero otherwise.
*/ */
int int mp_prime_fermat (mp_int * a, mp_int * b, int *result)
mp_prime_fermat (mp_int * a, mp_int * b, int *result)
{ {
mp_int t; mp_int t;
int err; int err;
/* default to composite */ /* default to composite */
*result = 0; *result = MP_NO;
/* ensure b > 1 */ /* ensure b > 1 */
if (mp_cmp_d(b, 1) != MP_GT) { if (mp_cmp_d(b, 1) != MP_GT) {
@ -4776,7 +4747,7 @@ mp_prime_fermat (mp_int * a, mp_int * b, int *result)
/* is it equal to b? */ /* is it equal to b? */
if (mp_cmp (&t, b) == MP_EQ) { if (mp_cmp (&t, b) == MP_EQ) {
*result = 1; *result = MP_YES;
} }
err = MP_OKAY; err = MP_OKAY;
@ -4808,14 +4779,13 @@ __T:mp_clear (&t);
* *
* sets result to 0 if not, 1 if yes * sets result to 0 if not, 1 if yes
*/ */
int int mp_prime_is_divisible (mp_int * a, int *result)
mp_prime_is_divisible (mp_int * a, int *result)
{ {
int err, ix; int err, ix;
mp_digit res; mp_digit res;
/* default to not */ /* default to not */
*result = 0; *result = MP_NO;
for (ix = 0; ix < PRIME_SIZE; ix++) { for (ix = 0; ix < PRIME_SIZE; ix++) {
/* what is a mod __prime_tab[ix] */ /* what is a mod __prime_tab[ix] */
@ -4825,7 +4795,7 @@ mp_prime_is_divisible (mp_int * a, int *result)
/* is the residue zero? */ /* is the residue zero? */
if (res == 0) { if (res == 0) {
*result = 1; *result = MP_YES;
return MP_OKAY; return MP_OKAY;
} }
} }
@ -4859,14 +4829,13 @@ mp_prime_is_divisible (mp_int * a, int *result)
* *
* Sets result to 1 if probably prime, 0 otherwise * Sets result to 1 if probably prime, 0 otherwise
*/ */
int int mp_prime_is_prime (mp_int * a, int t, int *result)
mp_prime_is_prime (mp_int * a, int t, int *result)
{ {
mp_int b; mp_int b;
int ix, err, res; int ix, err, res;
/* default to no */ /* default to no */
*result = 0; *result = MP_NO;
/* valid value of t? */ /* valid value of t? */
if (t <= 0 || t > PRIME_SIZE) { if (t <= 0 || t > PRIME_SIZE) {
@ -4887,7 +4856,7 @@ mp_prime_is_prime (mp_int * a, int t, int *result)
} }
/* return if it was trivially divisible */ /* return if it was trivially divisible */
if (res == 1) { if (res == MP_YES) {
return MP_OKAY; return MP_OKAY;
} }
@ -4904,13 +4873,13 @@ mp_prime_is_prime (mp_int * a, int t, int *result)
goto __B; goto __B;
} }
if (res == 0) { if (res == MP_NO) {
goto __B; goto __B;
} }
} }
/* passed the test */ /* passed the test */
*result = 1; *result = MP_YES;
__B:mp_clear (&b); __B:mp_clear (&b);
return err; return err;
} }
@ -4941,14 +4910,13 @@ __B:mp_clear (&b);
* Randomly the chance of error is no more than 1/4 and often * Randomly the chance of error is no more than 1/4 and often
* very much lower. * very much lower.
*/ */
int int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result)
mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result)
{ {
mp_int n1, y, r; mp_int n1, y, r;
int s, j, err; int s, j, err;
/* default */ /* default */
*result = 0; *result = MP_NO;
/* ensure b > 1 */ /* ensure b > 1 */
if (mp_cmp_d(b, 1) != MP_GT) { if (mp_cmp_d(b, 1) != MP_GT) {
@ -5010,7 +4978,7 @@ mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result)
} }
/* probably prime now */ /* probably prime now */
*result = 1; *result = MP_YES;
__Y:mp_clear (&y); __Y:mp_clear (&y);
__R:mp_clear (&r); __R:mp_clear (&r);
__N1:mp_clear (&n1); __N1:mp_clear (&n1);
@ -5168,12 +5136,12 @@ int mp_prime_next_prime(mp_int *a, int t, int bbs_style)
if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) { if ((err = mp_prime_miller_rabin(a, &b, &res)) != MP_OKAY) {
goto __ERR; goto __ERR;
} }
if (res == 0) { if (res == MP_NO) {
break; break;
} }
} }
if (res == 1) { if (res == MP_YES) {
break; break;
} }
} }
@ -5187,6 +5155,84 @@ __ERR:
/* End: bn_mp_prime_next_prime.c */ /* End: bn_mp_prime_next_prime.c */
/* Start: bn_mp_prime_random.c */
/* LibTomMath, multiple-precision integer library -- Tom St Denis
*
* LibTomMath is a library that provides multiple-precision
* integer arithmetic as well as number theoretic functionality.
*
* The library was designed directly after the MPI library by
* Michael Fromberger but has been written from scratch with
* additional optimizations in place.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
*/
#include <tommath.h>
/* makes a truly random prime of a given size (bytes),
* call with bbs = 1 if you want it to be congruent to 3 mod 4
*
* You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can
* have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself
* so it can be NULL
*
* The prime generated will be larger than 2^(8*size).
*/
/* this sole function may hold the key to enslaving all mankind! */
int mp_prime_random(mp_int *a, int t, int size, int bbs, ltm_prime_callback cb, void *dat)
{
unsigned char *tmp;
int res, err;
/* sanity check the input */
if (size <= 0) {
return MP_VAL;
}
/* we need a buffer of size+1 bytes */
tmp = XMALLOC(size+1);
if (tmp == NULL) {
return MP_MEM;
}
/* fix MSB */
tmp[0] = 1;
do {
/* read the bytes */
if (cb(tmp+1, size, dat) != size) {
err = MP_VAL;
goto error;
}
/* fix the LSB */
tmp[size] |= (bbs ? 3 : 1);
/* read it in */
if ((err = mp_read_unsigned_bin(a, tmp, size+1)) != MP_OKAY) {
goto error;
}
/* is it prime? */
if ((err = mp_prime_is_prime(a, t, &res)) != MP_OKAY) {
goto error;
}
} while (res == MP_NO);
err = MP_OKAY;
error:
XFREE(tmp);
return err;
}
/* End: bn_mp_prime_random.c */
/* Start: bn_mp_radix_size.c */ /* Start: bn_mp_radix_size.c */
/* LibTomMath, multiple-precision integer library -- Tom St Denis /* LibTomMath, multiple-precision integer library -- Tom St Denis
* *
@ -5217,28 +5263,36 @@ mp_radix_size (mp_int * a, int radix)
return mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1; return mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1;
} }
/* make sure the radix is in range */
if (radix < 2 || radix > 64) { if (radix < 2 || radix > 64) {
return 0; return 0;
} }
/* init a copy of the input */
if ((res = mp_init_copy (&t, a)) != MP_OKAY) { if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
return 0; return 0;
} }
/* digs is the digit count */
digs = 0; digs = 0;
/* if it's negative add one for the sign */
if (t.sign == MP_NEG) { if (t.sign == MP_NEG) {
++digs; ++digs;
t.sign = MP_ZPOS; t.sign = MP_ZPOS;
} }
/* fetch out all of the digits */
while (mp_iszero (&t) == 0) { while (mp_iszero (&t) == 0) {
if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) {
mp_clear (&t); mp_clear (&t);
return 0; return res;
} }
++digs; ++digs;
} }
mp_clear (&t); mp_clear (&t);
/* return digs + 1, the 1 is for the NULL byte that would be required. */
return digs + 1; return digs + 1;
} }
@ -5707,10 +5761,9 @@ mp_reduce_2k_setup(mp_int *a, mp_digit *d)
#include <tommath.h> #include <tommath.h>
/* determines if mp_reduce_2k can be used */ /* determines if mp_reduce_2k can be used */
int int mp_reduce_is_2k(mp_int *a)
mp_reduce_is_2k(mp_int *a)
{ {
int ix, iy; int ix, iy, iz, iw;
if (a->used == 0) { if (a->used == 0) {
return 0; return 0;
@ -5718,11 +5771,19 @@ mp_reduce_is_2k(mp_int *a)
return 1; return 1;
} else if (a->used > 1) { } else if (a->used > 1) {
iy = mp_count_bits(a); iy = mp_count_bits(a);
iz = 1;
iw = 1;
/* Test every bit from the second digit up, must be 1 */
for (ix = DIGIT_BIT; ix < iy; ix++) { for (ix = DIGIT_BIT; ix < iy; ix++) {
if ((a->dp[ix/DIGIT_BIT] & if ((a->dp[iw] & iz) == 0) {
((mp_digit)1 << (mp_digit)(ix % DIGIT_BIT))) == 0) {
return 0; return 0;
} }
iz <<= 1;
if (iz > (int)MP_MASK) {
++iw;
iz = 1;
}
} }
} }
return 1; return 1;
@ -5782,8 +5843,7 @@ mp_reduce_setup (mp_int * a, mp_int * b)
#include <tommath.h> #include <tommath.h>
/* shift right a certain amount of digits */ /* shift right a certain amount of digits */
void void mp_rshd (mp_int * a, int b)
mp_rshd (mp_int * a, int b)
{ {
int x; int x;
@ -5853,8 +5913,7 @@ mp_rshd (mp_int * a, int b)
#include <tommath.h> #include <tommath.h>
/* set to a digit */ /* set to a digit */
void void mp_set (mp_int * a, mp_digit b)
mp_set (mp_int * a, mp_digit b)
{ {
mp_zero (a); mp_zero (a);
a->dp[0] = b & MP_MASK; a->dp[0] = b & MP_MASK;
@ -5881,8 +5940,7 @@ mp_set (mp_int * a, mp_digit b)
#include <tommath.h> #include <tommath.h>
/* set a 32-bit const */ /* set a 32-bit const */
int int mp_set_int (mp_int * a, unsigned long b)
mp_set_int (mp_int * a, unsigned int b)
{ {
int x, res; int x, res;
@ -5928,13 +5986,14 @@ mp_set_int (mp_int * a, unsigned int b)
#include <tommath.h> #include <tommath.h>
/* shrink a bignum */ /* shrink a bignum */
int int mp_shrink (mp_int * a)
mp_shrink (mp_int * a)
{ {
mp_digit *tmp;
if (a->alloc != a->used) { if (a->alloc != a->used) {
if ((a->dp = OPT_CAST realloc (a->dp, sizeof (mp_digit) * a->used)) == NULL) { if ((tmp = OPT_CAST XREALLOC (a->dp, sizeof (mp_digit) * a->used)) == NULL) {
return MP_MEM; return MP_MEM;
} }
a->dp = tmp;
a->alloc = a->used; a->alloc = a->used;
} }
return MP_OKAY; return MP_OKAY;
@ -6841,6 +6900,7 @@ mp_toradix (mp_int * a, char *str, int radix)
mp_digit d; mp_digit d;
char *_s = str; char *_s = str;
/* check range of the radix */
if (radix < 2 || radix > 64) { if (radix < 2 || radix > 64) {
return MP_VAL; return MP_VAL;
} }
@ -6879,8 +6939,7 @@ mp_toradix (mp_int * a, char *str, int radix)
bn_reverse ((unsigned char *)_s, digs); bn_reverse ((unsigned char *)_s, digs);
/* append a NULL so the string is properly terminated */ /* append a NULL so the string is properly terminated */
*str++ = '\0'; *str = '\0';
mp_clear (&t); mp_clear (&t);
return MP_OKAY; return MP_OKAY;
@ -6993,6 +7052,79 @@ mp_zero (mp_int * a)
/* End: bn_mp_zero.c */ /* End: bn_mp_zero.c */
/* Start: bn_prime_sizes_tab.c */
/* LibTomMath, multiple-precision integer library -- Tom St Denis
*
* LibTomMath is a library that provides multiple-precision
* integer arithmetic as well as number theoretic functionality.
*
* The library was designed directly after the MPI library by
* Michael Fromberger but has been written from scratch with
* additional optimizations in place.
*
* The library is free for all purposes without any express
* guarantee it works.
*
* Tom St Denis, tomstdenis@iahu.ca, http://math.libtomcrypt.org
*/
#include <tommath.h>
/* this table gives the # of rabin miller trials for a prob of failure lower than 2^-96 */
static const struct {
int k, t;
} sizes[] = {
{ 128, 28 },
{ 256, 16 },
{ 384, 10 },
{ 512, 7 },
{ 640, 6 },
{ 768, 5 },
{ 896, 4 },
{ 1024, 4 },
{ 1152, 3 },
{ 1280, 3 },
{ 1408, 3 },
{ 1536, 3 },
{ 1664, 3 },
{ 1792, 2 },
{ 1920, 2 },
{ 2048, 2 },
{ 2176, 2 },
{ 2304, 2 },
{ 2432, 2 },
{ 2560, 2 },
{ 2688, 2 },
{ 2816, 2 },
{ 2944, 2 },
{ 3072, 2 },
{ 3200, 2 },
{ 3328, 2 },
{ 3456, 2 },
{ 3584, 2 },
{ 3712, 2 },
{ 3840, 1 },
{ 3968, 1 },
{ 4096, 1 } };
/* returns # of RM trials required for a given bit size */
int mp_prime_rabin_miller_trials(int size)
{
int x;
for (x = 0; x < (int)(sizeof(sizes)/(sizeof(sizes[0]))); x++) {
if (sizes[x].k == size) {
return sizes[x].t;
} else if (sizes[x].k > size) {
return (x == 0) ? sizes[0].t : sizes[x - 1].t;
}
}
return 1;
}
/* End: bn_prime_sizes_tab.c */
/* Start: bn_prime_tab.c */ /* Start: bn_prime_tab.c */
/* LibTomMath, multiple-precision integer library -- Tom St Denis /* LibTomMath, multiple-precision integer library -- Tom St Denis
* *
@ -7631,6 +7763,8 @@ s_mp_sqr (mp_int * a, mp_int * b)
if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) { if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) {
return res; return res;
} }
/* default used is maximum possible size */
t.used = 2*pa + 1; t.used = 2*pa + 1;
for (ix = 0; ix < pa; ix++) { for (ix = 0; ix < pa; ix++) {
@ -7640,20 +7774,20 @@ s_mp_sqr (mp_int * a, mp_int * b)
((mp_word)a->dp[ix])*((mp_word)a->dp[ix]); ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]);
/* store lower part in result */ /* store lower part in result */
t.dp[2*ix] = (mp_digit) (r & ((mp_word) MP_MASK)); t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK));
/* get the carry */ /* get the carry */
u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); u = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
/* left hand side of A[ix] * A[iy] */ /* left hand side of A[ix] * A[iy] */
tmpx = a->dp[ix]; tmpx = a->dp[ix];
/* alias for where to store the results */ /* alias for where to store the results */
tmpt = t.dp + (2*ix + 1); tmpt = t.dp + (2*ix + 1);
for (iy = ix + 1; iy < pa; iy++) { for (iy = ix + 1; iy < pa; iy++) {
/* first calculate the product */ /* first calculate the product */
r = ((mp_word)tmpx) * ((mp_word)a->dp[iy]); r = ((mp_word)tmpx) * ((mp_word)a->dp[iy]);
/* now calculate the double precision result, note we use /* now calculate the double precision result, note we use
* addition instead of *2 since it's easier to optimize * addition instead of *2 since it's easier to optimize

View File

@ -91,6 +91,24 @@ extern "C" {
#endif #endif
#endif #endif
/* define heap macros */
#ifndef CRYPT
/* default to libc stuff */
#ifndef XMALLOC
#define XMALLOC malloc
#define XFREE free
#define XREALLOC realloc
#define XCALLOC calloc
#endif
/* prototypes for our heap functions */
extern void *XMALLOC(size_t n);
extern void *REALLOC(void *p, size_t n);
extern void *XCALLOC(size_t n, size_t s);
extern void XFREE(void *p);
#endif
/* otherwise the bits per digit is calculated automatically from the size of a mp_digit */ /* otherwise the bits per digit is calculated automatically from the size of a mp_digit */
#ifndef DIGIT_BIT #ifndef DIGIT_BIT
#define DIGIT_BIT ((int)((CHAR_BIT * sizeof(mp_digit) - 1))) /* bits per digit */ #define DIGIT_BIT ((int)((CHAR_BIT * sizeof(mp_digit) - 1))) /* bits per digit */
@ -113,6 +131,9 @@ extern "C" {
#define MP_VAL -3 /* invalid input */ #define MP_VAL -3 /* invalid input */
#define MP_RANGE MP_VAL #define MP_RANGE MP_VAL
#define MP_YES 1 /* yes response */
#define MP_NO 0 /* no response */
typedef int mp_err; typedef int mp_err;
/* you'll have to tune these... */ /* you'll have to tune these... */
@ -130,11 +151,16 @@ extern int KARATSUBA_MUL_CUTOFF,
/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */ /* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */
#define MP_WARRAY (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1)) #define MP_WARRAY (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1))
/* the infamous mp_int structure */
typedef struct { typedef struct {
int used, alloc, sign; int used, alloc, sign;
mp_digit *dp; mp_digit *dp;
} mp_int; } mp_int;
/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */
typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);
#define USED(m) ((m)->used) #define USED(m) ((m)->used)
#define DIGIT(m,k) ((m)->dp[(k)]) #define DIGIT(m,k) ((m)->dp[(k)])
#define SIGN(m) ((m)->sign) #define SIGN(m) ((m)->sign)
@ -168,9 +194,9 @@ int mp_grow(mp_int *a, int size);
int mp_init_size(mp_int *a, int size); int mp_init_size(mp_int *a, int size);
/* ---> Basic Manipulations <--- */ /* ---> Basic Manipulations <--- */
#define mp_iszero(a) (((a)->used == 0) ? 1 : 0) #define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
#define mp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? 1 : 0) #define mp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
#define mp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? 1 : 0) #define mp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)
/* set to zero */ /* set to zero */
void mp_zero(mp_int *a); void mp_zero(mp_int *a);
@ -179,7 +205,7 @@ void mp_zero(mp_int *a);
void mp_set(mp_int *a, mp_digit b); void mp_set(mp_int *a, mp_digit b);
/* set a 32-bit const */ /* set a 32-bit const */
int mp_set_int(mp_int *a, unsigned int b); int mp_set_int(mp_int *a, unsigned long b);
/* copy, b = a */ /* copy, b = a */
int mp_copy(mp_int *a, mp_int *b); int mp_copy(mp_int *a, mp_int *b);
@ -219,6 +245,8 @@ int mp_2expt(mp_int *a, int b);
/* Counts the number of lsbs which are zero before the first zero bit */ /* Counts the number of lsbs which are zero before the first zero bit */
int mp_cnt_lsb(mp_int *a); int mp_cnt_lsb(mp_int *a);
/* I Love Earth! */
/* makes a pseudo-random int of a given size */ /* makes a pseudo-random int of a given size */
int mp_rand(mp_int *a, int digits); int mp_rand(mp_int *a, int digits);
@ -392,6 +420,11 @@ int mp_prime_fermat(mp_int *a, mp_int *b, int *result);
*/ */
int mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result); int mp_prime_miller_rabin(mp_int *a, mp_int *b, int *result);
/* This gives [for a given bit size] the number of trials required
* such that Miller-Rabin gives a prob of failure lower than 2^-96
*/
int mp_prime_rabin_miller_trials(int size);
/* performs t rounds of Miller-Rabin on "a" using the first /* performs t rounds of Miller-Rabin on "a" using the first
* t prime bases. Also performs an initial sieve of trial * t prime bases. Also performs an initial sieve of trial
* division. Determines if "a" is prime with probability * division. Determines if "a" is prime with probability
@ -408,6 +441,18 @@ int mp_prime_is_prime(mp_int *a, int t, int *result);
*/ */
int mp_prime_next_prime(mp_int *a, int t, int bbs_style); int mp_prime_next_prime(mp_int *a, int t, int bbs_style);
/* makes a truly random prime of a given size (bytes),
* call with bbs = 1 if you want it to be congruent to 3 mod 4
*
* You have to supply a callback which fills in a buffer with random bytes. "dat" is a parameter you can
* have passed to the callback (e.g. a state or something). This function doesn't use "dat" itself
* so it can be NULL
*
* The prime generated will be larger than 2^(8*size).
*/
int mp_prime_random(mp_int *a, int t, int size, int bbs, ltm_prime_callback cb, void *dat);
/* ---> radix conversion <--- */ /* ---> radix conversion <--- */
int mp_count_bits(mp_int *a); int mp_count_bits(mp_int *a);

139
tommath.out Normal file
View File

@ -0,0 +1,139 @@
\BOOKMARK [0][-]{chapter.1}{Introduction}{}
\BOOKMARK [1][-]{section.1.1}{Multiple Precision Arithmetic}{chapter.1}
\BOOKMARK [2][-]{subsection.1.1.1}{The Need for Multiple Precision Arithmetic}{section.1.1}
\BOOKMARK [2][-]{subsection.1.1.2}{What is Multiple Precision Arithmetic?}{section.1.1}
\BOOKMARK [2][-]{subsection.1.1.3}{Benefits of Multiple Precision Arithmetic}{section.1.1}
\BOOKMARK [1][-]{section.1.2}{Purpose of This Text}{chapter.1}
\BOOKMARK [1][-]{section.1.3}{Discussion and Notation}{chapter.1}
\BOOKMARK [2][-]{subsection.1.3.1}{Notation}{section.1.3}
\BOOKMARK [2][-]{subsection.1.3.2}{Precision Notation}{section.1.3}
\BOOKMARK [2][-]{subsection.1.3.3}{Algorithm Inputs and Outputs}{section.1.3}
\BOOKMARK [2][-]{subsection.1.3.4}{Mathematical Expressions}{section.1.3}
\BOOKMARK [2][-]{subsection.1.3.5}{Work Effort}{section.1.3}
\BOOKMARK [1][-]{section.1.4}{Exercises}{chapter.1}
\BOOKMARK [0][-]{chapter.2}{Introduction to LibTomMath}{}
\BOOKMARK [1][-]{section.2.1}{What is LibTomMath?}{chapter.2}
\BOOKMARK [1][-]{section.2.2}{Goals of LibTomMath}{chapter.2}
\BOOKMARK [1][-]{section.2.3}{Choice of LibTomMath}{chapter.2}
\BOOKMARK [2][-]{subsection.2.3.1}{Code Base}{section.2.3}
\BOOKMARK [2][-]{subsection.2.3.2}{API Simplicity}{section.2.3}
\BOOKMARK [2][-]{subsection.2.3.3}{Optimizations}{section.2.3}
\BOOKMARK [2][-]{subsection.2.3.4}{Portability and Stability}{section.2.3}
\BOOKMARK [2][-]{subsection.2.3.5}{Choice}{section.2.3}
\BOOKMARK [0][-]{chapter.3}{Getting Started}{}
\BOOKMARK [1][-]{section.3.1}{Library Basics}{chapter.3}
\BOOKMARK [1][-]{section.3.2}{What is a Multiple Precision Integer?}{chapter.3}
\BOOKMARK [2][-]{subsection.3.2.1}{The mp\137int Structure}{section.3.2}
\BOOKMARK [1][-]{section.3.3}{Argument Passing}{chapter.3}
\BOOKMARK [1][-]{section.3.4}{Return Values}{chapter.3}
\BOOKMARK [1][-]{section.3.5}{Initialization and Clearing}{chapter.3}
\BOOKMARK [2][-]{subsection.3.5.1}{Initializing an mp\137int}{section.3.5}
\BOOKMARK [2][-]{subsection.3.5.2}{Clearing an mp\137int}{section.3.5}
\BOOKMARK [1][-]{section.3.6}{Maintenance Algorithms}{chapter.3}
\BOOKMARK [2][-]{subsection.3.6.1}{Augmenting an mp\137int's Precision}{section.3.6}
\BOOKMARK [2][-]{subsection.3.6.2}{Initializing Variable Precision mp\137ints}{section.3.6}
\BOOKMARK [2][-]{subsection.3.6.3}{Multiple Integer Initializations and Clearings}{section.3.6}
\BOOKMARK [2][-]{subsection.3.6.4}{Clamping Excess Digits}{section.3.6}
\BOOKMARK [0][-]{chapter.4}{Basic Operations}{}
\BOOKMARK [1][-]{section.4.1}{Introduction}{chapter.4}
\BOOKMARK [1][-]{section.4.2}{Assigning Values to mp\137int Structures}{chapter.4}
\BOOKMARK [2][-]{subsection.4.2.1}{Copying an mp\137int}{section.4.2}
\BOOKMARK [2][-]{subsection.4.2.2}{Creating a Clone}{section.4.2}
\BOOKMARK [1][-]{section.4.3}{Zeroing an Integer}{chapter.4}
\BOOKMARK [1][-]{section.4.4}{Sign Manipulation}{chapter.4}
\BOOKMARK [2][-]{subsection.4.4.1}{Absolute Value}{section.4.4}
\BOOKMARK [2][-]{subsection.4.4.2}{Integer Negation}{section.4.4}
\BOOKMARK [1][-]{section.4.5}{Small Constants}{chapter.4}
\BOOKMARK [2][-]{subsection.4.5.1}{Setting Small Constants}{section.4.5}
\BOOKMARK [2][-]{subsection.4.5.2}{Setting Large Constants}{section.4.5}
\BOOKMARK [1][-]{section.4.6}{Comparisons}{chapter.4}
\BOOKMARK [2][-]{subsection.4.6.1}{Unsigned Comparisions}{section.4.6}
\BOOKMARK [2][-]{subsection.4.6.2}{Signed Comparisons}{section.4.6}
\BOOKMARK [0][-]{chapter.5}{Basic Arithmetic}{}
\BOOKMARK [1][-]{section.5.1}{Introduction}{chapter.5}
\BOOKMARK [1][-]{section.5.2}{Addition and Subtraction}{chapter.5}
\BOOKMARK [2][-]{subsection.5.2.1}{Low Level Addition}{section.5.2}
\BOOKMARK [2][-]{subsection.5.2.2}{Low Level Subtraction}{section.5.2}
\BOOKMARK [2][-]{subsection.5.2.3}{High Level Addition}{section.5.2}
\BOOKMARK [2][-]{subsection.5.2.4}{High Level Subtraction}{section.5.2}
\BOOKMARK [1][-]{section.5.3}{Bit and Digit Shifting}{chapter.5}
\BOOKMARK [2][-]{subsection.5.3.1}{Multiplication by Two}{section.5.3}
\BOOKMARK [2][-]{subsection.5.3.2}{Division by Two}{section.5.3}
\BOOKMARK [1][-]{section.5.4}{Polynomial Basis Operations}{chapter.5}
\BOOKMARK [2][-]{subsection.5.4.1}{Multiplication by x}{section.5.4}
\BOOKMARK [2][-]{subsection.5.4.2}{Division by x}{section.5.4}
\BOOKMARK [1][-]{section.5.5}{Powers of Two}{chapter.5}
\BOOKMARK [2][-]{subsection.5.5.1}{Multiplication by Power of Two}{section.5.5}
\BOOKMARK [2][-]{subsection.5.5.2}{Division by Power of Two}{section.5.5}
\BOOKMARK [2][-]{subsection.5.5.3}{Remainder of Division by Power of Two}{section.5.5}
\BOOKMARK [0][-]{chapter.6}{Multiplication and Squaring}{}
\BOOKMARK [1][-]{section.6.1}{The Multipliers}{chapter.6}
\BOOKMARK [1][-]{section.6.2}{Multiplication}{chapter.6}
\BOOKMARK [2][-]{subsection.6.2.1}{The Baseline Multiplication}{section.6.2}
\BOOKMARK [2][-]{subsection.6.2.2}{Faster Multiplication by the ``Comba'' Method}{section.6.2}
\BOOKMARK [2][-]{subsection.6.2.3}{Polynomial Basis Multiplication}{section.6.2}
\BOOKMARK [2][-]{subsection.6.2.4}{Karatsuba Multiplication}{section.6.2}
\BOOKMARK [2][-]{subsection.6.2.5}{Toom-Cook 3-Way Multiplication}{section.6.2}
\BOOKMARK [2][-]{subsection.6.2.6}{Signed Multiplication}{section.6.2}
\BOOKMARK [1][-]{section.6.3}{Squaring}{chapter.6}
\BOOKMARK [2][-]{subsection.6.3.1}{The Baseline Squaring Algorithm}{section.6.3}
\BOOKMARK [2][-]{subsection.6.3.2}{Faster Squaring by the ``Comba'' Method}{section.6.3}
\BOOKMARK [2][-]{subsection.6.3.3}{Polynomial Basis Squaring}{section.6.3}
\BOOKMARK [2][-]{subsection.6.3.4}{Karatsuba Squaring}{section.6.3}
\BOOKMARK [2][-]{subsection.6.3.5}{Toom-Cook Squaring}{section.6.3}
\BOOKMARK [2][-]{subsection.6.3.6}{High Level Squaring}{section.6.3}
\BOOKMARK [0][-]{chapter.7}{Modular Reduction}{}
\BOOKMARK [1][-]{section.7.1}{Basics of Modular Reduction}{chapter.7}
\BOOKMARK [1][-]{section.7.2}{The Barrett Reduction}{chapter.7}
\BOOKMARK [2][-]{subsection.7.2.1}{Fixed Point Arithmetic}{section.7.2}
\BOOKMARK [2][-]{subsection.7.2.2}{Choosing a Radix Point}{section.7.2}
\BOOKMARK [2][-]{subsection.7.2.3}{Trimming the Quotient}{section.7.2}
\BOOKMARK [2][-]{subsection.7.2.4}{Trimming the Residue}{section.7.2}
\BOOKMARK [2][-]{subsection.7.2.5}{The Barrett Algorithm}{section.7.2}
\BOOKMARK [2][-]{subsection.7.2.6}{The Barrett Setup Algorithm}{section.7.2}
\BOOKMARK [1][-]{section.7.3}{The Montgomery Reduction}{chapter.7}
\BOOKMARK [2][-]{subsection.7.3.1}{Digit Based Montgomery Reduction}{section.7.3}
\BOOKMARK [2][-]{subsection.7.3.2}{Baseline Montgomery Reduction}{section.7.3}
\BOOKMARK [2][-]{subsection.7.3.3}{Faster ``Comba'' Montgomery Reduction}{section.7.3}
\BOOKMARK [2][-]{subsection.7.3.4}{Montgomery Setup}{section.7.3}
\BOOKMARK [1][-]{section.7.4}{The Diminished Radix Algorithm}{chapter.7}
\BOOKMARK [2][-]{subsection.7.4.1}{Choice of Moduli}{section.7.4}
\BOOKMARK [2][-]{subsection.7.4.2}{Choice of k}{section.7.4}
\BOOKMARK [2][-]{subsection.7.4.3}{Restricted Diminished Radix Reduction}{section.7.4}
\BOOKMARK [2][-]{subsection.7.4.4}{Unrestricted Diminished Radix Reduction}{section.7.4}
\BOOKMARK [1][-]{section.7.5}{Algorithm Comparison}{chapter.7}
\BOOKMARK [0][-]{chapter.8}{Exponentiation}{}
\BOOKMARK [1][-]{section.8.1}{Exponentiation Basics}{chapter.8}
\BOOKMARK [2][-]{subsection.8.1.1}{Single Digit Exponentiation}{section.8.1}
\BOOKMARK [1][-]{section.8.2}{k-ary Exponentiation}{chapter.8}
\BOOKMARK [2][-]{subsection.8.2.1}{Optimal Values of k}{section.8.2}
\BOOKMARK [2][-]{subsection.8.2.2}{Sliding-Window Exponentiation}{section.8.2}
\BOOKMARK [1][-]{section.8.3}{Modular Exponentiation}{chapter.8}
\BOOKMARK [2][-]{subsection.8.3.1}{Barrett Modular Exponentiation}{section.8.3}
\BOOKMARK [1][-]{section.8.4}{Quick Power of Two}{chapter.8}
\BOOKMARK [0][-]{chapter.9}{Higher Level Algorithms}{}
\BOOKMARK [1][-]{section.9.1}{Integer Division with Remainder}{chapter.9}
\BOOKMARK [2][-]{subsection.9.1.1}{Quotient Estimation}{section.9.1}
\BOOKMARK [2][-]{subsection.9.1.2}{Normalized Integers}{section.9.1}
\BOOKMARK [2][-]{subsection.9.1.3}{Radix- Division with Remainder}{section.9.1}
\BOOKMARK [1][-]{section.9.2}{Single Digit Helpers}{chapter.9}
\BOOKMARK [2][-]{subsection.9.2.1}{Single Digit Addition and Subtraction}{section.9.2}
\BOOKMARK [2][-]{subsection.9.2.2}{Single Digit Multiplication}{section.9.2}
\BOOKMARK [2][-]{subsection.9.2.3}{Single Digit Division}{section.9.2}
\BOOKMARK [2][-]{subsection.9.2.4}{Single Digit Root Extraction}{section.9.2}
\BOOKMARK [1][-]{section.9.3}{Random Number Generation}{chapter.9}
\BOOKMARK [1][-]{section.9.4}{Formatted Representations}{chapter.9}
\BOOKMARK [2][-]{subsection.9.4.1}{Reading Radix-n Input}{section.9.4}
\BOOKMARK [2][-]{subsection.9.4.2}{Generating Radix-n Output}{section.9.4}
\BOOKMARK [0][-]{chapter.10}{Number Theoretic Algorithms}{}
\BOOKMARK [1][-]{section.10.1}{Greatest Common Divisor}{chapter.10}
\BOOKMARK [2][-]{subsection.10.1.1}{Complete Greatest Common Divisor}{section.10.1}
\BOOKMARK [1][-]{section.10.2}{Least Common Multiple}{chapter.10}
\BOOKMARK [1][-]{section.10.3}{Jacobi Symbol Computation}{chapter.10}
\BOOKMARK [2][-]{subsection.10.3.1}{Jacobi Symbol}{section.10.3}
\BOOKMARK [1][-]{section.10.4}{Modular Inverse}{chapter.10}
\BOOKMARK [2][-]{subsection.10.4.1}{General Case}{section.10.4}
\BOOKMARK [1][-]{section.10.5}{Primality Tests}{chapter.10}
\BOOKMARK [2][-]{subsection.10.5.1}{Trial Division}{section.10.5}
\BOOKMARK [2][-]{subsection.10.5.2}{The Fermat Test}{section.10.5}
\BOOKMARK [2][-]{subsection.10.5.3}{The Miller-Rabin Test}{section.10.5}

21175
tommath.pdf Normal file

File diff suppressed because one or more lines are too long

6268
tommath.src Normal file

File diff suppressed because it is too large Load Diff

10683
tommath.tex Normal file

File diff suppressed because it is too large Load Diff