diff options
Diffstat (limited to 'crypto/rsa/rsa_eay.c')
-rw-r--r-- | crypto/rsa/rsa_eay.c | 530 |
1 files changed, 370 insertions, 160 deletions
diff --git a/crypto/rsa/rsa_eay.c b/crypto/rsa/rsa_eay.c index b66b4bc140..c5eaeeae6b 100644 --- a/crypto/rsa/rsa_eay.c +++ b/crypto/rsa/rsa_eay.c @@ -55,6 +55,59 @@ * copied and put under another distribution licence * [including the GNU Public Licence.] */ +/* ==================================================================== + * Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ #include <stdio.h> #include "cryptlib.h" @@ -97,43 +150,6 @@ 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) { @@ -142,6 +158,28 @@ static int RSA_eay_public_encrypt(int flen, const unsigned char *from, unsigned char *buf=NULL; BN_CTX *ctx=NULL; + if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS) + { + RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_MODULUS_TOO_LARGE); + return -1; + } + + if (BN_ucmp(rsa->n, rsa->e) <= 0) + { + RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_BAD_E_VALUE); + return -1; + } + + /* for large moduli, enforce exponent limit */ + if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS) + { + if (BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS) + { + RSAerr(RSA_F_RSA_EAY_PUBLIC_ENCRYPT, RSA_R_BAD_E_VALUE); + return -1; + } + } + if ((ctx=BN_CTX_new()) == NULL) goto err; BN_CTX_start(ctx); f = BN_CTX_get(ctx); @@ -179,13 +217,15 @@ static int RSA_eay_public_encrypt(int flen, const unsigned char *from, 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_PUBLIC_ENCRYPT,RSA_R_DATA_TOO_LARGE_FOR_MODULUS); goto err; } - MONT_HELPER(rsa, ctx, n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err); + if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) + if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx)) + goto err; if (!rsa->meth->bn_mod_exp(ret,f,rsa->e,rsa->n,ctx, rsa->_method_mod_n)) goto err; @@ -212,64 +252,103 @@ err: 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; - } +static BN_BLINDING *rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx) +{ + BN_BLINDING *ret; + int got_write_lock = 0; + CRYPTO_THREADID cur; -#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) + CRYPTO_r_lock(CRYPTO_LOCK_RSA); -static BN_BLINDING *setup_blinding(RSA *rsa, BN_CTX *ctx) - { - BIGNUM *A, *Ai; - BN_BLINDING *ret = NULL; + if (rsa->blinding == NULL) + { + CRYPTO_r_unlock(CRYPTO_LOCK_RSA); + CRYPTO_w_lock(CRYPTO_LOCK_RSA); + got_write_lock = 1; - /* added in OpenSSL 0.9.6j and 0.9.7b */ + if (rsa->blinding == NULL) + rsa->blinding = RSA_setup_blinding(rsa, ctx); + } - /* 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 */ + ret = rsa->blinding; + if (ret == NULL) + goto err; - BN_CTX_start(ctx); - A = BN_CTX_get(ctx); - if ((RAND_status() == 0) && rsa->d != NULL && rsa->d->d != NULL) + CRYPTO_THREADID_current(&cur); + if (!CRYPTO_THREADID_cmp(&cur, BN_BLINDING_thread_id(ret))) { - /* 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; + /* rsa->blinding is ours! */ + + *local = 1; } else { - if (!BN_rand_range(A,rsa->n)) goto err; + /* resort to rsa->mt_blinding instead */ + + *local = 0; /* instructs rsa_blinding_convert(), rsa_blinding_invert() + * that the BN_BLINDING is shared, meaning that accesses + * require locks, and that the blinding factor must be + * stored outside the BN_BLINDING + */ + + if (rsa->mt_blinding == NULL) + { + if (!got_write_lock) + { + CRYPTO_r_unlock(CRYPTO_LOCK_RSA); + CRYPTO_w_lock(CRYPTO_LOCK_RSA); + got_write_lock = 1; + } + + if (rsa->mt_blinding == NULL) + rsa->mt_blinding = RSA_setup_blinding(rsa, ctx); + } + ret = rsa->mt_blinding; } - 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); + err: + if (got_write_lock) + CRYPTO_w_unlock(CRYPTO_LOCK_RSA); + else + CRYPTO_r_unlock(CRYPTO_LOCK_RSA); return ret; - } +} + +static int rsa_blinding_convert(BN_BLINDING *b, int local, BIGNUM *f, + BIGNUM *r, BN_CTX *ctx) +{ + if (local) + return BN_BLINDING_convert_ex(f, NULL, b, ctx); + else + { + int ret; + CRYPTO_r_lock(CRYPTO_LOCK_RSA_BLINDING); + ret = BN_BLINDING_convert_ex(f, r, b, ctx); + CRYPTO_r_unlock(CRYPTO_LOCK_RSA_BLINDING); + return ret; + } +} + +static int rsa_blinding_invert(BN_BLINDING *b, int local, BIGNUM *f, + BIGNUM *r, BN_CTX *ctx) +{ + if (local) + return BN_BLINDING_invert_ex(f, NULL, b, ctx); + else + { + int ret; + CRYPTO_w_lock(CRYPTO_LOCK_RSA_BLINDING); + ret = BN_BLINDING_invert_ex(f, r, b, ctx); + CRYPTO_w_unlock(CRYPTO_LOCK_RSA_BLINDING); + return ret; + } +} /* signing */ static int RSA_eay_private_encrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { - BIGNUM *f,*ret; + BIGNUM *f, *ret, *br, *res; int i,j,k,num=0,r= -1; unsigned char *buf=NULL; BN_CTX *ctx=NULL; @@ -278,9 +357,10 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from, if ((ctx=BN_CTX_new()) == NULL) goto err; BN_CTX_start(ctx); - f = BN_CTX_get(ctx); + f = BN_CTX_get(ctx); + br = BN_CTX_get(ctx); ret = BN_CTX_get(ctx); - num=BN_num_bytes(rsa->n); + num = BN_num_bytes(rsa->n); buf = OPENSSL_malloc(num); if(!f || !ret || !buf) { @@ -293,6 +373,9 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from, case RSA_PKCS1_PADDING: i=RSA_padding_add_PKCS1_type_1(buf,num,from,flen); break; + case RSA_X931_PADDING: + i=RSA_padding_add_X931(buf,num,from,flen); + break; case RSA_NO_PADDING: i=RSA_padding_add_none(buf,num,from,flen); break; @@ -312,17 +395,9 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from, 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)) { + blinding = rsa_get_blinding(rsa, &local_blinding, ctx); if (blinding == NULL) { RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); @@ -331,20 +406,8 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from, } 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_blinding_convert(blinding, local_blinding, f, br, ctx)) + goto err; if ( (rsa->flags & RSA_FLAG_EXT_PKEY) || ((rsa->p != NULL) && @@ -352,21 +415,50 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from, (rsa->dmp1 != NULL) && (rsa->dmq1 != NULL) && (rsa->iqmp != NULL)) ) - { if (!rsa->meth->rsa_mod_exp(ret,f,rsa,ctx)) goto err; } + { + if (!rsa->meth->rsa_mod_exp(ret, f, rsa, ctx)) goto err; + } else { - 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, + BIGNUM local_d; + BIGNUM *d = NULL; + + if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) + { + BN_init(&local_d); + d = &local_d; + BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME); + } + else + d= rsa->d; + + if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) + if(!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx)) + goto err; + + if (!rsa->meth->bn_mod_exp(ret,f,d,rsa->n,ctx, rsa->_method_mod_n)) goto err; } if (blinding) - if (!BN_BLINDING_invert(ret, blinding, ctx)) goto err; + if (!rsa_blinding_invert(blinding, local_blinding, ret, br, ctx)) + goto err; + + if (padding == RSA_X931_PADDING) + { + BN_sub(f, rsa->n, ret); + if (BN_cmp(ret, f)) + res = f; + else + res = ret; + } + else + res = ret; /* 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(res); + i=BN_bn2bin(res,&(to[num-j])); for (k=0; k<(num-i); k++) to[k]=0; @@ -377,8 +469,6 @@ err: BN_CTX_end(ctx); BN_CTX_free(ctx); } - if (local_blinding) - BN_BLINDING_free(blinding); if (buf != NULL) { OPENSSL_cleanse(buf,num); @@ -390,7 +480,7 @@ err: static int RSA_eay_private_decrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) { - BIGNUM *f,*ret; + BIGNUM *f, *ret, *br; int j,num=0,r= -1; unsigned char *p; unsigned char *buf=NULL; @@ -400,9 +490,10 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from, if((ctx = BN_CTX_new()) == NULL) goto err; BN_CTX_start(ctx); - f = BN_CTX_get(ctx); + f = BN_CTX_get(ctx); + br = BN_CTX_get(ctx); ret = BN_CTX_get(ctx); - num=BN_num_bytes(rsa->n); + num = BN_num_bytes(rsa->n); buf = OPENSSL_malloc(num); if(!f || !ret || !buf) { @@ -427,17 +518,9 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from, 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)) { + blinding = rsa_get_blinding(rsa, &local_blinding, ctx); if (blinding == NULL) { RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT, ERR_R_INTERNAL_ERROR); @@ -446,20 +529,8 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from, } 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_blinding_convert(blinding, local_blinding, f, br, ctx)) + goto err; /* do the decrypt */ if ( (rsa->flags & RSA_FLAG_EXT_PKEY) || @@ -468,17 +539,33 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from, (rsa->dmp1 != NULL) && (rsa->dmq1 != NULL) && (rsa->iqmp != NULL)) ) - { if (!rsa->meth->rsa_mod_exp(ret,f,rsa,ctx)) goto err; } + { + if (!rsa->meth->rsa_mod_exp(ret, f, rsa, ctx)) goto err; + } else { - 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, + BIGNUM local_d; + BIGNUM *d = NULL; + + if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) + { + d = &local_d; + BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME); + } + else + d = rsa->d; + + if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) + if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx)) + goto err; + if (!rsa->meth->bn_mod_exp(ret,f,d,rsa->n,ctx, rsa->_method_mod_n)) - goto err; + goto err; } if (blinding) - if (!BN_BLINDING_invert(ret, blinding, ctx)) goto err; + if (!rsa_blinding_invert(blinding, local_blinding, ret, br, ctx)) + goto err; p=buf; j=BN_bn2bin(ret,p); /* j is only used with no-padding mode */ @@ -512,8 +599,6 @@ err: BN_CTX_end(ctx); BN_CTX_free(ctx); } - if (local_blinding) - BN_BLINDING_free(blinding); if (buf != NULL) { OPENSSL_cleanse(buf,num); @@ -532,6 +617,28 @@ static int RSA_eay_public_decrypt(int flen, const unsigned char *from, unsigned char *buf=NULL; BN_CTX *ctx=NULL; + if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS) + { + RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT, RSA_R_MODULUS_TOO_LARGE); + return -1; + } + + if (BN_ucmp(rsa->n, rsa->e) <= 0) + { + RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT, RSA_R_BAD_E_VALUE); + return -1; + } + + /* for large moduli, enforce exponent limit */ + if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS) + { + if (BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS) + { + RSAerr(RSA_F_RSA_EAY_PUBLIC_DECRYPT, RSA_R_BAD_E_VALUE); + return -1; + } + } + if((ctx = BN_CTX_new()) == NULL) goto err; BN_CTX_start(ctx); f = BN_CTX_get(ctx); @@ -560,11 +667,16 @@ static int RSA_eay_public_decrypt(int flen, const unsigned char *from, goto err; } - MONT_HELPER(rsa, ctx, n, rsa->flags & RSA_FLAG_CACHE_PUBLIC, goto err); + if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) + if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx)) + goto err; if (!rsa->meth->bn_mod_exp(ret,f,rsa->e,rsa->n,ctx, rsa->_method_mod_n)) goto err; + if ((padding == RSA_X931_PADDING) && ((ret->d[0] & 0xf) != 12)) + BN_sub(ret, rsa->n, ret); + p=buf; i=BN_bn2bin(ret,p); @@ -573,6 +685,9 @@ static int RSA_eay_public_decrypt(int flen, const unsigned char *from, case RSA_PKCS1_PADDING: r=RSA_padding_check_PKCS1_type_1(to,num,buf,i,num); break; + case RSA_X931_PADDING: + r=RSA_padding_check_X931(to,num,buf,i,num); + break; case RSA_NO_PADDING: r=RSA_padding_check_none(to,num,buf,i,num); break; @@ -600,6 +715,8 @@ err: static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) { BIGNUM *r1,*m1,*vrfy; + BIGNUM local_dmp1,local_dmq1,local_c,local_r1; + BIGNUM *dmp1,*dmq1,*c,*pr1; int ret=0; BN_CTX_start(ctx); @@ -607,26 +724,106 @@ static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) m1 = BN_CTX_get(ctx); vrfy = BN_CTX_get(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); + { + BIGNUM local_p, local_q; + BIGNUM *p = NULL, *q = NULL; + + /* Make sure BN_mod_inverse in Montgomery intialization uses the + * BN_FLG_CONSTTIME flag (unless RSA_FLAG_NO_CONSTTIME is set) + */ + if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) + { + BN_init(&local_p); + p = &local_p; + BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME); + + BN_init(&local_q); + q = &local_q; + BN_with_flags(q, rsa->q, BN_FLG_CONSTTIME); + } + else + { + p = rsa->p; + q = rsa->q; + } + + if (rsa->flags & RSA_FLAG_CACHE_PRIVATE) + { + if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_p, CRYPTO_LOCK_RSA, p, ctx)) + goto err; + if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_q, CRYPTO_LOCK_RSA, q, ctx)) + goto err; + } + } + + if (rsa->flags & RSA_FLAG_CACHE_PUBLIC) + if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, CRYPTO_LOCK_RSA, rsa->n, ctx)) + goto err; + + /* compute I mod q */ + if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) + { + c = &local_c; + BN_with_flags(c, I, BN_FLG_CONSTTIME); + if (!BN_mod(r1,c,rsa->q,ctx)) goto err; + } + else + { + if (!BN_mod(r1,I,rsa->q,ctx)) goto err; + } - if (!BN_mod(r1,I,rsa->q,ctx)) goto err; - if (!rsa->meth->bn_mod_exp(m1,r1,rsa->dmq1,rsa->q,ctx, + /* compute r1^dmq1 mod q */ + if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) + { + dmq1 = &local_dmq1; + BN_with_flags(dmq1, rsa->dmq1, BN_FLG_CONSTTIME); + } + else + dmq1 = rsa->dmq1; + if (!rsa->meth->bn_mod_exp(m1,r1,dmq1,rsa->q,ctx, rsa->_method_mod_q)) goto err; - if (!BN_mod(r1,I,rsa->p,ctx)) goto err; - if (!rsa->meth->bn_mod_exp(r0,r1,rsa->dmp1,rsa->p,ctx, + /* compute I mod p */ + if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) + { + c = &local_c; + BN_with_flags(c, I, BN_FLG_CONSTTIME); + if (!BN_mod(r1,c,rsa->p,ctx)) goto err; + } + else + { + if (!BN_mod(r1,I,rsa->p,ctx)) goto err; + } + + /* compute r1^dmp1 mod p */ + if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) + { + dmp1 = &local_dmp1; + BN_with_flags(dmp1, rsa->dmp1, BN_FLG_CONSTTIME); + } + else + dmp1 = rsa->dmp1; + if (!rsa->meth->bn_mod_exp(r0,r1,dmp1,rsa->p,ctx, rsa->_method_mod_p)) 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 (BN_get_sign(r0)) + 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; + + /* Turn BN_FLG_CONSTTIME flag on before division operation */ + if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) + { + pr1 = &local_r1; + BN_with_flags(pr1, r1, BN_FLG_CONSTTIME); + } + else + pr1 = r1; + if (!BN_mod(r0,pr1,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 @@ -634,7 +831,7 @@ static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) * This will *never* happen with OpenSSL generated keys because * they ensure p > q [steve] */ - if (BN_get_sign(r0)) + 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; @@ -648,14 +845,27 @@ static int RSA_eay_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) * 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_get_sign(vrfy)) + 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; + + BIGNUM local_d; + BIGNUM *d = NULL; + + if (!(rsa->flags & RSA_FLAG_NO_CONSTTIME)) + { + d = &local_d; + BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME); + } + else + d = rsa->d; + if (!rsa->meth->bn_mod_exp(r0,I,d,rsa->n,ctx, + rsa->_method_mod_n)) goto err; + } } ret=1; err: |