You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			503 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Diff
		
	
			
		
		
	
	
			503 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			Diff
		
	
| From 9be2984bfbff9a83e7b38f47ac87c677e9a9a0b8 Mon Sep 17 00:00:00 2001
 | |
| From: Adam Langley <agl@chromium.org>
 | |
| Date: Thu, 24 Jan 2013 16:27:28 -0500
 | |
| Subject: dsa_nonce
 | |
| 
 | |
| Adds the option to calculate (EC)DSA nonces by hashing the message and
 | |
| private key along with entropy.
 | |
| ---
 | |
|  crypto/bn/bn.h          |  6 +++++
 | |
|  crypto/bn/bn_err.c      |  2 ++
 | |
|  crypto/bn/bn_rand.c     | 70 +++++++++++++++++++++++++++++++++++++++++++++++++
 | |
|  crypto/dsa/dsa.h        | 10 +++++--
 | |
|  crypto/dsa/dsa_err.c    |  1 +
 | |
|  crypto/dsa/dsa_ossl.c   | 28 ++++++++++++++++----
 | |
|  crypto/dsa/dsa_sign.c   |  9 ++++++-
 | |
|  crypto/ec/ec.h          | 11 ++++++++
 | |
|  crypto/ec/ec_key.c      | 12 +++++++++
 | |
|  crypto/ec/ec_lcl.h      |  1 +
 | |
|  crypto/ecdsa/ecdsa.h    |  1 +
 | |
|  crypto/ecdsa/ecs_err.c  |  1 +
 | |
|  crypto/ecdsa/ecs_locl.h |  5 ++--
 | |
|  crypto/ecdsa/ecs_ossl.c | 38 ++++++++++++++++++++-------
 | |
|  crypto/ecdsa/ecs_sign.c | 10 ++++++-
 | |
|  15 files changed, 185 insertions(+), 20 deletions(-)
 | |
| 
 | |
| diff --git a/crypto/bn/bn.h b/crypto/bn/bn.h
 | |
| index f34248e..9281ce5 100644
 | |
| --- a/crypto/bn/bn.h
 | |
| +++ b/crypto/bn/bn.h
 | |
| @@ -692,6 +692,10 @@ const BIGNUM *BN_get0_nist_prime_256(void);
 | |
|  const BIGNUM *BN_get0_nist_prime_384(void);
 | |
|  const BIGNUM *BN_get0_nist_prime_521(void);
 | |
|  
 | |
| +int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range, const BIGNUM *priv,
 | |
| +			  const unsigned char *message, size_t message_len,
 | |
| +			  BN_CTX *ctx);
 | |
| +
 | |
|  /* library internal functions */
 | |
|  
 | |
|  #define bn_expand(a,bits) ((((((bits+BN_BITS2-1))/BN_BITS2)) <= (a)->dmax)?\
 | |
| @@ -842,6 +846,7 @@ void ERR_load_BN_strings(void);
 | |
|  #define BN_F_BN_EXP					 123
 | |
|  #define BN_F_BN_EXPAND2					 108
 | |
|  #define BN_F_BN_EXPAND_INTERNAL				 120
 | |
| +#define BN_F_BN_GENERATE_DSA_NONCE			 140
 | |
|  #define BN_F_BN_GF2M_MOD				 131
 | |
|  #define BN_F_BN_GF2M_MOD_EXP				 132
 | |
|  #define BN_F_BN_GF2M_MOD_MUL				 133
 | |
| @@ -881,6 +886,7 @@ void ERR_load_BN_strings(void);
 | |
|  #define BN_R_NOT_INITIALIZED				 107
 | |
|  #define BN_R_NO_INVERSE					 108
 | |
|  #define BN_R_NO_SOLUTION				 116
 | |
| +#define BN_R_PRIVATE_KEY_TOO_LARGE			 117
 | |
|  #define BN_R_P_IS_NOT_PRIME				 112
 | |
|  #define BN_R_TOO_MANY_ITERATIONS			 113
 | |
|  #define BN_R_TOO_MANY_TEMPORARY_VARIABLES		 109
 | |
| diff --git a/crypto/bn/bn_err.c b/crypto/bn/bn_err.c
 | |
| index cfe2eb9..f722b52 100644
 | |
| --- a/crypto/bn/bn_err.c
 | |
| +++ b/crypto/bn/bn_err.c
 | |
| @@ -87,6 +87,7 @@ static ERR_STRING_DATA BN_str_functs[]=
 | |
|  {ERR_FUNC(BN_F_BN_EXP),	"BN_exp"},
 | |
|  {ERR_FUNC(BN_F_BN_EXPAND2),	"bn_expand2"},
 | |
|  {ERR_FUNC(BN_F_BN_EXPAND_INTERNAL),	"BN_EXPAND_INTERNAL"},
 | |
| +{ERR_FUNC(BN_F_BN_GENERATE_DSA_NONCE),	"BN_generate_dsa_nonce"},
 | |
|  {ERR_FUNC(BN_F_BN_GF2M_MOD),	"BN_GF2m_mod"},
 | |
|  {ERR_FUNC(BN_F_BN_GF2M_MOD_EXP),	"BN_GF2m_mod_exp"},
 | |
|  {ERR_FUNC(BN_F_BN_GF2M_MOD_MUL),	"BN_GF2m_mod_mul"},
 | |
| @@ -129,6 +130,7 @@ static ERR_STRING_DATA BN_str_reasons[]=
 | |
|  {ERR_REASON(BN_R_NOT_INITIALIZED)        ,"not initialized"},
 | |
|  {ERR_REASON(BN_R_NO_INVERSE)             ,"no inverse"},
 | |
|  {ERR_REASON(BN_R_NO_SOLUTION)            ,"no solution"},
 | |
| +{ERR_REASON(BN_R_PRIVATE_KEY_TOO_LARGE)  ,"private key too large"},
 | |
|  {ERR_REASON(BN_R_P_IS_NOT_PRIME)         ,"p is not prime"},
 | |
|  {ERR_REASON(BN_R_TOO_MANY_ITERATIONS)    ,"too many iterations"},
 | |
|  {ERR_REASON(BN_R_TOO_MANY_TEMPORARY_VARIABLES),"too many temporary variables"},
 | |
| diff --git a/crypto/bn/bn_rand.c b/crypto/bn/bn_rand.c
 | |
| index b376c28..55676f0 100644
 | |
| --- a/crypto/bn/bn_rand.c
 | |
| +++ b/crypto/bn/bn_rand.c
 | |
| @@ -114,6 +114,7 @@
 | |
|  #include "cryptlib.h"
 | |
|  #include "bn_lcl.h"
 | |
|  #include <openssl/rand.h>
 | |
| +#include <openssl/sha.h>
 | |
|  
 | |
|  static int bnrand(int pseudorand, BIGNUM *rnd, int bits, int top, int bottom)
 | |
|  	{
 | |
| @@ -303,3 +304,72 @@ int	BN_pseudo_rand_range(BIGNUM *r, const BIGNUM *range)
 | |
|  	{
 | |
|  	return bn_rand_range(1, r, range);
 | |
|  	}
 | |
| +
 | |
| +#ifndef OPENSSL_NO_SHA512
 | |
| +/* BN_generate_dsa_nonce generates a random number 0 <= out < range. Unlike
 | |
| + * BN_rand_range, it also includes the contents of |priv| and |message| in the
 | |
| + * generation so that an RNG failure isn't fatal as long as |priv| remains
 | |
| + * secret. This is intended for use in DSA and ECDSA where an RNG weakness
 | |
| + * leads directly to private key exposure unless this function is used. */
 | |
| +int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range, const BIGNUM* priv,
 | |
| +			  const unsigned char *message, size_t message_len,
 | |
| +			  BN_CTX *ctx)
 | |
| +	{
 | |
| +	SHA512_CTX sha;
 | |
| +	/* We use 512 bits of random data per iteration to
 | |
| +	 * ensure that we have at least |range| bits of randomness. */
 | |
| +	unsigned char random_bytes[64];
 | |
| +	unsigned char digest[SHA512_DIGEST_LENGTH];
 | |
| +	unsigned done, todo;
 | |
| +	/* We generate |range|+8 bytes of random output. */
 | |
| +	const unsigned num_k_bytes = BN_num_bytes(range) + 8;
 | |
| +	unsigned char private_bytes[96];
 | |
| +	unsigned char *k_bytes;
 | |
| +	int ret = 0;
 | |
| +
 | |
| +	k_bytes = OPENSSL_malloc(num_k_bytes);
 | |
| +	if (!k_bytes)
 | |
| +		goto err;
 | |
| +
 | |
| +	/* We copy |priv| into a local buffer to avoid exposing its length. */
 | |
| +	todo = sizeof(priv->d[0])*priv->top;
 | |
| +	if (todo > sizeof(private_bytes))
 | |
| +		{
 | |
| +		/* No reasonable DSA or ECDSA key should have a private key
 | |
| +		 * this large and we don't handle this case in order to avoid
 | |
| +		 * leaking the length of the private key. */
 | |
| +		BNerr(BN_F_BN_GENERATE_DSA_NONCE, BN_R_PRIVATE_KEY_TOO_LARGE);
 | |
| +		goto err;
 | |
| +		}
 | |
| +	memcpy(private_bytes, priv->d, todo);
 | |
| +	memset(private_bytes + todo, 0, sizeof(private_bytes) - todo);
 | |
| +
 | |
| +	for (done = 0; done < num_k_bytes;) {
 | |
| +		if (RAND_bytes(random_bytes, sizeof(random_bytes)) != 1)
 | |
| +			goto err;
 | |
| +		SHA512_Init(&sha);
 | |
| +		SHA512_Update(&sha, &done, sizeof(done));
 | |
| +		SHA512_Update(&sha, private_bytes, sizeof(private_bytes));
 | |
| +		SHA512_Update(&sha, message, message_len);
 | |
| +		SHA512_Update(&sha, random_bytes, sizeof(random_bytes));
 | |
| +		SHA512_Final(digest, &sha);
 | |
| +
 | |
| +		todo = num_k_bytes - done;
 | |
| +		if (todo > SHA512_DIGEST_LENGTH)
 | |
| +			todo = SHA512_DIGEST_LENGTH;
 | |
| +		memcpy(k_bytes + done, digest, todo);
 | |
| +		done += todo;
 | |
| +	}
 | |
| +
 | |
| +	if (!BN_bin2bn(k_bytes, num_k_bytes, out))
 | |
| +		goto err;
 | |
| +	if (BN_mod(out, out, range, ctx) != 1)
 | |
| +		goto err;
 | |
| +	ret = 1;
 | |
| +
 | |
| +err:
 | |
| +	if (k_bytes)
 | |
| +		OPENSSL_free(k_bytes);
 | |
| +	return ret;
 | |
| +	}
 | |
| +#endif  /* OPENSSL_NO_SHA512 */
 | |
| diff --git a/crypto/dsa/dsa.h b/crypto/dsa/dsa.h
 | |
| index b448d2a..71ef572 100644
 | |
| --- a/crypto/dsa/dsa.h
 | |
| +++ b/crypto/dsa/dsa.h
 | |
| @@ -96,6 +96,10 @@
 | |
|                                                * faster variable sliding window method to
 | |
|                                                * be used for all exponents.
 | |
|                                                */
 | |
| +#define DSA_FLAG_NONCE_FROM_HASH	0x04 /* Causes the DSA nonce to be calculated
 | |
| +						from SHA512(private_key + H(message) +
 | |
| +						random). This strengthens DSA against a
 | |
| +						weak PRNG. */
 | |
|  
 | |
|  
 | |
|  /* If this flag is set the DSA method is FIPS compliant and can be used
 | |
| @@ -131,8 +135,9 @@ struct dsa_method
 | |
|  	{
 | |
|  	const char *name;
 | |
|  	DSA_SIG * (*dsa_do_sign)(const unsigned char *dgst, int dlen, DSA *dsa);
 | |
| -	int (*dsa_sign_setup)(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
 | |
| -								BIGNUM **rp);
 | |
| +	int (*dsa_sign_setup)(DSA *dsa, BN_CTX *ctx_in,
 | |
| +			      BIGNUM **kinvp, BIGNUM **rp,
 | |
| +			      const unsigned char *dgst, int dlen);
 | |
|  	int (*dsa_do_verify)(const unsigned char *dgst, int dgst_len,
 | |
|  			     DSA_SIG *sig, DSA *dsa);
 | |
|  	int (*dsa_mod_exp)(DSA *dsa, BIGNUM *rr, BIGNUM *a1, BIGNUM *p1,
 | |
| @@ -325,6 +330,7 @@ void ERR_load_DSA_strings(void);
 | |
|  #define DSA_R_MISSING_PARAMETERS			 101
 | |
|  #define DSA_R_MODULUS_TOO_LARGE				 103
 | |
|  #define DSA_R_NEED_NEW_SETUP_VALUES			 110
 | |
| +#define DSA_R_NONCE_CANNOT_BE_PRECOMPUTED		 112
 | |
|  #define DSA_R_NON_FIPS_DSA_METHOD			 111
 | |
|  #define DSA_R_NO_PARAMETERS_SET				 107
 | |
|  #define DSA_R_PARAMETER_ENCODING_ERROR			 105
 | |
| diff --git a/crypto/dsa/dsa_err.c b/crypto/dsa/dsa_err.c
 | |
| index 00545b7..e6171cc 100644
 | |
| --- a/crypto/dsa/dsa_err.c
 | |
| +++ b/crypto/dsa/dsa_err.c
 | |
| @@ -109,6 +109,7 @@ static ERR_STRING_DATA DSA_str_reasons[]=
 | |
|  {ERR_REASON(DSA_R_MISSING_PARAMETERS)    ,"missing parameters"},
 | |
|  {ERR_REASON(DSA_R_MODULUS_TOO_LARGE)     ,"modulus too large"},
 | |
|  {ERR_REASON(DSA_R_NEED_NEW_SETUP_VALUES) ,"need new setup values"},
 | |
| +{ERR_REASON(DSA_R_NONCE_CANNOT_BE_PRECOMPUTED),"nonce cannot be precomputed"},
 | |
|  {ERR_REASON(DSA_R_NON_FIPS_DSA_METHOD)   ,"non fips dsa method"},
 | |
|  {ERR_REASON(DSA_R_NO_PARAMETERS_SET)     ,"no parameters set"},
 | |
|  {ERR_REASON(DSA_R_PARAMETER_ENCODING_ERROR),"parameter encoding error"},
 | |
| diff --git a/crypto/dsa/dsa_ossl.c b/crypto/dsa/dsa_ossl.c
 | |
| index a865a8c..15f8da2 100644
 | |
| --- a/crypto/dsa/dsa_ossl.c
 | |
| +++ b/crypto/dsa/dsa_ossl.c
 | |
| @@ -67,7 +67,9 @@
 | |
|  #include <openssl/asn1.h>
 | |
|  
 | |
|  static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa);
 | |
| -static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp);
 | |
| +static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in,
 | |
| +			  BIGNUM **kinvp, BIGNUM **rp,
 | |
| +			  const unsigned char *dgst, int dlen);
 | |
|  static int dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig,
 | |
|  			 DSA *dsa);
 | |
|  static int dsa_init(DSA *dsa);
 | |
| @@ -167,7 +169,8 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
 | |
|  redo:
 | |
|  	if ((dsa->kinv == NULL) || (dsa->r == NULL))
 | |
|  		{
 | |
| -		if (!DSA_sign_setup(dsa,ctx,&kinv,&r)) goto err;
 | |
| +		if (!dsa->meth->dsa_sign_setup(dsa,ctx,&kinv,&r,dgst,dlen))
 | |
| +			goto err;
 | |
|  		}
 | |
|  	else
 | |
|  		{
 | |
| @@ -226,7 +229,9 @@ err:
 | |
|  	return(ret);
 | |
|  	}
 | |
|  
 | |
| -static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
 | |
| +static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in,
 | |
| +			  BIGNUM **kinvp, BIGNUM **rp,
 | |
| +			  const unsigned char *dgst, int dlen)
 | |
|  	{
 | |
|  	BN_CTX *ctx;
 | |
|  	BIGNUM k,kq,*K,*kinv=NULL,*r=NULL;
 | |
| @@ -252,8 +257,21 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
 | |
|  
 | |
|  	/* Get random k */
 | |
|  	do
 | |
| -		if (!BN_rand_range(&k, dsa->q)) goto err;
 | |
| -	while (BN_is_zero(&k));
 | |
| +		{
 | |
| +#ifndef OPENSSL_NO_SHA512
 | |
| +		if (dsa->flags & DSA_FLAG_NONCE_FROM_HASH)
 | |
| +			{
 | |
| +			/* If DSA_FLAG_NONCE_FROM_HASH is set then we calculate k from
 | |
| +			 * SHA512(private_key + H(message) + random). This protects the
 | |
| +			 * private key from a weak PRNG. */
 | |
| +			if (!BN_generate_dsa_nonce(&k, dsa->q, dsa->priv_key, dgst,
 | |
| +						   dlen, ctx))
 | |
| +				goto err;
 | |
| +			}
 | |
| +		else
 | |
| +#endif
 | |
| +			if (!BN_rand_range(&k, dsa->q)) goto err;
 | |
| +		} while (BN_is_zero(&k));
 | |
|  	if ((dsa->flags & DSA_FLAG_NO_EXP_CONSTTIME) == 0)
 | |
|  		{
 | |
|  		BN_set_flags(&k, BN_FLG_CONSTTIME);
 | |
| diff --git a/crypto/dsa/dsa_sign.c b/crypto/dsa/dsa_sign.c
 | |
| index c3cc364..8ace300 100644
 | |
| --- a/crypto/dsa/dsa_sign.c
 | |
| +++ b/crypto/dsa/dsa_sign.c
 | |
| @@ -86,7 +86,14 @@ int DSA_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp)
 | |
|  		return 0;
 | |
|  		}
 | |
|  #endif
 | |
| -	return dsa->meth->dsa_sign_setup(dsa, ctx_in, kinvp, rp);
 | |
| +	if (dsa->flags & DSA_FLAG_NONCE_FROM_HASH)
 | |
| +		{
 | |
| +		/* You cannot precompute the DSA nonce if it is required to
 | |
| +		 * depend on the message. */
 | |
| +		DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_NONCE_CANNOT_BE_PRECOMPUTED);
 | |
| +		return 0;
 | |
| +		}
 | |
| +	return dsa->meth->dsa_sign_setup(dsa, ctx_in, kinvp, rp, NULL, 0);
 | |
|  	}
 | |
|  
 | |
|  DSA_SIG *DSA_SIG_new(void)
 | |
| diff --git a/crypto/ec/ec.h b/crypto/ec/ec.h
 | |
| index dfe8710..d008a0d 100644
 | |
| --- a/crypto/ec/ec.h
 | |
| +++ b/crypto/ec/ec.h
 | |
| @@ -819,6 +819,17 @@ void *EC_KEY_insert_key_method_data(EC_KEY *key, void *data,
 | |
|  /* wrapper functions for the underlying EC_GROUP object */
 | |
|  void EC_KEY_set_asn1_flag(EC_KEY *eckey, int asn1_flag);
 | |
|  
 | |
| +/** Sets whether ECDSA operations with the given key will calculate their k
 | |
| + * value from SHA512(private_key + message + random) in order to protect
 | |
| + * against a weak PRNG.
 | |
| + * \param  on  Whether to calculate k from a hash or not
 | |
| + */
 | |
| +void EC_KEY_set_nonce_from_hash(EC_KEY *key, int on);
 | |
| +
 | |
| +/** Returns the value of nonce_from_hash
 | |
| + */
 | |
| +int EC_KEY_get_nonce_from_hash(const EC_KEY *key);
 | |
| +
 | |
|  /** Creates a table of pre-computed multiples of the generator to 
 | |
|   *  accelerate further EC_KEY operations.
 | |
|   *  \param  key  EC_KEY object
 | |
| diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c
 | |
| index 7fa2475..73dd7b9 100644
 | |
| --- a/crypto/ec/ec_key.c
 | |
| +++ b/crypto/ec/ec_key.c
 | |
| @@ -85,6 +85,7 @@ EC_KEY *EC_KEY_new(void)
 | |
|  	ret->pub_key = NULL;
 | |
|  	ret->priv_key= NULL;
 | |
|  	ret->enc_flag= 0; 
 | |
| +	ret->nonce_from_hash_flag = 0;
 | |
|  	ret->conv_form = POINT_CONVERSION_UNCOMPRESSED;
 | |
|  	ret->references= 1;
 | |
|  	ret->method_data = NULL;
 | |
| @@ -198,6 +199,7 @@ EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
 | |
|  
 | |
|  	/* copy the rest */
 | |
|  	dest->enc_flag  = src->enc_flag;
 | |
| +	dest->nonce_from_hash_flag = src->nonce_from_hash_flag;
 | |
|  	dest->conv_form = src->conv_form;
 | |
|  	dest->version   = src->version;
 | |
|  	dest->flags = src->flags;
 | |
| @@ -505,6 +507,16 @@ void EC_KEY_set_enc_flags(EC_KEY *key, unsigned int flags)
 | |
|  	key->enc_flag = flags;
 | |
|  	}
 | |
|  
 | |
| +int EC_KEY_get_nonce_from_hash(const EC_KEY *key)
 | |
| +	{
 | |
| +	return key->nonce_from_hash_flag;
 | |
| +	}
 | |
| +
 | |
| +void EC_KEY_set_nonce_from_hash(EC_KEY *key, int on)
 | |
| +	{
 | |
| +	key->nonce_from_hash_flag = on != 0;
 | |
| +	}
 | |
| +
 | |
|  point_conversion_form_t EC_KEY_get_conv_form(const EC_KEY *key)
 | |
|  	{
 | |
|  	return key->conv_form;
 | |
| diff --git a/crypto/ec/ec_lcl.h b/crypto/ec/ec_lcl.h
 | |
| index da7967d..6f714c7 100644
 | |
| --- a/crypto/ec/ec_lcl.h
 | |
| +++ b/crypto/ec/ec_lcl.h
 | |
| @@ -246,6 +246,7 @@ struct ec_key_st {
 | |
|  	BIGNUM	 *priv_key;
 | |
|  
 | |
|  	unsigned int enc_flag;
 | |
| +	char nonce_from_hash_flag;
 | |
|  	point_conversion_form_t conv_form;
 | |
|  
 | |
|  	int 	references;
 | |
| diff --git a/crypto/ecdsa/ecdsa.h b/crypto/ecdsa/ecdsa.h
 | |
| index 7fb5254..dc6a36b 100644
 | |
| --- a/crypto/ecdsa/ecdsa.h
 | |
| +++ b/crypto/ecdsa/ecdsa.h
 | |
| @@ -250,6 +250,7 @@ void ERR_load_ECDSA_strings(void);
 | |
|  #define ECDSA_R_ERR_EC_LIB				 102
 | |
|  #define ECDSA_R_MISSING_PARAMETERS			 103
 | |
|  #define ECDSA_R_NEED_NEW_SETUP_VALUES			 106
 | |
| +#define ECDSA_R_NONCE_CANNOT_BE_PRECOMPUTED		 108
 | |
|  #define ECDSA_R_NON_FIPS_METHOD				 107
 | |
|  #define ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED		 104
 | |
|  #define ECDSA_R_SIGNATURE_MALLOC_FAILED			 105
 | |
| diff --git a/crypto/ecdsa/ecs_err.c b/crypto/ecdsa/ecs_err.c
 | |
| index 81542e6..7406c6d 100644
 | |
| --- a/crypto/ecdsa/ecs_err.c
 | |
| +++ b/crypto/ecdsa/ecs_err.c
 | |
| @@ -85,6 +85,7 @@ static ERR_STRING_DATA ECDSA_str_reasons[]=
 | |
|  {ERR_REASON(ECDSA_R_ERR_EC_LIB)          ,"err ec lib"},
 | |
|  {ERR_REASON(ECDSA_R_MISSING_PARAMETERS)  ,"missing parameters"},
 | |
|  {ERR_REASON(ECDSA_R_NEED_NEW_SETUP_VALUES),"need new setup values"},
 | |
| +{ERR_REASON(ECDSA_R_NONCE_CANNOT_BE_PRECOMPUTED),"nonce cannot be precomputed"},
 | |
|  {ERR_REASON(ECDSA_R_NON_FIPS_METHOD)     ,"non fips method"},
 | |
|  {ERR_REASON(ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED),"random number generation failed"},
 | |
|  {ERR_REASON(ECDSA_R_SIGNATURE_MALLOC_FAILED),"signature malloc failed"},
 | |
| diff --git a/crypto/ecdsa/ecs_locl.h b/crypto/ecdsa/ecs_locl.h
 | |
| index cb3be13..46f7ad9 100644
 | |
| --- a/crypto/ecdsa/ecs_locl.h
 | |
| +++ b/crypto/ecdsa/ecs_locl.h
 | |
| @@ -70,8 +70,9 @@ struct ecdsa_method
 | |
|  	const char *name;
 | |
|  	ECDSA_SIG *(*ecdsa_do_sign)(const unsigned char *dgst, int dgst_len, 
 | |
|  			const BIGNUM *inv, const BIGNUM *rp, EC_KEY *eckey);
 | |
| -	int (*ecdsa_sign_setup)(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, 
 | |
| -			BIGNUM **r);
 | |
| +	int (*ecdsa_sign_setup)(EC_KEY *eckey, BN_CTX *ctx,
 | |
| +				BIGNUM **kinv, BIGNUM **r,
 | |
| +				const unsigned char *dgst, int dlen);
 | |
|  	int (*ecdsa_do_verify)(const unsigned char *dgst, int dgst_len, 
 | |
|  			const ECDSA_SIG *sig, EC_KEY *eckey);
 | |
|  #if 0
 | |
| diff --git a/crypto/ecdsa/ecs_ossl.c b/crypto/ecdsa/ecs_ossl.c
 | |
| index 7725935..325aca8 100644
 | |
| --- a/crypto/ecdsa/ecs_ossl.c
 | |
| +++ b/crypto/ecdsa/ecs_ossl.c
 | |
| @@ -60,11 +60,13 @@
 | |
|  #include <openssl/err.h>
 | |
|  #include <openssl/obj_mac.h>
 | |
|  #include <openssl/bn.h>
 | |
| +#include <openssl/rand.h>
 | |
|  
 | |
|  static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dlen, 
 | |
|  		const BIGNUM *, const BIGNUM *, EC_KEY *eckey);
 | |
| -static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, 
 | |
| -		BIGNUM **rp);
 | |
| +static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
 | |
| +			    BIGNUM **kinvp, BIGNUM **rp,
 | |
| +			    const unsigned char *dgst, int dlen);
 | |
|  static int ecdsa_do_verify(const unsigned char *dgst, int dgst_len, 
 | |
|  		const ECDSA_SIG *sig, EC_KEY *eckey);
 | |
|  
 | |
| @@ -86,8 +88,9 @@ const ECDSA_METHOD *ECDSA_OpenSSL(void)
 | |
|  	return &openssl_ecdsa_meth;
 | |
|  }
 | |
|  
 | |
| -static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
 | |
| -		BIGNUM **rp)
 | |
| +static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in,
 | |
| +			    BIGNUM **kinvp, BIGNUM **rp,
 | |
| +			    const unsigned char *dgst, int dlen)
 | |
|  {
 | |
|  	BN_CTX   *ctx = NULL;
 | |
|  	BIGNUM	 *k = NULL, *r = NULL, *order = NULL, *X = NULL;
 | |
| @@ -136,11 +139,28 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
 | |
|  	{
 | |
|  		/* get random k */	
 | |
|  		do
 | |
| -			if (!BN_rand_range(k, order))
 | |
| +#ifndef OPENSSL_NO_SHA512
 | |
| +			if (EC_KEY_get_nonce_from_hash(eckey))
 | |
|  			{
 | |
| -				ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,
 | |
| -				 ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED);	
 | |
| -				goto err;
 | |
| +				if (!BN_generate_dsa_nonce(
 | |
| +					k, order,
 | |
| +					EC_KEY_get0_private_key(eckey),
 | |
| +					dgst, dlen, ctx))
 | |
| +					{
 | |
| +					ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,
 | |
| +						 ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED);
 | |
| +					goto err;
 | |
| +					}
 | |
| +			}
 | |
| +			else
 | |
| +#endif
 | |
| +			{
 | |
| +				if (!BN_rand_range(k, order))
 | |
| +				{
 | |
| +					ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP,
 | |
| +					 ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED);
 | |
| +					goto err;
 | |
| +				}
 | |
|  			}
 | |
|  		while (BN_is_zero(k));
 | |
|  
 | |
| @@ -282,7 +302,7 @@ static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len,
 | |
|  	{
 | |
|  		if (in_kinv == NULL || in_r == NULL)
 | |
|  		{
 | |
| -			if (!ECDSA_sign_setup(eckey, ctx, &kinv, &ret->r))
 | |
| +			if (!ecdsa->meth->ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, dgst, dgst_len))
 | |
|  			{
 | |
|  				ECDSAerr(ECDSA_F_ECDSA_DO_SIGN,ERR_R_ECDSA_LIB);
 | |
|  				goto err;
 | |
| diff --git a/crypto/ecdsa/ecs_sign.c b/crypto/ecdsa/ecs_sign.c
 | |
| index 353d5af..ea79a24 100644
 | |
| --- a/crypto/ecdsa/ecs_sign.c
 | |
| +++ b/crypto/ecdsa/ecs_sign.c
 | |
| @@ -58,6 +58,7 @@
 | |
|  #include <openssl/engine.h>
 | |
|  #endif
 | |
|  #include <openssl/rand.h>
 | |
| +#include <openssl/err.h>
 | |
|  
 | |
|  ECDSA_SIG *ECDSA_do_sign(const unsigned char *dgst, int dlen, EC_KEY *eckey)
 | |
|  {
 | |
| @@ -102,5 +103,12 @@ int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
 | |
|  	ECDSA_DATA *ecdsa = ecdsa_check(eckey);
 | |
|  	if (ecdsa == NULL)
 | |
|  		return 0;
 | |
| -	return ecdsa->meth->ecdsa_sign_setup(eckey, ctx_in, kinvp, rp); 
 | |
| +	if (EC_KEY_get_nonce_from_hash(eckey))
 | |
| +		{
 | |
| +		/* You cannot precompute the ECDSA nonce if it is required to
 | |
| +		 * depend on the message. */
 | |
| +		ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ECDSA_R_NONCE_CANNOT_BE_PRECOMPUTED);
 | |
| +		return 0;
 | |
| +		}
 | |
| +	return ecdsa->meth->ecdsa_sign_setup(eckey, ctx_in, kinvp, rp, NULL, 0);
 | |
|  }
 | |
| -- 
 | |
| 1.8.5.1
 | |
| 
 |