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.c600
1 files changed, 397 insertions, 203 deletions
diff --git a/src/lib/libcrypto/bn/bn_exp.c b/src/lib/libcrypto/bn/bn_exp.c
index c056a5083f..afdfd580fb 100644
--- a/src/lib/libcrypto/bn/bn_exp.c
+++ b/src/lib/libcrypto/bn/bn_exp.c
@@ -55,112 +55,145 @@
55 * copied and put under another distribution licence 55 * copied and put under another distribution licence
56 * [including the GNU Public Licence.] 56 * [including the GNU Public Licence.]
57 */ 57 */
58/* ====================================================================
59 * Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
60 *
61 * Redistribution and use in source and binary forms, with or without
62 * modification, are permitted provided that the following conditions
63 * are met:
64 *
65 * 1. Redistributions of source code must retain the above copyright
66 * notice, this list of conditions and the following disclaimer.
67 *
68 * 2. Redistributions in binary form must reproduce the above copyright
69 * notice, this list of conditions and the following disclaimer in
70 * the documentation and/or other materials provided with the
71 * distribution.
72 *
73 * 3. All advertising materials mentioning features or use of this
74 * software must display the following acknowledgment:
75 * "This product includes software developed by the OpenSSL Project
76 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
77 *
78 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
79 * endorse or promote products derived from this software without
80 * prior written permission. For written permission, please contact
81 * openssl-core@openssl.org.
82 *
83 * 5. Products derived from this software may not be called "OpenSSL"
84 * nor may "OpenSSL" appear in their names without prior written
85 * permission of the OpenSSL Project.
86 *
87 * 6. Redistributions of any form whatsoever must retain the following
88 * acknowledgment:
89 * "This product includes software developed by the OpenSSL Project
90 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
91 *
92 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
93 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
95 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
96 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
97 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
98 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
99 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
100 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
101 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
102 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
103 * OF THE POSSIBILITY OF SUCH DAMAGE.
104 * ====================================================================
105 *
106 * This product includes cryptographic software written by Eric Young
107 * (eay@cryptsoft.com). This product includes software written by Tim
108 * Hudson (tjh@cryptsoft.com).
109 *
110 */
111
58 112
59#include <stdio.h>
60#include "cryptlib.h" 113#include "cryptlib.h"
61#include "bn_lcl.h" 114#include "bn_lcl.h"
62 115
63/* slow but works */ 116#define TABLE_SIZE 32
64int BN_mod_mul(ret, a, b, m, ctx)
65BIGNUM *ret;
66BIGNUM *a;
67BIGNUM *b;
68BIGNUM *m;
69BN_CTX *ctx;
70 {
71 BIGNUM *t;
72 int r=0;
73
74 t=ctx->bn[ctx->tos++];
75 if (a == b)
76 { if (!BN_sqr(t,a,ctx)) goto err; }
77 else
78 { if (!BN_mul(t,a,b)) goto err; }
79 if (!BN_mod(ret,t,m,ctx)) goto err;
80 r=1;
81err:
82 ctx->tos--;
83 return(r);
84 }
85 117
86#if 0
87/* this one works - simple but works */ 118/* this one works - simple but works */
88int BN_mod_exp(r,a,p,m,ctx) 119int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
89BIGNUM *r,*a,*p,*m;
90BN_CTX *ctx;
91 { 120 {
92 int i,bits,ret=0; 121 int i,bits,ret=0;
93 BIGNUM *v,*tmp; 122 BIGNUM *v,*rr;
94 123
95 v=ctx->bn[ctx->tos++]; 124 BN_CTX_start(ctx);
96 tmp=ctx->bn[ctx->tos++]; 125 if ((r == a) || (r == p))
126 rr = BN_CTX_get(ctx);
127 else
128 rr = r;
129 if ((v = BN_CTX_get(ctx)) == NULL) goto err;
97 130
98 if (BN_copy(v,a) == NULL) goto err; 131 if (BN_copy(v,a) == NULL) goto err;
99 bits=BN_num_bits(p); 132 bits=BN_num_bits(p);
100 133
101 if (BN_is_odd(p)) 134 if (BN_is_odd(p))
102 { if (BN_copy(r,a) == NULL) goto err; } 135 { if (BN_copy(rr,a) == NULL) goto err; }
103 else { if (BN_one(r)) goto err; } 136 else { if (!BN_one(rr)) goto err; }
104 137
105 for (i=1; i<bits; i++) 138 for (i=1; i<bits; i++)
106 { 139 {
107 if (!BN_sqr(tmp,v,ctx)) goto err; 140 if (!BN_sqr(v,v,ctx)) goto err;
108 if (!BN_mod(v,tmp,m,ctx)) goto err;
109 if (BN_is_bit_set(p,i)) 141 if (BN_is_bit_set(p,i))
110 { 142 {
111 if (!BN_mul(tmp,r,v)) goto err; 143 if (!BN_mul(rr,rr,v,ctx)) goto err;
112 if (!BN_mod(r,tmp,m,ctx)) goto err;
113 } 144 }
114 } 145 }
115 ret=1; 146 ret=1;
116err: 147err:
117 ctx->tos-=2; 148 if (r != rr) BN_copy(r,rr);
149 BN_CTX_end(ctx);
118 return(ret); 150 return(ret);
119 } 151 }
120 152
121#endif
122
123/* this one works - simple but works */
124int BN_exp(r,a,p,ctx)
125BIGNUM *r,*a,*p;
126BN_CTX *ctx;
127 {
128 int i,bits,ret=0;
129 BIGNUM *v,*tmp;
130
131 v=ctx->bn[ctx->tos++];
132 tmp=ctx->bn[ctx->tos++];
133
134 if (BN_copy(v,a) == NULL) goto err;
135 bits=BN_num_bits(p);
136
137 if (BN_is_odd(p))
138 { if (BN_copy(r,a) == NULL) goto err; }
139 else { if (BN_one(r)) goto err; }
140
141 for (i=1; i<bits; i++)
142 {
143 if (!BN_sqr(tmp,v,ctx)) goto err;
144 if (BN_is_bit_set(p,i))
145 {
146 if (!BN_mul(tmp,r,v)) goto err;
147 }
148 }
149 ret=1;
150err:
151 ctx->tos-=2;
152 return(ret);
153 }
154 153
155int BN_mod_exp(r,a,p,m,ctx) 154int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
156BIGNUM *r; 155 BN_CTX *ctx)
157BIGNUM *a;
158BIGNUM *p;
159BIGNUM *m;
160BN_CTX *ctx;
161 { 156 {
162 int ret; 157 int ret;
163 158
159 bn_check_top(a);
160 bn_check_top(p);
161 bn_check_top(m);
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
164#ifdef MONT_MUL_MOD 197#ifdef MONT_MUL_MOD
165 /* 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
166 * 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
@@ -169,7 +202,17 @@ BN_CTX *ctx;
169/* if ((m->d[m->top-1]&BN_TBIT) && BN_is_odd(m)) */ 202/* if ((m->d[m->top-1]&BN_TBIT) && BN_is_odd(m)) */
170 203
171 if (BN_is_odd(m)) 204 if (BN_is_odd(m))
172 { ret=BN_mod_exp_mont(r,a,p,m,ctx,NULL); } 205 {
206# ifdef MONT_EXP_WORD
207 if (a->top == 1 && !a->neg)
208 {
209 BN_ULONG A = a->d[0];
210 ret=BN_mod_exp_mont_word(r,A,p,m,ctx,NULL);
211 }
212 else
213# endif
214 ret=BN_mod_exp_mont(r,a,p,m,ctx,NULL);
215 }
173 else 216 else
174#endif 217#endif
175#ifdef RECP_MUL_MOD 218#ifdef RECP_MUL_MOD
@@ -181,55 +224,65 @@ BN_CTX *ctx;
181 return(ret); 224 return(ret);
182 } 225 }
183 226
184/* #ifdef RECP_MUL_MOD */ 227
185int BN_mod_exp_recp(r,a,p,m,ctx) 228int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
186BIGNUM *r; 229 const BIGNUM *m, BN_CTX *ctx)
187BIGNUM *a;
188BIGNUM *p;
189BIGNUM *m;
190BN_CTX *ctx;
191 { 230 {
192 int nb,i,j,bits,ret=0,wstart,wend,window,wvalue; 231 int i,j,bits,ret=0,wstart,wend,window,wvalue;
193 int start=1; 232 int start=1,ts=0;
194 BIGNUM *d,*aa; 233 BIGNUM *aa;
195 BIGNUM *val[16]; 234 BIGNUM val[TABLE_SIZE];
235 BN_RECP_CTX recp;
196 236
197 d=ctx->bn[ctx->tos++];
198 aa=ctx->bn[ctx->tos++];
199 bits=BN_num_bits(p); 237 bits=BN_num_bits(p);
200 238
201 if (bits == 0) 239 if (bits == 0)
202 { 240 {
203 BN_one(r); 241 ret = BN_one(r);
204 return(1); 242 return ret;
243 }
244
245 BN_CTX_start(ctx);
246 if ((aa = BN_CTX_get(ctx)) == NULL) goto err;
247
248 BN_RECP_CTX_init(&recp);
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;
205 } 255 }
206 nb=BN_reciprocal(d,m,ctx);
207 if (nb == -1) goto err;
208
209 val[0]=BN_new();
210 if (!BN_mod(val[0],a,m,ctx)) goto err; /* 1 */
211 if (!BN_mod_mul_reciprocal(aa,val[0],val[0],m,d,nb,ctx))
212 goto err; /* 2 */
213
214 if (bits <= 17) /* This is probably 3 or 0x10001, so just do singles */
215 window=1;
216 else if (bits >= 256)
217 window=5; /* max size of window */
218 else if (bits >= 128)
219 window=4;
220 else 256 else
221 window=3; 257 {
258 if (BN_RECP_CTX_set(&recp,m,ctx) <= 0) goto err;
259 }
260
261 BN_init(&(val[0]));
262 ts=1;
222 263
223 j=1<<(window-1); 264 if (!BN_nnmod(&(val[0]),a,m,ctx)) goto err; /* 1 */
224 for (i=1; i<j; i++) 265 if (BN_is_zero(&(val[0])))
225 { 266 {
226 val[i]=BN_new(); 267 ret = BN_zero(r);
227 if (!BN_mod_mul_reciprocal(val[i],val[i-1],aa,m,d,nb,ctx)) 268 goto err;
228 goto err;
229 } 269 }
230 for (; i<16; i++)
231 val[i]=NULL;
232 270
271 window = BN_window_bits_for_exponent_size(bits);
272 if (window > 1)
273 {
274 if (!BN_mod_mul_reciprocal(aa,&(val[0]),&(val[0]),&recp,ctx))
275 goto err; /* 2 */
276 j=1<<(window-1);
277 for (i=1; i<j; i++)
278 {
279 BN_init(&val[i]);
280 if (!BN_mod_mul_reciprocal(&(val[i]),&(val[i-1]),aa,&recp,ctx))
281 goto err;
282 }
283 ts=i;
284 }
285
233 start=1; /* This is used to avoid multiplication etc 286 start=1; /* This is used to avoid multiplication etc
234 * when there is only the value '1' in the 287 * when there is only the value '1' in the
235 * buffer. */ 288 * buffer. */
@@ -244,7 +297,7 @@ BN_CTX *ctx;
244 if (BN_is_bit_set(p,wstart) == 0) 297 if (BN_is_bit_set(p,wstart) == 0)
245 { 298 {
246 if (!start) 299 if (!start)
247 if (!BN_mod_mul_reciprocal(r,r,r,m,d,nb,ctx)) 300 if (!BN_mod_mul_reciprocal(r,r,r,&recp,ctx))
248 goto err; 301 goto err;
249 if (wstart == 0) break; 302 if (wstart == 0) break;
250 wstart--; 303 wstart--;
@@ -274,12 +327,12 @@ BN_CTX *ctx;
274 if (!start) 327 if (!start)
275 for (i=0; i<j; i++) 328 for (i=0; i<j; i++)
276 { 329 {
277 if (!BN_mod_mul_reciprocal(r,r,r,m,d,nb,ctx)) 330 if (!BN_mod_mul_reciprocal(r,r,r,&recp,ctx))
278 goto err; 331 goto err;
279 } 332 }
280 333
281 /* wvalue will be an odd number < 2^window */ 334 /* wvalue will be an odd number < 2^window */
282 if (!BN_mod_mul_reciprocal(r,r,val[wvalue>>1],m,d,nb,ctx)) 335 if (!BN_mod_mul_reciprocal(r,r,&(val[wvalue>>1]),&recp,ctx))
283 goto err; 336 goto err;
284 337
285 /* move the 'window' down further */ 338 /* move the 'window' down further */
@@ -290,84 +343,86 @@ BN_CTX *ctx;
290 } 343 }
291 ret=1; 344 ret=1;
292err: 345err:
293 ctx->tos-=2; 346 BN_CTX_end(ctx);
294 for (i=0; i<16; i++) 347 for (i=0; i<ts; i++)
295 if (val[i] != NULL) BN_clear_free(val[i]); 348 BN_clear_free(&(val[i]));
349 BN_RECP_CTX_free(&recp);
296 return(ret); 350 return(ret);
297 } 351 }
298/* #endif */ 352
299 353
300/* #ifdef MONT_MUL_MOD */ 354int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
301int BN_mod_exp_mont(r,a,p,m,ctx,in_mont) 355 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
302BIGNUM *r;
303BIGNUM *a;
304BIGNUM *p;
305BIGNUM *m;
306BN_CTX *ctx;
307BN_MONT_CTX *in_mont;
308 { 356 {
309#define TABLE_SIZE 16
310 int i,j,bits,ret=0,wstart,wend,window,wvalue; 357 int i,j,bits,ret=0,wstart,wend,window,wvalue;
311 int start=1; 358 int start=1,ts=0;
312 BIGNUM *d,*aa; 359 BIGNUM *d,*r;
313 BIGNUM *val[TABLE_SIZE]; 360 const BIGNUM *aa;
361 BIGNUM val[TABLE_SIZE];
314 BN_MONT_CTX *mont=NULL; 362 BN_MONT_CTX *mont=NULL;
315 363
364 bn_check_top(a);
365 bn_check_top(p);
366 bn_check_top(m);
367
316 if (!(m->d[0] & 1)) 368 if (!(m->d[0] & 1))
317 { 369 {
318 BNerr(BN_F_BN_MOD_EXP_MONT,BN_R_CALLED_WITH_EVEN_MODULUS); 370 BNerr(BN_F_BN_MOD_EXP_MONT,BN_R_CALLED_WITH_EVEN_MODULUS);
319 return(0); 371 return(0);
320 } 372 }
321 d=ctx->bn[ctx->tos++];
322 bits=BN_num_bits(p); 373 bits=BN_num_bits(p);
323 if (bits == 0) 374 if (bits == 0)
324 { 375 {
325 BN_one(r); 376 ret = BN_one(rr);
326 return(1); 377 return ret;
327 } 378 }
328 379
380 BN_CTX_start(ctx);
381 d = BN_CTX_get(ctx);
382 r = BN_CTX_get(ctx);
383 if (d == NULL || r == NULL) goto err;
384
329 /* If this is not done, things will break in the montgomery 385 /* If this is not done, things will break in the montgomery
330 * part */ 386 * part */
331 387
332#if 1
333 if (in_mont != NULL) 388 if (in_mont != NULL)
334 mont=in_mont; 389 mont=in_mont;
335 else 390 else
336#endif
337 { 391 {
338 if ((mont=BN_MONT_CTX_new()) == NULL) goto err; 392 if ((mont=BN_MONT_CTX_new()) == NULL) goto err;
339 if (!BN_MONT_CTX_set(mont,m,ctx)) goto err; 393 if (!BN_MONT_CTX_set(mont,m,ctx)) goto err;
340 } 394 }
341 395
342 val[0]=BN_new(); 396 BN_init(&val[0]);
343 if (BN_ucmp(a,m) >= 0) 397 ts=1;
398 if (a->neg || BN_ucmp(a,m) >= 0)
344 { 399 {
345 BN_mod(val[0],a,m,ctx); 400 if (!BN_nnmod(&(val[0]),a,m,ctx))
346 aa=val[0]; 401 goto err;
402 aa= &(val[0]);
347 } 403 }
348 else 404 else
349 aa=a; 405 aa=a;
350 if (!BN_to_montgomery(val[0],aa,mont,ctx)) goto err; /* 1 */ 406 if (BN_is_zero(aa))
351 if (!BN_mod_mul_montgomery(d,val[0],val[0],mont,ctx)) goto err; /* 2 */ 407 {
352 408 ret = BN_zero(rr);
353 if (bits <= 20) /* This is probably 3 or 0x10001, so just do singles */ 409 goto err;
354 window=1; 410 }
355 else if (bits > 250) 411 if (!BN_to_montgomery(&(val[0]),aa,mont,ctx)) goto err; /* 1 */
356 window=5; /* max size of window */
357 else if (bits >= 120)
358 window=4;
359 else
360 window=3;
361 412
362 j=1<<(window-1); 413 window = BN_window_bits_for_exponent_size(bits);
363 for (i=1; i<j; i++) 414 if (window > 1)
364 { 415 {
365 val[i]=BN_new(); 416 if (!BN_mod_mul_montgomery(d,&(val[0]),&(val[0]),mont,ctx)) goto err; /* 2 */
366 if (!BN_mod_mul_montgomery(val[i],val[i-1],d,mont,ctx)) 417 j=1<<(window-1);
367 goto err; 418 for (i=1; i<j; i++)
419 {
420 BN_init(&(val[i]));
421 if (!BN_mod_mul_montgomery(&(val[i]),&(val[i-1]),d,mont,ctx))
422 goto err;
423 }
424 ts=i;
368 } 425 }
369 for (; i<TABLE_SIZE; i++)
370 val[i]=NULL;
371 426
372 start=1; /* This is used to avoid multiplication etc 427 start=1; /* This is used to avoid multiplication etc
373 * when there is only the value '1' in the 428 * when there is only the value '1' in the
@@ -376,7 +431,7 @@ BN_MONT_CTX *in_mont;
376 wstart=bits-1; /* The top bit of the window */ 431 wstart=bits-1; /* The top bit of the window */
377 wend=0; /* The bottom bit of the window */ 432 wend=0; /* The bottom bit of the window */
378 433
379 if (!BN_to_montgomery(r,BN_value_one(),mont,ctx)) goto err; 434 if (!BN_to_montgomery(r,BN_value_one(),mont,ctx)) goto err;
380 for (;;) 435 for (;;)
381 { 436 {
382 if (BN_is_bit_set(p,wstart) == 0) 437 if (BN_is_bit_set(p,wstart) == 0)
@@ -419,7 +474,7 @@ BN_MONT_CTX *in_mont;
419 } 474 }
420 475
421 /* wvalue will be an odd number < 2^window */ 476 /* wvalue will be an odd number < 2^window */
422 if (!BN_mod_mul_montgomery(r,r,val[wvalue>>1],mont,ctx)) 477 if (!BN_mod_mul_montgomery(r,r,&(val[wvalue>>1]),mont,ctx))
423 goto err; 478 goto err;
424 479
425 /* move the 'window' down further */ 480 /* move the 'window' down further */
@@ -428,62 +483,201 @@ BN_MONT_CTX *in_mont;
428 start=0; 483 start=0;
429 if (wstart < 0) break; 484 if (wstart < 0) break;
430 } 485 }
431 BN_from_montgomery(r,r,mont,ctx); 486 if (!BN_from_montgomery(rr,r,mont,ctx)) goto err;
432 ret=1; 487 ret=1;
433err: 488err:
434 if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont); 489 if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont);
435 ctx->tos--; 490 BN_CTX_end(ctx);
436 for (i=0; i<TABLE_SIZE; i++) 491 for (i=0; i<ts; i++)
437 if (val[i] != NULL) BN_clear_free(val[i]); 492 BN_clear_free(&(val[i]));
438 return(ret); 493 return(ret);
439 } 494 }
440/* #endif */ 495
496int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,
497 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
498 {
499 BN_MONT_CTX *mont = NULL;
500 int b, bits, ret=0;
501 int r_is_one;
502 BN_ULONG w, next_w;
503 BIGNUM *d, *r, *t;
504 BIGNUM *swap_tmp;
505#define BN_MOD_MUL_WORD(r, w, m) \
506 (BN_mul_word(r, (w)) && \
507 (/* BN_ucmp(r, (m)) < 0 ? 1 :*/ \
508 (BN_mod(t, r, m, ctx) && (swap_tmp = r, r = t, t = swap_tmp, 1))))
509 /* BN_MOD_MUL_WORD is only used with 'w' large,
510 * so the BN_ucmp test is probably more overhead
511 * than always using BN_mod (which uses BN_copy if
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 */
517#define BN_TO_MONTGOMERY_WORD(r, w, mont) \
518 (BN_set_word(r, (w)) && BN_to_montgomery(r, r, (mont), ctx))
519
520 bn_check_top(p);
521 bn_check_top(m);
522
523 if (m->top == 0 || !(m->d[0] & 1))
524 {
525 BNerr(BN_F_BN_MOD_EXP_MONT_WORD,BN_R_CALLED_WITH_EVEN_MODULUS);
526 return(0);
527 }
528 if (m->top == 1)
529 a %= m->d[0]; /* make sure that 'a' is reduced */
530
531 bits = BN_num_bits(p);
532 if (bits == 0)
533 {
534 ret = BN_one(rr);
535 return ret;
536 }
537 if (a == 0)
538 {
539 ret = BN_zero(rr);
540 return ret;
541 }
542
543 BN_CTX_start(ctx);
544 d = BN_CTX_get(ctx);
545 r = BN_CTX_get(ctx);
546 t = BN_CTX_get(ctx);
547 if (d == NULL || r == NULL || t == NULL) goto err;
548
549 if (in_mont != NULL)
550 mont=in_mont;
551 else
552 {
553 if ((mont = BN_MONT_CTX_new()) == NULL) goto err;
554 if (!BN_MONT_CTX_set(mont, m, ctx)) goto err;
555 }
556
557 r_is_one = 1; /* except for Montgomery factor */
558
559 /* bits-1 >= 0 */
560
561 /* The result is accumulated in the product r*w. */
562 w = a; /* bit 'bits-1' of 'p' is always set */
563 for (b = bits-2; b >= 0; b--)
564 {
565 /* First, square r*w. */
566 next_w = w*w;
567 if ((next_w/w) != w) /* overflow */
568 {
569 if (r_is_one)
570 {
571 if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) goto err;
572 r_is_one = 0;
573 }
574 else
575 {
576 if (!BN_MOD_MUL_WORD(r, w, m)) goto err;
577 }
578 next_w = 1;
579 }
580 w = next_w;
581 if (!r_is_one)
582 {
583 if (!BN_mod_mul_montgomery(r, r, r, mont, ctx)) goto err;
584 }
585
586 /* Second, multiply r*w by 'a' if exponent bit is set. */
587 if (BN_is_bit_set(p, b))
588 {
589 next_w = w*a;
590 if ((next_w/a) != w) /* overflow */
591 {
592 if (r_is_one)
593 {
594 if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) goto err;
595 r_is_one = 0;
596 }
597 else
598 {
599 if (!BN_MOD_MUL_WORD(r, w, m)) goto err;
600 }
601 next_w = a;
602 }
603 w = next_w;
604 }
605 }
606
607 /* Finally, set r:=r*w. */
608 if (w != 1)
609 {
610 if (r_is_one)
611 {
612 if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) goto err;
613 r_is_one = 0;
614 }
615 else
616 {
617 if (!BN_MOD_MUL_WORD(r, w, m)) goto err;
618 }
619 }
620
621 if (r_is_one) /* can happen only if a == 1*/
622 {
623 if (!BN_one(rr)) goto err;
624 }
625 else
626 {
627 if (!BN_from_montgomery(rr, r, mont, ctx)) goto err;
628 }
629 ret = 1;
630err:
631 if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont);
632 BN_CTX_end(ctx);
633 return(ret);
634 }
635
441 636
442/* The old fallback, simple version :-) */ 637/* The old fallback, simple version :-) */
443int BN_mod_exp_simple(r,a,p,m,ctx) 638int BN_mod_exp_simple(BIGNUM *r,
444BIGNUM *r; 639 const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
445BIGNUM *a; 640 BN_CTX *ctx)
446BIGNUM *p;
447BIGNUM *m;
448BN_CTX *ctx;
449 { 641 {
450 int i,j,bits,ret=0,wstart,wend,window,wvalue; 642 int i,j,bits,ret=0,wstart,wend,window,wvalue,ts=0;
451 int start=1; 643 int start=1;
452 BIGNUM *d; 644 BIGNUM *d;
453 BIGNUM *val[16]; 645 BIGNUM val[TABLE_SIZE];
454 646
455 d=ctx->bn[ctx->tos++];
456 bits=BN_num_bits(p); 647 bits=BN_num_bits(p);
457 648
458 if (bits == 0) 649 if (bits == 0)
459 { 650 {
460 BN_one(r); 651 ret = BN_one(r);
461 return(1); 652 return ret;
462 } 653 }
463 654
464 val[0]=BN_new(); 655 BN_CTX_start(ctx);
465 if (!BN_mod(val[0],a,m,ctx)) goto err; /* 1 */ 656 if ((d = BN_CTX_get(ctx)) == NULL) goto err;
466 if (!BN_mod_mul(d,val[0],val[0],m,ctx))
467 goto err; /* 2 */
468
469 if (bits <= 17) /* This is probably 3 or 0x10001, so just do singles */
470 window=1;
471 else if (bits >= 256)
472 window=5; /* max size of window */
473 else if (bits >= 128)
474 window=4;
475 else
476 window=3;
477 657
478 j=1<<(window-1); 658 BN_init(&(val[0]));
479 for (i=1; i<j; i++) 659 ts=1;
660 if (!BN_nnmod(&(val[0]),a,m,ctx)) goto err; /* 1 */
661 if (BN_is_zero(&(val[0])))
480 { 662 {
481 val[i]=BN_new(); 663 ret = BN_zero(r);
482 if (!BN_mod_mul(val[i],val[i-1],d,m,ctx)) 664 goto err;
483 goto err; 665 }
666
667 window = BN_window_bits_for_exponent_size(bits);
668 if (window > 1)
669 {
670 if (!BN_mod_mul(d,&(val[0]),&(val[0]),m,ctx))
671 goto err; /* 2 */
672 j=1<<(window-1);
673 for (i=1; i<j; i++)
674 {
675 BN_init(&(val[i]));
676 if (!BN_mod_mul(&(val[i]),&(val[i-1]),d,m,ctx))
677 goto err;
678 }
679 ts=i;
484 } 680 }
485 for (; i<16; i++)
486 val[i]=NULL;
487 681
488 start=1; /* This is used to avoid multiplication etc 682 start=1; /* This is used to avoid multiplication etc
489 * when there is only the value '1' in the 683 * when there is only the value '1' in the
@@ -534,7 +728,7 @@ BN_CTX *ctx;
534 } 728 }
535 729
536 /* wvalue will be an odd number < 2^window */ 730 /* wvalue will be an odd number < 2^window */
537 if (!BN_mod_mul(r,r,val[wvalue>>1],m,ctx)) 731 if (!BN_mod_mul(r,r,&(val[wvalue>>1]),m,ctx))
538 goto err; 732 goto err;
539 733
540 /* move the 'window' down further */ 734 /* move the 'window' down further */
@@ -545,9 +739,9 @@ BN_CTX *ctx;
545 } 739 }
546 ret=1; 740 ret=1;
547err: 741err:
548 ctx->tos--; 742 BN_CTX_end(ctx);
549 for (i=0; i<16; i++) 743 for (i=0; i<ts; i++)
550 if (val[i] != NULL) BN_clear_free(val[i]); 744 BN_clear_free(&(val[i]));
551 return(ret); 745 return(ret);
552 } 746 }
553 747