summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/bn/bn_exp.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/bn/bn_exp.c')
-rw-r--r--src/lib/libcrypto/bn/bn_exp.c149
1 files changed, 100 insertions, 49 deletions
diff --git a/src/lib/libcrypto/bn/bn_exp.c b/src/lib/libcrypto/bn/bn_exp.c
index d2c91628ac..afdfd580fb 100644
--- a/src/lib/libcrypto/bn/bn_exp.c
+++ b/src/lib/libcrypto/bn/bn_exp.c
@@ -110,38 +110,13 @@
110 */ 110 */
111 111
112 112
113#include <stdio.h>
114#include "cryptlib.h" 113#include "cryptlib.h"
115#include "bn_lcl.h" 114#include "bn_lcl.h"
116 115
117#define TABLE_SIZE 32 116#define TABLE_SIZE 32
118 117
119/* slow but works */
120int BN_mod_mul(BIGNUM *ret, BIGNUM *a, BIGNUM *b, const BIGNUM *m, BN_CTX *ctx)
121 {
122 BIGNUM *t;
123 int r=0;
124
125 bn_check_top(a);
126 bn_check_top(b);
127 bn_check_top(m);
128
129 BN_CTX_start(ctx);
130 if ((t = BN_CTX_get(ctx)) == NULL) goto err;
131 if (a == b)
132 { if (!BN_sqr(t,a,ctx)) goto err; }
133 else
134 { if (!BN_mul(t,a,b,ctx)) goto err; }
135 if (!BN_mod(ret,t,m,ctx)) goto err;
136 r=1;
137err:
138 BN_CTX_end(ctx);
139 return(r);
140 }
141
142
143/* this one works - simple but works */ 118/* this one works - simple but works */
144int BN_exp(BIGNUM *r, BIGNUM *a, BIGNUM *p, BN_CTX *ctx) 119int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
145 { 120 {
146 int i,bits,ret=0; 121 int i,bits,ret=0;
147 BIGNUM *v,*rr; 122 BIGNUM *v,*rr;
@@ -176,7 +151,7 @@ err:
176 } 151 }
177 152
178 153
179int BN_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p, const BIGNUM *m, 154int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
180 BN_CTX *ctx) 155 BN_CTX *ctx)
181 { 156 {
182 int ret; 157 int ret;
@@ -185,6 +160,40 @@ int BN_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
185 bn_check_top(p); 160 bn_check_top(p);
186 bn_check_top(m); 161 bn_check_top(m);
187 162
163 /* For even modulus m = 2^k*m_odd, it might make sense to compute
164 * a^p mod m_odd and a^p mod 2^k separately (with Montgomery
165 * exponentiation for the odd part), using appropriate exponent
166 * reductions, and combine the results using the CRT.
167 *
168 * For now, we use Montgomery only if the modulus is odd; otherwise,
169 * exponentiation using the reciprocal-based quick remaindering
170 * algorithm is used.
171 *
172 * (Timing obtained with expspeed.c [computations a^p mod m
173 * where a, p, m are of the same length: 256, 512, 1024, 2048,
174 * 4096, 8192 bits], compared to the running time of the
175 * standard algorithm:
176 *
177 * BN_mod_exp_mont 33 .. 40 % [AMD K6-2, Linux, debug configuration]
178 * 55 .. 77 % [UltraSparc processor, but
179 * debug-solaris-sparcv8-gcc conf.]
180 *
181 * BN_mod_exp_recp 50 .. 70 % [AMD K6-2, Linux, debug configuration]
182 * 62 .. 118 % [UltraSparc, debug-solaris-sparcv8-gcc]
183 *
184 * On the Sparc, BN_mod_exp_recp was faster than BN_mod_exp_mont
185 * at 2048 and more bits, but at 512 and 1024 bits, it was
186 * slower even than the standard algorithm!
187 *
188 * "Real" timings [linux-elf, solaris-sparcv9-gcc configurations]
189 * should be obtained when the new Montgomery reduction code
190 * has been integrated into OpenSSL.)
191 */
192
193#define MONT_MUL_MOD
194#define MONT_EXP_WORD
195#define RECP_MUL_MOD
196
188#ifdef MONT_MUL_MOD 197#ifdef MONT_MUL_MOD
189 /* I have finally been able to take out this pre-condition of 198 /* I have finally been able to take out this pre-condition of
190 * the top bit being set. It was caused by an error in BN_div 199 * the top bit being set. It was caused by an error in BN_div
@@ -194,12 +203,14 @@ int BN_mod_exp(BIGNUM *r, BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
194 203
195 if (BN_is_odd(m)) 204 if (BN_is_odd(m))
196 { 205 {
197 if (a->top == 1) 206# ifdef MONT_EXP_WORD
207 if (a->top == 1 && !a->neg)
198 { 208 {
199 BN_ULONG A = a->d[0]; 209 BN_ULONG A = a->d[0];
200 ret=BN_mod_exp_mont_word(r,A,p,m,ctx,NULL); 210 ret=BN_mod_exp_mont_word(r,A,p,m,ctx,NULL);
201 } 211 }
202 else 212 else
213# endif
203 ret=BN_mod_exp_mont(r,a,p,m,ctx,NULL); 214 ret=BN_mod_exp_mont(r,a,p,m,ctx,NULL);
204 } 215 }
205 else 216 else
@@ -227,20 +238,35 @@ int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
227 238
228 if (bits == 0) 239 if (bits == 0)
229 { 240 {
230 BN_one(r); 241 ret = BN_one(r);
231 return(1); 242 return ret;
232 } 243 }
233 244
234 BN_CTX_start(ctx); 245 BN_CTX_start(ctx);
235 if ((aa = BN_CTX_get(ctx)) == NULL) goto err; 246 if ((aa = BN_CTX_get(ctx)) == NULL) goto err;
236 247
237 BN_RECP_CTX_init(&recp); 248 BN_RECP_CTX_init(&recp);
238 if (BN_RECP_CTX_set(&recp,m,ctx) <= 0) goto err; 249 if (m->neg)
250 {
251 /* ignore sign of 'm' */
252 if (!BN_copy(aa, m)) goto err;
253 aa->neg = 0;
254 if (BN_RECP_CTX_set(&recp,aa,ctx) <= 0) goto err;
255 }
256 else
257 {
258 if (BN_RECP_CTX_set(&recp,m,ctx) <= 0) goto err;
259 }
239 260
240 BN_init(&(val[0])); 261 BN_init(&(val[0]));
241 ts=1; 262 ts=1;
242 263
243 if (!BN_mod(&(val[0]),a,m,ctx)) goto err; /* 1 */ 264 if (!BN_nnmod(&(val[0]),a,m,ctx)) goto err; /* 1 */
265 if (BN_is_zero(&(val[0])))
266 {
267 ret = BN_zero(r);
268 goto err;
269 }
244 270
245 window = BN_window_bits_for_exponent_size(bits); 271 window = BN_window_bits_for_exponent_size(bits);
246 if (window > 1) 272 if (window > 1)
@@ -325,13 +351,13 @@ err:
325 } 351 }
326 352
327 353
328int BN_mod_exp_mont(BIGNUM *rr, BIGNUM *a, const BIGNUM *p, 354int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
329 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont) 355 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
330 { 356 {
331 int i,j,bits,ret=0,wstart,wend,window,wvalue; 357 int i,j,bits,ret=0,wstart,wend,window,wvalue;
332 int start=1,ts=0; 358 int start=1,ts=0;
333 BIGNUM *d,*r; 359 BIGNUM *d,*r;
334 BIGNUM *aa; 360 const BIGNUM *aa;
335 BIGNUM val[TABLE_SIZE]; 361 BIGNUM val[TABLE_SIZE];
336 BN_MONT_CTX *mont=NULL; 362 BN_MONT_CTX *mont=NULL;
337 363
@@ -347,9 +373,10 @@ int BN_mod_exp_mont(BIGNUM *rr, BIGNUM *a, const BIGNUM *p,
347 bits=BN_num_bits(p); 373 bits=BN_num_bits(p);
348 if (bits == 0) 374 if (bits == 0)
349 { 375 {
350 BN_one(rr); 376 ret = BN_one(rr);
351 return(1); 377 return ret;
352 } 378 }
379
353 BN_CTX_start(ctx); 380 BN_CTX_start(ctx);
354 d = BN_CTX_get(ctx); 381 d = BN_CTX_get(ctx);
355 r = BN_CTX_get(ctx); 382 r = BN_CTX_get(ctx);
@@ -368,14 +395,19 @@ int BN_mod_exp_mont(BIGNUM *rr, BIGNUM *a, const BIGNUM *p,
368 395
369 BN_init(&val[0]); 396 BN_init(&val[0]);
370 ts=1; 397 ts=1;
371 if (BN_ucmp(a,m) >= 0) 398 if (a->neg || BN_ucmp(a,m) >= 0)
372 { 399 {
373 if (!BN_mod(&(val[0]),a,m,ctx)) 400 if (!BN_nnmod(&(val[0]),a,m,ctx))
374 goto err; 401 goto err;
375 aa= &(val[0]); 402 aa= &(val[0]);
376 } 403 }
377 else 404 else
378 aa=a; 405 aa=a;
406 if (BN_is_zero(aa))
407 {
408 ret = BN_zero(rr);
409 goto err;
410 }
379 if (!BN_to_montgomery(&(val[0]),aa,mont,ctx)) goto err; /* 1 */ 411 if (!BN_to_montgomery(&(val[0]),aa,mont,ctx)) goto err; /* 1 */
380 412
381 window = BN_window_bits_for_exponent_size(bits); 413 window = BN_window_bits_for_exponent_size(bits);
@@ -475,26 +507,39 @@ int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,
475 (/* BN_ucmp(r, (m)) < 0 ? 1 :*/ \ 507 (/* BN_ucmp(r, (m)) < 0 ? 1 :*/ \
476 (BN_mod(t, r, m, ctx) && (swap_tmp = r, r = t, t = swap_tmp, 1)))) 508 (BN_mod(t, r, m, ctx) && (swap_tmp = r, r = t, t = swap_tmp, 1))))
477 /* BN_MOD_MUL_WORD is only used with 'w' large, 509 /* BN_MOD_MUL_WORD is only used with 'w' large,
478 * so the BN_ucmp test is probably more overhead 510 * so the BN_ucmp test is probably more overhead
479 * than always using BN_mod (which uses BN_copy if 511 * than always using BN_mod (which uses BN_copy if
480 * a similar test returns true). */ 512 * a similar test returns true). */
513 /* We can use BN_mod and do not need BN_nnmod because our
514 * accumulator is never negative (the result of BN_mod does
515 * not depend on the sign of the modulus).
516 */
481#define BN_TO_MONTGOMERY_WORD(r, w, mont) \ 517#define BN_TO_MONTGOMERY_WORD(r, w, mont) \
482 (BN_set_word(r, (w)) && BN_to_montgomery(r, r, (mont), ctx)) 518 (BN_set_word(r, (w)) && BN_to_montgomery(r, r, (mont), ctx))
483 519
484 bn_check_top(p); 520 bn_check_top(p);
485 bn_check_top(m); 521 bn_check_top(m);
486 522
487 if (!(m->d[0] & 1)) 523 if (m->top == 0 || !(m->d[0] & 1))
488 { 524 {
489 BNerr(BN_F_BN_MOD_EXP_MONT_WORD,BN_R_CALLED_WITH_EVEN_MODULUS); 525 BNerr(BN_F_BN_MOD_EXP_MONT_WORD,BN_R_CALLED_WITH_EVEN_MODULUS);
490 return(0); 526 return(0);
491 } 527 }
528 if (m->top == 1)
529 a %= m->d[0]; /* make sure that 'a' is reduced */
530
492 bits = BN_num_bits(p); 531 bits = BN_num_bits(p);
493 if (bits == 0) 532 if (bits == 0)
494 { 533 {
495 BN_one(rr); 534 ret = BN_one(rr);
496 return(1); 535 return ret;
536 }
537 if (a == 0)
538 {
539 ret = BN_zero(rr);
540 return ret;
497 } 541 }
542
498 BN_CTX_start(ctx); 543 BN_CTX_start(ctx);
499 d = BN_CTX_get(ctx); 544 d = BN_CTX_get(ctx);
500 r = BN_CTX_get(ctx); 545 r = BN_CTX_get(ctx);
@@ -590,8 +635,9 @@ err:
590 635
591 636
592/* The old fallback, simple version :-) */ 637/* The old fallback, simple version :-) */
593int BN_mod_exp_simple(BIGNUM *r, BIGNUM *a, BIGNUM *p, BIGNUM *m, 638int BN_mod_exp_simple(BIGNUM *r,
594 BN_CTX *ctx) 639 const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
640 BN_CTX *ctx)
595 { 641 {
596 int i,j,bits,ret=0,wstart,wend,window,wvalue,ts=0; 642 int i,j,bits,ret=0,wstart,wend,window,wvalue,ts=0;
597 int start=1; 643 int start=1;
@@ -602,8 +648,8 @@ int BN_mod_exp_simple(BIGNUM *r, BIGNUM *a, BIGNUM *p, BIGNUM *m,
602 648
603 if (bits == 0) 649 if (bits == 0)
604 { 650 {
605 BN_one(r); 651 ret = BN_one(r);
606 return(1); 652 return ret;
607 } 653 }
608 654
609 BN_CTX_start(ctx); 655 BN_CTX_start(ctx);
@@ -611,7 +657,12 @@ int BN_mod_exp_simple(BIGNUM *r, BIGNUM *a, BIGNUM *p, BIGNUM *m,
611 657
612 BN_init(&(val[0])); 658 BN_init(&(val[0]));
613 ts=1; 659 ts=1;
614 if (!BN_mod(&(val[0]),a,m,ctx)) goto err; /* 1 */ 660 if (!BN_nnmod(&(val[0]),a,m,ctx)) goto err; /* 1 */
661 if (BN_is_zero(&(val[0])))
662 {
663 ret = BN_zero(r);
664 goto err;
665 }
615 666
616 window = BN_window_bits_for_exponent_size(bits); 667 window = BN_window_bits_for_exponent_size(bits);
617 if (window > 1) 668 if (window > 1)