From http://openssl.org/news/patch-CVE-2007-3108.txt
This are upstream changes of bn_mont.c between 1.36.2.4 and 1.36.2.6
Kurt Roeckx
16 years ago
175 | 175 | |
176 | 176 | max=(nl+al+1); /* allow for overflow (no?) XXX */ |
177 | 177 | if (bn_wexpand(r,max) == NULL) goto err; |
178 | if (bn_wexpand(ret,max) == NULL) goto err; | |
179 | 178 | |
180 | 179 | r->neg=a->neg^n->neg; |
181 | 180 | np=n->d; |
227 | 226 | } |
228 | 227 | bn_correct_top(r); |
229 | 228 | |
230 | /* mont->ri will be a multiple of the word size */ | |
231 | #if 0 | |
232 | BN_rshift(ret,r,mont->ri); | |
233 | #else | |
234 | ret->neg = r->neg; | |
235 | x=ri; | |
229 | /* mont->ri will be a multiple of the word size and below code | |
230 | * is kind of BN_rshift(ret,r,mont->ri) equivalent */ | |
231 | if (r->top <= ri) | |
232 | { | |
233 | ret->top=0; | |
234 | retn=1; | |
235 | goto err; | |
236 | } | |
237 | al=r->top-ri; | |
238 | ||
239 | # define BRANCH_FREE 1 | |
240 | # if BRANCH_FREE | |
241 | if (bn_wexpand(ret,ri) == NULL) goto err; | |
242 | x=0-(((al-ri)>>(sizeof(al)*8-1))&1); | |
243 | ret->top=x=(ri&~x)|(al&x); /* min(ri,al) */ | |
244 | ret->neg=r->neg; | |
245 | ||
236 | 246 | rp=ret->d; |
237 | ap= &(r->d[x]); | |
238 | if (r->top < x) | |
239 | al=0; | |
240 | else | |
241 | al=r->top-x; | |
247 | ap=&(r->d[ri]); | |
248 | ||
249 | { | |
250 | size_t m1,m2; | |
251 | ||
252 | v=bn_sub_words(rp,ap,np,ri); | |
253 | /* this ----------------^^ works even in al<ri case | |
254 | * thanks to zealous zeroing of top of the vector in the | |
255 | * beginning. */ | |
256 | ||
257 | /* if (al==ri && !v) || al>ri) nrp=rp; else nrp=ap; */ | |
258 | /* in other words if subtraction result is real, then | |
259 | * trick unconditional memcpy below to perform in-place | |
260 | * "refresh" instead of actual copy. */ | |
261 | m1=0-(size_t)(((al-ri)>>(sizeof(al)*8-1))&1); /* al<ri */ | |
262 | m2=0-(size_t)(((ri-al)>>(sizeof(al)*8-1))&1); /* al>ri */ | |
263 | m1|=m2; /* (al!=ri) */ | |
264 | m1|=(0-(size_t)v); /* (al!=ri || v) */ | |
265 | m1&=~m2; /* (al!=ri || v) && !al>ri */ | |
266 | nrp=(BN_ULONG *)(((size_t)rp&~m1)|((size_t)ap&m1)); | |
267 | } | |
268 | ||
269 | /* 'i<ri' is chosen to eliminate dependency on input data, even | |
270 | * though it results in redundant copy in al<ri case. */ | |
271 | for (i=0,ri-=4; i<ri; i+=4) | |
272 | { | |
273 | BN_ULONG t1,t2,t3,t4; | |
274 | ||
275 | t1=nrp[i+0]; | |
276 | t2=nrp[i+1]; | |
277 | t3=nrp[i+2]; ap[i+0]=0; | |
278 | t4=nrp[i+3]; ap[i+1]=0; | |
279 | rp[i+0]=t1; ap[i+2]=0; | |
280 | rp[i+1]=t2; ap[i+3]=0; | |
281 | rp[i+2]=t3; | |
282 | rp[i+3]=t4; | |
283 | } | |
284 | for (ri+=4; i<ri; i++) | |
285 | rp[i]=nrp[i], ap[i]=0; | |
286 | # else | |
287 | if (bn_wexpand(ret,al) == NULL) goto err; | |
242 | 288 | ret->top=al; |
289 | ret->neg=r->neg; | |
290 | ||
291 | rp=ret->d; | |
292 | ap=&(r->d[ri]); | |
243 | 293 | al-=4; |
244 | 294 | for (i=0; i<al; i+=4) |
245 | 295 | { |
257 | 307 | al+=4; |
258 | 308 | for (; i<al; i++) |
259 | 309 | rp[i]=ap[i]; |
260 | #endif | |
310 | # endif | |
261 | 311 | #else /* !MONT_WORD */ |
262 | 312 | BIGNUM *t1,*t2; |
263 | 313 | |
277 | 327 | if (!BN_rshift(ret,t2,mont->ri)) goto err; |
278 | 328 | #endif /* MONT_WORD */ |
279 | 329 | |
330 | #if !defined(BRANCH_FREE) || BRANCH_FREE==0 | |
280 | 331 | if (BN_ucmp(ret, &(mont->N)) >= 0) |
281 | 332 | { |
282 | 333 | if (!BN_usub(ret,ret,&(mont->N))) goto err; |
283 | 334 | } |
335 | #endif | |
284 | 336 | retn=1; |
285 | 337 | bn_check_top(ret); |
286 | 338 | err: |