Renaming branch
--HG-- branch : libtommath extra : convert_revision : 19ff91f614ebf6603fd4c1482036019ef1f0d501
parents
LICENSE
0 → 100644
bn_error.c
0 → 100644
/* 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, [email protected], http://math.libtomcrypt.org | ||
*/ | ||
#include <tommath.h> | ||
static const struct { | ||
int code; | ||
char *msg; | ||
} msgs[] = { | ||
{ MP_OKAY, "Successful" }, | ||
{ MP_MEM, "Out of heap" }, | ||
{ MP_VAL, "Value out of range" } | ||
}; | ||
/* return a char * string for a given code */ | ||
char *mp_error_to_string(int code) | ||
{ | ||
int x; | ||
/* scan the lookup table for the given message */ | ||
for (x = 0; x < (int)(sizeof(msgs) / sizeof(msgs[0])); x++) { | ||
if (msgs[x].code == code) { | ||
return msgs[x].msg; | ||
} | ||
} | ||
/* generic reply for invalid code */ | ||
return "Invalid error code"; | ||
} | ||
bn_fast_mp_invmod.c
0 → 100644
/* 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, [email protected], http://math.libtomcrypt.org | ||
*/ | ||
#include <tommath.h> | ||
/* computes the modular inverse via binary extended euclidean algorithm, | ||
* that is c = 1/a mod b | ||
* | ||
* Based on mp_invmod except this is optimized for the case where b is | ||
* odd as per HAC Note 14.64 on pp. 610 | ||
*/ | ||
int | ||
fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c) | ||
{ | ||
mp_int x, y, u, v, B, D; | ||
int res, neg; | ||
/* 2. [modified] b must be odd */ | ||
if (mp_iseven (b) == 1) { | ||
return MP_VAL; | ||
} | ||
/* init all our temps */ | ||
if ((res = mp_init_multi(&x, &y, &u, &v, &B, &D, NULL)) != MP_OKAY) { | ||
return res; | ||
} | ||
/* x == modulus, y == value to invert */ | ||
if ((res = mp_copy (b, &x)) != MP_OKAY) { | ||
goto __ERR; | ||
} | ||
/* we need y = |a| */ | ||
if ((res = mp_abs (a, &y)) != MP_OKAY) { | ||
goto __ERR; | ||
} | ||
/* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ | ||
if ((res = mp_copy (&x, &u)) != MP_OKAY) { | ||
goto __ERR; | ||
} | ||
if ((res = mp_copy (&y, &v)) != MP_OKAY) { | ||
goto __ERR; | ||
} | ||
mp_set (&D, 1); | ||
top: | ||
/* 4. while u is even do */ | ||
while (mp_iseven (&u) == 1) { | ||
/* 4.1 u = u/2 */ | ||
if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { | ||
goto __ERR; | ||
} | ||
/* 4.2 if B is odd then */ | ||
if (mp_isodd (&B) == 1) { | ||
if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) { | ||
goto __ERR; | ||
} | ||
} | ||
/* B = B/2 */ | ||
if ((res = mp_div_2 (&B, &B)) != MP_OKAY) { | ||
goto __ERR; | ||
} | ||
} | ||
/* 5. while v is even do */ | ||
while (mp_iseven (&v) == 1) { | ||
/* 5.1 v = v/2 */ | ||
if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { | ||
goto __ERR; | ||
} | ||
/* 5.2 if D is odd then */ | ||
if (mp_isodd (&D) == 1) { | ||
/* D = (D-x)/2 */ | ||
if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) { | ||
goto __ERR; | ||
} | ||
} | ||
/* D = D/2 */ | ||
if ((res = mp_div_2 (&D, &D)) != MP_OKAY) { | ||
goto __ERR; | ||
} | ||
} | ||
/* 6. if u >= v then */ | ||
if (mp_cmp (&u, &v) != MP_LT) { | ||
/* u = u - v, B = B - D */ | ||
if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) { | ||
goto __ERR; | ||
} | ||
if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) { | ||
goto __ERR; | ||
} | ||
} else { | ||
/* v - v - u, D = D - B */ | ||
if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) { | ||
goto __ERR; | ||
} | ||
if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) { | ||
goto __ERR; | ||
} | ||
} | ||
/* if not zero goto step 4 */ | ||
if (mp_iszero (&u) == 0) { | ||
goto top; | ||
} | ||
/* now a = C, b = D, gcd == g*v */ | ||
/* if v != 1 then there is no inverse */ | ||
if (mp_cmp_d (&v, 1) != MP_EQ) { | ||
res = MP_VAL; | ||
goto __ERR; | ||
} | ||
/* b is now the inverse */ | ||
neg = a->sign; | ||
while (D.sign == MP_NEG) { | ||
if ((res = mp_add (&D, b, &D)) != MP_OKAY) { | ||
goto __ERR; | ||
} | ||
} | ||
mp_exch (&D, c); | ||
c->sign = neg; | ||
res = MP_OKAY; | ||
__ERR:mp_clear_multi (&x, &y, &u, &v, &B, &D, NULL); | ||
return res; | ||
} |
/* 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, [email protected], http://math.libtomcrypt.org | ||
*/ | ||
#include <tommath.h> | ||
/* computes xR**-1 == x (mod N) via Montgomery Reduction | ||
* | ||
* This is an optimized implementation of mp_montgomery_reduce | ||
* which uses the comba method to quickly calculate the columns of the | ||
* reduction. | ||
* | ||
* Based on Algorithm 14.32 on pp.601 of HAC. | ||
*/ | ||
int | ||
fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) | ||
{ | ||
int ix, res, olduse; | ||
mp_word W[MP_WARRAY]; | ||
/* get old used count */ | ||
olduse = x->used; | ||
/* grow a as required */ | ||
if (x->alloc < n->used + 1) { | ||
if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) { | ||
return res; | ||
} | ||
} | ||
/* first we have to get the digits of the input into | ||
* an array of double precision words W[...] | ||
*/ | ||
{ | ||
register mp_word *_W; | ||
register mp_digit *tmpx; | ||
/* alias for the W[] array */ | ||
_W = W; | ||
/* alias for the digits of x*/ | ||
tmpx = x->dp; | ||
/* copy the digits of a into W[0..a->used-1] */ | ||
for (ix = 0; ix < x->used; ix++) { | ||
*_W++ = *tmpx++; | ||
} | ||
/* zero the high words of W[a->used..m->used*2] */ | ||
for (; ix < n->used * 2 + 1; ix++) { | ||
*_W++ = 0; | ||
} | ||
} | ||
/* now we proceed to zero successive digits | ||
* from the least significant upwards | ||
*/ | ||
for (ix = 0; ix < n->used; ix++) { | ||
/* mu = ai * m' mod b | ||
* | ||
* We avoid a double precision multiplication (which isn't required) | ||
* by casting the value down to a mp_digit. Note this requires | ||
* that W[ix-1] have the carry cleared (see after the inner loop) | ||
*/ | ||
register mp_digit mu; | ||
mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK); | ||
/* a = a + mu * m * b**i | ||
* | ||
* This is computed in place and on the fly. The multiplication | ||
* by b**i is handled by offseting which columns the results | ||
* are added to. | ||
* | ||
* Note the comba method normally doesn't handle carries in the | ||
* inner loop In this case we fix the carry from the previous | ||
* column since the Montgomery reduction requires digits of the | ||
* result (so far) [see above] to work. This is | ||
* handled by fixing up one carry after the inner loop. The | ||
* carry fixups are done in order so after these loops the | ||
* first m->used words of W[] have the carries fixed | ||
*/ | ||
{ | ||
register int iy; | ||
register mp_digit *tmpn; | ||
register mp_word *_W; | ||
/* alias for the digits of the modulus */ | ||
tmpn = n->dp; | ||
/* Alias for the columns set by an offset of ix */ | ||
_W = W + ix; | ||
/* inner loop */ | ||
for (iy = 0; iy < n->used; iy++) { | ||
*_W++ += ((mp_word)mu) * ((mp_word)*tmpn++); | ||
} | ||
} | ||
/* now fix carry for next digit, W[ix+1] */ | ||
W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT); | ||
} | ||
/* now we have to propagate the carries and | ||
* shift the words downward [all those least | ||
* significant digits we zeroed]. | ||
*/ | ||
{ | ||
register mp_digit *tmpx; | ||
register mp_word *_W, *_W1; | ||
/* nox fix rest of carries */ | ||
/* alias for current word */ | ||
_W1 = W + ix; | ||
/* alias for next word, where the carry goes */ | ||
_W = W + ++ix; | ||
for (; ix <= n->used * 2 + 1; ix++) { | ||
*_W++ += *_W1++ >> ((mp_word) DIGIT_BIT); | ||
} | ||
/* copy out, A = A/b**n | ||
* | ||
* The result is A/b**n but instead of converting from an | ||
* array of mp_word to mp_digit than calling mp_rshd | ||
* we just copy them in the right order | ||
*/ | ||
/* alias for destination word */ | ||
tmpx = x->dp; | ||
/* alias for shifted double precision result */ | ||
_W = W + n->used; | ||
for (ix = 0; ix < n->used + 1; ix++) { | ||
*tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK)); | ||
} | ||
/* zero oldused digits, if the input a was larger than | ||
* m->used+1 we'll have to clear the digits | ||
*/ | ||
for (; ix < olduse; ix++) { | ||
*tmpx++ = 0; | ||
} | ||
} | ||
/* set the max used and clamp */ | ||
x->used = n->used + 1; | ||
mp_clamp (x); | ||
/* if A >= m then A = A - m */ | ||
if (mp_cmp_mag (x, n) != MP_LT) { | ||
return s_mp_sub (x, n, x); | ||
} | ||
return MP_OKAY; | ||
} |
bn_fast_s_mp_mul_digs.c
0 → 100644
/* 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, [email protected], http://math.libtomcrypt.org | ||
*/ | ||
#include <tommath.h> | ||
/* Fast (comba) multiplier | ||
* | ||
* This is the fast column-array [comba] multiplier. It is | ||
* designed to compute the columns of the product first | ||
* then handle the carries afterwards. This has the effect | ||
* of making the nested loops that compute the columns very | ||
* simple and schedulable on super-scalar processors. | ||
* | ||
* This has been modified to produce a variable number of | ||
* digits of output so if say only a half-product is required | ||
* you don't have to compute the upper half (a feature | ||
* required for fast Barrett reduction). | ||
* | ||
* Based on Algorithm 14.12 on pp.595 of HAC. | ||
* | ||
*/ | ||
int | ||
fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) | ||
{ | ||
int olduse, res, pa, ix; | ||
mp_word W[MP_WARRAY]; | ||
/* grow the destination as required */ | ||
if (c->alloc < digs) { | ||
if ((res = mp_grow (c, digs)) != MP_OKAY) { | ||
return res; | ||
} | ||
} | ||
/* clear temp buf (the columns) */ | ||
memset (W, 0, sizeof (mp_word) * digs); | ||
/* calculate the columns */ | ||
pa = a->used; | ||
for (ix = 0; ix < pa; ix++) { | ||
/* this multiplier has been modified to allow you to | ||
* control how many digits of output are produced. | ||
* So at most we want to make upto "digs" digits of output. | ||
* | ||
* this adds products to distinct columns (at ix+iy) of W | ||
* note that each step through the loop is not dependent on | ||
* the previous which means the compiler can easily unroll | ||
* the loop without scheduling problems | ||
*/ | ||
{ | ||
register mp_digit tmpx, *tmpy; | ||
register mp_word *_W; | ||
register int iy, pb; | ||
/* alias for the the word on the left e.g. A[ix] * A[iy] */ | ||
tmpx = a->dp[ix]; | ||
/* alias for the right side */ | ||
tmpy = b->dp; | ||
/* alias for the columns, each step through the loop adds a new | ||
term to each column | ||
*/ | ||
_W = W + ix; | ||
/* the number of digits is limited by their placement. E.g. | ||
we avoid multiplying digits that will end up above the # of | ||
digits of precision requested | ||
*/ | ||
pb = MIN (b->used, digs - ix); | ||
for (iy = 0; iy < pb; iy++) { | ||
*_W++ += ((mp_word)tmpx) * ((mp_word)*tmpy++); | ||
} | ||
} | ||
} | ||
/* setup dest */ | ||
olduse = c->used; | ||
c->used = digs; | ||
{ | ||
register mp_digit *tmpc; | ||
/* At this point W[] contains the sums of each column. To get the | ||
* correct result we must take the extra bits from each column and | ||
* carry them down | ||
* | ||
* Note that while this adds extra code to the multiplier it | ||
* saves time since the carry propagation is removed from the | ||
* above nested loop.This has the effect of reducing the work | ||
* from N*(N+N*c)==N**2 + c*N**2 to N**2 + N*c where c is the | ||
* cost of the shifting. On very small numbers this is slower | ||
* but on most cryptographic size numbers it is faster. | ||
* | ||
* In this particular implementation we feed the carries from | ||
* behind which means when the loop terminates we still have one | ||
* last digit to copy | ||
*/ | ||
tmpc = c->dp; | ||
for (ix = 1; ix < digs; ix++) { | ||
/* forward the carry from the previous temp */ | ||
W[ix] += (W[ix - 1] >> ((mp_word) DIGIT_BIT)); | ||
/* now extract the previous digit [below the carry] */ | ||
*tmpc++ = (mp_digit) (W[ix - 1] & ((mp_word) MP_MASK)); | ||
} | ||
/* fetch the last digit */ | ||
*tmpc++ = (mp_digit) (W[digs - 1] & ((mp_word) MP_MASK)); | ||
/* clear unused digits [that existed in the old copy of c] */ | ||
for (; ix < olduse; ix++) { | ||
*tmpc++ = 0; | ||
} | ||
} | ||
mp_clamp (c); | ||
return MP_OKAY; | ||
} |
bn_fast_s_mp_mul_high_digs.c
0 → 100644
/* 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, [email protected], http://math.libtomcrypt.org | ||
*/ | ||
#include <tommath.h> | ||
/* this is a modified version of fast_s_mp_mul_digs that only produces | ||
* output digits *above* digs. See the comments for fast_s_mp_mul_digs | ||
* to see how it works. | ||
* | ||
* This is used in the Barrett reduction since for one of the multiplications | ||
* only the higher digits were needed. This essentially halves the work. | ||
* | ||
* Based on Algorithm 14.12 on pp.595 of HAC. | ||
*/ | ||
int | ||
fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) | ||
{ | ||
int oldused, newused, res, pa, pb, ix; | ||
mp_word W[MP_WARRAY]; | ||
/* calculate size of product and allocate more space if required */ | ||
newused = a->used + b->used + 1; | ||
if (c->alloc < newused) { | ||
if ((res = mp_grow (c, newused)) != MP_OKAY) { | ||
return res; | ||
} | ||
} | ||
/* like the other comba method we compute the columns first */ | ||
pa = a->used; | ||
pb = b->used; | ||
memset (W + digs, 0, (pa + pb + 1 - digs) * sizeof (mp_word)); | ||
for (ix = 0; ix < pa; ix++) { | ||
{ | ||
register mp_digit tmpx, *tmpy; | ||
register int iy; | ||
register mp_word *_W; | ||
/* work todo, that is we only calculate digits that are at "digs" or above */ | ||
iy = digs - ix; | ||
/* copy of word on the left of A[ix] * B[iy] */ | ||
tmpx = a->dp[ix]; | ||
/* alias for right side */ | ||
tmpy = b->dp + iy; | ||
/* alias for the columns of output. Offset to be equal to or above the | ||
* smallest digit place requested | ||
*/ | ||
_W = W + digs; | ||
/* skip cases below zero where ix > digs */ | ||
if (iy < 0) { | ||
iy = abs(iy); | ||
tmpy += iy; | ||
_W += iy; | ||
iy = 0; | ||
} | ||
/* compute column products for digits above the minimum */ | ||
for (; iy < pb; iy++) { | ||
*_W++ += ((mp_word) tmpx) * ((mp_word)*tmpy++); | ||
} | ||
} | ||
} | ||
/* setup dest */ | ||
oldused = c->used; | ||
c->used = newused; | ||
/* now convert the array W downto what we need | ||
* | ||
* See comments in bn_fast_s_mp_mul_digs.c | ||
*/ | ||
for (ix = digs + 1; ix < newused; ix++) { | ||
W[ix] += (W[ix - 1] >> ((mp_word) DIGIT_BIT)); | ||
c->dp[ix - 1] = (mp_digit) (W[ix - 1] & ((mp_word) MP_MASK)); | ||
} | ||
c->dp[newused - 1] = (mp_digit) (W[newused - 1] & ((mp_word) MP_MASK)); | ||
for (; ix < oldused; ix++) { | ||
c->dp[ix] = 0; | ||
} | ||
mp_clamp (c); | ||
return MP_OKAY; | ||
} |
bn_fast_s_mp_sqr.c
0 → 100644
/* 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, [email protected], http://math.libtomcrypt.org | ||
*/ | ||
#include <tommath.h> | ||
/* fast squaring | ||
* | ||
* This is the comba method where the columns of the product | ||
* are computed first then the carries are computed. This | ||
* has the effect of making a very simple inner loop that | ||
* is executed the most | ||
* | ||
* W2 represents the outer products and W the inner. | ||
* | ||
* A further optimizations is made because the inner | ||
* products are of the form "A * B * 2". The *2 part does | ||
* not need to be computed until the end which is good | ||
* because 64-bit shifts are slow! | ||
* | ||
* Based on Algorithm 14.16 on pp.597 of HAC. | ||
* | ||
*/ | ||
int fast_s_mp_sqr (mp_int * a, mp_int * b) | ||
{ | ||