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