BN_BLINDING multi-threading fix.
Submitted by: Emilia Kasper (Google)
This commit is contained in:
parent
dacd94b9c8
commit
195d6bf760
3 changed files with 84 additions and 43 deletions
10
CHANGES
10
CHANGES
|
@ -4,6 +4,16 @@
|
||||||
|
|
||||||
Changes between 0.9.8r and 0.9.8s [xx XXX xxxx]
|
Changes between 0.9.8r and 0.9.8s [xx XXX xxxx]
|
||||||
|
|
||||||
|
*) Fix handling of BN_BLINDING: now BN_BLINDING_invert_ex (rather than
|
||||||
|
BN_BLINDING_invert_ex) calls BN_BLINDING_update, ensuring that concurrent
|
||||||
|
threads won't reuse the same blinding coefficients.
|
||||||
|
|
||||||
|
This also avoids the need to obtain the CRYPTO_LOCK_RSA_BLINDING
|
||||||
|
lock to call BN_BLINDING_invert_ex, and avoids one use of
|
||||||
|
BN_BLINDING_update for each BN_BLINDING structure (previously,
|
||||||
|
the last update always remained unused).
|
||||||
|
[Emilia Käsper (Google)]
|
||||||
|
|
||||||
*) Fix SSL memory handling for (EC)DH ciphersuites, in particular
|
*) Fix SSL memory handling for (EC)DH ciphersuites, in particular
|
||||||
for multi-threaded use of ECDH.
|
for multi-threaded use of ECDH.
|
||||||
[Adam Langley (Google)]
|
[Adam Langley (Google)]
|
||||||
|
|
|
@ -123,7 +123,7 @@ struct bn_blinding_st
|
||||||
BIGNUM *mod; /* just a reference */
|
BIGNUM *mod; /* just a reference */
|
||||||
unsigned long thread_id; /* added in OpenSSL 0.9.6j and 0.9.7b;
|
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 only by crypto/rsa/rsa_eay.c, rsa_lib.c */
|
||||||
unsigned int counter;
|
int counter;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
BN_MONT_CTX *m_ctx;
|
BN_MONT_CTX *m_ctx;
|
||||||
int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
|
int (*bn_mod_exp)(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
|
||||||
|
@ -157,7 +157,10 @@ BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, /* const */ BIGN
|
||||||
if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0)
|
if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0)
|
||||||
BN_set_flags(ret->mod, BN_FLG_CONSTTIME);
|
BN_set_flags(ret->mod, BN_FLG_CONSTTIME);
|
||||||
|
|
||||||
ret->counter = BN_BLINDING_COUNTER;
|
/* Set the counter to the special value -1
|
||||||
|
* to indicate that this is never-used fresh blinding
|
||||||
|
* that does not need updating before first use. */
|
||||||
|
ret->counter = -1;
|
||||||
return(ret);
|
return(ret);
|
||||||
err:
|
err:
|
||||||
if (ret != NULL) BN_BLINDING_free(ret);
|
if (ret != NULL) BN_BLINDING_free(ret);
|
||||||
|
@ -186,7 +189,10 @@ int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (--(b->counter) == 0 && b->e != NULL &&
|
if (b->counter == -1)
|
||||||
|
b->counter = 0;
|
||||||
|
|
||||||
|
if (++b->counter == BN_BLINDING_COUNTER && b->e != NULL &&
|
||||||
!(b->flags & BN_BLINDING_NO_RECREATE))
|
!(b->flags & BN_BLINDING_NO_RECREATE))
|
||||||
{
|
{
|
||||||
/* re-create blinding parameters */
|
/* re-create blinding parameters */
|
||||||
|
@ -201,8 +207,8 @@ int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx)
|
||||||
|
|
||||||
ret=1;
|
ret=1;
|
||||||
err:
|
err:
|
||||||
if (b->counter == 0)
|
if (b->counter == BN_BLINDING_COUNTER)
|
||||||
b->counter = BN_BLINDING_COUNTER;
|
b->counter = 0;
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,6 +229,12 @@ int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *ctx)
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (b->counter == -1)
|
||||||
|
/* Fresh blinding, doesn't need updating. */
|
||||||
|
b->counter = 0;
|
||||||
|
else if (!BN_BLINDING_update(b,ctx))
|
||||||
|
return(0);
|
||||||
|
|
||||||
if (r != NULL)
|
if (r != NULL)
|
||||||
{
|
{
|
||||||
if (!BN_copy(r, b->Ai)) ret=0;
|
if (!BN_copy(r, b->Ai)) ret=0;
|
||||||
|
@ -243,22 +255,19 @@ int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b, BN_CTX *ct
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
bn_check_top(n);
|
bn_check_top(n);
|
||||||
if ((b->A == NULL) || (b->Ai == NULL))
|
|
||||||
{
|
|
||||||
BNerr(BN_F_BN_BLINDING_INVERT_EX,BN_R_NOT_INITIALIZED);
|
|
||||||
return(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (r != NULL)
|
if (r != NULL)
|
||||||
ret = BN_mod_mul(n, n, r, b->mod, ctx);
|
ret = BN_mod_mul(n, n, r, b->mod, ctx);
|
||||||
else
|
else
|
||||||
ret = BN_mod_mul(n, n, b->Ai, b->mod, ctx);
|
|
||||||
|
|
||||||
if (ret >= 0)
|
|
||||||
{
|
{
|
||||||
if (!BN_BLINDING_update(b,ctx))
|
if (b->Ai == NULL)
|
||||||
|
{
|
||||||
|
BNerr(BN_F_BN_BLINDING_INVERT_EX,BN_R_NOT_INITIALIZED);
|
||||||
return(0);
|
return(0);
|
||||||
|
}
|
||||||
|
ret = BN_mod_mul(n, n, b->Ai, b->mod, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
bn_check_top(n);
|
bn_check_top(n);
|
||||||
return(ret);
|
return(ret);
|
||||||
}
|
}
|
||||||
|
|
|
@ -312,51 +312,56 @@ static BN_BLINDING *rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rsa_blinding_convert(BN_BLINDING *b, int local, BIGNUM *f,
|
static int rsa_blinding_convert(BN_BLINDING *b, BIGNUM *f, BIGNUM *unblind,
|
||||||
BIGNUM *r, BN_CTX *ctx)
|
BN_CTX *ctx)
|
||||||
{
|
{
|
||||||
if (local)
|
if (unblind == NULL)
|
||||||
|
/* Local blinding: store the unblinding factor
|
||||||
|
* in BN_BLINDING. */
|
||||||
return BN_BLINDING_convert_ex(f, NULL, b, ctx);
|
return BN_BLINDING_convert_ex(f, NULL, b, ctx);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int ret;
|
/* Shared blinding: store the unblinding factor
|
||||||
CRYPTO_r_lock(CRYPTO_LOCK_RSA_BLINDING);
|
* outside BN_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;
|
int ret;
|
||||||
CRYPTO_w_lock(CRYPTO_LOCK_RSA_BLINDING);
|
CRYPTO_w_lock(CRYPTO_LOCK_RSA_BLINDING);
|
||||||
ret = BN_BLINDING_invert_ex(f, r, b, ctx);
|
ret = BN_BLINDING_convert_ex(f, unblind, b, ctx);
|
||||||
CRYPTO_w_unlock(CRYPTO_LOCK_RSA_BLINDING);
|
CRYPTO_w_unlock(CRYPTO_LOCK_RSA_BLINDING);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int rsa_blinding_invert(BN_BLINDING *b, BIGNUM *f, BIGNUM *unblind,
|
||||||
|
BN_CTX *ctx)
|
||||||
|
{
|
||||||
|
/* For local blinding, unblind is set to NULL, and BN_BLINDING_invert_ex
|
||||||
|
* will use the unblinding factor stored in BN_BLINDING.
|
||||||
|
* If BN_BLINDING is shared between threads, unblind must be non-null:
|
||||||
|
* BN_BLINDING_invert_ex will then use the local unblinding factor,
|
||||||
|
* and will only read the modulus from BN_BLINDING.
|
||||||
|
* In both cases it's safe to access the blinding without a lock.
|
||||||
|
*/
|
||||||
|
return BN_BLINDING_invert_ex(f, unblind, b, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
/* signing */
|
/* signing */
|
||||||
static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
|
static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
|
||||||
unsigned char *to, RSA *rsa, int padding)
|
unsigned char *to, RSA *rsa, int padding)
|
||||||
{
|
{
|
||||||
BIGNUM *f, *ret, *br, *res;
|
BIGNUM *f, *ret, *res;
|
||||||
int i,j,k,num=0,r= -1;
|
int i,j,k,num=0,r= -1;
|
||||||
unsigned char *buf=NULL;
|
unsigned char *buf=NULL;
|
||||||
BN_CTX *ctx=NULL;
|
BN_CTX *ctx=NULL;
|
||||||
int local_blinding = 0;
|
int local_blinding = 0;
|
||||||
|
/* Used only if the blinding structure is shared. A non-NULL unblind
|
||||||
|
* instructs rsa_blinding_convert() and rsa_blinding_invert() to store
|
||||||
|
* the unblinding factor outside the blinding structure. */
|
||||||
|
BIGNUM *unblind = NULL;
|
||||||
BN_BLINDING *blinding = NULL;
|
BN_BLINDING *blinding = NULL;
|
||||||
|
|
||||||
if ((ctx=BN_CTX_new()) == NULL) goto err;
|
if ((ctx=BN_CTX_new()) == NULL) goto err;
|
||||||
BN_CTX_start(ctx);
|
BN_CTX_start(ctx);
|
||||||
f = BN_CTX_get(ctx);
|
f = BN_CTX_get(ctx);
|
||||||
br = BN_CTX_get(ctx);
|
|
||||||
ret = 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);
|
buf = OPENSSL_malloc(num);
|
||||||
|
@ -404,8 +409,15 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blinding != NULL)
|
if (blinding != NULL)
|
||||||
if (!rsa_blinding_convert(blinding, local_blinding, f, br, ctx))
|
{
|
||||||
|
if (!local_blinding && ((unblind = BN_CTX_get(ctx)) == NULL))
|
||||||
|
{
|
||||||
|
RSAerr(RSA_F_RSA_EAY_PRIVATE_ENCRYPT,ERR_R_MALLOC_FAILURE);
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
|
if (!rsa_blinding_convert(blinding, f, unblind, ctx))
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
if ( (rsa->flags & RSA_FLAG_EXT_PKEY) ||
|
if ( (rsa->flags & RSA_FLAG_EXT_PKEY) ||
|
||||||
((rsa->p != NULL) &&
|
((rsa->p != NULL) &&
|
||||||
|
@ -439,7 +451,7 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blinding)
|
if (blinding)
|
||||||
if (!rsa_blinding_invert(blinding, local_blinding, ret, br, ctx))
|
if (!rsa_blinding_invert(blinding, ret, unblind, ctx))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (padding == RSA_X931_PADDING)
|
if (padding == RSA_X931_PADDING)
|
||||||
|
@ -478,18 +490,21 @@ err:
|
||||||
static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
|
static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
|
||||||
unsigned char *to, RSA *rsa, int padding)
|
unsigned char *to, RSA *rsa, int padding)
|
||||||
{
|
{
|
||||||
BIGNUM *f, *ret, *br;
|
BIGNUM *f, *ret;
|
||||||
int j,num=0,r= -1;
|
int j,num=0,r= -1;
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
unsigned char *buf=NULL;
|
unsigned char *buf=NULL;
|
||||||
BN_CTX *ctx=NULL;
|
BN_CTX *ctx=NULL;
|
||||||
int local_blinding = 0;
|
int local_blinding = 0;
|
||||||
|
/* Used only if the blinding structure is shared. A non-NULL unblind
|
||||||
|
* instructs rsa_blinding_convert() and rsa_blinding_invert() to store
|
||||||
|
* the unblinding factor outside the blinding structure. */
|
||||||
|
BIGNUM *unblind = NULL;
|
||||||
BN_BLINDING *blinding = NULL;
|
BN_BLINDING *blinding = NULL;
|
||||||
|
|
||||||
if((ctx = BN_CTX_new()) == NULL) goto err;
|
if((ctx = BN_CTX_new()) == NULL) goto err;
|
||||||
BN_CTX_start(ctx);
|
BN_CTX_start(ctx);
|
||||||
f = BN_CTX_get(ctx);
|
f = BN_CTX_get(ctx);
|
||||||
br = BN_CTX_get(ctx);
|
|
||||||
ret = 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);
|
buf = OPENSSL_malloc(num);
|
||||||
|
@ -527,8 +542,15 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blinding != NULL)
|
if (blinding != NULL)
|
||||||
if (!rsa_blinding_convert(blinding, local_blinding, f, br, ctx))
|
{
|
||||||
|
if (!local_blinding && ((unblind = BN_CTX_get(ctx)) == NULL))
|
||||||
|
{
|
||||||
|
RSAerr(RSA_F_RSA_EAY_PRIVATE_DECRYPT,ERR_R_MALLOC_FAILURE);
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
|
if (!rsa_blinding_convert(blinding, f, unblind, ctx))
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
/* do the decrypt */
|
/* do the decrypt */
|
||||||
if ( (rsa->flags & RSA_FLAG_EXT_PKEY) ||
|
if ( (rsa->flags & RSA_FLAG_EXT_PKEY) ||
|
||||||
|
@ -562,7 +584,7 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blinding)
|
if (blinding)
|
||||||
if (!rsa_blinding_invert(blinding, local_blinding, ret, br, ctx))
|
if (!rsa_blinding_invert(blinding, ret, unblind, ctx))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
p=buf;
|
p=buf;
|
||||||
|
|
Loading…
Reference in a new issue