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, 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:
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,*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);