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]
 | 
					 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;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user