X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Frsa%2Frsa_eay.c;h=3ee753ec86d1f3027afcfe0f04ce14fbdf0176b4;hp=6a68770031d6d651b3903d24a8529ce2eda2715e;hb=ff22e913a3fbeb025e612828859102aa1a3effaa;hpb=975842f9fb216e453b67c19ffe4509837fb59ccb diff --git a/crypto/rsa/rsa_eay.c b/crypto/rsa/rsa_eay.c index 6a68770031..3ee753ec86 100644 --- a/crypto/rsa/rsa_eay.c +++ b/crypto/rsa/rsa_eay.c @@ -61,7 +61,6 @@ #include #include #include -#include #ifndef RSA_NULL @@ -73,21 +72,24 @@ static int RSA_eay_public_decrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa,int padding); static int RSA_eay_private_decrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa,int padding); -static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *i, RSA *rsa); +static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *i, RSA *rsa, BN_CTX *ctx); static int RSA_eay_init(RSA *rsa); static int RSA_eay_finish(RSA *rsa); static RSA_METHOD rsa_pkcs1_eay_meth={ "Eric Young's PKCS#1 RSA", RSA_eay_public_encrypt, - RSA_eay_public_decrypt, - RSA_eay_private_encrypt, + RSA_eay_public_decrypt, /* signature verification */ + RSA_eay_private_encrypt, /* signing */ RSA_eay_private_decrypt, RSA_eay_mod_exp, BN_mod_exp_mont, /* XXX probably we should not use Montgomery if e == 3 */ RSA_eay_init, RSA_eay_finish, - 0, + 0, /* flags */ NULL, + 0, /* rsa_sign */ + 0, /* rsa_verify */ + NULL /* rsa_keygen */ }; const RSA_METHOD *RSA_PKCS1_SSLeay(void) @@ -95,21 +97,58 @@ const RSA_METHOD *RSA_PKCS1_SSLeay(void) return(&rsa_pkcs1_eay_meth); } +/* Static helper to reduce oodles of code duplication. As a slight + * optimisation, the "MONT_HELPER() macro must be used as front-end to this + * function, to prevent unnecessary function calls - there is an initial test + * that is performed by the macro-generated code. */ +static int rsa_eay_mont_helper(BN_MONT_CTX **ptr, const BIGNUM *modulus, BN_CTX *ctx) + { + BN_MONT_CTX *bn_mont_ctx; + if((bn_mont_ctx = BN_MONT_CTX_new()) == NULL) + return 0; + if(!BN_MONT_CTX_set(bn_mont_ctx, modulus, ctx)) + { + BN_MONT_CTX_free(bn_mont_ctx); + return 0; + } + if (*ptr == NULL) /* other thread may have finished first */ + { + CRYPTO_w_lock(CRYPTO_LOCK_RSA); + if (*ptr == NULL) /* check again in the lock to stop races */ + { + *ptr = bn_mont_ctx; + bn_mont_ctx = NULL; + } + CRYPTO_w_unlock(CRYPTO_LOCK_RSA); + } + if (bn_mont_ctx) + BN_MONT_CTX_free(bn_mont_ctx); + return 1; + } +/* Usage example; + * MONT_HELPER(rsa, bn_ctx, p, rsa->flags & RSA_FLAG_CACHE_PRIVATE, goto err); + */ +#define MONT_HELPER(rsa, ctx, m, pre_cond, err_instr) \ + if((pre_cond) && ((rsa)->_method_mod_##m == NULL) && \ + !rsa_eay_mont_helper(&((rsa)->_method_mod_##m), \ + (rsa)->m, (ctx))) \ + err_instr + static int RSA_eay_public_encrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { - const RSA_METHOD *meth; - BIGNUM f,ret; + BIGNUM *f,*ret; int i,j,k,num=0,r= -1; unsigned char *buf=NULL; BN_CTX *ctx=NULL; - meth = ENGINE_get_RSA(rsa->engine); - BN_init(&f); - BN_init(&ret); if ((ctx=BN_CTX_new()) == NULL) goto err; + BN_CTX_start(ctx); + f = BN_CTX_get(ctx); + ret = BN_CTX_get(ctx); num=BN_num_bytes(rsa->n); - if ((buf=(unsigned char *)OPENSSL_malloc(num)) == NULL) + buf = OPENSSL_malloc(num); + if (!f || !ret || !buf) { RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT,ERR_R_MALLOC_FAILURE); goto err; @@ -120,7 +159,7 @@ static int RSA_eay_public_encrypt(int flen, const unsigned char *from, case RSA_PKCS1_PADDING: i=RSA_padding_add_PKCS1_type_2(buf,num,from,flen); break; -#ifndef NO_SHA +#ifndef OPENSSL_NO_SHA case RSA_PKCS1_OAEP_PADDING: i=RSA_padding_add_PKCS1_OAEP(buf,num,from,flen,NULL,0); break; @@ -137,71 +176,113 @@ static int RSA_eay_public_encrypt(int flen, const unsigned char *from, } if (i <= 0) goto err; - if (BN_bin2bn(buf,num,&f) == NULL) goto err; + if (BN_bin2bn(buf,num,f) == NULL) goto err; - if ((rsa->_method_mod_n == NULL) && (rsa->flags & RSA_FLAG_CACHE_PUBLIC)) - { - BN_MONT_CTX* bn_mont_ctx; - if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL) - goto err; - if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->n,ctx)) - { - BN_MONT_CTX_free(bn_mont_ctx); - goto err; - } - if (rsa->_method_mod_n == NULL) /* other thread may have finished first */ - { - CRYPTO_w_lock(CRYPTO_LOCK_RSA); - if (rsa->_method_mod_n == NULL) - { - rsa->_method_mod_n = bn_mont_ctx; - bn_mont_ctx = NULL; - } - CRYPTO_w_unlock(CRYPTO_LOCK_RSA); - } - if (bn_mont_ctx) - BN_MONT_CTX_free(bn_mont_ctx); + if (BN_ucmp(f, rsa->n) >= 0) + { + /* usually the padding functions would catch this */ + RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT,RSA_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; } - - if (!meth->bn_mod_exp(&ret,&f,rsa->e,rsa->n,ctx, + + MONT_HELPER(rsa, ctx, n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err); + + if (!rsa->meth->bn_mod_exp(ret,f,rsa->e,rsa->n,ctx, rsa->_method_mod_n)) goto err; /* put in leading 0 bytes if the number is less than the * length of the modulus */ - j=BN_num_bytes(&ret); - i=BN_bn2bin(&ret,&(to[num-j])); + j=BN_num_bytes(ret); + i=BN_bn2bin(ret,&(to[num-j])); for (k=0; k<(num-i); k++) to[k]=0; r=num; err: - if (ctx != NULL) BN_CTX_free(ctx); - BN_clear_free(&f); - BN_clear_free(&ret); + if (ctx != NULL) + { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } if (buf != NULL) { - memset(buf,0,num); + OPENSSL_cleanse(buf,num); OPENSSL_free(buf); } return(r); } +static int rsa_eay_blinding(RSA *rsa, BN_CTX *ctx) + { + int ret = 1; + CRYPTO_w_lock(CRYPTO_LOCK_RSA); + /* Check again inside the lock - the macro's check is racey */ + if(rsa->blinding == NULL) + ret = RSA_blinding_on(rsa, ctx); + CRYPTO_w_unlock(CRYPTO_LOCK_RSA); + return ret; + } + +#define BLINDING_HELPER(rsa, ctx, err_instr) \ + do { \ + if((!((rsa)->flags & RSA_FLAG_NO_BLINDING)) && \ + ((rsa)->blinding == NULL) && \ + !rsa_eay_blinding(rsa, ctx)) \ + err_instr \ + } while(0) + +static BN_BLINDING *setup_blinding(RSA *rsa, BN_CTX *ctx) + { + BIGNUM *A, *Ai; + BN_BLINDING *ret = NULL; + + /* added in OpenSSL 0.9.6j and 0.9.7b */ + + /* NB: similar code appears in RSA_blinding_on (rsa_lib.c); + * this should be placed in a new function of its own, but for reasons + * of binary compatibility can't */ + + BN_CTX_start(ctx); + A = BN_CTX_get(ctx); + if ((RAND_status() == 0) && rsa->d != NULL && rsa->d->d != NULL) + { + /* if PRNG is not properly seeded, resort to secret exponent as unpredictable seed */ + RAND_add(rsa->d->d, rsa->d->dmax * sizeof rsa->d->d[0], 0.0); + if (!BN_pseudo_rand_range(A,rsa->n)) goto err; + } + else + { + if (!BN_rand_range(A,rsa->n)) goto err; + } + if ((Ai=BN_mod_inverse(NULL,A,rsa->n,ctx)) == NULL) goto err; + + if (!rsa->meth->bn_mod_exp(A,A,rsa->e,rsa->n,ctx,rsa->_method_mod_n)) + goto err; + ret = BN_BLINDING_new(A,Ai,rsa->n); + BN_free(Ai); +err: + BN_CTX_end(ctx); + return ret; + } + +/* signing */ static int RSA_eay_private_encrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { - const RSA_METHOD *meth; - BIGNUM f,ret; + BIGNUM *f,*ret; int i,j,k,num=0,r= -1; unsigned char *buf=NULL; BN_CTX *ctx=NULL; - - meth = ENGINE_get_RSA(rsa->engine); - BN_init(&f); - BN_init(&ret); + int local_blinding = 0; + BN_BLINDING *blinding = NULL; if ((ctx=BN_CTX_new()) == NULL) goto err; + BN_CTX_start(ctx); + f = BN_CTX_get(ctx); + ret = BN_CTX_get(ctx); num=BN_num_bytes(rsa->n); - if ((buf=(unsigned char *)OPENSSL_malloc(num)) == NULL) + buf = OPENSSL_malloc(num); + if(!f || !ret || !buf) { RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,ERR_R_MALLOC_FAILURE); goto err; @@ -222,12 +303,48 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from, } if (i <= 0) goto err; - if (BN_bin2bn(buf,num,&f) == NULL) goto err; + if (BN_bin2bn(buf,num,f) == NULL) goto err; + + if (BN_ucmp(f, rsa->n) >= 0) + { + /* usually the padding functions would catch this */ + RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,RSA_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } - if ((rsa->flags & RSA_FLAG_BLINDING) && (rsa->blinding == NULL)) - RSA_blinding_on(rsa,ctx); - if (rsa->flags & RSA_FLAG_BLINDING) - if (!BN_BLINDING_convert(&f,rsa->blinding,ctx)) goto err; + BLINDING_HELPER(rsa, ctx, goto err;); + blinding = rsa->blinding; + + /* Now unless blinding is disabled, 'blinding' is non-NULL. + * But the BN_BLINDING object may be owned by some other thread + * (we don't want to keep it constant and we don't want to use + * lots of locking to avoid race conditions, so only a single + * thread can use it; other threads have to use local blinding + * factors) */ + if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) + { + if (blinding == NULL) + { + RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); + goto err; + } + } + + if (blinding != NULL) + { + if (blinding->thread_id != CRYPTO_thread_id()) + { + /* we need a local one-time blinding factor */ + + blinding = setup_blinding(rsa, ctx); + if (blinding == NULL) + goto err; + local_blinding = 1; + } + } + + if (blinding) + if (!BN_BLINDING_convert(f, blinding, ctx)) goto err; if ( (rsa->flags & RSA_FLAG_EXT_PKEY) || ((rsa->p != NULL) && @@ -235,30 +352,36 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from, (rsa->dmp1 != NULL) && (rsa->dmq1 != NULL) && (rsa->iqmp != NULL)) ) - { if (!meth->rsa_mod_exp(&ret,&f,rsa)) goto err; } + { if (!rsa->meth->rsa_mod_exp(ret,f,rsa,ctx)) goto err; } else { - if (!meth->bn_mod_exp(&ret,&f,rsa->d,rsa->n,ctx,NULL)) goto err; + MONT_HELPER(rsa, ctx, n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err); + if (!rsa->meth->bn_mod_exp(ret,f,rsa->d,rsa->n,ctx, + rsa->_method_mod_n)) goto err; } - if (rsa->flags & RSA_FLAG_BLINDING) - if (!BN_BLINDING_invert(&ret,rsa->blinding,ctx)) goto err; + if (blinding) + if (!BN_BLINDING_invert(ret, blinding, ctx)) goto err; /* put in leading 0 bytes if the number is less than the * length of the modulus */ - j=BN_num_bytes(&ret); - i=BN_bn2bin(&ret,&(to[num-j])); + j=BN_num_bytes(ret); + i=BN_bn2bin(ret,&(to[num-j])); for (k=0; k<(num-i); k++) to[k]=0; r=num; err: - if (ctx != NULL) BN_CTX_free(ctx); - BN_clear_free(&ret); - BN_clear_free(&f); + if (ctx != NULL) + { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + if (local_blinding) + BN_BLINDING_free(blinding); if (buf != NULL) { - memset(buf,0,num); + OPENSSL_cleanse(buf,num); OPENSSL_free(buf); } return(r); @@ -267,22 +390,21 @@ err: static int RSA_eay_private_decrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { - const RSA_METHOD *meth; - BIGNUM f,ret; + BIGNUM *f,*ret; int j,num=0,r= -1; unsigned char *p; unsigned char *buf=NULL; BN_CTX *ctx=NULL; + int local_blinding = 0; + BN_BLINDING *blinding = NULL; - meth = ENGINE_get_RSA(rsa->engine); - BN_init(&f); - BN_init(&ret); - ctx=BN_CTX_new(); - if (ctx == NULL) goto err; - + if((ctx = BN_CTX_new()) == NULL) goto err; + BN_CTX_start(ctx); + f = BN_CTX_get(ctx); + ret = BN_CTX_get(ctx); num=BN_num_bytes(rsa->n); - - if ((buf=(unsigned char *)OPENSSL_malloc(num)) == NULL) + buf = OPENSSL_malloc(num); + if(!f || !ret || !buf) { RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT,ERR_R_MALLOC_FAILURE); goto err; @@ -297,12 +419,47 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from, } /* make data into a big number */ - if (BN_bin2bn(from,(int)flen,&f) == NULL) goto err; + if (BN_bin2bn(from,(int)flen,f) == NULL) goto err; - if ((rsa->flags & RSA_FLAG_BLINDING) && (rsa->blinding == NULL)) - RSA_blinding_on(rsa,ctx); - if (rsa->flags & RSA_FLAG_BLINDING) - if (!BN_BLINDING_convert(&f,rsa->blinding,ctx)) goto err; + if (BN_ucmp(f, rsa->n) >= 0) + { + RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT,RSA_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; + } + + BLINDING_HELPER(rsa, ctx, goto err;); + blinding = rsa->blinding; + + /* Now unless blinding is disabled, 'blinding' is non-NULL. + * But the BN_BLINDING object may be owned by some other thread + * (we don't want to keep it constant and we don't want to use + * lots of locking to avoid race conditions, so only a single + * thread can use it; other threads have to use local blinding + * factors) */ + if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) + { + if (blinding == NULL) + { + RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT, ERR_R_INTERNAL_ERROR); + goto err; + } + } + + if (blinding != NULL) + { + if (blinding->thread_id != CRYPTO_thread_id()) + { + /* we need a local one-time blinding factor */ + + blinding = setup_blinding(rsa, ctx); + if (blinding == NULL) + goto err; + local_blinding = 1; + } + } + + if (blinding) + if (!BN_BLINDING_convert(f, blinding, ctx)) goto err; /* do the decrypt */ if ( (rsa->flags & RSA_FLAG_EXT_PKEY) || @@ -311,25 +468,27 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from, (rsa->dmp1 != NULL) && (rsa->dmq1 != NULL) && (rsa->iqmp != NULL)) ) - { if (!meth->rsa_mod_exp(&ret,&f,rsa)) goto err; } + { if (!rsa->meth->rsa_mod_exp(ret,f,rsa,ctx)) goto err; } else { - if (!meth->bn_mod_exp(&ret,&f,rsa->d,rsa->n,ctx,NULL)) + MONT_HELPER(rsa, ctx, n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err); + if (!rsa->meth->bn_mod_exp(ret,f,rsa->d,rsa->n,ctx, + rsa->_method_mod_n)) goto err; } - if (rsa->flags & RSA_FLAG_BLINDING) - if (!BN_BLINDING_invert(&ret,rsa->blinding,ctx)) goto err; + if (blinding) + if (!BN_BLINDING_invert(ret, blinding, ctx)) goto err; p=buf; - j=BN_bn2bin(&ret,p); /* j is only used with no-padding mode */ + j=BN_bn2bin(ret,p); /* j is only used with no-padding mode */ switch (padding) { case RSA_PKCS1_PADDING: r=RSA_padding_check_PKCS1_type_2(to,num,buf,j,num); break; -#ifndef NO_SHA +#ifndef OPENSSL_NO_SHA case RSA_PKCS1_OAEP_PADDING: r=RSA_padding_check_PKCS1_OAEP(to,num,buf,j,num,NULL,0); break; @@ -348,36 +507,38 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from, RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT,RSA_R_PADDING_CHECK_FAILED); err: - if (ctx != NULL) BN_CTX_free(ctx); - BN_clear_free(&f); - BN_clear_free(&ret); + if (ctx != NULL) + { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } + if (local_blinding) + BN_BLINDING_free(blinding); if (buf != NULL) { - memset(buf,0,num); + OPENSSL_cleanse(buf,num); OPENSSL_free(buf); } return(r); } +/* signature verification */ static int RSA_eay_public_decrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { - const RSA_METHOD *meth; - BIGNUM f,ret; + BIGNUM *f,*ret; int i,num=0,r= -1; unsigned char *p; unsigned char *buf=NULL; BN_CTX *ctx=NULL; - meth = ENGINE_get_RSA(rsa->engine); - BN_init(&f); - BN_init(&ret); - ctx=BN_CTX_new(); - if (ctx == NULL) goto err; - + if((ctx = BN_CTX_new()) == NULL) goto err; + BN_CTX_start(ctx); + f = BN_CTX_get(ctx); + ret = BN_CTX_get(ctx); num=BN_num_bytes(rsa->n); - buf=(unsigned char *)OPENSSL_malloc(num); - if (buf == NULL) + buf = OPENSSL_malloc(num); + if(!f || !ret || !buf) { RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT,ERR_R_MALLOC_FAILURE); goto err; @@ -391,37 +552,21 @@ static int RSA_eay_public_decrypt(int flen, const unsigned char *from, goto err; } - if (BN_bin2bn(from,flen,&f) == NULL) goto err; - /* do the decrypt */ - if ((rsa->_method_mod_n == NULL) && (rsa->flags & RSA_FLAG_CACHE_PUBLIC)) + if (BN_bin2bn(from,flen,f) == NULL) goto err; + + if (BN_ucmp(f, rsa->n) >= 0) { - BN_MONT_CTX* bn_mont_ctx; - if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL) - goto err; - if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->n,ctx)) - { - BN_MONT_CTX_free(bn_mont_ctx); - goto err; - } - if (rsa->_method_mod_n == NULL) /* other thread may have finished first */ - { - CRYPTO_w_lock(CRYPTO_LOCK_RSA); - if (rsa->_method_mod_n == NULL) - { - rsa->_method_mod_n = bn_mont_ctx; - bn_mont_ctx = NULL; - } - CRYPTO_w_unlock(CRYPTO_LOCK_RSA); - } - if (bn_mont_ctx) - BN_MONT_CTX_free(bn_mont_ctx); + RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT,RSA_R_DATA_TOO_LARGE_FOR_MODULUS); + goto err; } - - if (!meth->bn_mod_exp(&ret,&f,rsa->e,rsa->n,ctx, + + MONT_HELPER(rsa, ctx, n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err); + + if (!rsa->meth->bn_mod_exp(ret,f,rsa->e,rsa->n,ctx, rsa->_method_mod_n)) goto err; p=buf; - i=BN_bn2bin(&ret,p); + i=BN_bn2bin(ret,p); switch (padding) { @@ -439,96 +584,49 @@ static int RSA_eay_public_decrypt(int flen, const unsigned char *from, RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT,RSA_R_PADDING_CHECK_FAILED); err: - if (ctx != NULL) BN_CTX_free(ctx); - BN_clear_free(&f); - BN_clear_free(&ret); + if (ctx != NULL) + { + BN_CTX_end(ctx); + BN_CTX_free(ctx); + } if (buf != NULL) { - memset(buf,0,num); + OPENSSL_cleanse(buf,num); OPENSSL_free(buf); } return(r); } -static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa) +static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) { - const RSA_METHOD *meth; - BIGNUM r1,m1; + BIGNUM *r1,*m1,*vrfy; int ret=0; - BN_CTX *ctx; - meth = ENGINE_get_RSA(rsa->engine); - if ((ctx=BN_CTX_new()) == NULL) goto err; - BN_init(&m1); - BN_init(&r1); + BN_CTX_start(ctx); + r1 = BN_CTX_get(ctx); + m1 = BN_CTX_get(ctx); + vrfy = BN_CTX_get(ctx); - if (rsa->flags & RSA_FLAG_CACHE_PRIVATE) - { - if (rsa->_method_mod_p == NULL) - { - BN_MONT_CTX* bn_mont_ctx; - if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL) - goto err; - if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->p,ctx)) - { - BN_MONT_CTX_free(bn_mont_ctx); - goto err; - } - if (rsa->_method_mod_p == NULL) /* other thread may have finished first */ - { - CRYPTO_w_lock(CRYPTO_LOCK_RSA); - if (rsa->_method_mod_p == NULL) - { - rsa->_method_mod_p = bn_mont_ctx; - bn_mont_ctx = NULL; - } - CRYPTO_w_unlock(CRYPTO_LOCK_RSA); - } - if (bn_mont_ctx) - BN_MONT_CTX_free(bn_mont_ctx); - } + MONT_HELPER(rsa, ctx, p, rsa->flags & RSA_FLAG_CACHE_PRIVATE, goto err); + MONT_HELPER(rsa, ctx, q, rsa->flags & RSA_FLAG_CACHE_PRIVATE, goto err); + MONT_HELPER(rsa, ctx, n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err); - if (rsa->_method_mod_q == NULL) - { - BN_MONT_CTX* bn_mont_ctx; - if ((bn_mont_ctx=BN_MONT_CTX_new()) == NULL) - goto err; - if (!BN_MONT_CTX_set(bn_mont_ctx,rsa->q,ctx)) - { - BN_MONT_CTX_free(bn_mont_ctx); - goto err; - } - if (rsa->_method_mod_q == NULL) /* other thread may have finished first */ - { - CRYPTO_w_lock(CRYPTO_LOCK_RSA); - if (rsa->_method_mod_q == NULL) - { - rsa->_method_mod_q = bn_mont_ctx; - bn_mont_ctx = NULL; - } - CRYPTO_w_unlock(CRYPTO_LOCK_RSA); - } - if (bn_mont_ctx) - BN_MONT_CTX_free(bn_mont_ctx); - } - } - - if (!BN_mod(&r1,I,rsa->q,ctx)) goto err; - if (!meth->bn_mod_exp(&m1,&r1,rsa->dmq1,rsa->q,ctx, + if (!BN_mod(r1,I,rsa->q,ctx)) goto err; + if (!rsa->meth->bn_mod_exp(m1,r1,rsa->dmq1,rsa->q,ctx, rsa->_method_mod_q)) goto err; - if (!BN_mod(&r1,I,rsa->p,ctx)) goto err; - if (!meth->bn_mod_exp(r0,&r1,rsa->dmp1,rsa->p,ctx, + if (!BN_mod(r1,I,rsa->p,ctx)) goto err; + if (!rsa->meth->bn_mod_exp(r0,r1,rsa->dmp1,rsa->p,ctx, rsa->_method_mod_p)) goto err; - if (!BN_sub(r0,r0,&m1)) goto err; + if (!BN_sub(r0,r0,m1)) goto err; /* This will help stop the size of r0 increasing, which does * affect the multiply if it optimised for a power of 2 size */ - if (r0->neg) + if (BN_is_negative(r0)) if (!BN_add(r0,r0,rsa->p)) goto err; - if (!BN_mul(&r1,r0,rsa->iqmp,ctx)) goto err; - if (!BN_mod(r0,&r1,rsa->p,ctx)) goto err; + if (!BN_mul(r1,r0,rsa->iqmp,ctx)) goto err; + if (!BN_mod(r0,r1,rsa->p,ctx)) goto err; /* If p < q it is occasionally possible for the correction of * adding 'p' if r0 is negative above to leave the result still * negative. This can break the private key operations: the following @@ -536,16 +634,32 @@ static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa) * This will *never* happen with OpenSSL generated keys because * they ensure p > q [steve] */ - if (r0->neg) + if (BN_is_negative(r0)) if (!BN_add(r0,r0,rsa->p)) goto err; - if (!BN_mul(&r1,r0,rsa->q,ctx)) goto err; - if (!BN_add(r0,&r1,&m1)) goto err; + if (!BN_mul(r1,r0,rsa->q,ctx)) goto err; + if (!BN_add(r0,r1,m1)) goto err; + if (rsa->e && rsa->n) + { + if (!rsa->meth->bn_mod_exp(vrfy,r0,rsa->e,rsa->n,ctx,rsa->_method_mod_n)) goto err; + /* If 'I' was greater than (or equal to) rsa->n, the operation + * will be equivalent to using 'I mod n'. However, the result of + * the verify will *always* be less than 'n' so we don't check + * for absolute equality, just congruency. */ + if (!BN_sub(vrfy, vrfy, I)) goto err; + if (!BN_mod(vrfy, vrfy, rsa->n, ctx)) goto err; + if (BN_is_negative(vrfy)) + if (!BN_add(vrfy, vrfy, rsa->n)) goto err; + if (!BN_is_zero(vrfy)) + /* 'I' and 'vrfy' aren't congruent mod n. Don't leak + * miscalculated CRT output, just do a raw (slower) + * mod_exp and return that instead. */ + if (!rsa->meth->bn_mod_exp(r0,I,rsa->d,rsa->n,ctx, + rsa->_method_mod_n)) goto err; + } ret=1; err: - BN_clear_free(&m1); - BN_clear_free(&r1); - BN_CTX_free(ctx); + BN_CTX_end(ctx); return(ret); }