From: Nils Larsch Date: Tue, 26 Apr 2005 22:31:48 +0000 (+0000) Subject: some updates for the blinding code; summary: X-Git-Tag: OpenSSL_0_9_8-beta1~13^2~113 X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=commitdiff_plain;h=800e400de5ca30491577301ded618445b48c7911 some updates for the blinding code; summary: - possibility of re-creation of the blinding parameters after a fixed number of uses (suggested by Bodo) - calculatition of the rsa::e in case it's absent and p and q are present (see bug report #785) - improve the performance when if one rsa structure is shared by more than a thread (see bug report #555) - fix the problem described in bug report #827 - hide the definition ot the BN_BLINDING structure in bn_blind.c --- diff --git a/CHANGES b/CHANGES index f75ddd90bf..90b64f4e46 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,18 @@ Changes between 0.9.7g and 0.9.8 [xx XXX xxxx] + *) Add new functionality to the bn blinding code: + - automatic re-creation of the BN_BLINDING parameters after + a fixed number of uses (currently 32) + - add new function for parameter creation + - introduce flags to control the update behaviour of the + BN_BLINDING parameters + - hide BN_BLINDING structure + Add a second BN_BLINDING slot to the RSA structure to improve + performance when a single RSA object is shared among several + threads. + [Nils Larsch] + *) Add support for DTLS. [Nagendra Modadugu and Ben Laurie] diff --git a/crypto/bn/bn.h b/crypto/bn/bn.h index 5f57eb86f7..1c75fd0719 100644 --- a/crypto/bn/bn.h +++ b/crypto/bn/bn.h @@ -274,16 +274,6 @@ struct bignum_st int flags; }; -struct bn_blinding_st - { - int init; - BIGNUM *A; - BIGNUM *Ai; - BIGNUM *mod; /* just a reference */ - unsigned long thread_id; /* added in OpenSSL 0.9.6j and 0.9.7b; - * used only by crypto/rsa/rsa_eay.c, rsa_lib.c */ - }; - /* Used for montgomery multiplication */ struct bn_mont_ctx_st { @@ -521,11 +511,26 @@ void BN_MONT_CTX_free(BN_MONT_CTX *mont); int BN_MONT_CTX_set(BN_MONT_CTX *mont,const BIGNUM *mod,BN_CTX *ctx); BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to,BN_MONT_CTX *from); -BN_BLINDING *BN_BLINDING_new(BIGNUM *A,BIGNUM *Ai,BIGNUM *mod); +/* BN_BLINDING flags */ +#define BN_BLINDING_NO_UPDATE 0x00000001 +#define BN_BLINDING_NO_RECREATE 0x00000002 + +BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod); void BN_BLINDING_free(BN_BLINDING *b); int BN_BLINDING_update(BN_BLINDING *b,BN_CTX *ctx); -int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *r, BN_CTX *ctx); +int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx); int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx); +int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *); +int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, BN_CTX *); +unsigned long BN_BLINDING_get_thread_id(const BN_BLINDING *); +void BN_BLINDING_set_thread_id(BN_BLINDING *, unsigned long); +unsigned long BN_BLINDING_get_flags(const BN_BLINDING *); +void BN_BLINDING_set_flags(BN_BLINDING *, unsigned long); +BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b, + const BIGNUM *e, BIGNUM *m, BN_CTX *ctx, + int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx), + BN_MONT_CTX *m_ctx); #ifndef OPENSSL_NO_DEPRECATED void BN_set_params(int mul,int high,int low,int mont); @@ -727,6 +732,7 @@ void ERR_load_BN_strings(void); /* Function codes. */ #define BN_F_BNRAND 114 #define BN_F_BN_BLINDING_CONVERT 100 +#define BN_F_BN_BLINDING_CREATE_PARAM 133 #define BN_F_BN_BLINDING_INVERT 101 #define BN_F_BN_BLINDING_NEW 102 #define BN_F_BN_BLINDING_UPDATE 103 diff --git a/crypto/bn/bn_blind.c b/crypto/bn/bn_blind.c index 011d37f1ff..1f41740c95 100644 --- a/crypto/bn/bn_blind.c +++ b/crypto/bn/bn_blind.c @@ -1,4 +1,57 @@ /* crypto/bn/bn_blind.c */ +/* ==================================================================== + * Copyright (c) 1998-2005 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). + * + */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -60,11 +113,28 @@ #include "cryptlib.h" #include "bn_lcl.h" -BN_BLINDING *BN_BLINDING_new(BIGNUM *A, BIGNUM *Ai, BIGNUM *mod) +#define BN_BLINDING_COUNTER 32 + +struct bn_blinding_st + { + BIGNUM *A; + BIGNUM *Ai; + BIGNUM *e; + BIGNUM *mod; /* just a reference */ + unsigned long thread_id; /* added in OpenSSL 0.9.6j and 0.9.7b; + * used only by crypto/rsa/rsa_eay.c, rsa_lib.c */ + unsigned int counter; + unsigned long flags; + BN_MONT_CTX *m_ctx; + int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, + BN_MONT_CTX *m_ctx); + }; + +BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod) { BN_BLINDING *ret=NULL; - bn_check_top(Ai); bn_check_top(mod); if ((ret=(BN_BLINDING *)OPENSSL_malloc(sizeof(BN_BLINDING))) == NULL) @@ -73,11 +143,16 @@ BN_BLINDING *BN_BLINDING_new(BIGNUM *A, BIGNUM *Ai, BIGNUM *mod) return(NULL); } memset(ret,0,sizeof(BN_BLINDING)); - if ((ret->A=BN_new()) == NULL) goto err; - if ((ret->Ai=BN_new()) == NULL) goto err; - if (!BN_copy(ret->A,A)) goto err; - if (!BN_copy(ret->Ai,Ai)) goto err; - ret->mod=mod; + if (A != NULL) + { + if ((ret->A = BN_dup(A)) == NULL) goto err; + } + if (Ai != NULL) + { + if ((ret->Ai = BN_dup(Ai)) == NULL) goto err; + } + ret->mod = mod; + ret->counter = BN_BLINDING_COUNTER; return(ret); err: if (ret != NULL) BN_BLINDING_free(ret); @@ -91,6 +166,7 @@ void BN_BLINDING_free(BN_BLINDING *r) if (r->A != NULL) BN_free(r->A ); if (r->Ai != NULL) BN_free(r->Ai); + if (r->e != NULL) BN_free(r->e ); OPENSSL_free(r); } @@ -103,16 +179,33 @@ int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx) BNerr(BN_F_BN_BLINDING_UPDATE,BN_R_NOT_INITIALIZED); goto err; } - - if (!BN_mod_mul(b->A,b->A,b->A,b->mod,ctx)) goto err; - if (!BN_mod_mul(b->Ai,b->Ai,b->Ai,b->mod,ctx)) goto err; + + if (--(b->counter) == 0 && b->e != NULL && + !(b->flags & BN_BLINDING_NO_RECREATE)) + { + /* re-create blinding parameters */ + if (!BN_BLINDING_create_param(b, NULL, NULL, ctx, NULL, NULL)) + goto err; + } + else if (!(b->flags & BN_BLINDING_NO_UPDATE)) + { + if (!BN_mod_mul(b->A,b->A,b->A,b->mod,ctx)) goto err; + if (!BN_mod_mul(b->Ai,b->Ai,b->Ai,b->mod,ctx)) goto err; + } ret=1; err: + if (b->counter == 0) + b->counter = BN_BLINDING_COUNTER; return(ret); } int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx) + { + return BN_BLINDING_convert_ex(n, NULL, b, ctx); + } + +int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *ctx) { bn_check_top(n); @@ -121,10 +214,19 @@ int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx) BNerr(BN_F_BN_BLINDING_CONVERT,BN_R_NOT_INITIALIZED); return(0); } - return(BN_mod_mul(n,n,b->A,b->mod,ctx)); + + if (r != NULL) + BN_copy(r, b->Ai); + + return BN_mod_mul(n,n,b->A,b->mod,ctx); } int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx) + { + return BN_BLINDING_invert_ex(n, NULL, b, ctx); + } + +int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, BN_CTX *ctx) { int ret; @@ -134,7 +236,13 @@ int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx) BNerr(BN_F_BN_BLINDING_INVERT,BN_R_NOT_INITIALIZED); return(0); } - if ((ret=BN_mod_mul(n,n,b->Ai,b->mod,ctx)) >= 0) + + if (r != NULL) + ret = BN_mod_mul(n, n, r, b->mod, ctx); + else + ret = BN_mod_mul(n, n, b->Ai, b->mod, ctx); + + if (ret >= 0) { if (!BN_BLINDING_update(b,ctx)) return(0); @@ -143,3 +251,105 @@ int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx) return(ret); } +unsigned long BN_BLINDING_get_thread_id(const BN_BLINDING *b) + { + return b->thread_id; + } + +void BN_BLINDING_set_thread_id(BN_BLINDING *b, unsigned long n) + { + b->thread_id = n; + } + +unsigned long BN_BLINDING_get_flags(const BN_BLINDING *b) + { + return b->flags; + } + +void BN_BLINDING_set_flags(BN_BLINDING *b, unsigned long flags) + { + b->flags = flags; + } + +BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b, + const BIGNUM *e, BIGNUM *m, BN_CTX *ctx, + int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, + const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx), + BN_MONT_CTX *m_ctx) +{ + int retry_counter = 32; + BIGNUM *a, *ai; + BN_BLINDING *ret = NULL; + + if (b == NULL) + ret = BN_BLINDING_new(NULL, NULL, m); + else + ret = b; + + if (ret == NULL) + goto err; + + if (ret->A == NULL && (ret->A = BN_new()) == NULL) + goto err; + if (ret->Ai == NULL && (ret->Ai = BN_new()) == NULL) + goto err; + + if (e != NULL) + { + if (ret->e != NULL) + BN_free(ret->e); + ret->e = BN_dup(e); + } + if (ret->e == NULL) + goto err; + + if (bn_mod_exp != NULL) + ret->bn_mod_exp = bn_mod_exp; + if (m_ctx != NULL) + ret->m_ctx = m_ctx; + + do { + if (!BN_rand_range(ret->A, ret->mod)) goto err; + if (BN_mod_inverse(ret->Ai, ret->A, ret->mod, ctx) == NULL) + { + /* this should almost never happen for good RSA keys */ + unsigned long error = ERR_peek_last_error(); + if (ERR_GET_REASON(error) == BN_R_NO_INVERSE) + { + if (retry_counter-- == 0) + { + BNerr(BN_F_BN_BLINDING_CREATE_PARAM, + BN_R_TOO_MANY_ITERATIONS); + goto err; + } + ERR_clear_error(); + } + else + goto err; + } + else + break; + } while (1); + + if (ret->bn_mod_exp != NULL && ret->m_ctx != NULL) + { + if (!ret->bn_mod_exp(ret->A, ret->A, ret->e, ret->mod, ctx, ret->m_ctx)) + goto err; + } + else + { + if (!BN_mod_exp(ret->A, ret->A, ret->e, ret->mod, ctx)) + goto err; + } + + return ret; +err: + if (b == NULL && ret != NULL) + { + BN_BLINDING_free(ret); + ret = NULL; + } + + return ret; +} + diff --git a/crypto/bn/bn_err.c b/crypto/bn/bn_err.c index 42db405a65..37aa709617 100644 --- a/crypto/bn/bn_err.c +++ b/crypto/bn/bn_err.c @@ -72,6 +72,7 @@ static ERR_STRING_DATA BN_str_functs[]= { {ERR_FUNC(BN_F_BNRAND), "BNRAND"}, {ERR_FUNC(BN_F_BN_BLINDING_CONVERT), "BN_BLINDING_convert"}, +{ERR_FUNC(BN_F_BN_BLINDING_CREATE_PARAM), "BN_BLINDING_create_param"}, {ERR_FUNC(BN_F_BN_BLINDING_INVERT), "BN_BLINDING_invert"}, {ERR_FUNC(BN_F_BN_BLINDING_NEW), "BN_BLINDING_new"}, {ERR_FUNC(BN_F_BN_BLINDING_UPDATE), "BN_BLINDING_update"}, diff --git a/crypto/rsa/rsa.h b/crypto/rsa/rsa.h index 4bfd51a4bb..4e28bbc39c 100644 --- a/crypto/rsa/rsa.h +++ b/crypto/rsa/rsa.h @@ -156,6 +156,7 @@ struct rsa_st * NULL */ char *bignum_data; BN_BLINDING *blinding; + BN_BLINDING *mt_blinding; }; #define RSA_3 0x3L @@ -279,6 +280,7 @@ int RSA_verify_ASN1_OCTET_STRING(int type, int RSA_blinding_on(RSA *rsa, BN_CTX *ctx); void RSA_blinding_off(RSA *rsa); +BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *ctx); int RSA_padding_add_PKCS1_type_1(unsigned char *to,int tlen, const unsigned char *f,int fl); @@ -341,6 +343,7 @@ void ERR_load_RSA_strings(void); #define RSA_F_RSA_PADDING_CHECK_SSLV23 114 #define RSA_F_RSA_PRINT 115 #define RSA_F_RSA_PRINT_FP 116 +#define RSA_F_RSA_SETUP_BLINDING 125 #define RSA_F_RSA_SIGN 117 #define RSA_F_RSA_SIGN_ASN1_OCTET_STRING 118 #define RSA_F_RSA_VERIFY 119 @@ -367,6 +370,7 @@ void ERR_load_RSA_strings(void); #define RSA_R_INVALID_MESSAGE_LENGTH 131 #define RSA_R_IQMP_NOT_INVERSE_OF_Q 126 #define RSA_R_KEY_SIZE_TOO_SMALL 120 +#define RSA_R_NO_PUBLIC_EXPONENT 133 #define RSA_R_NULL_BEFORE_BLOCK_MISSING 113 #define RSA_R_N_DOES_NOT_EQUAL_P_Q 127 #define RSA_R_OAEP_DECODING_ERROR 121 diff --git a/crypto/rsa/rsa_eay.c b/crypto/rsa/rsa_eay.c index 3ee753ec86..6bf681f1f9 100644 --- a/crypto/rsa/rsa_eay.c +++ b/crypto/rsa/rsa_eay.c @@ -212,64 +212,78 @@ 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, BIGNUM **r, int *local, BN_CTX *ctx) +{ + BN_BLINDING *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) + if (rsa->blinding == NULL) + { + if (rsa->blinding == NULL) + { + CRYPTO_w_lock(CRYPTO_LOCK_RSA); + if (rsa->blinding == NULL) + rsa->blinding = RSA_setup_blinding(rsa, ctx); + CRYPTO_w_unlock(CRYPTO_LOCK_RSA); + } + } -static BN_BLINDING *setup_blinding(RSA *rsa, BN_CTX *ctx) - { - BIGNUM *A, *Ai; - BN_BLINDING *ret = NULL; + ret = rsa->blinding; + if (ret == NULL) + return NULL; - /* added in OpenSSL 0.9.6j and 0.9.7b */ + if (BN_BLINDING_get_thread_id(ret) != CRYPTO_thread_id()) + { + *local = 0; + if (rsa->mt_blinding == NULL) + { + CRYPTO_w_lock(CRYPTO_LOCK_RSA); + if (rsa->mt_blinding == NULL) + rsa->mt_blinding = RSA_setup_blinding(rsa, ctx); + CRYPTO_w_unlock(CRYPTO_LOCK_RSA); + } + ret = rsa->mt_blinding; + } + else + *local = 1; - /* 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 */ + return ret; +} - BN_CTX_start(ctx); - A = BN_CTX_get(ctx); - if ((RAND_status() == 0) && rsa->d != NULL && rsa->d->d != NULL) +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 { - /* 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; - } + int ret; + CRYPTO_w_lock(CRYPTO_LOCK_RSA_BLINDING); + ret = BN_BLINDING_convert_ex(f, r, b, ctx); + CRYPTO_w_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 { - if (!BN_rand_range(A,rsa->n)) goto err; + int ret; + CRYPTO_r_lock(CRYPTO_LOCK_RSA_BLINDING); + ret = BN_BLINDING_invert_ex(f, r, b, ctx); + CRYPTO_r_unlock(CRYPTO_LOCK_RSA_BLINDING); + return ret; } - 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) { - BIGNUM *f,*ret; + BIGNUM *f, *ret, *br; int i,j,k,num=0,r= -1; unsigned char *buf=NULL; BN_CTX *ctx=NULL; @@ -278,9 +292,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) { @@ -312,17 +327,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, &br, &local_blinding, ctx); if (blinding == NULL) { RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); @@ -331,20 +338,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) && @@ -361,7 +356,8 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from, } if (blinding) - if (!BN_BLINDING_invert(ret, blinding, ctx)) goto err; + if (!rsa_blinding_invert(blinding, local_blinding, ret, br, ctx)) + goto err; /* put in leading 0 bytes if the number is less than the * length of the modulus */ @@ -377,8 +373,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 +384,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 +394,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,39 +422,19 @@ 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, &br, &local_blinding, ctx); if (blinding == NULL) { - RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT, ERR_R_INTERNAL_ERROR); + 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_blinding_convert(blinding, local_blinding, f, br, ctx)) + goto err; /* do the decrypt */ if ( (rsa->flags & RSA_FLAG_EXT_PKEY) || @@ -478,7 +453,8 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from, } 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 +488,6 @@ err: BN_CTX_end(ctx); BN_CTX_free(ctx); } - if (local_blinding) - BN_BLINDING_free(blinding); if (buf != NULL) { OPENSSL_cleanse(buf,num); diff --git a/crypto/rsa/rsa_err.c b/crypto/rsa/rsa_err.c index 07ef9df0cd..6641e61c7f 100644 --- a/crypto/rsa/rsa_err.c +++ b/crypto/rsa/rsa_err.c @@ -91,6 +91,7 @@ static ERR_STRING_DATA RSA_str_functs[]= {ERR_FUNC(RSA_F_RSA_PADDING_CHECK_SSLV23), "RSA_padding_check_SSLv23"}, {ERR_FUNC(RSA_F_RSA_PRINT), "RSA_print"}, {ERR_FUNC(RSA_F_RSA_PRINT_FP), "RSA_print_fp"}, +{ERR_FUNC(RSA_F_RSA_SETUP_BLINDING), "RSA_setup_blinding"}, {ERR_FUNC(RSA_F_RSA_SIGN), "RSA_sign"}, {ERR_FUNC(RSA_F_RSA_SIGN_ASN1_OCTET_STRING), "RSA_sign_ASN1_OCTET_STRING"}, {ERR_FUNC(RSA_F_RSA_VERIFY), "RSA_verify"}, @@ -120,6 +121,7 @@ static ERR_STRING_DATA RSA_str_reasons[]= {ERR_REASON(RSA_R_INVALID_MESSAGE_LENGTH),"invalid message length"}, {ERR_REASON(RSA_R_IQMP_NOT_INVERSE_OF_Q) ,"iqmp not inverse of q"}, {ERR_REASON(RSA_R_KEY_SIZE_TOO_SMALL) ,"key size too small"}, +{ERR_REASON(RSA_R_NO_PUBLIC_EXPONENT) ,"no public exponent"}, {ERR_REASON(RSA_R_NULL_BEFORE_BLOCK_MISSING),"null before block missing"}, {ERR_REASON(RSA_R_N_DOES_NOT_EQUAL_P_Q) ,"n does not equal p q"}, {ERR_REASON(RSA_R_OAEP_DECODING_ERROR) ,"oaep decoding error"}, diff --git a/crypto/rsa/rsa_lib.c b/crypto/rsa/rsa_lib.c index cba2dd66cd..0447fd5c70 100644 --- a/crypto/rsa/rsa_lib.c +++ b/crypto/rsa/rsa_lib.c @@ -179,6 +179,7 @@ RSA *RSA_new_method(ENGINE *engine) ret->_method_mod_p=NULL; ret->_method_mod_q=NULL; ret->blinding=NULL; + ret->mt_blinding=NULL; ret->bignum_data=NULL; ret->flags=ret->meth->flags; CRYPTO_new_ex_data(CRYPTO_EX_INDEX_RSA, ret, &ret->ex_data); @@ -232,6 +233,7 @@ void RSA_free(RSA *r) if (r->dmq1 != NULL) BN_clear_free(r->dmq1); if (r->iqmp != NULL) BN_clear_free(r->iqmp); if (r->blinding != NULL) BN_BLINDING_free(r->blinding); + if (r->mt_blinding != NULL) BN_BLINDING_free(r->mt_blinding); if (r->bignum_data != NULL) OPENSSL_free_locked(r->bignum_data); OPENSSL_free(r); } @@ -314,59 +316,100 @@ void RSA_blinding_off(RSA *rsa) rsa->flags |= RSA_FLAG_NO_BLINDING; } -int RSA_blinding_on(RSA *rsa, BN_CTX *p_ctx) +int RSA_blinding_on(RSA *rsa, BN_CTX *ctx) { - BIGNUM *A,*Ai = NULL; - BN_CTX *ctx; int ret=0; - if (p_ctx == NULL) + if (rsa->blinding != NULL) + RSA_blinding_off(rsa); + + rsa->blinding = RSA_setup_blinding(rsa, ctx); + if (rsa->blinding == NULL) + goto err; + + rsa->flags |= RSA_FLAG_BLINDING; + rsa->flags &= ~RSA_FLAG_NO_BLINDING; + ret=1; +err: + return(ret); + } + +static BIGNUM *rsa_get_public_exp(const BIGNUM *d, const BIGNUM *p, + const BIGNUM *q, BN_CTX *ctx) +{ + BIGNUM *ret = NULL, *r0, *r1, *r2; + + if (d == NULL || p == NULL || q == NULL) + return NULL; + + BN_CTX_start(ctx); + r0 = BN_CTX_get(ctx); + r1 = BN_CTX_get(ctx); + r2 = BN_CTX_get(ctx); + if (r2 == NULL) + goto err; + + if (!BN_sub(r1, p, BN_value_one())) goto err; + if (!BN_sub(r2, q, BN_value_one())) goto err; + if (!BN_mul(r0, r1, r2, ctx)) goto err; + + ret = BN_mod_inverse(NULL, d, r0, ctx); +err: + BN_CTX_end(ctx); + return ret; +} + +BN_BLINDING *RSA_setup_blinding(RSA *rsa, BN_CTX *in_ctx) +{ + BIGNUM *e; + BN_CTX *ctx; + BN_BLINDING *ret = NULL; + + if (in_ctx == NULL) { - if ((ctx=BN_CTX_new()) == NULL) goto err; + if ((ctx = BN_CTX_new()) == NULL) return 0; } else - ctx=p_ctx; + ctx = in_ctx; - /* XXXXX: Shouldn't this be RSA_blinding_off(rsa)? */ - if (rsa->blinding != NULL) + BN_CTX_start(ctx); + e = BN_CTX_get(ctx); + if (e == NULL) { - BN_BLINDING_free(rsa->blinding); - rsa->blinding = NULL; + RSAerr(RSA_F_RSA_SETUP_BLINDING, ERR_R_MALLOC_FAILURE); + goto err; } - /* NB: similar code appears in setup_blinding (rsa_eay.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 (rsa->e == 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; + e = rsa_get_public_exp(rsa->d, rsa->p, rsa->q, ctx); + if (e == NULL) + { + RSAerr(RSA_F_RSA_SETUP_BLINDING, RSA_R_NO_PUBLIC_EXPONENT); + goto err; + } } else + e = rsa->e; + + + if ((RAND_status() == 0) && rsa->d != NULL && rsa->d->d != NULL) { - if (!BN_rand_range(A,rsa->n)) goto err; + /* 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 ((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; - if ((rsa->blinding=BN_BLINDING_new(A,Ai,rsa->n)) == NULL) goto err; - /* to make things thread-safe without excessive locking, - * rsa->blinding will be used just by the current thread: */ - rsa->blinding->thread_id = CRYPTO_thread_id(); - rsa->flags |= RSA_FLAG_BLINDING; - rsa->flags &= ~RSA_FLAG_NO_BLINDING; - ret=1; + ret = BN_BLINDING_create_param(NULL, e, rsa->n, ctx, + rsa->meth->bn_mod_exp, rsa->_method_mod_n); + BN_BLINDING_set_thread_id(ret, CRYPTO_thread_id()); err: - if (Ai != NULL) BN_free(Ai); BN_CTX_end(ctx); - if (ctx != p_ctx) BN_CTX_free(ctx); - return(ret); - } + if (in_ctx == NULL) + BN_CTX_free(ctx); + + return ret; +} int RSA_memory_lock(RSA *r) { diff --git a/util/libeay.num b/util/libeay.num index d589dd3e8e..b9485abf4f 100755 --- a/util/libeay.num +++ b/util/libeay.num @@ -3305,3 +3305,11 @@ BN_set_negative 3704 EXIST::FUNCTION: BIO_new_dgram 3705 EXIST::FUNCTION: BIO_s_datagram 3706 EXIST::FUNCTION:DGRAM BIO_dgram_non_fatal_error 3707 EXIST::FUNCTION: +RSA_setup_blinding 3708 EXIST::FUNCTION:RSA +BN_BLINDING_set_thread_id 3709 EXIST::FUNCTION: +BN_BLINDING_convert_ex 3710 EXIST::FUNCTION: +BN_BLINDING_create_param 3711 EXIST::FUNCTION: +BN_BLINDING_set_flags 3712 EXIST::FUNCTION: +BN_BLINDING_invert_ex 3713 EXIST::FUNCTION: +BN_BLINDING_get_thread_id 3714 EXIST::FUNCTION: +BN_BLINDING_get_flags 3715 EXIST::FUNCTION: