diff options
Diffstat (limited to 'src/lib/libcrypto/bn/bn_mont.c')
-rw-r--r-- | src/lib/libcrypto/bn/bn_mont.c | 116 |
1 files changed, 29 insertions, 87 deletions
diff --git a/src/lib/libcrypto/bn/bn_mont.c b/src/lib/libcrypto/bn/bn_mont.c index 1a866880f5..427b5cf4df 100644 --- a/src/lib/libcrypto/bn/bn_mont.c +++ b/src/lib/libcrypto/bn/bn_mont.c | |||
@@ -177,31 +177,26 @@ err: | |||
177 | static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) | 177 | static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) |
178 | { | 178 | { |
179 | BIGNUM *n; | 179 | BIGNUM *n; |
180 | BN_ULONG *ap,*np,*rp,n0,v,*nrp; | 180 | BN_ULONG *ap,*np,*rp,n0,v,carry; |
181 | int al,nl,max,i,x,ri; | 181 | int nl,max,i; |
182 | 182 | ||
183 | n= &(mont->N); | 183 | n= &(mont->N); |
184 | /* mont->ri is the size of mont->N in bits (rounded up | ||
185 | to the word size) */ | ||
186 | al=ri=mont->ri/BN_BITS2; | ||
187 | |||
188 | nl=n->top; | 184 | nl=n->top; |
189 | if ((al == 0) || (nl == 0)) { ret->top=0; return(1); } | 185 | if (nl == 0) { ret->top=0; return(1); } |
190 | 186 | ||
191 | max=(nl+al+1); /* allow for overflow (no?) XXX */ | 187 | max=(2*nl); /* carry is stored separately */ |
192 | if (bn_wexpand(r,max) == NULL) return(0); | 188 | if (bn_wexpand(r,max) == NULL) return(0); |
193 | 189 | ||
194 | r->neg^=n->neg; | 190 | r->neg^=n->neg; |
195 | np=n->d; | 191 | np=n->d; |
196 | rp=r->d; | 192 | rp=r->d; |
197 | nrp= &(r->d[nl]); | ||
198 | 193 | ||
199 | /* clear the top words of T */ | 194 | /* clear the top words of T */ |
200 | #if 1 | 195 | #if 1 |
201 | for (i=r->top; i<max; i++) /* memset? XXX */ | 196 | for (i=r->top; i<max; i++) /* memset? XXX */ |
202 | r->d[i]=0; | 197 | rp[i]=0; |
203 | #else | 198 | #else |
204 | memset(&(r->d[r->top]),0,(max-r->top)*sizeof(BN_ULONG)); | 199 | memset(&(rp[r->top]),0,(max-r->top)*sizeof(BN_ULONG)); |
205 | #endif | 200 | #endif |
206 | 201 | ||
207 | r->top=max; | 202 | r->top=max; |
@@ -210,7 +205,7 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) | |||
210 | #ifdef BN_COUNT | 205 | #ifdef BN_COUNT |
211 | fprintf(stderr,"word BN_from_montgomery_word %d * %d\n",nl,nl); | 206 | fprintf(stderr,"word BN_from_montgomery_word %d * %d\n",nl,nl); |
212 | #endif | 207 | #endif |
213 | for (i=0; i<nl; i++) | 208 | for (carry=0, i=0; i<nl; i++, rp++) |
214 | { | 209 | { |
215 | #ifdef __TANDEM | 210 | #ifdef __TANDEM |
216 | { | 211 | { |
@@ -228,61 +223,33 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) | |||
228 | #else | 223 | #else |
229 | v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2); | 224 | v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2); |
230 | #endif | 225 | #endif |
231 | nrp++; | 226 | v = (v+carry+rp[nl])&BN_MASK2; |
232 | rp++; | 227 | carry |= (v != rp[nl]); |
233 | if (((nrp[-1]+=v)&BN_MASK2) >= v) | 228 | carry &= (v <= rp[nl]); |
234 | continue; | 229 | rp[nl]=v; |
235 | else | ||
236 | { | ||
237 | if (((++nrp[0])&BN_MASK2) != 0) continue; | ||
238 | if (((++nrp[1])&BN_MASK2) != 0) continue; | ||
239 | for (x=2; (((++nrp[x])&BN_MASK2) == 0); x++) ; | ||
240 | } | ||
241 | } | ||
242 | bn_correct_top(r); | ||
243 | |||
244 | /* mont->ri will be a multiple of the word size and below code | ||
245 | * is kind of BN_rshift(ret,r,mont->ri) equivalent */ | ||
246 | if (r->top <= ri) | ||
247 | { | ||
248 | ret->top=0; | ||
249 | return(1); | ||
250 | } | 230 | } |
251 | al=r->top-ri; | ||
252 | 231 | ||
253 | #define BRANCH_FREE 1 | 232 | if (bn_wexpand(ret,nl) == NULL) return(0); |
254 | #if BRANCH_FREE | 233 | ret->top=nl; |
255 | if (bn_wexpand(ret,ri) == NULL) return(0); | ||
256 | x=0-(((al-ri)>>(sizeof(al)*8-1))&1); | ||
257 | ret->top=x=(ri&~x)|(al&x); /* min(ri,al) */ | ||
258 | ret->neg=r->neg; | 234 | ret->neg=r->neg; |
259 | 235 | ||
260 | rp=ret->d; | 236 | rp=ret->d; |
261 | ap=&(r->d[ri]); | 237 | ap=&(r->d[nl]); |
262 | 238 | ||
239 | #define BRANCH_FREE 1 | ||
240 | #if BRANCH_FREE | ||
263 | { | 241 | { |
264 | size_t m1,m2; | 242 | BN_ULONG *nrp; |
265 | 243 | size_t m; | |
266 | v=bn_sub_words(rp,ap,np,ri); | ||
267 | /* this ----------------^^ works even in al<ri case | ||
268 | * thanks to zealous zeroing of top of the vector in the | ||
269 | * beginning. */ | ||
270 | 244 | ||
271 | /* if (al==ri && !v) || al>ri) nrp=rp; else nrp=ap; */ | 245 | v=bn_sub_words(rp,ap,np,nl)-carry; |
272 | /* in other words if subtraction result is real, then | 246 | /* if subtraction result is real, then |
273 | * trick unconditional memcpy below to perform in-place | 247 | * trick unconditional memcpy below to perform in-place |
274 | * "refresh" instead of actual copy. */ | 248 | * "refresh" instead of actual copy. */ |
275 | m1=0-(size_t)(((al-ri)>>(sizeof(al)*8-1))&1); /* al<ri */ | 249 | m=(0-(size_t)v); |
276 | m2=0-(size_t)(((ri-al)>>(sizeof(al)*8-1))&1); /* al>ri */ | 250 | nrp=(BN_ULONG *)(((PTR_SIZE_INT)rp&~m)|((PTR_SIZE_INT)ap&m)); |
277 | m1|=m2; /* (al!=ri) */ | ||
278 | m1|=(0-(size_t)v); /* (al!=ri || v) */ | ||
279 | m1&=~m2; /* (al!=ri || v) && !al>ri */ | ||
280 | nrp=(BN_ULONG *)(((PTR_SIZE_INT)rp&~m1)|((PTR_SIZE_INT)ap&m1)); | ||
281 | } | ||
282 | 251 | ||
283 | /* 'i<ri' is chosen to eliminate dependency on input data, even | 252 | for (i=0,nl-=4; i<nl; i+=4) |
284 | * though it results in redundant copy in al<ri case. */ | ||
285 | for (i=0,ri-=4; i<ri; i+=4) | ||
286 | { | 253 | { |
287 | BN_ULONG t1,t2,t3,t4; | 254 | BN_ULONG t1,t2,t3,t4; |
288 | 255 | ||
@@ -295,40 +262,15 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) | |||
295 | rp[i+2]=t3; | 262 | rp[i+2]=t3; |
296 | rp[i+3]=t4; | 263 | rp[i+3]=t4; |
297 | } | 264 | } |
298 | for (ri+=4; i<ri; i++) | 265 | for (nl+=4; i<nl; i++) |
299 | rp[i]=nrp[i], ap[i]=0; | 266 | rp[i]=nrp[i], ap[i]=0; |
300 | bn_correct_top(r); | 267 | } |
301 | bn_correct_top(ret); | ||
302 | #else | 268 | #else |
303 | if (bn_wexpand(ret,al) == NULL) return(0); | 269 | if (bn_sub_words (rp,ap,np,nl)-carry) |
304 | ret->top=al; | 270 | memcpy(rp,ap,nl*sizeof(BN_ULONG)); |
305 | ret->neg=r->neg; | ||
306 | |||
307 | rp=ret->d; | ||
308 | ap=&(r->d[ri]); | ||
309 | al-=4; | ||
310 | for (i=0; i<al; i+=4) | ||
311 | { | ||
312 | BN_ULONG t1,t2,t3,t4; | ||
313 | |||
314 | t1=ap[i+0]; | ||
315 | t2=ap[i+1]; | ||
316 | t3=ap[i+2]; | ||
317 | t4=ap[i+3]; | ||
318 | rp[i+0]=t1; | ||
319 | rp[i+1]=t2; | ||
320 | rp[i+2]=t3; | ||
321 | rp[i+3]=t4; | ||
322 | } | ||
323 | al+=4; | ||
324 | for (; i<al; i++) | ||
325 | rp[i]=ap[i]; | ||
326 | |||
327 | if (BN_ucmp(ret, &(mont->N)) >= 0) | ||
328 | { | ||
329 | if (!BN_usub(ret,ret,&(mont->N))) return(0); | ||
330 | } | ||
331 | #endif | 271 | #endif |
272 | bn_correct_top(r); | ||
273 | bn_correct_top(ret); | ||
332 | bn_check_top(ret); | 274 | bn_check_top(ret); |
333 | 275 | ||
334 | return(1); | 276 | return(1); |