| 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 |
| |