X-Git-Url: https://git.openssl.org/?a=blobdiff_plain;f=crypto%2Fbn%2Fbn_mont.c;h=287392db0f000b8a3aec38f668e8548859071e29;hb=c86f2054f39c7005bc03f91db2d7bcf38f0a92ac;hp=e0aa3c769d227dc5f58e9052627b6edb070819d4;hpb=dfeab0689f69c0b4bd3480ffd37a9cacc2f17d9c;p=openssl.git diff --git a/crypto/bn/bn_mont.c b/crypto/bn/bn_mont.c index e0aa3c769d..287392db0f 100644 --- a/crypto/bn/bn_mont.c +++ b/crypto/bn/bn_mont.c @@ -56,38 +56,33 @@ * [including the GNU Public Licence.] */ +/* + * Details about Montgomery multiplication algorithms can be found at + * http://security.ece.orst.edu/publications.html, e.g. + * http://security.ece.orst.edu/koc/papers/j37acmon.pdf and + * sections 3.8 and 4.2 in http://security.ece.orst.edu/koc/papers/r01rsasw.pdf + */ + #include #include "cryptlib.h" #include "bn_lcl.h" -#define MONT_WORD +#define MONT_WORD /* use the faster word-based algorithm */ -int BN_mod_mul_montgomery(r,a,b,mont,ctx) -BIGNUM *r,*a,*b; -BN_MONT_CTX *mont; -BN_CTX *ctx; +int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, + BN_MONT_CTX *mont, BN_CTX *ctx) { - BIGNUM *tmp,*tmp2; + BIGNUM *tmp; + int ret=0; - tmp= &(ctx->bn[ctx->tos]); - tmp2= &(ctx->bn[ctx->tos]); - ctx->tos+=2; + BN_CTX_start(ctx); + tmp = BN_CTX_get(ctx); + if (tmp == NULL) goto err; bn_check_top(tmp); - bn_check_top(tmp2); - if (a == b) { -#if 0 - bn_wexpand(tmp,a->top*2); - bn_wexpand(tmp2,a->top*4); - bn_sqr_recursive(tmp->d,a->d,a->top,tmp2->d); - tmp->top=a->top*2; - if (tmp->d[tmp->top-1] == 0) - tmp->top--; -#else if (!BN_sqr(tmp,a,ctx)) goto err; -#endif } else { @@ -95,179 +90,157 @@ BN_CTX *ctx; } /* reduce from aRR to aR */ if (!BN_from_montgomery(r,tmp,mont,ctx)) goto err; - ctx->tos-=2; - return(1); + bn_check_top(r); + ret=1; err: - return(0); + BN_CTX_end(ctx); + return(ret); } -int BN_from_montgomery(ret,a,mont,ctx) -BIGNUM *ret; -BIGNUM *a; -BN_MONT_CTX *mont; -BN_CTX *ctx; +int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont, + BN_CTX *ctx) { -#ifdef BN_RECURSION - if (mont->use_word) -#endif - { - BIGNUM *n,*r; - BN_ULONG *ap,*np,*rp,n0,v,*nrp; - int al,nl,max,i,x,ri; - int retn=0; + int retn=0; - r= &(ctx->bn[ctx->tos]); +#ifdef MONT_WORD + BIGNUM *n,*r; + BN_ULONG *ap,*np,*rp,n0,v,*nrp; + int al,nl,max,i,x,ri; - if (!BN_copy(r,a)) goto err1; - n= &(mont->N); + BN_CTX_start(ctx); + if ((r = BN_CTX_get(ctx)) == NULL) goto err; - ap=a->d; - /* mont->ri is the size of mont->N in bits/words */ - al=ri=mont->ri/BN_BITS2; + if (!BN_copy(r,a)) goto err; + n= &(mont->N); - nl=n->top; - if ((al == 0) || (nl == 0)) { r->top=0; return(1); } + ap=a->d; + /* mont->ri is the size of mont->N in bits (rounded up + to the word size) */ + al=ri=mont->ri/BN_BITS2; + + nl=n->top; + if ((al == 0) || (nl == 0)) { r->top=0; return(1); } - max=(nl+al+1); /* allow for overflow (no?) XXX */ - if (bn_wexpand(r,max) == NULL) goto err1; - if (bn_wexpand(ret,max) == NULL) goto err1; + max=(nl+al+1); /* allow for overflow (no?) XXX */ + if (bn_wexpand(r,max) == NULL) goto err; + if (bn_wexpand(ret,max) == NULL) goto err; - r->neg=a->neg^n->neg; - np=n->d; - rp=r->d; - nrp= &(r->d[nl]); + r->neg=a->neg^n->neg; + np=n->d; + rp=r->d; + nrp= &(r->d[nl]); - /* clear the top words of T */ + /* clear the top words of T */ #if 1 - for (i=r->top; id[i]=0; + for (i=r->top; id[i]=0; #else - memset(&(r->d[r->top]),0,(max-r->top)*sizeof(BN_ULONG)); + memset(&(r->d[r->top]),0,(max-r->top)*sizeof(BN_ULONG)); #endif - r->top=max; - n0=mont->n0; + r->top=max; + n0=mont->n0; #ifdef BN_COUNT -printf("word BN_from_montgomery %d * %d\n",nl,nl); + fprintf(stderr,"word BN_from_montgomery %d * %d\n",nl,nl); #endif - for (i=0; i= v) - continue; - else - { - if (((++nrp[0])&BN_MASK2) != 0) continue; - if (((++nrp[1])&BN_MASK2) != 0) continue; - for (x=2; (((++nrp[x])&BN_MASK2) == 0); x++) ; - } - } - bn_fix_top(r); - - /* mont->ri will be a multiple of the word size */ -#if 0 - BN_rshift(ret,r,mont->ri); + for (i=0; id; - ap= &(r->d[x]); - if (r->top < x) - al=0; - else - al=r->top-x; - ret->top=al; - al-=4; - for (i=0; iN)) >= 0) + nrp++; + rp++; + if (((nrp[-1]+=v)&BN_MASK2) >= v) + continue; + else { - BN_usub(ret,ret,&(mont->N)); /* XXX */ + if (((++nrp[0])&BN_MASK2) != 0) continue; + if (((++nrp[1])&BN_MASK2) != 0) continue; + for (x=2; (((++nrp[x])&BN_MASK2) == 0); x++) ; } - retn=1; -err1: - return(retn); } -#ifdef BN_RECURSION - else /* bignum version */ + bn_correct_top(r); + + /* mont->ri will be a multiple of the word size */ +#if 0 + BN_rshift(ret,r,mont->ri); +#else + ret->neg = r->neg; + x=ri; + rp=ret->d; + ap= &(r->d[x]); + if (r->top < x) + al=0; + else + al=r->top-x; + ret->top=al; + al-=4; + for (i=0; ibn[ctx->tos]); - t2= &(ctx->bn[ctx->tos+1]); - t3= &(ctx->bn[ctx->tos+2]); - - i=mont->Ni.top; - bn_wexpand(ret,i); /* perhaps only i*2 */ - bn_wexpand(t1,i*4); /* perhaps only i*2 */ - bn_wexpand(t2,i*2); /* perhaps only i */ - - bn_mul_low_recursive(t2->d,a->d,mont->Ni.d,i,t1->d); - - BN_zero(t3); - BN_set_bit(t3,mont->N.top*BN_BITS2); - bn_sub_words(t3->d,t3->d,a->d,i); - bn_mul_high(ret->d,t2->d,mont->N.d,t3->d,i,t1->d); - - /* hmm... if a is between i and 2*i, things are bad */ - if (a->top > i) - { - j=bn_add_words(ret->d,ret->d,&(a->d[i]),i); - if (j) /* overflow */ - bn_sub_words(ret->d,ret->d,mont->N.d,i); - } - ret->top=i; - bn_fix_top(ret); - if (a->d[0]) - BN_add_word(ret,1); /* Always? */ - else /* Very very rare */ - { - for (i=1; iN.top-1; i++) - { - if (a->d[i]) - { - BN_add_word(ret,1); /* Always? */ - break; - } - } - } - - if (BN_ucmp(ret,&(mont->N)) >= 0) - BN_usub(ret,ret,&(mont->N)); - - return(1); + BN_ULONG t1,t2,t3,t4; + + t1=ap[i+0]; + t2=ap[i+1]; + t3=ap[i+2]; + t4=ap[i+3]; + rp[i+0]=t1; + rp[i+1]=t2; + rp[i+2]=t3; + rp[i+3]=t4; } + al+=4; + for (; iri); + + if (!BN_mul(t2,t1,&mont->Ni,ctx)) goto err; + BN_mask_bits(t2,mont->ri); + + if (!BN_mul(t1,t2,&mont->N,ctx)) goto err; + if (!BN_add(t2,a,t1)) goto err; + if (!BN_rshift(ret,t2,mont->ri)) goto err; +#endif /* MONT_WORD */ + + if (BN_ucmp(ret, &(mont->N)) >= 0) + { + if (!BN_usub(ret,ret,&(mont->N))) goto err; + } + retn=1; + bn_check_top(ret); + err: + BN_CTX_end(ctx); + return(retn); } -BN_MONT_CTX *BN_MONT_CTX_new() +BN_MONT_CTX *BN_MONT_CTX_new(void) { BN_MONT_CTX *ret; - if ((ret=(BN_MONT_CTX *)Malloc(sizeof(BN_MONT_CTX))) == NULL) + if ((ret=(BN_MONT_CTX *)OPENSSL_malloc(sizeof(BN_MONT_CTX))) == NULL) return(NULL); BN_MONT_CTX_init(ret); @@ -275,10 +248,8 @@ BN_MONT_CTX *BN_MONT_CTX_new() return(ret); } -void BN_MONT_CTX_init(ctx) -BN_MONT_CTX *ctx; +void BN_MONT_CTX_init(BN_MONT_CTX *ctx) { - ctx->use_word=0; ctx->ri=0; BN_init(&(ctx->RR)); BN_init(&(ctx->N)); @@ -286,122 +257,94 @@ BN_MONT_CTX *ctx; ctx->flags=0; } -void BN_MONT_CTX_free(mont) -BN_MONT_CTX *mont; +void BN_MONT_CTX_free(BN_MONT_CTX *mont) { + if(mont == NULL) + return; + BN_free(&(mont->RR)); BN_free(&(mont->N)); BN_free(&(mont->Ni)); if (mont->flags & BN_FLG_MALLOCED) - Free(mont); + OPENSSL_free(mont); } -int BN_MONT_CTX_set(mont,mod,ctx) -BN_MONT_CTX *mont; -BIGNUM *mod; -BN_CTX *ctx; +int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) { - BIGNUM Ri,*R; + int ret = 0; + BIGNUM *Ri,*R; - BN_init(&Ri); + BN_CTX_start(ctx); + if((Ri = BN_CTX_get(ctx)) == NULL) goto err; R= &(mont->RR); /* grab RR as a temp */ BN_copy(&(mont->N),mod); /* Set N */ + mont->N.neg = 0; -#ifdef BN_RECURSION - if (mont->N.top < BN_MONT_CTX_SET_SIZE_WORD) -#endif +#ifdef MONT_WORD { BIGNUM tmod; BN_ULONG buf[2]; - mont->use_word=1; - mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2; BN_zero(R); - BN_set_bit(R,BN_BITS2); - /* I was bad, this modification of a passed variable was - * breaking the multithreaded stuff :-( - * z=mod->top; - * mod->top=1; */ + if (!(BN_set_bit(R,BN_BITS2))) goto err; /* R */ - buf[0]=mod->d[0]; + buf[0]=mod->d[0]; /* tmod = N mod word size */ buf[1]=0; tmod.d=buf; tmod.top=1; - tmod.max=mod->max; - tmod.neg=mod->neg; - - if ((BN_mod_inverse(&Ri,R,&tmod,ctx)) == NULL) + tmod.dmax=2; + tmod.neg=0; + /* Ri = R^-1 mod N*/ + if ((BN_mod_inverse(Ri,R,&tmod,ctx)) == NULL) goto err; - BN_lshift(&Ri,&Ri,BN_BITS2); /* R*Ri */ - if (!BN_is_zero(&Ri)) + if (!BN_lshift(Ri,Ri,BN_BITS2)) goto err; /* R*Ri */ + if (!BN_is_zero(Ri)) { -#if 1 - BN_sub_word(&Ri,1); -#else - BN_usub(&Ri,&Ri,BN_value_one()); /* R*Ri - 1 */ -#endif + if (!BN_sub_word(Ri,1)) goto err; } - else + else /* if N mod word size == 1 */ { - /* This is not common..., 1 in BN_MASK2, - * It happens when buf[0] was == 1. So for 8 bit, - * this is 1/256, 16bit, 1 in 2^16 etc. - */ - BN_set_word(&Ri,BN_MASK2); + if (!BN_set_word(Ri,BN_MASK2)) goto err; /* Ri-- (mod word size) */ } - BN_div(&Ri,NULL,&Ri,&tmod,ctx); - mont->n0=Ri.d[0]; - BN_free(&Ri); - /* mod->top=z; */ + if (!BN_div(Ri,NULL,Ri,&tmod,ctx)) goto err; + /* Ni = (R*Ri-1)/N, + * keep only least significant word: */ + mont->n0 = (Ri->top > 0) ? Ri->d[0] : 0; } -#ifdef BN_RECURSION - else - { - mont->use_word=0; - mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2; -#if 1 +#else /* !MONT_WORD */ + { /* bignum version */ + mont->ri=BN_num_bits(&mont->N); BN_zero(R); - BN_set_bit(R,mont->ri); -#else - BN_lshift(R,BN_value_one(),mont->ri); /* R */ -#endif - if ((BN_mod_inverse(&Ri,R,mod,ctx)) == NULL) + if (!BN_set_bit(R,mont->ri)) goto err; /* R = 2^ri */ + /* Ri = R^-1 mod N*/ + if ((BN_mod_inverse(Ri,R,&mont->N,ctx)) == NULL) goto err; - BN_lshift(&Ri,&Ri,mont->ri); /* R*Ri */ -#if 1 - BN_sub_word(&Ri,1); -#else - BN_usub(&Ri,&Ri,BN_value_one()); /* R*Ri - 1 */ -#endif - BN_div(&(mont->Ni),NULL,&Ri,mod,ctx); - BN_free(&Ri); + if (!BN_lshift(Ri,Ri,mont->ri)) goto err; /* R*Ri */ + if (!BN_sub_word(Ri,1)) goto err; + /* Ni = (R*Ri-1) / N */ + if (!BN_div(&(mont->Ni),NULL,Ri,&mont->N,ctx)) goto err; } #endif /* setup RR for conversions */ -#if 1 BN_zero(&(mont->RR)); - BN_set_bit(&(mont->RR),mont->ri*2); -#else - BN_lshift(mont->RR,BN_value_one(),mont->ri*2); -#endif - BN_mod(&(mont->RR),&(mont->RR),&(mont->N),ctx); + if (!BN_set_bit(&(mont->RR),mont->ri*2)) goto err; + if (!BN_mod(&(mont->RR),&(mont->RR),&(mont->N),ctx)) goto err; - return(1); + ret = 1; err: - return(0); + BN_CTX_end(ctx); + return ret; } -BN_MONT_CTX *BN_MONT_CTX_copy(to, from) -BN_MONT_CTX *to, *from; +BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from) { if (to == from) return(to); - BN_copy(&(to->RR),&(from->RR)); - BN_copy(&(to->N),&(from->N)); - BN_copy(&(to->Ni),&(from->Ni)); - to->use_word=from->use_word; + if (!BN_copy(&(to->RR),&(from->RR))) return NULL; + if (!BN_copy(&(to->N),&(from->N))) return NULL; + if (!BN_copy(&(to->Ni),&(from->Ni))) return NULL; to->ri=from->ri; to->n0=from->n0; return(to);