summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/bn/bn_mont.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/libcrypto/bn/bn_mont.c')
-rw-r--r--src/lib/libcrypto/bn/bn_mont.c116
1 files changed, 87 insertions, 29 deletions
diff --git a/src/lib/libcrypto/bn/bn_mont.c b/src/lib/libcrypto/bn/bn_mont.c
index 427b5cf4df..1a866880f5 100644
--- a/src/lib/libcrypto/bn/bn_mont.c
+++ b/src/lib/libcrypto/bn/bn_mont.c
@@ -177,26 +177,31 @@ err:
177static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) 177static 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,carry; 180 BN_ULONG *ap,*np,*rp,n0,v,*nrp;
181 int nl,max,i; 181 int al,nl,max,i,x,ri;
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
184 nl=n->top; 188 nl=n->top;
185 if (nl == 0) { ret->top=0; return(1); } 189 if ((al == 0) || (nl == 0)) { ret->top=0; return(1); }
186 190
187 max=(2*nl); /* carry is stored separately */ 191 max=(nl+al+1); /* allow for overflow (no?) XXX */
188 if (bn_wexpand(r,max) == NULL) return(0); 192 if (bn_wexpand(r,max) == NULL) return(0);
189 193
190 r->neg^=n->neg; 194 r->neg^=n->neg;
191 np=n->d; 195 np=n->d;
192 rp=r->d; 196 rp=r->d;
197 nrp= &(r->d[nl]);
193 198
194 /* clear the top words of T */ 199 /* clear the top words of T */
195#if 1 200#if 1
196 for (i=r->top; i<max; i++) /* memset? XXX */ 201 for (i=r->top; i<max; i++) /* memset? XXX */
197 rp[i]=0; 202 r->d[i]=0;
198#else 203#else
199 memset(&(rp[r->top]),0,(max-r->top)*sizeof(BN_ULONG)); 204 memset(&(r->d[r->top]),0,(max-r->top)*sizeof(BN_ULONG));
200#endif 205#endif
201 206
202 r->top=max; 207 r->top=max;
@@ -205,7 +210,7 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
205#ifdef BN_COUNT 210#ifdef BN_COUNT
206 fprintf(stderr,"word BN_from_montgomery_word %d * %d\n",nl,nl); 211 fprintf(stderr,"word BN_from_montgomery_word %d * %d\n",nl,nl);
207#endif 212#endif
208 for (carry=0, i=0; i<nl; i++, rp++) 213 for (i=0; i<nl; i++)
209 { 214 {
210#ifdef __TANDEM 215#ifdef __TANDEM
211 { 216 {
@@ -223,33 +228,61 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
223#else 228#else
224 v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2); 229 v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2);
225#endif 230#endif
226 v = (v+carry+rp[nl])&BN_MASK2; 231 nrp++;
227 carry |= (v != rp[nl]); 232 rp++;
228 carry &= (v <= rp[nl]); 233 if (((nrp[-1]+=v)&BN_MASK2) >= v)
229 rp[nl]=v; 234 continue;
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);
230 } 250 }
251 al=r->top-ri;
231 252
232 if (bn_wexpand(ret,nl) == NULL) return(0); 253#define BRANCH_FREE 1
233 ret->top=nl; 254#if BRANCH_FREE
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) */
234 ret->neg=r->neg; 258 ret->neg=r->neg;
235 259
236 rp=ret->d; 260 rp=ret->d;
237 ap=&(r->d[nl]); 261 ap=&(r->d[ri]);
238 262
239#define BRANCH_FREE 1
240#if BRANCH_FREE
241 { 263 {
242 BN_ULONG *nrp; 264 size_t m1,m2;
243 size_t m; 265
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. */
244 270
245 v=bn_sub_words(rp,ap,np,nl)-carry; 271 /* if (al==ri && !v) || al>ri) nrp=rp; else nrp=ap; */
246 /* if subtraction result is real, then 272 /* in other words if subtraction result is real, then
247 * trick unconditional memcpy below to perform in-place 273 * trick unconditional memcpy below to perform in-place
248 * "refresh" instead of actual copy. */ 274 * "refresh" instead of actual copy. */
249 m=(0-(size_t)v); 275 m1=0-(size_t)(((al-ri)>>(sizeof(al)*8-1))&1); /* al<ri */
250 nrp=(BN_ULONG *)(((PTR_SIZE_INT)rp&~m)|((PTR_SIZE_INT)ap&m)); 276 m2=0-(size_t)(((ri-al)>>(sizeof(al)*8-1))&1); /* al>ri */
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 }
251 282
252 for (i=0,nl-=4; i<nl; i+=4) 283 /* 'i<ri' is chosen to eliminate dependency on input data, even
284 * though it results in redundant copy in al<ri case. */
285 for (i=0,ri-=4; i<ri; i+=4)
253 { 286 {
254 BN_ULONG t1,t2,t3,t4; 287 BN_ULONG t1,t2,t3,t4;
255 288
@@ -262,15 +295,40 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
262 rp[i+2]=t3; 295 rp[i+2]=t3;
263 rp[i+3]=t4; 296 rp[i+3]=t4;
264 } 297 }
265 for (nl+=4; i<nl; i++) 298 for (ri+=4; i<ri; i++)
266 rp[i]=nrp[i], ap[i]=0; 299 rp[i]=nrp[i], ap[i]=0;
267 }
268#else
269 if (bn_sub_words (rp,ap,np,nl)-carry)
270 memcpy(rp,ap,nl*sizeof(BN_ULONG));
271#endif
272 bn_correct_top(r); 300 bn_correct_top(r);
273 bn_correct_top(ret); 301 bn_correct_top(ret);
302#else
303 if (bn_wexpand(ret,al) == NULL) return(0);
304 ret->top=al;
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
274 bn_check_top(ret); 332 bn_check_top(ret);
275 333
276 return(1); 334 return(1);