diff options
Diffstat (limited to 'src/lib/libcrypto/bn/bn_mont.c')
-rw-r--r-- | src/lib/libcrypto/bn/bn_mont.c | 313 |
1 files changed, 122 insertions, 191 deletions
diff --git a/src/lib/libcrypto/bn/bn_mont.c b/src/lib/libcrypto/bn/bn_mont.c index ee0f410c22..7bb0b91223 100644 --- a/src/lib/libcrypto/bn/bn_mont.c +++ b/src/lib/libcrypto/bn/bn_mont.c | |||
@@ -57,25 +57,27 @@ | |||
57 | */ | 57 | */ |
58 | 58 | ||
59 | /* | 59 | /* |
60 | * Details about Montgomery multiplication algorithms can be found at: | 60 | * Details about Montgomery multiplication algorithms can be found at |
61 | * http://www.ece.orst.edu/ISL/Publications.html | 61 | * http://security.ece.orst.edu/publications.html, e.g. |
62 | * http://www.ece.orst.edu/ISL/Koc/papers/j37acmon.pdf | 62 | * http://security.ece.orst.edu/koc/papers/j37acmon.pdf and |
63 | * sections 3.8 and 4.2 in http://security.ece.orst.edu/koc/papers/r01rsasw.pdf | ||
63 | */ | 64 | */ |
64 | 65 | ||
65 | #include <stdio.h> | 66 | #include <stdio.h> |
66 | #include "cryptlib.h" | 67 | #include "cryptlib.h" |
67 | #include "bn_lcl.h" | 68 | #include "bn_lcl.h" |
68 | 69 | ||
69 | #define MONT_WORD | 70 | #define MONT_WORD /* use the faster word-based algorithm */ |
70 | 71 | ||
71 | int BN_mod_mul_montgomery(BIGNUM *r, BIGNUM *a, BIGNUM *b, | 72 | int BN_mod_mul_montgomery(BIGNUM *r, BIGNUM *a, BIGNUM *b, |
72 | BN_MONT_CTX *mont, BN_CTX *ctx) | 73 | BN_MONT_CTX *mont, BN_CTX *ctx) |
73 | { | 74 | { |
74 | BIGNUM *tmp,*tmp2; | 75 | BIGNUM *tmp,*tmp2; |
75 | 76 | ||
76 | tmp= &(ctx->bn[ctx->tos]); | 77 | BN_CTX_start(ctx); |
77 | tmp2= &(ctx->bn[ctx->tos]); | 78 | tmp = BN_CTX_get(ctx); |
78 | ctx->tos+=2; | 79 | tmp2 = BN_CTX_get(ctx); |
80 | if (tmp == NULL || tmp2 == NULL) goto err; | ||
79 | 81 | ||
80 | bn_check_top(tmp); | 82 | bn_check_top(tmp); |
81 | bn_check_top(tmp2); | 83 | bn_check_top(tmp2); |
@@ -99,7 +101,7 @@ int BN_mod_mul_montgomery(BIGNUM *r, BIGNUM *a, BIGNUM *b, | |||
99 | } | 101 | } |
100 | /* reduce from aRR to aR */ | 102 | /* reduce from aRR to aR */ |
101 | if (!BN_from_montgomery(r,tmp,mont,ctx)) goto err; | 103 | if (!BN_from_montgomery(r,tmp,mont,ctx)) goto err; |
102 | ctx->tos-=2; | 104 | BN_CTX_end(ctx); |
103 | return(1); | 105 | return(1); |
104 | err: | 106 | err: |
105 | return(0); | 107 | return(0); |
@@ -108,160 +110,123 @@ err: | |||
108 | int BN_from_montgomery(BIGNUM *ret, BIGNUM *a, BN_MONT_CTX *mont, | 110 | int BN_from_montgomery(BIGNUM *ret, BIGNUM *a, BN_MONT_CTX *mont, |
109 | BN_CTX *ctx) | 111 | BN_CTX *ctx) |
110 | { | 112 | { |
111 | #ifdef BN_RECURSION_MONT | 113 | int retn=0; |
112 | if (mont->use_word) | ||
113 | #endif | ||
114 | { | ||
115 | BIGNUM *n,*r; | ||
116 | BN_ULONG *ap,*np,*rp,n0,v,*nrp; | ||
117 | int al,nl,max,i,x,ri; | ||
118 | int retn=0; | ||
119 | 114 | ||
120 | r= &(ctx->bn[ctx->tos]); | 115 | #ifdef MONT_WORD |
116 | BIGNUM *n,*r; | ||
117 | BN_ULONG *ap,*np,*rp,n0,v,*nrp; | ||
118 | int al,nl,max,i,x,ri; | ||
121 | 119 | ||
122 | if (!BN_copy(r,a)) goto err1; | 120 | BN_CTX_start(ctx); |
123 | n= &(mont->N); | 121 | if ((r = BN_CTX_get(ctx)) == NULL) goto err; |
124 | 122 | ||
125 | ap=a->d; | 123 | if (!BN_copy(r,a)) goto err; |
126 | /* mont->ri is the size of mont->N in bits/words */ | 124 | n= &(mont->N); |
127 | al=ri=mont->ri/BN_BITS2; | ||
128 | 125 | ||
129 | nl=n->top; | 126 | ap=a->d; |
130 | if ((al == 0) || (nl == 0)) { r->top=0; return(1); } | 127 | /* mont->ri is the size of mont->N in bits (rounded up |
128 | to the word size) */ | ||
129 | al=ri=mont->ri/BN_BITS2; | ||
130 | |||
131 | nl=n->top; | ||
132 | if ((al == 0) || (nl == 0)) { r->top=0; return(1); } | ||
131 | 133 | ||
132 | max=(nl+al+1); /* allow for overflow (no?) XXX */ | 134 | max=(nl+al+1); /* allow for overflow (no?) XXX */ |
133 | if (bn_wexpand(r,max) == NULL) goto err1; | 135 | if (bn_wexpand(r,max) == NULL) goto err; |
134 | if (bn_wexpand(ret,max) == NULL) goto err1; | 136 | if (bn_wexpand(ret,max) == NULL) goto err; |
135 | 137 | ||
136 | r->neg=a->neg^n->neg; | 138 | r->neg=a->neg^n->neg; |
137 | np=n->d; | 139 | np=n->d; |
138 | rp=r->d; | 140 | rp=r->d; |
139 | nrp= &(r->d[nl]); | 141 | nrp= &(r->d[nl]); |
140 | 142 | ||
141 | /* clear the top words of T */ | 143 | /* clear the top words of T */ |
142 | #if 1 | 144 | #if 1 |
143 | for (i=r->top; i<max; i++) /* memset? XXX */ | 145 | for (i=r->top; i<max; i++) /* memset? XXX */ |
144 | r->d[i]=0; | 146 | r->d[i]=0; |
145 | #else | 147 | #else |
146 | memset(&(r->d[r->top]),0,(max-r->top)*sizeof(BN_ULONG)); | 148 | memset(&(r->d[r->top]),0,(max-r->top)*sizeof(BN_ULONG)); |
147 | #endif | 149 | #endif |
148 | 150 | ||
149 | r->top=max; | 151 | r->top=max; |
150 | n0=mont->n0; | 152 | n0=mont->n0; |
151 | 153 | ||
152 | #ifdef BN_COUNT | 154 | #ifdef BN_COUNT |
153 | printf("word BN_from_montgomery %d * %d\n",nl,nl); | 155 | printf("word BN_from_montgomery %d * %d\n",nl,nl); |
154 | #endif | 156 | #endif |
155 | for (i=0; i<nl; i++) | 157 | for (i=0; i<nl; i++) |
156 | { | 158 | { |
157 | v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2); | 159 | v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2); |
158 | nrp++; | 160 | nrp++; |
159 | rp++; | 161 | rp++; |
160 | if (((nrp[-1]+=v)&BN_MASK2) >= v) | 162 | if (((nrp[-1]+=v)&BN_MASK2) >= v) |
161 | continue; | 163 | continue; |
162 | else | ||
163 | { | ||
164 | if (((++nrp[0])&BN_MASK2) != 0) continue; | ||
165 | if (((++nrp[1])&BN_MASK2) != 0) continue; | ||
166 | for (x=2; (((++nrp[x])&BN_MASK2) == 0); x++) ; | ||
167 | } | ||
168 | } | ||
169 | bn_fix_top(r); | ||
170 | |||
171 | /* mont->ri will be a multiple of the word size */ | ||
172 | #if 0 | ||
173 | BN_rshift(ret,r,mont->ri); | ||
174 | #else | ||
175 | x=ri; | ||
176 | rp=ret->d; | ||
177 | ap= &(r->d[x]); | ||
178 | if (r->top < x) | ||
179 | al=0; | ||
180 | else | 164 | else |
181 | al=r->top-x; | ||
182 | ret->top=al; | ||
183 | al-=4; | ||
184 | for (i=0; i<al; i+=4) | ||
185 | { | 165 | { |
186 | BN_ULONG t1,t2,t3,t4; | 166 | if (((++nrp[0])&BN_MASK2) != 0) continue; |
187 | 167 | if (((++nrp[1])&BN_MASK2) != 0) continue; | |
188 | t1=ap[i+0]; | 168 | for (x=2; (((++nrp[x])&BN_MASK2) == 0); x++) ; |
189 | t2=ap[i+1]; | ||
190 | t3=ap[i+2]; | ||
191 | t4=ap[i+3]; | ||
192 | rp[i+0]=t1; | ||
193 | rp[i+1]=t2; | ||
194 | rp[i+2]=t3; | ||
195 | rp[i+3]=t4; | ||
196 | } | 169 | } |
197 | al+=4; | ||
198 | for (; i<al; i++) | ||
199 | rp[i]=ap[i]; | ||
200 | #endif | ||
201 | |||
202 | if (BN_ucmp(ret, &(mont->N)) >= 0) | ||
203 | { | ||
204 | BN_usub(ret,ret,&(mont->N)); /* XXX */ | ||
205 | } | ||
206 | retn=1; | ||
207 | err1: | ||
208 | return(retn); | ||
209 | } | 170 | } |
210 | #ifdef BN_RECURSION_MONT | 171 | bn_fix_top(r); |
211 | else /* bignum version */ | 172 | |
173 | /* mont->ri will be a multiple of the word size */ | ||
174 | #if 0 | ||
175 | BN_rshift(ret,r,mont->ri); | ||
176 | #else | ||
177 | x=ri; | ||
178 | rp=ret->d; | ||
179 | ap= &(r->d[x]); | ||
180 | if (r->top < x) | ||
181 | al=0; | ||
182 | else | ||
183 | al=r->top-x; | ||
184 | ret->top=al; | ||
185 | al-=4; | ||
186 | for (i=0; i<al; i+=4) | ||
212 | { | 187 | { |
213 | BIGNUM *t1,*t2,*t3; | 188 | BN_ULONG t1,t2,t3,t4; |
214 | int j,i; | 189 | |
215 | 190 | t1=ap[i+0]; | |
216 | #ifdef BN_COUNT | 191 | t2=ap[i+1]; |
217 | printf("number BN_from_montgomery\n"); | 192 | t3=ap[i+2]; |
218 | #endif | 193 | t4=ap[i+3]; |
219 | 194 | rp[i+0]=t1; | |
220 | t1= &(ctx->bn[ctx->tos]); | 195 | rp[i+1]=t2; |
221 | t2= &(ctx->bn[ctx->tos+1]); | 196 | rp[i+2]=t3; |
222 | t3= &(ctx->bn[ctx->tos+2]); | 197 | rp[i+3]=t4; |
223 | |||
224 | i=mont->Ni.top; | ||
225 | bn_wexpand(ret,i); /* perhaps only i*2 */ | ||
226 | bn_wexpand(t1,i*4); /* perhaps only i*2 */ | ||
227 | bn_wexpand(t2,i*2); /* perhaps only i */ | ||
228 | |||
229 | bn_mul_low_recursive(t2->d,a->d,mont->Ni.d,i,t1->d); | ||
230 | |||
231 | BN_zero(t3); | ||
232 | BN_set_bit(t3,mont->N.top*BN_BITS2); | ||
233 | bn_sub_words(t3->d,t3->d,a->d,i); | ||
234 | bn_mul_high(ret->d,t2->d,mont->N.d,t3->d,i,t1->d); | ||
235 | |||
236 | /* hmm... if a is between i and 2*i, things are bad */ | ||
237 | if (a->top > i) | ||
238 | { | ||
239 | j=(int)(bn_add_words(ret->d,ret->d,&(a->d[i]),i)); | ||
240 | if (j) /* overflow */ | ||
241 | bn_sub_words(ret->d,ret->d,mont->N.d,i); | ||
242 | } | ||
243 | ret->top=i; | ||
244 | bn_fix_top(ret); | ||
245 | if (a->d[0]) | ||
246 | BN_add_word(ret,1); /* Always? */ | ||
247 | else /* Very very rare */ | ||
248 | { | ||
249 | for (i=1; i<mont->N.top-1; i++) | ||
250 | { | ||
251 | if (a->d[i]) | ||
252 | { | ||
253 | BN_add_word(ret,1); /* Always? */ | ||
254 | break; | ||
255 | } | ||
256 | } | ||
257 | } | ||
258 | |||
259 | if (BN_ucmp(ret,&(mont->N)) >= 0) | ||
260 | BN_usub(ret,ret,&(mont->N)); | ||
261 | |||
262 | return(1); | ||
263 | } | 198 | } |
199 | al+=4; | ||
200 | for (; i<al; i++) | ||
201 | rp[i]=ap[i]; | ||
264 | #endif | 202 | #endif |
203 | #else /* !MONT_WORD */ | ||
204 | BIGNUM *t1,*t2; | ||
205 | |||
206 | BN_CTX_start(ctx); | ||
207 | t1 = BN_CTX_get(ctx); | ||
208 | t2 = BN_CTX_get(ctx); | ||
209 | if (t1 == NULL || t2 == NULL) goto err; | ||
210 | |||
211 | if (!BN_copy(t1,a)) goto err; | ||
212 | BN_mask_bits(t1,mont->ri); | ||
213 | |||
214 | if (!BN_mul(t2,t1,&mont->Ni,ctx)) goto err; | ||
215 | BN_mask_bits(t2,mont->ri); | ||
216 | |||
217 | if (!BN_mul(t1,t2,&mont->N,ctx)) goto err; | ||
218 | if (!BN_add(t2,a,t1)) goto err; | ||
219 | BN_rshift(ret,t2,mont->ri); | ||
220 | #endif /* MONT_WORD */ | ||
221 | |||
222 | if (BN_ucmp(ret, &(mont->N)) >= 0) | ||
223 | { | ||
224 | BN_usub(ret,ret,&(mont->N)); | ||
225 | } | ||
226 | retn=1; | ||
227 | err: | ||
228 | BN_CTX_end(ctx); | ||
229 | return(retn); | ||
265 | } | 230 | } |
266 | 231 | ||
267 | BN_MONT_CTX *BN_MONT_CTX_new(void) | 232 | BN_MONT_CTX *BN_MONT_CTX_new(void) |
@@ -278,7 +243,6 @@ BN_MONT_CTX *BN_MONT_CTX_new(void) | |||
278 | 243 | ||
279 | void BN_MONT_CTX_init(BN_MONT_CTX *ctx) | 244 | void BN_MONT_CTX_init(BN_MONT_CTX *ctx) |
280 | { | 245 | { |
281 | ctx->use_word=0; | ||
282 | ctx->ri=0; | 246 | ctx->ri=0; |
283 | BN_init(&(ctx->RR)); | 247 | BN_init(&(ctx->RR)); |
284 | BN_init(&(ctx->N)); | 248 | BN_init(&(ctx->N)); |
@@ -306,85 +270,53 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) | |||
306 | R= &(mont->RR); /* grab RR as a temp */ | 270 | R= &(mont->RR); /* grab RR as a temp */ |
307 | BN_copy(&(mont->N),mod); /* Set N */ | 271 | BN_copy(&(mont->N),mod); /* Set N */ |
308 | 272 | ||
309 | #ifdef BN_RECURSION_MONT | 273 | #ifdef MONT_WORD |
310 | if (mont->N.top < BN_MONT_CTX_SET_SIZE_WORD) | ||
311 | #endif | ||
312 | { | 274 | { |
313 | BIGNUM tmod; | 275 | BIGNUM tmod; |
314 | BN_ULONG buf[2]; | 276 | BN_ULONG buf[2]; |
315 | 277 | ||
316 | mont->use_word=1; | ||
317 | |||
318 | mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2; | 278 | mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2; |
319 | BN_zero(R); | 279 | BN_zero(R); |
320 | BN_set_bit(R,BN_BITS2); | 280 | BN_set_bit(R,BN_BITS2); /* R */ |
321 | /* I was bad, this modification of a passed variable was | ||
322 | * breaking the multithreaded stuff :-( | ||
323 | * z=mod->top; | ||
324 | * mod->top=1; */ | ||
325 | 281 | ||
326 | buf[0]=mod->d[0]; | 282 | buf[0]=mod->d[0]; /* tmod = N mod word size */ |
327 | buf[1]=0; | 283 | buf[1]=0; |
328 | tmod.d=buf; | 284 | tmod.d=buf; |
329 | tmod.top=1; | 285 | tmod.top=1; |
330 | tmod.max=mod->max; | 286 | tmod.max=2; |
331 | tmod.neg=mod->neg; | 287 | tmod.neg=mod->neg; |
332 | 288 | /* Ri = R^-1 mod N*/ | |
333 | if ((BN_mod_inverse(&Ri,R,&tmod,ctx)) == NULL) | 289 | if ((BN_mod_inverse(&Ri,R,&tmod,ctx)) == NULL) |
334 | goto err; | 290 | goto err; |
335 | BN_lshift(&Ri,&Ri,BN_BITS2); /* R*Ri */ | 291 | BN_lshift(&Ri,&Ri,BN_BITS2); /* R*Ri */ |
336 | if (!BN_is_zero(&Ri)) | 292 | if (!BN_is_zero(&Ri)) |
337 | { | ||
338 | #if 1 | ||
339 | BN_sub_word(&Ri,1); | 293 | BN_sub_word(&Ri,1); |
340 | #else | 294 | else /* if N mod word size == 1 */ |
341 | BN_usub(&Ri,&Ri,BN_value_one()); /* R*Ri - 1 */ | 295 | BN_set_word(&Ri,BN_MASK2); /* Ri-- (mod word size) */ |
342 | #endif | 296 | BN_div(&Ri,NULL,&Ri,&tmod,ctx); /* Ni = (R*Ri-1)/N, |
343 | } | 297 | * keep only least significant word: */ |
344 | else | ||
345 | { | ||
346 | /* This is not common..., 1 in BN_MASK2, | ||
347 | * It happens when buf[0] was == 1. So for 8 bit, | ||
348 | * this is 1/256, 16bit, 1 in 2^16 etc. | ||
349 | */ | ||
350 | BN_set_word(&Ri,BN_MASK2); | ||
351 | } | ||
352 | BN_div(&Ri,NULL,&Ri,&tmod,ctx); | ||
353 | mont->n0=Ri.d[0]; | 298 | mont->n0=Ri.d[0]; |
354 | BN_free(&Ri); | 299 | BN_free(&Ri); |
355 | /* mod->top=z; */ | ||
356 | } | 300 | } |
357 | #ifdef BN_RECURSION_MONT | 301 | #else /* !MONT_WORD */ |
358 | else | 302 | { /* bignum version */ |
359 | { | 303 | mont->ri=BN_num_bits(mod); |
360 | mont->use_word=0; | ||
361 | mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2; | ||
362 | #if 1 | ||
363 | BN_zero(R); | 304 | BN_zero(R); |
364 | BN_set_bit(R,mont->ri); | 305 | BN_set_bit(R,mont->ri); /* R = 2^ri */ |
365 | #else | 306 | /* Ri = R^-1 mod N*/ |
366 | BN_lshift(R,BN_value_one(),mont->ri); /* R */ | ||
367 | #endif | ||
368 | if ((BN_mod_inverse(&Ri,R,mod,ctx)) == NULL) | 307 | if ((BN_mod_inverse(&Ri,R,mod,ctx)) == NULL) |
369 | goto err; | 308 | goto err; |
370 | BN_lshift(&Ri,&Ri,mont->ri); /* R*Ri */ | 309 | BN_lshift(&Ri,&Ri,mont->ri); /* R*Ri */ |
371 | #if 1 | ||
372 | BN_sub_word(&Ri,1); | 310 | BN_sub_word(&Ri,1); |
373 | #else | 311 | /* Ni = (R*Ri-1) / N */ |
374 | BN_usub(&Ri,&Ri,BN_value_one()); /* R*Ri - 1 */ | ||
375 | #endif | ||
376 | BN_div(&(mont->Ni),NULL,&Ri,mod,ctx); | 312 | BN_div(&(mont->Ni),NULL,&Ri,mod,ctx); |
377 | BN_free(&Ri); | 313 | BN_free(&Ri); |
378 | } | 314 | } |
379 | #endif | 315 | #endif |
380 | 316 | ||
381 | /* setup RR for conversions */ | 317 | /* setup RR for conversions */ |
382 | #if 1 | ||
383 | BN_zero(&(mont->RR)); | 318 | BN_zero(&(mont->RR)); |
384 | BN_set_bit(&(mont->RR),mont->ri*2); | 319 | BN_set_bit(&(mont->RR),mont->ri*2); |
385 | #else | ||
386 | BN_lshift(mont->RR,BN_value_one(),mont->ri*2); | ||
387 | #endif | ||
388 | BN_mod(&(mont->RR),&(mont->RR),&(mont->N),ctx); | 320 | BN_mod(&(mont->RR),&(mont->RR),&(mont->N),ctx); |
389 | 321 | ||
390 | return(1); | 322 | return(1); |
@@ -399,7 +331,6 @@ BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from) | |||
399 | BN_copy(&(to->RR),&(from->RR)); | 331 | BN_copy(&(to->RR),&(from->RR)); |
400 | BN_copy(&(to->N),&(from->N)); | 332 | BN_copy(&(to->N),&(from->N)); |
401 | BN_copy(&(to->Ni),&(from->Ni)); | 333 | BN_copy(&(to->Ni),&(from->Ni)); |
402 | to->use_word=from->use_word; | ||
403 | to->ri=from->ri; | 334 | to->ri=from->ri; |
404 | to->n0=from->n0; | 335 | to->n0=from->n0; |
405 | return(to); | 336 | return(to); |