From b66471f74f1f16ebd823f71c5602cc6b68e69574 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Fri, 28 Feb 2003 16:09:08 +0000 Subject: [PATCH] added libtommath-0.13 --- bn.pdf | Bin 177343 -> 177814 bytes bn.tex | 33 ++++++----- bn_fast_mp_invmod.c | 20 +++++-- bn_fast_mp_montgomery_reduce.c | 77 +++++++++++++++++--------- bn_fast_s_mp_mul_digs.c | 60 +++++++++++--------- bn_fast_s_mp_mul_high_digs.c | 13 +++-- bn_fast_s_mp_sqr.c | 59 +++++++++++++------- bn_mp_2expt.c | 8 ++- bn_mp_abs.c | 7 ++- bn_mp_add.c | 4 +- bn_mp_add_d.c | 5 +- bn_mp_addmod.c | 5 +- bn_mp_and.c | 4 +- bn_mp_clamp.c | 8 ++- bn_mp_cmp.c | 4 +- bn_mp_cmp_mag.c | 3 +- bn_mp_copy.c | 24 +++++--- bn_mp_count_bits.c | 4 +- bn_mp_div.c | 16 +++--- bn_mp_div_2.c | 33 +++++++---- bn_mp_div_2d.c | 6 +- bn_mp_div_d.c | 4 +- bn_mp_exch.c | 2 +- bn_mp_expt_d.c | 4 +- bn_mp_exptmod.c | 29 ++++++---- bn_mp_exptmod_fast.c | 32 ++++------- bn_mp_gcd.c | 10 ++-- bn_mp_grow.c | 3 +- bn_mp_init_copy.c | 5 +- bn_mp_invmod.c | 8 +-- bn_mp_jacobi.c | 6 +- bn_mp_karatsuba_mul.c | 4 +- bn_mp_karatsuba_sqr.c | 4 +- bn_mp_lcm.c | 4 +- bn_mp_lshd.c | 2 +- bn_mp_mod.c | 4 +- bn_mp_mod_2d.c | 5 +- bn_mp_mod_d.c | 4 +- bn_mp_montgomery_calc_normalization.c | 53 ++++++++++++++++++ bn_mp_montgomery_reduce.c | 15 ++--- bn_mp_montgomery_setup.c | 4 +- bn_mp_mul.c | 18 +++++- bn_mp_mul_2.c | 51 ++++++++++++----- bn_mp_mul_2d.c | 4 +- bn_mp_mul_d.c | 47 ++++++++++------ bn_mp_mulmod.c | 4 +- bn_mp_n_root.c | 8 ++- bn_mp_neg.c | 2 +- bn_mp_or.c | 4 +- bn_mp_rand.c | 15 ++--- bn_mp_read_signed_bin.c | 2 +- bn_mp_read_unsigned_bin.c | 2 +- bn_mp_reduce.c | 6 +- bn_mp_rshd.c | 2 +- bn_mp_set_int.c | 2 +- bn_mp_sqr.c | 11 +++- bn_mp_sqrmod.c | 4 +- bn_mp_sub.c | 2 +- bn_mp_sub_d.c | 4 +- bn_mp_submod.c | 4 +- bn_mp_to_signed_bin.c | 2 +- bn_mp_to_unsigned_bin.c | 4 +- bn_mp_unsigned_bin_size.c | 2 +- bn_mp_xor.c | 4 +- bn_radix.c | 21 ++++--- bn_reverse.c | 2 +- bn_s_mp_add.c | 62 ++++++++++++--------- bn_s_mp_mul_digs.c | 26 ++------- bn_s_mp_mul_high_digs.c | 21 +++---- bn_s_mp_sqr.c | 20 ++----- bn_s_mp_sub.c | 62 ++++++++++++--------- bncore.c | 6 +- changes.txt | 6 ++ demo/demo.c | 60 +++++++------------- etc/makefile | 19 ++++--- etc/pprime.c | 2 +- etc/tune.c | 10 ++-- gen.pl | 27 +++++++++ ltmtest.exe | Bin 49664 -> 0 bytes makefile | 8 +-- mpitest.exe | Bin 58368 -> 0 bytes mtest/mtest.c | 2 +- timings.txt | 75 ++++++++++++------------- timings2.txt | 36 ++++++++++++ timings3.txt | 5 ++ tommath.h | 6 +- 86 files changed, 754 insertions(+), 521 deletions(-) create mode 100644 bn_mp_montgomery_calc_normalization.c create mode 100644 gen.pl delete mode 100644 ltmtest.exe delete mode 100644 mpitest.exe create mode 100644 timings2.txt create mode 100644 timings3.txt diff --git a/bn.pdf b/bn.pdf index df69417ba1b7d4d0441ad1abefee794c6f1e84af..6b5a2d15fecd9d4ecfb79a3b5a66d09116226f58 100644 GIT binary patch delta 75637 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μMX1$ON7UbKPjI{ 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 delta 75213 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�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 diff --git a/bn.tex b/bn.tex index b5f0227..5c40174 100644 --- a/bn.tex +++ b/bn.tex @@ -1,7 +1,7 @@ \documentclass{article} \begin{document} -\title{LibTomMath v0.12 \\ A Free Multiple Precision Integer Library} +\title{LibTomMath v0.13 \\ A Free Multiple Precision Integer Library} \author{Tom St Denis \\ tomstdenis@iahu.ca} \maketitle \newpage @@ -409,7 +409,6 @@ of $c$ is the maximum length of the two inputs. Computes $c = a \land b$, pseudo-extends with zeroes whichever of $a$ or $b$ is shorter such that the length of $c$ is the maximum length of the two inputs. - \subsection{Basic Arithmetic} \subsubsection{mp\_cmp(mp\_int *a, mp\_int *b)} @@ -440,19 +439,18 @@ This function requires no additional memory and $O(N)$ time. Computes $c = a \cdot b$ using signed arithmetic. Handles the sign of the numbers correctly which means it will correct the sign of the product as required, e.g. $a \cdot -b$ turns into $-ab$. -For relatively small inputs, that is less than 80 digits a standard baseline or comba-baseline multiplier is used. It -requires no additional memory and $O(N^2)$ time. The comba-baseline multiplier is only used if it can safely be used -without losing carry digits. The comba method is faster than the baseline method but cannot always be used which is why -both are provided. The code will automatically determine when it can be used. If the digit count is higher -than 80 for the inputs than a Karatsuba multiplier is used which requires approximately $O(6 \cdot N)$ memory and -$O(N^{lg(3)})$ time. +This function requires $O(N^2)$ time for small inputs and $O(N^{1.584})$ time for relatively large +inputs (\textit{above the }KARATSUBA\_MUL\_CUTOFF \textit{value defined in bncore.c.}). There is +considerable overhead in the Karatsuba method which only pays off when the digit count is fairly high +(\textit{typically around 80}). For small inputs the function requires $O(2N)$ memory, otherwise it +requires $O(6 \cdot \mbox{lg}(N) \cdot N)$ memory. + \subsubsection{mp\_sqr(mp\_int *a, mp\_int *b)} -Computes $b = a^2$. -For relatively small inputs, that is less than 80 digits a modified squaring or comba-squaring algorithm is used. It -requires no additional memory and $O((N^2 + N)/2)$ time. The comba-squaring method is used only if it can be safely used -without losing carry digits. After 80 digits a Karatsuba squaring algorithm is used whcih requires approximately -$O(4 \cdot N)$ memory and $O(N^{lg(3)})$ time. +Computes $b = a^2$ and fixes the sign of $b$ to be positive. + +This function has a running time and memory requirement profile very similar to that of the +mp\_mul function. It is always faster and uses less memory for the larger inputs. \subsubsection{mp\_div(mp\_int *a, mp\_int *b, mp\_int *c, mp\_int *d)} Computes $c = \lfloor a/b \rfloor$ and $d \equiv a \mbox{ (mod }b\mbox{)}$. The division is signed which means the sign @@ -482,7 +480,8 @@ Also note that these functions use mp\_mod which means the result are guaranteed \subsubsection{mp\_invmod(mp\_int *a, mp\_int *b, mp\_int *c)} This function will find $c = 1/a \mbox{ (mod }b\mbox{)}$ for any value of $a$ such that $(a, b) = 1$ and $b > 0$. When -$b$ is odd a ``fast'' variant is used which finds the inverse twice as fast. +$b$ is odd a ``fast'' variant is used which finds the inverse twice as fast. If no inverse is found (e.g. $(a, b) \ne 1$) then +the function returns \textbf{MP\_VAL} and the result in $c$ is undefined. \subsubsection{mp\_gcd(mp\_int *a, mp\_int *b, mp\_int *c)} Finds the greatest common divisor of both $a$ and $b$ and places the result in $c$. Will work with either positive @@ -497,13 +496,13 @@ both. Functions requires no additional memory and approximately $O(4 \cdot N^2)$ time. -\subsubsection{mp\_n\_root(mp\_int *a, mp\_digit b, mp\_int c)} +\subsubsection{mp\_n\_root(mp\_int *a, mp\_digit b, mp\_int *c)} Finds the $b$'th root of $a$ and stores it in $b$. The roots are found such that $\vert c \vert^b \le \vert a \vert$. Uses the Newton approximation approach which means it converges in $O(log \beta^N)$ time to a final result. Each iteration requires $b$ multiplications and one division for a total work of $O(6N^2 \cdot log \beta^N) = O(6N^3 \cdot log \beta)$. -If the input $a$ is negative and $b$ is even the function returns an error. Otherwise the function will return a root -that has a sign that agrees with the sign of $a$. +If the input $a$ is negative and $b$ is even the function returns \textbf{MP\_VAL}. Otherwise the function will +return a root that has a sign that agrees with the sign of $a$. \subsubsection{mp\_jacobi(mp\_int *a, mp\_int *n, int *c)} Computes $c = \left ( {a \over n} \right )$ or the Jacobi function of $(a, n)$ and stores the result in an integer addressed diff --git a/bn_fast_mp_invmod.c b/bn_fast_mp_invmod.c index e1dcce3..249ff43 100644 --- a/bn_fast_mp_invmod.c +++ b/bn_fast_mp_invmod.c @@ -14,13 +14,17 @@ */ #include -/* computes the modular inverse via binary extended euclidean algorithm, that is c = 1/a mod b */ +/* 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; - + mp_int x, y, u, v, B, D; + int res, neg; if ((res = mp_init (&x)) != MP_OKAY) { goto __ERR; @@ -58,7 +62,10 @@ fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c) goto __D; } - /* 2. [modified] if x,y are both even then return an error! */ + /* 2. [modified] if x,y are both even then return an error! + * + * That is if gcd(x,y) = 2 * k then obviously there is no inverse. + */ if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) { res = MP_VAL; goto __D; @@ -135,8 +142,9 @@ top: } /* if not zero goto step 4 */ - if (mp_iszero (&u) == 0) + if (mp_iszero (&u) == 0) { goto top; + } /* now a = C, b = D, gcd == g*v */ diff --git a/bn_fast_mp_montgomery_reduce.c b/bn_fast_mp_montgomery_reduce.c index dbc3478..2e03936 100644 --- a/bn_fast_mp_montgomery_reduce.c +++ b/bn_fast_mp_montgomery_reduce.c @@ -14,12 +14,19 @@ */ #include -/* computes xR^-1 == x (mod N) via Montgomery Reduction (comba) */ +/* 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 * a, mp_int * m, mp_digit mp) { - int ix, res, olduse; - mp_word W[512]; + int ix, res, olduse; + mp_word W[512]; /* get old used count */ olduse = a->used; @@ -31,14 +38,22 @@ fast_mp_montgomery_reduce (mp_int * a, mp_int * m, mp_digit mp) } } - /* copy the digits of a */ - for (ix = 0; ix < a->used; ix++) { - W[ix] = a->dp[ix]; - } + { + register mp_word *_W; + register mp_digit *tmpa; - /* zero the high words */ - for (; ix < m->used * 2 + 1; ix++) { - W[ix] = 0; + _W = W; + tmpa = a->dp; + + /* copy the digits of a */ + for (ix = 0; ix < a->used; ix++) { + *_W++ = *tmpa++; + } + + /* zero the high words */ + for (; ix < m->used * 2 + 1; ix++) { + *_W++ = 0; + } } for (ix = 0; ix < m->used; ix++) { @@ -69,8 +84,10 @@ fast_mp_montgomery_reduce (mp_int * a, mp_int * m, mp_digit mp) register mp_digit *tmpx; register mp_word *_W; - /* aliases */ + /* alias for the digits of the modulus */ tmpx = m->dp; + + /* Alias for the columns set by an offset of ix */ _W = W + ix; /* inner loop */ @@ -88,24 +105,32 @@ fast_mp_montgomery_reduce (mp_int * a, mp_int * m, mp_digit mp) W[ix] += (W[ix - 1] >> ((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 - */ - for (ix = 0; ix < m->used + 1; ix++) { - a->dp[ix] = W[ix + m->used] & ((mp_word) MP_MASK); + { + register mp_digit *tmpa; + register mp_word *_W; + + /* 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 + */ + tmpa = a->dp; + _W = W + m->used; + + for (ix = 0; ix < m->used + 1; ix++) { + *tmpa++ = *_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++) { + *tmpa++ = 0; + } } - /* set the max used */ + /* set the max used and clamp */ a->used = m->used + 1; - - /* zero oldused digits, if the input a was larger than - * m->used+1 we'll have to clear the digits */ - for (; ix < olduse; ix++) { - a->dp[ix] = 0; - } mp_clamp (a); /* if A >= m then A = A - m */ diff --git a/bn_fast_s_mp_mul_digs.c b/bn_fast_s_mp_mul_digs.c index c433dd7..dc0c33e 100644 --- a/bn_fast_s_mp_mul_digs.c +++ b/bn_fast_s_mp_mul_digs.c @@ -21,13 +21,20 @@ * 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[512]; + int olduse, res, pa, ix; + mp_word W[512]; + /* grow the destination as required */ if (c->alloc < digs) { if ((res = mp_grow (c, digs)) != MP_OKAY) { return res; @@ -43,11 +50,9 @@ fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) /* 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 + * 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 @@ -85,27 +90,30 @@ fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) 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. - */ + /* 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. + */ + tmpc = c->dp; + for (ix = 1; ix < digs; ix++) { + W[ix] += (W[ix - 1] >> ((mp_word) DIGIT_BIT)); + *tmpc++ = (mp_digit) (W[ix - 1] & ((mp_word) MP_MASK)); + } + *tmpc++ = (mp_digit) (W[digs - 1] & ((mp_word) MP_MASK)); - for (ix = 1; ix < digs; 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[digs - 1] = (mp_digit) (W[digs - 1] & ((mp_word) MP_MASK)); - - /* clear unused */ - for (; ix < olduse; ix++) { - c->dp[ix] = 0; + /* clear unused */ + for (; ix < olduse; ix++) { + *tmpc++ = 0; + } } mp_clamp (c); diff --git a/bn_fast_s_mp_mul_high_digs.c b/bn_fast_s_mp_mul_high_digs.c index cc30386..3458d96 100644 --- a/bn_fast_s_mp_mul_high_digs.c +++ b/bn_fast_s_mp_mul_high_digs.c @@ -20,14 +20,16 @@ * * 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[512]; - + int oldused, newused, res, pa, pb, ix; + mp_word W[512]; + /* 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) { @@ -38,7 +40,7 @@ fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) /* 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)); + memset (W + digs, 0, (pa + pb + 1 - digs) * sizeof (mp_word)); for (ix = 0; ix < pa; ix++) { { register mp_digit tmpx, *tmpy; @@ -75,8 +77,7 @@ fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) W[ix] += (W[ix - 1] >> ((mp_word) DIGIT_BIT)); c->dp[ix - 1] = (mp_digit) (W[ix - 1] & ((mp_word) MP_MASK)); } - c->dp[(pa + pb + 1) - 1] = - (mp_digit) (W[(pa + pb + 1) - 1] & ((mp_word) MP_MASK)); + c->dp[(pa + pb + 1) - 1] = (mp_digit) (W[(pa + pb + 1) - 1] & ((mp_word) MP_MASK)); for (; ix < oldused; ix++) { c->dp[ix] = 0; diff --git a/bn_fast_s_mp_sqr.c b/bn_fast_s_mp_sqr.c index c4f786d..2b945ba 100644 --- a/bn_fast_s_mp_sqr.c +++ b/bn_fast_s_mp_sqr.c @@ -26,14 +26,16 @@ * "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) { - int olduse, newused, res, ix, pa; - mp_word W2[512], W[512]; + int olduse, newused, res, ix, pa; + mp_word W2[512], W[512]; + /* calculate size of product and allocate as required */ pa = a->used; newused = pa + pa + 1; if (b->alloc < newused) { @@ -51,15 +53,31 @@ fast_s_mp_sqr (mp_int * a, mp_int * b) * the inner product can be doubled using n doublings instead of * n^2 */ - memset (W, 0, newused * sizeof (mp_word)); + memset (W, 0, newused * sizeof (mp_word)); memset (W2, 0, newused * sizeof (mp_word)); +/* note optimization + * values in W2 are only written in even locations which means + * we can collapse the array to 256 words [and fixup the memset above] + * provided we also fix up the summations below. Ideally + * the fixup loop should be unrolled twice to handle the even/odd + * cases, and then a final step to handle odd cases [e.g. newused == odd] + * + * This will not only save ~8*256 = 2KB of stack but lower the number of + * operations required to finally fix up the columns + */ + /* This computes the inner product. To simplify the inner N^2 loop * the multiplication by two is done afterwards in the N loop. */ for (ix = 0; ix < pa; ix++) { - /* compute the outer product */ - W2[ix + ix] += ((mp_word) a->dp[ix]) * ((mp_word) a->dp[ix]); + /* compute the outer product + * + * Note that every outer product is computed + * for a particular column only once which means that + * there is no need todo a double precision addition + */ + W2[ix + ix] = ((mp_word) a->dp[ix]) * ((mp_word) a->dp[ix]); { register mp_digit tmpx, *tmpy; @@ -90,22 +108,25 @@ fast_s_mp_sqr (mp_int * a, mp_int * b) W[0] += W[0] + W2[0]; /* now compute digits */ - for (ix = 1; ix < newused; ix++) { - /* double/add next digit */ - W[ix] += W[ix] + W2[ix]; + { + register mp_digit *tmpb; - W[ix] = W[ix] + (W[ix - 1] >> ((mp_word) DIGIT_BIT)); - b->dp[ix - 1] = (mp_digit) (W[ix - 1] & ((mp_word) MP_MASK)); + tmpb = b->dp; + + for (ix = 1; ix < newused; ix++) { + /* double/add next digit */ + W[ix] += W[ix] + W2[ix]; + + W[ix] = W[ix] + (W[ix - 1] >> ((mp_word) DIGIT_BIT)); + *tmpb++ = (mp_digit) (W[ix - 1] & ((mp_word) MP_MASK)); + } + *tmpb++ = (mp_digit) (W[(newused) - 1] & ((mp_word) MP_MASK)); + + /* clear high */ + for (; ix < olduse; ix++) { + *tmpb++ = 0; + } } - b->dp[(newused) - 1] = (mp_digit) (W[(newused) - 1] & ((mp_word) MP_MASK)); - - /* clear high */ - for (; ix < olduse; ix++) { - b->dp[ix] = 0; - } - - /* fix the sign (since we no longer make a fresh temp) */ - b->sign = MP_ZPOS; mp_clamp (b); return MP_OKAY; diff --git a/bn_mp_2expt.c b/bn_mp_2expt.c index ace1b99..71d04e9 100644 --- a/bn_mp_2expt.c +++ b/bn_mp_2expt.c @@ -14,11 +14,15 @@ */ #include -/* computes a = 2^b */ +/* computes a = 2^b + * + * Simple algorithm which zeroes the int, grows it then just sets one bit + * as required. + */ int mp_2expt (mp_int * a, int b) { - int res; + int res; mp_zero (a); if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) { diff --git a/bn_mp_abs.c b/bn_mp_abs.c index 299d3b6..9e6956e 100644 --- a/bn_mp_abs.c +++ b/bn_mp_abs.c @@ -14,11 +14,14 @@ */ #include -/* b = |a| */ +/* b = |a| + * + * Simple function copies the input and fixes the sign to positive + */ int mp_abs (mp_int * a, mp_int * b) { - int res; + int res; if ((res = mp_copy (a, b)) != MP_OKAY) { return res; } diff --git a/bn_mp_add.c b/bn_mp_add.c index a2ad4fd..a8addfb 100644 --- a/bn_mp_add.c +++ b/bn_mp_add.c @@ -18,9 +18,9 @@ int mp_add (mp_int * a, mp_int * b, mp_int * c) { - int sa, sb, res; - + int sa, sb, res; + /* get sign of both inputs */ sa = a->sign; sb = b->sign; diff --git a/bn_mp_add_d.c b/bn_mp_add_d.c index 0391bc1..1b30fa4 100644 --- a/bn_mp_add_d.c +++ b/bn_mp_add_d.c @@ -18,9 +18,8 @@ int mp_add_d (mp_int * a, mp_digit b, mp_int * c) { - mp_int t; - int res; - + mp_int t; + int res; if ((res = mp_init (&t)) != MP_OKAY) { return res; diff --git a/bn_mp_addmod.c b/bn_mp_addmod.c index adce5d5..abc3719 100644 --- a/bn_mp_addmod.c +++ b/bn_mp_addmod.c @@ -18,9 +18,8 @@ int mp_addmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) { - int res; - mp_int t; - + int res; + mp_int t; if ((res = mp_init (&t)) != MP_OKAY) { return res; diff --git a/bn_mp_and.c b/bn_mp_and.c index d153c44..6c05d68 100644 --- a/bn_mp_and.c +++ b/bn_mp_and.c @@ -18,8 +18,8 @@ int mp_and (mp_int * a, mp_int * b, mp_int * c) { - int res, ix, px; - mp_int t, *x; + int res, ix, px; + mp_int t, *x; if (a->used > b->used) { if ((res = mp_init_copy (&t, a)) != MP_OKAY) { diff --git a/bn_mp_clamp.c b/bn_mp_clamp.c index 77f3e1a..3741f62 100644 --- a/bn_mp_clamp.c +++ b/bn_mp_clamp.c @@ -14,7 +14,13 @@ */ #include -/* trim unused digits */ +/* trim unused digits + * + * This is used to ensure that leading zero digits are + * trimed and the leading "used" digit will be non-zero + * Typically very fast. Also fixes the sign if there + * are no more leading digits + */ void mp_clamp (mp_int * a) { diff --git a/bn_mp_cmp.c b/bn_mp_cmp.c index 527d35c..ca0c463 100644 --- a/bn_mp_cmp.c +++ b/bn_mp_cmp.c @@ -18,13 +18,11 @@ int mp_cmp (mp_int * a, mp_int * b) { - int res; /* compare based on sign */ if (a->sign == MP_NEG && b->sign == MP_ZPOS) { return MP_LT; } else if (a->sign == MP_ZPOS && b->sign == MP_NEG) { return MP_GT; } - res = mp_cmp_mag (a, b); - return res; + return mp_cmp_mag (a, b); } diff --git a/bn_mp_cmp_mag.c b/bn_mp_cmp_mag.c index efe5b2b..6d4a02d 100644 --- a/bn_mp_cmp_mag.c +++ b/bn_mp_cmp_mag.c @@ -18,8 +18,7 @@ int mp_cmp_mag (mp_int * a, mp_int * b) { - int n; - + int n; /* compare based on # of non-zero digits */ if (a->used > b->used) { diff --git a/bn_mp_copy.c b/bn_mp_copy.c index a502620..68705a4 100644 --- a/bn_mp_copy.c +++ b/bn_mp_copy.c @@ -18,8 +18,7 @@ int mp_copy (mp_int * a, mp_int * b) { - int res, n; - + int res, n; /* if dst == src do nothing */ if (a == b || a->dp == b->dp) { @@ -35,14 +34,21 @@ mp_copy (mp_int * a, mp_int * b) b->used = a->used; b->sign = a->sign; - /* copy all the digits */ - for (n = 0; n < a->used; n++) { - b->dp[n] = a->dp[n]; - } + { + register mp_digit *tmpa, *tmpb; - /* clear high digits */ - for (n = b->used; n < b->alloc; n++) { - b->dp[n] = 0; + tmpa = a->dp; + tmpb = b->dp; + + /* copy all the digits */ + for (n = 0; n < a->used; n++) { + *tmpb++ = *tmpa++; + } + + /* clear high digits */ + for (; n < b->alloc; n++) { + *tmpb++ = 0; + } } return MP_OKAY; } diff --git a/bn_mp_count_bits.c b/bn_mp_count_bits.c index 3f6ed28..09992d4 100644 --- a/bn_mp_count_bits.c +++ b/bn_mp_count_bits.c @@ -18,8 +18,8 @@ int mp_count_bits (mp_int * a) { - int r; - mp_digit q; + int r; + mp_digit q; if (a->used == 0) { return 0; diff --git a/bn_mp_div.c b/bn_mp_div.c index b324d2d..3954c9f 100644 --- a/bn_mp_div.c +++ b/bn_mp_div.c @@ -26,8 +26,8 @@ int mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d) { - mp_int q, x, y, t1, t2; - int res, n, t, i, norm, neg; + mp_int q, x, y, t1, t2; + int res, n, t, i, norm, neg; /* is divisor zero ? */ @@ -75,13 +75,12 @@ mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d) /* normalize both x and y, ensure that y >= b/2, [b == 2^DIGIT_BIT] */ norm = 0; - while ((y.dp[y.used - 1] & (((mp_digit) 1) << (DIGIT_BIT - 1))) == - ((mp_digit) 0)) { + while ((y.dp[y.used - 1] & (((mp_digit) 1) << (DIGIT_BIT - 1))) == ((mp_digit) 0)) { ++norm; - if ((res = mp_mul_2d (&x, 1, &x)) != MP_OKAY) { + if ((res = mp_mul_2 (&x, &x)) != MP_OKAY) { goto __Y; } - if ((res = mp_mul_2d (&y, 1, &y)) != MP_OKAY) { + if ((res = mp_mul_2 (&y, &y)) != MP_OKAY) { goto __Y; } } @@ -114,7 +113,7 @@ mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d) if (x.dp[i] == y.dp[t]) { q.dp[i - t - 1] = ((1UL << DIGIT_BIT) - 1UL); } else { - mp_word tmp; + mp_word tmp; tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT); tmp |= ((mp_word) x.dp[i - 1]); tmp /= ((mp_word) y.dp[t]); @@ -142,8 +141,7 @@ mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d) t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1]; t2.dp[2] = x.dp[i]; t2.used = 3; - } - while (mp_cmp (&t1, &t2) == MP_GT); + } while (mp_cmp (&t1, &t2) == MP_GT); /* step 3.3 x = x - q{i-t-1} * y * b^{i-t-1} */ if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) { diff --git a/bn_mp_div_2.c b/bn_mp_div_2.c index bc7dc28..284f330 100644 --- a/bn_mp_div_2.c +++ b/bn_mp_div_2.c @@ -18,20 +18,33 @@ int mp_div_2 (mp_int * a, mp_int * b) { - mp_digit r, rr; - int x, res; - + int x, res, oldused; /* copy */ - if ((res = mp_copy (a, b)) != MP_OKAY) { - return res; + if (b->alloc < a->used) { + if ((res = mp_grow (b, a->used)) != MP_OKAY) { + return res; + } } - r = 0; - for (x = b->used - 1; x >= 0; x--) { - rr = b->dp[x] & 1; - b->dp[x] = (b->dp[x] >> 1) | (r << (DIGIT_BIT - 1)); - r = rr; + oldused = b->used; + b->used = a->used; + { + register mp_digit r, rr, *tmpa, *tmpb; + + tmpa = a->dp + b->used - 1; + tmpb = b->dp + b->used - 1; + r = 0; + for (x = b->used - 1; x >= 0; x--) { + rr = *tmpa & 1; + *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1)); + r = rr; + } + + tmpb = b->dp + b->used; + for (x = b->used; x < oldused; x++) { + *tmpb++ = 0; + } } mp_clamp (b); return MP_OKAY; diff --git a/bn_mp_div_2d.c b/bn_mp_div_2d.c index 3bfa5aa..9d24e10 100644 --- a/bn_mp_div_2d.c +++ b/bn_mp_div_2d.c @@ -18,9 +18,9 @@ int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d) { - mp_digit D, r, rr; - int x, res; - mp_int t; + mp_digit D, r, rr; + int x, res; + mp_int t; /* if the shift count is <= 0 then we do no work */ diff --git a/bn_mp_div_d.c b/bn_mp_div_d.c index 321f030..e43802a 100644 --- a/bn_mp_div_d.c +++ b/bn_mp_div_d.c @@ -18,8 +18,8 @@ int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d) { - mp_int t, t2; - int res; + mp_int t, t2; + int res; if ((res = mp_init (&t)) != MP_OKAY) { diff --git a/bn_mp_exch.c b/bn_mp_exch.c index 44e7087..2ccaf9e 100644 --- a/bn_mp_exch.c +++ b/bn_mp_exch.c @@ -17,7 +17,7 @@ void mp_exch (mp_int * a, mp_int * b) { - mp_int t; + mp_int t; t = *a; *a = *b; diff --git a/bn_mp_expt_d.c b/bn_mp_expt_d.c index 80f9578..e5106be 100644 --- a/bn_mp_expt_d.c +++ b/bn_mp_expt_d.c @@ -17,8 +17,8 @@ int mp_expt_d (mp_int * a, mp_digit b, mp_int * c) { - int res, x; - mp_int g; + int res, x; + mp_int g; if ((res = mp_init_copy (&g, a)) != MP_OKAY) { diff --git a/bn_mp_exptmod.c b/bn_mp_exptmod.c index ce81953..ea58a4f 100644 --- a/bn_mp_exptmod.c +++ b/bn_mp_exptmod.c @@ -14,19 +14,30 @@ */ #include +static int f_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y); + +/* this is a shell function that calls either the normal or Montgomery + * exptmod functions. Originally the call to the montgomery code was + * 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) + */ int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) { - mp_int M[256], res, mu; - mp_digit buf; - int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; - - /* if the modulus is odd use the fast method */ if (mp_isodd (P) == 1 && P->used > 4 && P->used < MONTGOMERY_EXPT_CUTOFF) { - err = mp_exptmod_fast (G, X, P, Y); - return err; + return mp_exptmod_fast (G, X, P, Y); + } else { + return f_mp_exptmod (G, X, P, Y); } +} + +static int +f_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +{ + mp_int M[256], res, mu; + mp_digit buf; + int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; /* find window size */ x = mp_count_bits (X); @@ -80,9 +91,7 @@ mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) } for (x = 0; x < (winsize - 1); x++) { - if ((err = - mp_sqr (&M[1 << (winsize - 1)], - &M[1 << (winsize - 1)])) != MP_OKAY) { + if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) { goto __MU; } if ((err = mp_reduce (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) { diff --git a/bn_mp_exptmod_fast.c b/bn_mp_exptmod_fast.c index bd25b3e..fe0dfcb 100644 --- a/bn_mp_exptmod_fast.c +++ b/bn_mp_exptmod_fast.c @@ -24,9 +24,9 @@ int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) { - mp_int M[256], res; - mp_digit buf, mp; - int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; + mp_int M[256], res; + mp_digit buf, mp; + int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; /* find window size */ x = mp_count_bits (X); @@ -48,7 +48,7 @@ mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) /* init G array */ for (x = 0; x < (1 << winsize); x++) { - if ((err = mp_init_size (&M[x], 1)) != MP_OKAY) { + if ((err = mp_init (&M[x])) != MP_OKAY) { for (y = 0; y < x; y++) { mp_clear (&M[y]); } @@ -66,44 +66,32 @@ mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) goto __RES; } - /* now we need R mod m */ - if ((err = mp_2expt (&res, P->used * DIGIT_BIT)) != MP_OKAY) { - goto __RES; - } - - /* res = R mod m (can use modified double/subtract ...) */ - if ((err = mp_mod (&res, P, &res)) != MP_OKAY) { - goto __RES; - } - /* create M table * * The M table contains powers of the input base, e.g. M[x] = G^x mod P * * The first half of the table is not computed though accept for M[0] and M[1] */ - if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) { + + /* now we need R mod m */ + if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) { goto __RES; } /* now set M[1] to G * R mod m */ - if ((err = mp_mulmod (&M[1], &res, P, &M[1])) != MP_OKAY) { + if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) { goto __RES; } - /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */ if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) { goto __RES; } for (x = 0; x < (winsize - 1); x++) { - if ((err = - mp_sqr (&M[1 << (winsize - 1)], - &M[1 << (winsize - 1)])) != MP_OKAY) { + if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) { goto __RES; } - if ((err = - mp_montgomery_reduce (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) { + if ((err = mp_montgomery_reduce (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) { goto __RES; } } diff --git a/bn_mp_gcd.c b/bn_mp_gcd.c index e2594b5..35b287e 100644 --- a/bn_mp_gcd.c +++ b/bn_mp_gcd.c @@ -19,8 +19,8 @@ int mp_gcd (mp_int * a, mp_int * b, mp_int * c) { - mp_int u, v, t; - int k, res, neg; + mp_int u, v, t; + int k, res, neg; /* either zero than gcd is the largest */ @@ -57,10 +57,10 @@ mp_gcd (mp_int * a, mp_int * b, mp_int * c) k = 0; while ((u.dp[0] & 1) == 0 && (v.dp[0] & 1) == 0) { ++k; - if ((res = mp_div_2d (&u, 1, &u, NULL)) != MP_OKAY) { + if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { goto __T; } - if ((res = mp_div_2d (&v, 1, &v, NULL)) != MP_OKAY) { + if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { goto __T; } } @@ -80,7 +80,7 @@ mp_gcd (mp_int * a, mp_int * b, mp_int * c) do { /* B3 (and B4). Halve t, if even */ while (t.used != 0 && (t.dp[0] & 1) == 0) { - if ((res = mp_div_2d (&t, 1, &t, NULL)) != MP_OKAY) { + if ((res = mp_div_2 (&t, &t)) != MP_OKAY) { goto __T; } } diff --git a/bn_mp_grow.c b/bn_mp_grow.c index 2a12369..91c1867 100644 --- a/bn_mp_grow.c +++ b/bn_mp_grow.c @@ -18,8 +18,7 @@ int mp_grow (mp_int * a, int size) { - int i, n; - + int i, n; /* if the alloc size is smaller alloc more ram */ if (a->alloc < size) { diff --git a/bn_mp_init_copy.c b/bn_mp_init_copy.c index b3f25ee..f79d2b1 100644 --- a/bn_mp_init_copy.c +++ b/bn_mp_init_copy.c @@ -18,11 +18,10 @@ int mp_init_copy (mp_int * a, mp_int * b) { - int res; + int res; if ((res = mp_init (a)) != MP_OKAY) { return res; } - res = mp_copy (b, a); - return res; + return mp_copy (b, a); } diff --git a/bn_mp_invmod.c b/bn_mp_invmod.c index 1051eb0..006efd2 100644 --- a/bn_mp_invmod.c +++ b/bn_mp_invmod.c @@ -17,9 +17,8 @@ int mp_invmod (mp_int * a, mp_int * b, mp_int * c) { - mp_int x, y, u, v, A, B, C, D; - int res; - + mp_int x, y, u, v, A, B, C, D; + int res; /* b cannot be negative */ if (b->sign == MP_NEG) { @@ -28,8 +27,7 @@ mp_invmod (mp_int * a, mp_int * b, mp_int * c) /* if the modulus is odd we can use a faster routine instead */ if (mp_iseven (b) == 0) { - res = fast_mp_invmod (a, b, c); - return res; + return fast_mp_invmod (a, b, c); } if ((res = mp_init (&x)) != MP_OKAY) { diff --git a/bn_mp_jacobi.c b/bn_mp_jacobi.c index b97d5f3..95aee42 100644 --- a/bn_mp_jacobi.c +++ b/bn_mp_jacobi.c @@ -20,9 +20,9 @@ int mp_jacobi (mp_int * a, mp_int * n, int *c) { - mp_int a1, n1, e; - int s, r, res; - mp_digit residue; + mp_int a1, n1, e; + int s, r, res; + mp_digit residue; /* step 1. if a == 0, return 0 */ if (mp_iszero (a) == 1) { diff --git a/bn_mp_karatsuba_mul.c b/bn_mp_karatsuba_mul.c index 0a8c34e..bee8eaa 100644 --- a/bn_mp_karatsuba_mul.c +++ b/bn_mp_karatsuba_mul.c @@ -36,8 +36,8 @@ int mp_karatsuba_mul (mp_int * a, mp_int * b, mp_int * c) { - mp_int x0, x1, y0, y1, t1, t2, x0y0, x1y1; - int B, err, x; + mp_int x0, x1, y0, y1, t1, t2, x0y0, x1y1; + int B, err, x; err = MP_MEM; diff --git a/bn_mp_karatsuba_sqr.c b/bn_mp_karatsuba_sqr.c index 29396ba..3078588 100644 --- a/bn_mp_karatsuba_sqr.c +++ b/bn_mp_karatsuba_sqr.c @@ -22,8 +22,8 @@ int mp_karatsuba_sqr (mp_int * a, mp_int * b) { - mp_int x0, x1, t1, t2, x0x0, x1x1; - int B, err, x; + mp_int x0, x1, t1, t2, x0x0, x1x1; + int B, err, x; err = MP_MEM; diff --git a/bn_mp_lcm.c b/bn_mp_lcm.c index 7d38135..60d5461 100644 --- a/bn_mp_lcm.c +++ b/bn_mp_lcm.c @@ -18,8 +18,8 @@ int mp_lcm (mp_int * a, mp_int * b, mp_int * c) { - int res; - mp_int t; + int res; + mp_int t; if ((res = mp_init (&t)) != MP_OKAY) { diff --git a/bn_mp_lshd.c b/bn_mp_lshd.c index ea02409..44b0588 100644 --- a/bn_mp_lshd.c +++ b/bn_mp_lshd.c @@ -18,7 +18,7 @@ int mp_lshd (mp_int * a, int b) { - int x, res; + int x, res; /* if its less than zero return */ diff --git a/bn_mp_mod.c b/bn_mp_mod.c index 5b208a6..c4a7374 100644 --- a/bn_mp_mod.c +++ b/bn_mp_mod.c @@ -18,8 +18,8 @@ int mp_mod (mp_int * a, mp_int * b, mp_int * c) { - mp_int t; - int res; + mp_int t; + int res; if ((res = mp_init (&t)) != MP_OKAY) { diff --git a/bn_mp_mod_2d.c b/bn_mp_mod_2d.c index df73612..4c6f1f1 100644 --- a/bn_mp_mod_2d.c +++ b/bn_mp_mod_2d.c @@ -18,7 +18,7 @@ int mp_mod_2d (mp_int * a, int b, mp_int * c) { - int x, res; + int x, res; /* if b is <= 0 then zero the int */ @@ -44,8 +44,7 @@ mp_mod_2d (mp_int * a, int b, mp_int * c) } /* clear the digit that is not completely outside/inside the modulus */ c->dp[b / DIGIT_BIT] &= - (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - - ((mp_digit) 1)); + (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1)); mp_clamp (c); return MP_OKAY; } diff --git a/bn_mp_mod_d.c b/bn_mp_mod_d.c index 7b08d23..b557381 100644 --- a/bn_mp_mod_d.c +++ b/bn_mp_mod_d.c @@ -17,8 +17,8 @@ int mp_mod_d (mp_int * a, mp_digit b, mp_digit * c) { - mp_int t, t2; - int res; + mp_int t, t2; + int res; if ((res = mp_init (&t)) != MP_OKAY) { diff --git a/bn_mp_montgomery_calc_normalization.c b/bn_mp_montgomery_calc_normalization.c new file mode 100644 index 0000000..06252de --- /dev/null +++ b/bn_mp_montgomery_calc_normalization.c @@ -0,0 +1,53 @@ +/* LibTomMath, multiple-precision integer library -- Tom St Denis + * + * LibTomMath is library that provides for multiple-precision + * integer arithmetic as well as number theoretic functionality. + * + * The library is 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://libtommath.iahu.ca + */ +#include + +/* calculates a = B^n mod b for Montgomery reduction + * Where B is the base [e.g. 2^DIGIT_BIT]. + * B^n mod b is computed by first computing + * A = B^(n-1) which doesn't require a reduction but a simple OR. + * then C = A * B = B^n is computed by performing upto DIGIT_BIT + * shifts with subtractions when the result is greater than b. + * + * The method is slightly modified to shift B unconditionally upto just under + * the leading bit of b. This saves alot of multiple precision shifting. + */ +int +mp_montgomery_calc_normalization (mp_int * a, mp_int * b) +{ + int x, bits, res; + + /* how many bits of last digit does b use */ + bits = mp_count_bits (b) % DIGIT_BIT; + + /* compute A = B^(n-1) * 2^(bits-1) */ + if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) { + return res; + } + + /* now compute C = A * B mod b */ + for (x = bits - 1; x < DIGIT_BIT; x++) { + if ((res = mp_mul_2 (a, a)) != MP_OKAY) { + return res; + } + if (mp_cmp_mag (a, b) != MP_LT) { + if ((res = s_mp_sub (a, b, a)) != MP_OKAY) { + return res; + } + } + } + + return MP_OKAY; +} diff --git a/bn_mp_montgomery_reduce.c b/bn_mp_montgomery_reduce.c index aeb2cde..586142a 100644 --- a/bn_mp_montgomery_reduce.c +++ b/bn_mp_montgomery_reduce.c @@ -18,14 +18,13 @@ int mp_montgomery_reduce (mp_int * a, mp_int * m, mp_digit mp) { - int ix, res, digs; - mp_digit ui; + int ix, res, digs; + mp_digit ui; digs = m->used * 2 + 1; if ((digs < 512) && digs < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { - res = fast_mp_montgomery_reduce (a, m, mp); - return res; + return fast_mp_montgomery_reduce (a, m, mp); } if (a->alloc < m->used * 2 + 1) { @@ -51,9 +50,7 @@ mp_montgomery_reduce (mp_int * a, mp_int * m, mp_digit mp) mu = 0; for (iy = 0; iy < m->used; iy++) { - r = - ((mp_word) ui) * ((mp_word) * tmpx++) + ((mp_word) mu) + - ((mp_word) * tmpy); + r = ((mp_word) ui) * ((mp_word) * tmpx++) + ((mp_word) mu) + ((mp_word) * tmpy); mu = (r >> ((mp_word) DIGIT_BIT)); *tmpy++ = (r & ((mp_word) MP_MASK)); } @@ -71,9 +68,7 @@ mp_montgomery_reduce (mp_int * a, mp_int * m, mp_digit mp) /* if A >= m then A = A - m */ if (mp_cmp_mag (a, m) != MP_LT) { - if ((res = s_mp_sub (a, m, a)) != MP_OKAY) { - return res; - } + return s_mp_sub (a, m, a); } return MP_OKAY; diff --git a/bn_mp_montgomery_setup.c b/bn_mp_montgomery_setup.c index 601e74c..c739895 100644 --- a/bn_mp_montgomery_setup.c +++ b/bn_mp_montgomery_setup.c @@ -18,8 +18,8 @@ int mp_montgomery_setup (mp_int * a, mp_digit * mp) { - mp_int t, tt; - int res; + mp_int t, tt; + int res; if ((res = mp_init (&t)) != MP_OKAY) { return res; diff --git a/bn_mp_mul.c b/bn_mp_mul.c index cfa1467..064fc85 100644 --- a/bn_mp_mul.c +++ b/bn_mp_mul.c @@ -18,12 +18,26 @@ int 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; if (MIN (a->used, b->used) > KARATSUBA_MUL_CUTOFF) { res = mp_karatsuba_mul (a, b, c); } else { - res = s_mp_mul (a, b, c); + + /* can we use the fast multiplier? + * + * The fast multiplier can be used if the output will have less than + * 512 digits and the number of digits won't affect carry propagation + */ + int digs = a->used + b->used + 1; + + if ((digs < 512) + && digs < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + res = fast_s_mp_mul_digs (a, b, c, digs); + } else { + res = s_mp_mul (a, b, c); + } + } c->sign = neg; return res; diff --git a/bn_mp_mul_2.c b/bn_mp_mul_2.c index dd5ecca..8174d0a 100644 --- a/bn_mp_mul_2.c +++ b/bn_mp_mul_2.c @@ -18,27 +18,48 @@ int mp_mul_2 (mp_int * a, mp_int * b) { - mp_digit r, rr; - int x, res; + int x, res, oldused; + /* Optimization: should copy and shift at the same time */ - /* copy */ - if ((res = mp_copy (a, b)) != MP_OKAY) { - return res; + if (b->alloc < a->used) { + if ((res = mp_grow (b, a->used)) != MP_OKAY) { + return res; + } } - if ((res = mp_grow (b, b->used + 1)) != MP_OKAY) { - return res; - } - ++b->used; + oldused = b->used; + b->used = a->used; /* shift any bit count < DIGIT_BIT */ - r = 0; - for (x = 0; x < b->used; x++) { - rr = (b->dp[x] >> (DIGIT_BIT - 1)) & 1; - b->dp[x] = ((b->dp[x] << 1) | r) & MP_MASK; - r = rr; + { + register mp_digit r, rr, *tmpa, *tmpb; + + r = 0; + tmpa = a->dp; + tmpb = b->dp; + for (x = 0; x < b->used; x++) { + rr = *tmpa >> (DIGIT_BIT - 1); + *tmpb++ = ((*tmpa++ << 1) | r) & MP_MASK; + r = rr; + } + + /* new leading digit? */ + if (r != 0) { + if (b->alloc == b->used) { + if ((res = mp_grow (b, b->used + 1)) != MP_OKAY) { + return res; + } + } + /* add a MSB of 1 */ + *tmpb = 1; + ++b->used; + } + + tmpb = b->dp + b->used; + for (x = b->used; x < oldused; x++) { + *tmpb++ = 0; + } } - mp_clamp (b); return MP_OKAY; } diff --git a/bn_mp_mul_2d.c b/bn_mp_mul_2d.c index 7823eb9..97ee26c 100644 --- a/bn_mp_mul_2d.c +++ b/bn_mp_mul_2d.c @@ -18,8 +18,8 @@ int mp_mul_2d (mp_int * a, int b, mp_int * c) { - mp_digit d, r, rr; - int x, res; + mp_digit d, r, rr; + int x, res; /* copy */ diff --git a/bn_mp_mul_d.c b/bn_mp_mul_d.c index bced9b7..164bcac 100644 --- a/bn_mp_mul_d.c +++ b/bn_mp_mul_d.c @@ -18,29 +18,40 @@ int mp_mul_d (mp_int * a, mp_digit b, mp_int * c) { - int res, pa, ix; - mp_word r; - mp_digit u; - mp_int t; - + int res, pa, olduse; pa = a->used; - if ((res = mp_init_size (&t, pa + 2)) != MP_OKAY) { - return res; + if (c->alloc < pa + 1) { + if ((res = mp_grow (c, pa + 1)) != MP_OKAY) { + return res; + } } - t.used = pa + 2; - u = 0; - for (ix = 0; ix < pa; ix++) { - r = ((mp_word) u) + ((mp_word) a->dp[ix]) * ((mp_word) b); - t.dp[ix] = (mp_digit) (r & ((mp_word) MP_MASK)); - u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); + olduse = c->used; + c->used = pa + 1; + + { + register mp_digit u, *tmpa, *tmpc; + register mp_word r; + register int ix; + + tmpc = c->dp + c->used; + for (ix = c->used; ix < olduse; ix++) { + *tmpc++ = 0; + } + + tmpa = a->dp; + tmpc = c->dp; + + u = 0; + for (ix = 0; ix < pa; ix++) { + r = ((mp_word) u) + ((mp_word) * tmpa++) * ((mp_word) b); + *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK)); + u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); + } + *tmpc = u; } - t.dp[ix] = u; - t.sign = a->sign; - mp_clamp (&t); - mp_exch (&t, c); - mp_clear (&t); + mp_clamp (c); return MP_OKAY; } diff --git a/bn_mp_mulmod.c b/bn_mp_mulmod.c index 2cdbdda..abdf77b 100644 --- a/bn_mp_mulmod.c +++ b/bn_mp_mulmod.c @@ -18,8 +18,8 @@ int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) { - int res; - mp_int t; + int res; + mp_int t; if ((res = mp_init (&t)) != MP_OKAY) { diff --git a/bn_mp_n_root.c b/bn_mp_n_root.c index 72b3a8c..eb49b3f 100644 --- a/bn_mp_n_root.c +++ b/bn_mp_n_root.c @@ -17,12 +17,16 @@ /* find the n'th root of an integer * * Result found such that (c)^b <= a and (c+1)^b > a + * + * This algorithm uses Newton's approximation x[i+1] = x[i] - f(x[i])/f'(x[i]) + * which will find the root in log(N) time where each step involves a fair bit. This + * is not meant to find huge roots [square and cube at most]. */ int mp_n_root (mp_int * a, mp_digit b, mp_int * c) { - mp_int t1, t2, t3; - int res, neg; + mp_int t1, t2, t3; + int res, neg; /* input must be positive if b is even */ if ((b & 1) == 0 && a->sign == MP_NEG) { diff --git a/bn_mp_neg.c b/bn_mp_neg.c index a2bb7c4..fd2e497 100644 --- a/bn_mp_neg.c +++ b/bn_mp_neg.c @@ -18,7 +18,7 @@ int mp_neg (mp_int * a, mp_int * b) { - int res; + int res; if ((res = mp_copy (a, b)) != MP_OKAY) { return res; } diff --git a/bn_mp_or.c b/bn_mp_or.c index a3843d9..e821bac 100644 --- a/bn_mp_or.c +++ b/bn_mp_or.c @@ -18,8 +18,8 @@ int mp_or (mp_int * a, mp_int * b, mp_int * c) { - int res, ix, px; - mp_int t, *x; + int res, ix, px; + mp_int t, *x; if (a->used > b->used) { if ((res = mp_init_copy (&t, a)) != MP_OKAY) { diff --git a/bn_mp_rand.c b/bn_mp_rand.c index c72dec9..dc13534 100644 --- a/bn_mp_rand.c +++ b/bn_mp_rand.c @@ -18,8 +18,8 @@ int mp_rand (mp_int * a, int digits) { - int res; - mp_digit d; + int res; + mp_digit d; mp_zero (a); if (digits <= 0) { @@ -27,19 +27,20 @@ mp_rand (mp_int * a, int digits) } /* first place a random non-zero digit */ - d = ((mp_digit) abs (rand ())); - d = d == 0 ? 1 : d; + do { + d = ((mp_digit) abs (rand ())); + } while (d == 0); if ((res = mp_add_d (a, d, a)) != MP_OKAY) { return res; } - while (digits-- > 0) { - if ((res = mp_add_d (a, ((mp_digit) abs (rand ())), a)) != MP_OKAY) { + if ((res = mp_lshd (a, 1)) != MP_OKAY) { return res; } - if ((res = mp_lshd (a, 1)) != MP_OKAY) { + + if ((res = mp_add_d (a, ((mp_digit) abs (rand ())), a)) != MP_OKAY) { return res; } } diff --git a/bn_mp_read_signed_bin.c b/bn_mp_read_signed_bin.c index b5af4c0..8a9df88 100644 --- a/bn_mp_read_signed_bin.c +++ b/bn_mp_read_signed_bin.c @@ -18,7 +18,7 @@ int mp_read_signed_bin (mp_int * a, unsigned char *b, int c) { - int res; + int res; if ((res = mp_read_unsigned_bin (a, b + 1, c - 1)) != MP_OKAY) { return res; diff --git a/bn_mp_read_unsigned_bin.c b/bn_mp_read_unsigned_bin.c index 726b574..16e2f29 100644 --- a/bn_mp_read_unsigned_bin.c +++ b/bn_mp_read_unsigned_bin.c @@ -18,7 +18,7 @@ int mp_read_unsigned_bin (mp_int * a, unsigned char *b, int c) { - int res; + int res; mp_zero (a); while (c-- > 0) { if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) { diff --git a/bn_mp_reduce.c b/bn_mp_reduce.c index be5d18e..8f15458 100644 --- a/bn_mp_reduce.c +++ b/bn_mp_reduce.c @@ -20,7 +20,7 @@ int mp_reduce_setup (mp_int * a, mp_int * b) { - int res; + int res; if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) { @@ -36,8 +36,8 @@ mp_reduce_setup (mp_int * a, mp_int * b) int mp_reduce (mp_int * x, mp_int * m, mp_int * mu) { - mp_int q; - int res, um = m->used; + mp_int q; + int res, um = m->used; if ((res = mp_init_copy (&q, x)) != MP_OKAY) { diff --git a/bn_mp_rshd.c b/bn_mp_rshd.c index 8b37d09..39e631e 100644 --- a/bn_mp_rshd.c +++ b/bn_mp_rshd.c @@ -18,7 +18,7 @@ void mp_rshd (mp_int * a, int b) { - int x; + int x; /* if b <= 0 then ignore it */ diff --git a/bn_mp_set_int.c b/bn_mp_set_int.c index a690bb4..f22ab69 100644 --- a/bn_mp_set_int.c +++ b/bn_mp_set_int.c @@ -18,7 +18,7 @@ int mp_set_int (mp_int * a, unsigned long b) { - int x, res; + int x, res; mp_zero (a); diff --git a/bn_mp_sqr.c b/bn_mp_sqr.c index 2ba877c..c8b5cb7 100644 --- a/bn_mp_sqr.c +++ b/bn_mp_sqr.c @@ -18,11 +18,18 @@ int mp_sqr (mp_int * a, mp_int * b) { - int res; + int res; if (a->used > KARATSUBA_SQR_CUTOFF) { res = mp_karatsuba_sqr (a, b); } else { - res = s_mp_sqr (a, b); + + /* can we use the fast multiplier? */ + if (((a->used * 2 + 1) < 512) + && a->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT) - 1))) { + res = fast_s_mp_sqr (a, b); + } else { + res = s_mp_sqr (a, b); + } } b->sign = MP_ZPOS; return res; diff --git a/bn_mp_sqrmod.c b/bn_mp_sqrmod.c index 66135d4..44f608f 100644 --- a/bn_mp_sqrmod.c +++ b/bn_mp_sqrmod.c @@ -18,8 +18,8 @@ int mp_sqrmod (mp_int * a, mp_int * b, mp_int * c) { - int res; - mp_int t; + int res; + mp_int t; if ((res = mp_init (&t)) != MP_OKAY) { diff --git a/bn_mp_sub.c b/bn_mp_sub.c index 045dee5..1366c55 100644 --- a/bn_mp_sub.c +++ b/bn_mp_sub.c @@ -18,7 +18,7 @@ int mp_sub (mp_int * a, mp_int * b, mp_int * c) { - int sa, sb, res; + int sa, sb, res; sa = a->sign; diff --git a/bn_mp_sub_d.c b/bn_mp_sub_d.c index 9839d5e..aebc414 100644 --- a/bn_mp_sub_d.c +++ b/bn_mp_sub_d.c @@ -18,8 +18,8 @@ int mp_sub_d (mp_int * a, mp_digit b, mp_int * c) { - mp_int t; - int res; + mp_int t; + int res; if ((res = mp_init (&t)) != MP_OKAY) { diff --git a/bn_mp_submod.c b/bn_mp_submod.c index b56d921..16fee71 100644 --- a/bn_mp_submod.c +++ b/bn_mp_submod.c @@ -18,8 +18,8 @@ int mp_submod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) { - int res; - mp_int t; + int res; + mp_int t; if ((res = mp_init (&t)) != MP_OKAY) { diff --git a/bn_mp_to_signed_bin.c b/bn_mp_to_signed_bin.c index b00cf8f..41abac1 100644 --- a/bn_mp_to_signed_bin.c +++ b/bn_mp_to_signed_bin.c @@ -18,7 +18,7 @@ int mp_to_signed_bin (mp_int * a, unsigned char *b) { - int res; + int res; if ((res = mp_to_unsigned_bin (a, b + 1)) != MP_OKAY) { return res; diff --git a/bn_mp_to_unsigned_bin.c b/bn_mp_to_unsigned_bin.c index b122555..eec9f75 100644 --- a/bn_mp_to_unsigned_bin.c +++ b/bn_mp_to_unsigned_bin.c @@ -18,8 +18,8 @@ int mp_to_unsigned_bin (mp_int * a, unsigned char *b) { - int x, res; - mp_int t; + int x, res; + mp_int t; if ((res = mp_init_copy (&t, a)) != MP_OKAY) { return res; diff --git a/bn_mp_unsigned_bin_size.c b/bn_mp_unsigned_bin_size.c index 1c92b5c..bee88e6 100644 --- a/bn_mp_unsigned_bin_size.c +++ b/bn_mp_unsigned_bin_size.c @@ -18,6 +18,6 @@ int mp_unsigned_bin_size (mp_int * a) { - int size = mp_count_bits (a); + int size = mp_count_bits (a); return (size / 8 + ((size & 7) != 0 ? 1 : 0)); } diff --git a/bn_mp_xor.c b/bn_mp_xor.c index c8e9f43..4a2ff9b 100644 --- a/bn_mp_xor.c +++ b/bn_mp_xor.c @@ -18,8 +18,8 @@ int mp_xor (mp_int * a, mp_int * b, mp_int * c) { - int res, ix, px; - mp_int t, *x; + int res, ix, px; + mp_int t, *x; if (a->used > b->used) { if ((res = mp_init_copy (&t, a)) != MP_OKAY) { diff --git a/bn_radix.c b/bn_radix.c index 1fc4b35..205c148 100644 --- a/bn_radix.c +++ b/bn_radix.c @@ -15,16 +15,15 @@ #include /* chars used in radix conversions */ -static const char *s_rmap = - "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; +static const char *s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/"; /* read a string [ASCII] in a given radix */ int mp_read_radix (mp_int * a, char *str, int radix) { - int y, res, neg; - char ch; + int y, res, neg; + char ch; if (radix < 2 || radix > 64) { return MP_VAL; @@ -66,10 +65,10 @@ mp_read_radix (mp_int * a, char *str, int radix) int mp_toradix (mp_int * a, char *str, int radix) { - int res, digs; - mp_int t; - mp_digit d; - char *_s = str; + int res, digs; + mp_int t; + mp_digit d; + char *_s = str; if (radix < 2 || radix > 64) { return MP_VAL; @@ -104,9 +103,9 @@ mp_toradix (mp_int * a, char *str, int radix) int mp_radix_size (mp_int * a, int radix) { - int res, digs; - mp_int t; - mp_digit d; + int res, digs; + mp_int t; + mp_digit d; /* special case for binary */ if (radix == 2) { diff --git a/bn_reverse.c b/bn_reverse.c index 10c2375..50109d7 100644 --- a/bn_reverse.c +++ b/bn_reverse.c @@ -18,7 +18,7 @@ void bn_reverse (unsigned char *s, int len) { - int ix, iy; + int ix, iy; unsigned char t; ix = 0; diff --git a/bn_s_mp_add.c b/bn_s_mp_add.c index 369a0e1..328ec06 100644 --- a/bn_s_mp_add.c +++ b/bn_s_mp_add.c @@ -18,10 +18,8 @@ int s_mp_add (mp_int * a, mp_int * b, mp_int * c) { - mp_int *x; - int olduse, res, min, max, i; - mp_digit u; - + mp_int *x; + int olduse, res, min, max; /* find sizes, we let |a| <= |b| which means we have to sort * them. "x" will point to the input with the most digits @@ -52,38 +50,48 @@ s_mp_add (mp_int * a, mp_int * b, mp_int * c) /* add digits from lower part */ /* set the carry to zero */ - u = 0; - for (i = 0; i < min; i++) { - /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */ - c->dp[i] = a->dp[i] + b->dp[i] + u; + { + register mp_digit u, *tmpa, *tmpb, *tmpc; + register int i; - /* U = carry bit of T[i] */ - u = (c->dp[i] >> DIGIT_BIT) & 1; + /* alias for digit pointers */ + tmpa = a->dp; + tmpb = b->dp; + tmpc = c->dp; - /* take away carry bit from T[i] */ - c->dp[i] &= MP_MASK; - } - - /* now copy higher words if any, that is in A+B if A or B has more digits add those in */ - if (min != max) { - for (; i < max; i++) { - /* T[i] = X[i] + U */ - c->dp[i] = x->dp[i] + u; + u = 0; + for (i = 0; i < min; i++) { + /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */ + *tmpc = *tmpa++ + *tmpb++ + u; /* U = carry bit of T[i] */ - u = (c->dp[i] >> DIGIT_BIT) & 1; + u = *tmpc >> DIGIT_BIT; /* take away carry bit from T[i] */ - c->dp[i] &= MP_MASK; + *tmpc++ &= MP_MASK; } - } - /* add carry */ - c->dp[i] = u; + /* now copy higher words if any, that is in A+B if A or B has more digits add those in */ + if (min != max) { + for (; i < max; i++) { + /* T[i] = X[i] + U */ + *tmpc = x->dp[i] + u; - /* clear digits above used (since we may not have grown result above) */ - for (i = c->used; i < olduse; i++) { - c->dp[i] = 0; + /* U = carry bit of T[i] */ + u = *tmpc >> DIGIT_BIT; + + /* take away carry bit from T[i] */ + *tmpc++ &= MP_MASK; + } + } + + /* add carry */ + *tmpc++ = u; + + /* clear digits above used (since we may not have grown result above) */ + for (i = c->used; i < olduse; i++) { + *tmpc++ = 0; + } } mp_clamp (c); diff --git a/bn_s_mp_mul_digs.c b/bn_s_mp_mul_digs.c index 55522a1..f2b0d13 100644 --- a/bn_s_mp_mul_digs.c +++ b/bn_s_mp_mul_digs.c @@ -21,23 +21,11 @@ int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) { - mp_int t; - int res, pa, pb, ix, iy; - mp_digit u; - mp_word r; - mp_digit tmpx, *tmpt, *tmpy; - - - /* can we use the fast multiplier? - * - * The fast multiplier can be used if the output will have less than - * 512 digits and the number of digits won't affect carry propagation - */ - if ((digs < 512) - && digs < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { - res = fast_s_mp_mul_digs (a, b, c, digs); - return res; - } + mp_int t; + int res, pa, pb, ix, iy; + mp_digit u; + mp_word r; + mp_digit tmpx, *tmpt, *tmpy; if ((res = mp_init_size (&t, digs)) != MP_OKAY) { return res; @@ -61,9 +49,7 @@ s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) /* compute the columns of the output and propagate the carry */ for (iy = 0; iy < pb; iy++) { /* compute the column as a mp_word */ - r = - ((mp_word) * tmpt) + ((mp_word) tmpx) * ((mp_word) * tmpy++) + - ((mp_word) u); + r = ((mp_word) * tmpt) + ((mp_word) tmpx) * ((mp_word) * tmpy++) + ((mp_word) u); /* the new column is the lower part of the result */ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); diff --git a/bn_s_mp_mul_high_digs.c b/bn_s_mp_mul_high_digs.c index ff2530f..a43a593 100644 --- a/bn_s_mp_mul_high_digs.c +++ b/bn_s_mp_mul_high_digs.c @@ -20,20 +20,17 @@ int s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) { - mp_int t; - int res, pa, pb, ix, iy; - mp_digit u; - mp_word r; - mp_digit tmpx, *tmpt, *tmpy; + mp_int t; + int res, pa, pb, ix, iy; + mp_digit u; + mp_word r; + mp_digit tmpx, *tmpt, *tmpy; /* can we use the fast multiplier? */ if (((a->used + b->used + 1) < 512) - && MAX (a->used, - b->used) < - (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { - res = fast_s_mp_mul_high_digs (a, b, c, digs); - return res; + && MAX (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + return fast_s_mp_mul_high_digs (a, b, c, digs); } if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) { @@ -58,9 +55,7 @@ s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) for (iy = digs - ix; iy < pb; iy++) { /* calculate the double precision result */ - r = - ((mp_word) * tmpt) + ((mp_word) tmpx) * ((mp_word) * tmpy++) + - ((mp_word) u); + r = ((mp_word) * tmpt) + ((mp_word) tmpx) * ((mp_word) * tmpy++) + ((mp_word) u); /* get the lower part */ *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); diff --git a/bn_s_mp_sqr.c b/bn_s_mp_sqr.c index 94449a3..a0ec38b 100644 --- a/bn_s_mp_sqr.c +++ b/bn_s_mp_sqr.c @@ -18,18 +18,10 @@ int s_mp_sqr (mp_int * a, mp_int * b) { - mp_int t; - int res, ix, iy, pa; - mp_word r, u; - mp_digit tmpx, *tmpt; - - /* can we use the fast multiplier? */ - if (((a->used * 2 + 1) < 512) - && a->used < - (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT) - 1))) { - res = fast_s_mp_sqr (a, b); - return res; - } + mp_int t; + int res, ix, iy, pa; + mp_word r, u; + mp_digit tmpx, *tmpt; pa = a->used; if ((res = mp_init_size (&t, pa + pa + 1)) != MP_OKAY) { @@ -40,9 +32,7 @@ s_mp_sqr (mp_int * a, mp_int * b) for (ix = 0; ix < pa; ix++) { /* first calculate the digit at 2*ix */ /* calculate double precision result */ - r = - ((mp_word) t.dp[ix + ix]) + - ((mp_word) a->dp[ix]) * ((mp_word) a->dp[ix]); + r = ((mp_word) t.dp[ix + ix]) + ((mp_word) a->dp[ix]) * ((mp_word) a->dp[ix]); /* store lower part in result */ t.dp[ix + ix] = (mp_digit) (r & ((mp_word) MP_MASK)); diff --git a/bn_s_mp_sub.c b/bn_s_mp_sub.c index f6da162..fe15d23 100644 --- a/bn_s_mp_sub.c +++ b/bn_s_mp_sub.c @@ -18,9 +18,7 @@ int s_mp_sub (mp_int * a, mp_int * b, mp_int * c) { - int olduse, res, min, max, i; - mp_digit u; - + int olduse, res, min, max; /* find sizes */ min = b->used; @@ -37,36 +35,48 @@ s_mp_sub (mp_int * a, mp_int * b, mp_int * c) /* sub digits from lower part */ - /* set carry to zero */ - u = 0; - for (i = 0; i < min; i++) { - /* T[i] = A[i] - B[i] - U */ - c->dp[i] = a->dp[i] - (b->dp[i] + u); + { + register mp_digit u, *tmpa, *tmpb, *tmpc; + register int i; - /* U = carry bit of T[i] */ - u = (c->dp[i] >> DIGIT_BIT) & 1; + /* alias for digit pointers */ + tmpa = a->dp; + tmpb = b->dp; + tmpc = c->dp; - /* Clear carry from T[i] */ - c->dp[i] &= MP_MASK; - } + /* set carry to zero */ + u = 0; + for (i = 0; i < min; i++) { + /* T[i] = A[i] - B[i] - U */ + *tmpc = *tmpa++ - *tmpb++ - u; - /* now copy higher words if any, e.g. if A has more digits than B */ - if (min != max) { - for (; i < max; i++) { - /* T[i] = A[i] - U */ - c->dp[i] = a->dp[i] - u; - - /* U = carry bit of T[i] */ - u = (c->dp[i] >> DIGIT_BIT) & 1; + /* U = carry bit of T[i] + * Note this saves performing an AND operation since + * if a carry does occur it will propagate all the way to the + * MSB. As a result a single shift is required to get the carry + */ + u = *tmpc >> (CHAR_BIT * sizeof (mp_digit) - 1); /* Clear carry from T[i] */ - c->dp[i] &= MP_MASK; + *tmpc++ &= MP_MASK; } - } - /* clear digits above used (since we may not have grown result above) */ - for (i = c->used; i < olduse; i++) { - c->dp[i] = 0; + /* now copy higher words if any, e.g. if A has more digits than B */ + for (; i < max; i++) { + /* T[i] = A[i] - U */ + *tmpc = *tmpa++ - u; + + /* U = carry bit of T[i] */ + u = *tmpc >> (CHAR_BIT * sizeof (mp_digit) - 1); + + /* Clear carry from T[i] */ + *tmpc++ &= MP_MASK; + } + + /* clear digits above used (since we may not have grown result above) */ + for (i = c->used; i < olduse; i++) { + *tmpc++ = 0; + } } mp_clamp (c); diff --git a/bncore.c b/bncore.c index 5c7d098..8863935 100644 --- a/bncore.c +++ b/bncore.c @@ -14,6 +14,6 @@ */ #include -int KARATSUBA_MUL_CUTOFF = 80, /* Min. number of digits before Karatsuba multiplication is used. */ - KARATSUBA_SQR_CUTOFF = 80, /* Min. number of digits before Karatsuba squaring is used. */ - MONTGOMERY_EXPT_CUTOFF = 40; /* max. number of digits that montgomery reductions will help for */ +int KARATSUBA_MUL_CUTOFF = 80, /* Min. number of digits before Karatsuba multiplication is used. */ + KARATSUBA_SQR_CUTOFF = 80, /* Min. number of digits before Karatsuba squaring is used. */ + MONTGOMERY_EXPT_CUTOFF = 74; /* max. number of digits that montgomery reductions will help for */ diff --git a/changes.txt b/changes.txt index e2c9903..c31526e 100644 --- a/changes.txt +++ b/changes.txt @@ -1,3 +1,9 @@ +Feb 13th, 2003 +v0.13 -- tons of minor speed-ups in low level add, sub, mul_2 and div_2 which propagate + to other functions like mp_invmod, mp_div, etc... + -- Sped up mp_exptmod_fast by using new code to find R mod m [e.g. B^n mod m] + -- minor fixes + Jan 17th, 2003 v0.12 -- re-wrote the majority of the makefile so its more portable and will install via "make install" on most *nix platforms diff --git a/demo/demo.c b/demo/demo.c index 3c3ef07..8bf9acd 100644 --- a/demo/demo.c +++ b/demo/demo.c @@ -76,7 +76,7 @@ int main(void) { mp_int a, b, c, d, e, f; unsigned long expt_n, add_n, sub_n, mul_n, div_n, sqr_n, mul2d_n, div2d_n, gcd_n, lcm_n, inv_n; - int rr; + unsigned rr; #ifdef TIMER int n; @@ -90,42 +90,20 @@ int main(void) mp_init(&e); mp_init(&f); -#ifdef DEBUG - mp_read_radix(&a, "347743159439876626079252796797422223177535447388206607607181663903045907591201940478223621722118173270898487582987137708656414344685816179420855160986340457973820182883508387588163122354089264395604796675278966117567294812714812796820596564876450716066283126720010859041484786529056457896367683122960411136319", 10); - mp_read_radix(&b, "347743159439876626079252796797422223177535447388206607607181663903045907591201940478223621722118173270898487582987137708656414344685816179420855160986340457973820182883508387588163122354089264395604796675278966117567294812714812796820596564876450716066283126720010859041484786529056457896367683122960411136318", 10); - mp_set(&c, 1); - reset_timings(); - mp_exptmod(&c, &b, &a, &d); - mp_exptmod(&c, &b, &a, &d); - mp_exptmod(&c, &b, &a, &d); - mp_exptmod(&c, &b, &a, &d); - mp_exptmod(&c, &b, &a, &d); - mp_exptmod(&c, &b, &a, &d); - mp_exptmod(&c, &b, &a, &d); - mp_exptmod(&c, &b, &a, &d); - mp_exptmod(&c, &b, &a, &d); - mp_exptmod(&c, &b, &a, &d); - mp_exptmod(&c, &b, &a, &d); - mp_exptmod(&c, &b, &a, &d); - mp_exptmod(&c, &b, &a, &d); - mp_exptmod(&c, &b, &a, &d); - mp_exptmod(&c, &b, &a, &d); - mp_exptmod(&c, &b, &a, &d); - dump_timings(); - return 0; -#endif #ifdef TIMER +goto multtime; + printf("CLOCKS_PER_SEC == %lu\n", CLOCKS_PER_SEC); mp_read_radix(&a, "340282366920938463463374607431768211455", 10); mp_read_radix(&b, "340282366920938463463574607431768211455", 10); while (a.used * DIGIT_BIT < 8192) { reset(); - for (rr = 0; rr < 1000000; rr++) { + for (rr = 0; rr < 10000000; rr++) { mp_add(&a, &b, &c); } tt = rdtsc(); - printf("Adding %d-bit took %f ticks\n", mp_count_bits(&a), (double)tt / ((double)1000000)); + printf("Adding\t\t%4d-bit => %9llu/sec, %9llu ticks\n", mp_count_bits(&a), (((unsigned long long)rr)*CLOCKS_PER_SEC)/tt, tt); mp_sqr(&a, &a); mp_sqr(&b, &b); } @@ -134,37 +112,40 @@ int main(void) mp_read_radix(&b, "340282366920938463463574607431768211455", 10); while (a.used * DIGIT_BIT < 8192) { reset(); - for (rr = 0; rr < 1000000; rr++) { + for (rr = 0; rr < 10000000; rr++) { mp_sub(&a, &b, &c); } tt = rdtsc(); - printf("Subtracting %d-bit took %f ticks\n", mp_count_bits(&a), (double)tt / ((double)1000000)); + printf("Subtracting\t%4d-bit => %9llu/sec, %9llu ticks\n", mp_count_bits(&a), (((unsigned long long)rr)*CLOCKS_PER_SEC)/tt, tt); mp_sqr(&a, &a); mp_sqr(&b, &b); } + +multtime: mp_read_radix(&a, "340282366920938463463374607431768211455", 10); while (a.used * DIGIT_BIT < 8192) { reset(); - for (rr = 0; rr < 1000000; rr++) { + for (rr = 0; rr < 250000; rr++) { mp_sqr(&a, &b); } tt = rdtsc(); - printf("Squaring %d-bit took %f ticks\n", mp_count_bits(&a), (double)tt / ((double)1000000)); + printf("Squaring\t%4d-bit => %9llu/sec, %9llu ticks\n", mp_count_bits(&a), (((unsigned long long)rr)*CLOCKS_PER_SEC)/tt, tt); mp_copy(&b, &a); } mp_read_radix(&a, "340282366920938463463374607431768211455", 10); while (a.used * DIGIT_BIT < 8192) { reset(); - for (rr = 0; rr < 1000000; rr++) { + for (rr = 0; rr < 250000; rr++) { mp_mul(&a, &a, &b); } tt = rdtsc(); - printf("Multiplying %d-bit took %f ticks\n", mp_count_bits(&a), (double)tt / ((double)1000000)); + printf("Multiplying\t%4d-bit => %9llu/sec, %9llu ticks\n", mp_count_bits(&a), (((unsigned long long)rr)*CLOCKS_PER_SEC)/tt, tt); mp_copy(&b, &a); } - + +expttime: { char *primes[] = { "17933601194860113372237070562165128350027320072176844226673287945873370751245439587792371960615073855669274087805055507977323024886880985062002853331424203", @@ -180,7 +161,7 @@ int main(void) mp_read_radix(&a, primes[n], 10); mp_zero(&b); for (rr = 0; rr < mp_count_bits(&a); rr++) { - mp_mul_2d(&b, 1, &b); + mp_mul_2(&b, &b); b.dp[0] |= lbit(); b.used += 1; } @@ -188,7 +169,7 @@ int main(void) mp_mod(&b, &c, &b); mp_set(&c, 3); reset(); - for (rr = 0; rr < 100; rr++) { + for (rr = 0; rr < 50; rr++) { mp_exptmod(&c, &b, &a, &d); } tt = rdtsc(); @@ -201,16 +182,15 @@ int main(void) draw(&d); exit(0); } - printf("Exponentiating %d-bit took %f ticks\n", mp_count_bits(&a), (double)tt / ((double)100)); + printf("Exponentiating\t%4d-bit => %9llu/sec, %9llu ticks\n", mp_count_bits(&a), (((unsigned long long)rr)*CLOCKS_PER_SEC)/tt, tt); } } - mp_read_radix(&a, "340282366920938463463374607431768211455", 10); mp_read_radix(&b, "234892374891378913789237289378973232333", 10); while (a.used * DIGIT_BIT < 8192) { reset(); - for (rr = 0; rr < 100; rr++) { + for (rr = 0; rr < 10000; rr++) { mp_invmod(&b, &a, &c); } tt = rdtsc(); @@ -219,7 +199,7 @@ int main(void) printf("Failed to invert\n"); return 0; } - printf("Inverting mod %d-bit took %f ticks\n", mp_count_bits(&a), (double)tt / ((double)100)); + printf("Inverting mod\t%4d-bit => %9llu/sec, %9llu ticks\n", mp_count_bits(&a), (((unsigned long long)rr)*CLOCKS_PER_SEC)/tt, tt); mp_sqr(&a, &a); mp_sqr(&b, &b); } diff --git a/etc/makefile b/etc/makefile index 7a98e09..bf4befb 100644 --- a/etc/makefile +++ b/etc/makefile @@ -1,15 +1,20 @@ -CFLAGS += -Wall -W -Wshadow -O3 -fomit-frame-pointer -funroll-loops +CFLAGS += -Wall -W -Wshadow -O3 -fomit-frame-pointer -funroll-loops -I../ + + +# default lib name (requires install with root) +# LIBNAME=-ltommath + +# libname when you can't install the lib with install +LIBNAME=../libtommath.a pprime: pprime.o - $(CC) pprime.o -ltommath -o pprime + $(CC) pprime.o $(LIBNAME) -o pprime tune: tune.o - $(CC) tune.o -ltommath -o tune + $(CC) tune.o $(LIBNAME) -o tune mersenne: mersenne.o - $(CC) mersenne.o -ltommath -o mersenne + $(CC) mersenne.o $(LIBNAME) -o mersenne clean: - rm -f *.o pprime tune mersenne - - + rm -f *.o *.exe pprime tune mersenne \ No newline at end of file diff --git a/etc/pprime.c b/etc/pprime.c index c136901..6fea3da 100644 --- a/etc/pprime.c +++ b/etc/pprime.c @@ -5,7 +5,7 @@ * Tom St Denis, tomstdenis@iahu.ca, http://tom.iahu.ca */ #include -#include "bn.h" +#include "tommath.h" /* fast square root */ static mp_digit diff --git a/etc/tune.c b/etc/tune.c index 0d03e77..73a44b7 100644 --- a/etc/tune.c +++ b/etc/tune.c @@ -18,9 +18,9 @@ time_mult (void) t1 = clock (); for (x = 8; x <= 128; x += 8) { - mp_rand (&a, x); - mp_rand (&b, x); - for (y = 0; y < 10000; y++) { + for (y = 0; y < 1000; y++) { + mp_rand (&a, x); + mp_rand (&b, x); mp_mul (&a, &b, &c); } } @@ -42,8 +42,8 @@ time_sqr (void) t1 = clock (); for (x = 8; x <= 128; x += 8) { - mp_rand (&a, x); - for (y = 0; y < 10000; y++) { + for (y = 0; y < 1000; y++) { + mp_rand (&a, x); mp_sqr (&a, &b); } } diff --git a/gen.pl b/gen.pl new file mode 100644 index 0000000..fcfd57d --- /dev/null +++ b/gen.pl @@ -0,0 +1,27 @@ +#!/usr/bin/perl +# +#Generates a "single file" you can use to quickly add the whole source +#without any makefile troubles +# + +opendir(DIR,"."); +@files = readdir(DIR); +closedir(DIR); + +open(OUT,">mpi.c"); +print OUT "/* File Generated Automatically by gen.pl */\n\n"; +for (@files) { + if ($_ =~ /\.c/ && !($_ =~ /mpi\.c/)) { + $fname = $_; + open(SRC,"<$fname"); + print OUT "/* Start: $fname */\n"; + while () { + print OUT $_; + } + close(SRC); + print OUT "\n/* End: $fname */\n\n"; + } +} +print OUT "\n/* EOF */\n"; +close(OUT); + \ No newline at end of file diff --git a/ltmtest.exe b/ltmtest.exe deleted file mode 100644 index cc5c1f527ef8bd2b5390f81aee0cade8570440bf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49664 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%0D1{ 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 Ma(y5E{F5#42L#$CUjP6A diff --git a/makefile b/makefile index 5f6bcc6..9e6127d 100644 --- a/makefile +++ b/makefile @@ -1,6 +1,6 @@ CFLAGS += -I./ -Wall -W -Wshadow -O3 -fomit-frame-pointer -funroll-loops -VERSION=0.12 +VERSION=0.13 default: libtommath.a @@ -30,7 +30,7 @@ bn_mp_reduce.o bn_mp_montgomery_setup.o bn_fast_mp_montgomery_reduce.o bn_mp_mon 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_radix.o \ -bn_mp_xor.o bn_mp_and.o bn_mp_or.o bn_mp_rand.o +bn_mp_xor.o bn_mp_and.o bn_mp_or.o bn_mp_rand.o bn_mp_montgomery_calc_normalization.o libtommath.a: $(OBJECTS) $(AR) $(ARFLAGS) libtommath.a $(OBJECTS) @@ -60,8 +60,8 @@ docs: docdvi rm -f bn.log bn.aux bn.dvi clean: - rm -f *.pdf *.o *.a etclib/*.o demo/demo.o test ltmtest mpitest mtest/mtest \ - bn.log bn.aux bn.dvi *.log *.s + rm -f *.pdf *.o *.a *.exe etclib/*.o demo/demo.o test ltmtest mpitest mtest/mtest mtest/mtest.exe \ + bn.log bn.aux bn.dvi *.log *.s mpi.c cd etc ; make clean zipup: clean docs diff --git a/mpitest.exe b/mpitest.exe deleted file mode 100644 index d32553a3fbc32b23fc6cbd25cabbb350f509c5b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58368 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 K`@gT_z<&VQLV%tC diff --git a/mtest/mtest.c b/mtest/mtest.c index 17aef8d..3759d15 100644 --- a/mtest/mtest.c +++ b/mtest/mtest.c @@ -89,7 +89,7 @@ int main(void) } for (;;) { - n = fgetc(rng) % 11; + n = 4; // fgetc(rng) % 11; if (n == 0) { /* add tests */ diff --git a/timings.txt b/timings.txt index 117b9c5..128649e 100644 --- a/timings.txt +++ b/timings.txt @@ -1,39 +1,36 @@ -CLOCKS_PER_SEC == 1000000 -Adding 128-bit took 0.070000 ticks -Adding 256-bit took 0.100000 ticks -Adding 512-bit took 0.140000 ticks -Adding 1024-bit took 0.210000 ticks -Adding 2048-bit took 0.360000 ticks -Adding 4096-bit took 0.670000 ticks -Subtracting 128-bit took 0.090000 ticks -Subtracting 256-bit took 0.120000 ticks -Subtracting 512-bit took 0.140000 ticks -Subtracting 1024-bit took 0.210000 ticks -Subtracting 2048-bit took 0.330000 ticks -Subtracting 4096-bit took 0.580000 ticks -Squaring 128-bit took 0.320000 ticks -Squaring 256-bit took 0.620000 ticks -Squaring 512-bit took 1.410000 ticks -Squaring 1024-bit took 3.730000 ticks -Squaring 2048-bit took 11.580000 ticks -Squaring 4096-bit took 44.540000 ticks -Multiplying 128-bit took 0.270000 ticks -Multiplying 256-bit took 0.650000 ticks -Multiplying 512-bit took 1.630000 ticks -Multiplying 1024-bit took 5.180000 ticks -Multiplying 2048-bit took 19.210000 ticks -Multiplying 4096-bit took 67.500000 ticks -Exponentiating 513-bit took 2000.000000 ticks -Exponentiating 769-bit took 5200.000000 ticks -Exponentiating 1025-bit took 11400.000000 ticks -Exponentiating 2049-bit took 75100.000000 ticks -Exponentiating 2561-bit took 150000.000000 ticks -Exponentiating 3073-bit took 237800.000000 ticks -Exponentiating 4097-bit took 510600.000000 ticks -Inverting mod 128-bit took 0.000000 ticks -Inverting mod 256-bit took 200.000000 ticks -Inverting mod 512-bit took 300.000000 ticks -Inverting mod 1024-bit took 800.000000 ticks -Inverting mod 2048-bit took 2500.000000 ticks -Inverting mod 4096-bit took 8400.000000 ticks - +CLOCKS_PER_SEC == 1000 +Adding 128-bit => 14534883/sec, 688 ticks +Adding 256-bit => 11037527/sec, 906 ticks +Adding 512-bit => 8650519/sec, 1156 ticks +Adding 1024-bit => 5871990/sec, 1703 ticks +Adding 2048-bit => 3575259/sec, 2797 ticks +Adding 4096-bit => 2018978/sec, 4953 ticks +Subtracting 128-bit => 11025358/sec, 907 ticks +Subtracting 256-bit => 9149130/sec, 1093 ticks +Subtracting 512-bit => 7440476/sec, 1344 ticks +Subtracting 1024-bit => 5078720/sec, 1969 ticks +Subtracting 2048-bit => 3168567/sec, 3156 ticks +Subtracting 4096-bit => 1833852/sec, 5453 ticks +Squaring 128-bit => 3205128/sec, 78 ticks +Squaring 256-bit => 1592356/sec, 157 ticks +Squaring 512-bit => 696378/sec, 359 ticks +Squaring 1024-bit => 266808/sec, 937 ticks +Squaring 2048-bit => 85999/sec, 2907 ticks +Squaring 4096-bit => 21949/sec, 11390 ticks +Multiplying 128-bit => 3205128/sec, 78 ticks +Multiplying 256-bit => 1592356/sec, 157 ticks +Multiplying 512-bit => 615763/sec, 406 ticks +Multiplying 1024-bit => 192752/sec, 1297 ticks +Multiplying 2048-bit => 53510/sec, 4672 ticks +Multiplying 4096-bit => 14801/sec, 16890 ticks +Exponentiating 513-bit => 531/sec, 47 ticks +Exponentiating 769-bit => 177/sec, 141 ticks +Exponentiating 1025-bit => 88/sec, 282 ticks +Exponentiating 2049-bit => 13/sec, 1890 ticks +Exponentiating 2561-bit => 6/sec, 3812 ticks +Exponentiating 3073-bit => 4/sec, 6031 ticks +Exponentiating 4097-bit => 1/sec, 12843 ticks +Inverting mod 128-bit => 19160/sec, 5219 ticks +Inverting mod 256-bit => 8290/sec, 12062 ticks +Inverting mod 512-bit => 3565/sec, 28047 ticks +Inverting mod 1024-bit => 1305/sec, 76594 ticks \ No newline at end of file diff --git a/timings2.txt b/timings2.txt new file mode 100644 index 0000000..0b87e21 --- /dev/null +++ b/timings2.txt @@ -0,0 +1,36 @@ +CLOCKS_PER_SEC == 1000 +Adding 128-bit => 15600624/sec, 641 ticks +Adding 256-bit => 12804097/sec, 781 ticks +Adding 512-bit => 10000000/sec, 1000 ticks +Adding 1024-bit => 7032348/sec, 1422 ticks +Adding 2048-bit => 4076640/sec, 2453 ticks +Adding 4096-bit => 2424242/sec, 4125 ticks +Subtracting 128-bit => 10845986/sec, 922 ticks +Subtracting 256-bit => 9416195/sec, 1062 ticks +Subtracting 512-bit => 7710100/sec, 1297 ticks +Subtracting 1024-bit => 5159958/sec, 1938 ticks +Subtracting 2048-bit => 3299241/sec, 3031 ticks +Subtracting 4096-bit => 1987676/sec, 5031 ticks +Squaring 128-bit => 3205128/sec, 78 ticks +Squaring 256-bit => 1592356/sec, 157 ticks +Squaring 512-bit => 696378/sec, 359 ticks +Squaring 1024-bit => 266524/sec, 938 ticks +Squaring 2048-bit => 86505/sec, 2890 ticks +Squaring 4096-bit => 22471/sec, 11125 ticks +Multiplying 128-bit => 3205128/sec, 78 ticks +Multiplying 256-bit => 1592356/sec, 157 ticks +Multiplying 512-bit => 615763/sec, 406 ticks +Multiplying 1024-bit => 190548/sec, 1312 ticks +Multiplying 2048-bit => 54418/sec, 4594 ticks +Multiplying 4096-bit => 14897/sec, 16781 ticks +Exponentiating 513-bit => 531/sec, 47 ticks +Exponentiating 769-bit => 177/sec, 141 ticks +Exponentiating 1025-bit => 84/sec, 297 ticks +Exponentiating 2049-bit => 13/sec, 1875 ticks +Exponentiating 2561-bit => 6/sec, 3766 ticks +Exponentiating 3073-bit => 4/sec, 6000 ticks +Exponentiating 4097-bit => 1/sec, 12750 ticks +Inverting mod 128-bit => 17301/sec, 578 ticks +Inverting mod 256-bit => 8103/sec, 1234 ticks +Inverting mod 512-bit => 3422/sec, 2922 ticks +Inverting mod 1024-bit => 1330/sec, 7516 ticks \ No newline at end of file diff --git a/timings3.txt b/timings3.txt new file mode 100644 index 0000000..f269c2b --- /dev/null +++ b/timings3.txt @@ -0,0 +1,5 @@ +Exponentiating 513-bit => 531/sec, 94 ticks +Exponentiating 769-bit => 187/sec, 266 ticks +Exponentiating 1025-bit => 88/sec, 562 ticks +Exponentiating 2049-bit => 13/sec, 3719 ticks + diff --git a/tommath.h b/tommath.h index 4ac6173..9db1781 100644 --- a/tommath.h +++ b/tommath.h @@ -289,6 +289,11 @@ int mp_reduce(mp_int *a, mp_int *b, mp_int *c); /* setups the montgomery reduction */ int mp_montgomery_setup(mp_int *a, mp_digit *mp); +/* computes a = B^n mod b without division or multiplication useful for + * normalizing numbers in a Montgomery system. + */ +int mp_montgomery_calc_normalization(mp_int *a, mp_int *b); + /* computes xR^-1 == x (mod N) via Montgomery Reduction */ int mp_montgomery_reduce(mp_int *a, mp_int *m, mp_digit mp); @@ -343,6 +348,5 @@ void bn_reverse(unsigned char *s, int len); } #endif - #endif