BN_BLINDING multi-threading fix.
Submitted by: Emilia Kasper (Google)
This commit is contained in:
		
							
								
								
									
										10
									
								
								CHANGES
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								CHANGES
									
									
									
									
									
								
							@@ -4,6 +4,16 @@
 | 
			
		||||
 | 
			
		||||
 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
 | 
			
		||||
     for multi-threaded use of ECDH.
 | 
			
		||||
     [Adam Langley (Google)]
 | 
			
		||||
 
 | 
			
		||||
@@ -123,7 +123,7 @@ struct bn_blinding_st
 | 
			
		||||
	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;
 | 
			
		||||
	int counter;
 | 
			
		||||
	unsigned long flags;
 | 
			
		||||
	BN_MONT_CTX *m_ctx;
 | 
			
		||||
	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)
 | 
			
		||||
		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);
 | 
			
		||||
err:
 | 
			
		||||
	if (ret != NULL) BN_BLINDING_free(ret);
 | 
			
		||||
@@ -186,7 +189,10 @@ int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx)
 | 
			
		||||
		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))
 | 
			
		||||
		{
 | 
			
		||||
		/* re-create blinding parameters */
 | 
			
		||||
@@ -201,8 +207,8 @@ int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx)
 | 
			
		||||
 | 
			
		||||
	ret=1;
 | 
			
		||||
err:
 | 
			
		||||
	if (b->counter == 0)
 | 
			
		||||
		b->counter = BN_BLINDING_COUNTER;
 | 
			
		||||
	if (b->counter == BN_BLINDING_COUNTER)
 | 
			
		||||
		b->counter = 0;
 | 
			
		||||
	return(ret);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -223,6 +229,12 @@ int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *ctx)
 | 
			
		||||
		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 (!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;
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
		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))
 | 
			
		||||
		if (b->Ai == NULL)
 | 
			
		||||
			{
 | 
			
		||||
			BNerr(BN_F_BN_BLINDING_INVERT_EX,BN_R_NOT_INITIALIZED);
 | 
			
		||||
			return(0);
 | 
			
		||||
			}
 | 
			
		||||
		ret = BN_mod_mul(n, n, b->Ai, b->mod, ctx);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	bn_check_top(n);
 | 
			
		||||
	return(ret);
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -312,51 +312,56 @@ static BN_BLINDING *rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx)
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int rsa_blinding_convert(BN_BLINDING *b, int local, BIGNUM *f,
 | 
			
		||||
	BIGNUM *r, BN_CTX *ctx)
 | 
			
		||||
static int rsa_blinding_convert(BN_BLINDING *b, BIGNUM *f, BIGNUM *unblind,
 | 
			
		||||
	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);
 | 
			
		||||
	else
 | 
			
		||||
		{
 | 
			
		||||
		/* Shared blinding: store the unblinding factor
 | 
			
		||||
		 * outside BN_BLINDING. */
 | 
			
		||||
		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);
 | 
			
		||||
		CRYPTO_w_lock(CRYPTO_LOCK_RSA_BLINDING);
 | 
			
		||||
		ret = BN_BLINDING_convert_ex(f, unblind, 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)
 | 
			
		||||
static int rsa_blinding_invert(BN_BLINDING *b, BIGNUM *f, BIGNUM *unblind,
 | 
			
		||||
	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;
 | 
			
		||||
		}
 | 
			
		||||
	/* 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 */
 | 
			
		||||
static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
 | 
			
		||||
	     unsigned char *to, RSA *rsa, int padding)
 | 
			
		||||
	{
 | 
			
		||||
	BIGNUM *f, *ret, *br, *res;
 | 
			
		||||
	BIGNUM *f, *ret, *res;
 | 
			
		||||
	int i,j,k,num=0,r= -1;
 | 
			
		||||
	unsigned char *buf=NULL;
 | 
			
		||||
	BN_CTX *ctx=NULL;
 | 
			
		||||
	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;
 | 
			
		||||
 | 
			
		||||
	if ((ctx=BN_CTX_new()) == NULL) goto err;
 | 
			
		||||
	BN_CTX_start(ctx);
 | 
			
		||||
	f   = BN_CTX_get(ctx);
 | 
			
		||||
	br  = BN_CTX_get(ctx);
 | 
			
		||||
	ret = BN_CTX_get(ctx);
 | 
			
		||||
	num = BN_num_bytes(rsa->n);
 | 
			
		||||
	buf = OPENSSL_malloc(num);
 | 
			
		||||
@@ -404,8 +409,15 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
 | 
			
		||||
		}
 | 
			
		||||
	
 | 
			
		||||
	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;
 | 
			
		||||
			}
 | 
			
		||||
		if (!rsa_blinding_convert(blinding, f, unblind, ctx))
 | 
			
		||||
			goto err;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	if ( (rsa->flags & RSA_FLAG_EXT_PKEY) ||
 | 
			
		||||
		((rsa->p != NULL) &&
 | 
			
		||||
@@ -439,7 +451,7 @@ static int RSA_eay_private_encrypt(int flen, const unsigned char *from,
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	if (blinding)
 | 
			
		||||
		if (!rsa_blinding_invert(blinding, local_blinding, ret, br, ctx))
 | 
			
		||||
		if (!rsa_blinding_invert(blinding, ret, unblind, ctx))
 | 
			
		||||
			goto err;
 | 
			
		||||
 | 
			
		||||
	if (padding == RSA_X931_PADDING)
 | 
			
		||||
@@ -478,18 +490,21 @@ err:
 | 
			
		||||
static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
 | 
			
		||||
	     unsigned char *to, RSA *rsa, int padding)
 | 
			
		||||
	{
 | 
			
		||||
	BIGNUM *f, *ret, *br;
 | 
			
		||||
	BIGNUM *f, *ret;
 | 
			
		||||
	int j,num=0,r= -1;
 | 
			
		||||
	unsigned char *p;
 | 
			
		||||
	unsigned char *buf=NULL;
 | 
			
		||||
	BN_CTX *ctx=NULL;
 | 
			
		||||
	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;
 | 
			
		||||
 | 
			
		||||
	if((ctx = BN_CTX_new()) == NULL) goto err;
 | 
			
		||||
	BN_CTX_start(ctx);
 | 
			
		||||
	f   = BN_CTX_get(ctx);
 | 
			
		||||
	br  = BN_CTX_get(ctx);
 | 
			
		||||
	ret = BN_CTX_get(ctx);
 | 
			
		||||
	num = BN_num_bytes(rsa->n);
 | 
			
		||||
	buf = OPENSSL_malloc(num);
 | 
			
		||||
@@ -527,8 +542,15 @@ static int RSA_eay_private_decrypt(int flen, const unsigned char *from,
 | 
			
		||||
		}
 | 
			
		||||
	
 | 
			
		||||
	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;
 | 
			
		||||
			}
 | 
			
		||||
		if (!rsa_blinding_convert(blinding, f, unblind, ctx))
 | 
			
		||||
			goto err;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	/* do the decrypt */
 | 
			
		||||
	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 (!rsa_blinding_invert(blinding, local_blinding, ret, br, ctx))
 | 
			
		||||
		if (!rsa_blinding_invert(blinding, ret, unblind, ctx))
 | 
			
		||||
			goto err;
 | 
			
		||||
 | 
			
		||||
	p=buf;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user