diff options
author | slontis <shane.lontis@oracle.com> | 2022-07-15 21:22:01 +1000 |
---|---|---|
committer | Hugo Landau <hlandau@openssl.org> | 2022-11-30 07:31:53 +0000 |
commit | f3090fc710e30a749acaf9e5dfbe20dd163cf15d (patch) | |
tree | 720d4b3cada6e81a69a2b2b68f6e8cf592c3e003 /crypto/ec | |
parent | 9ba4f489ecd30901603d66a8ec578cbca08fac06 (diff) |
Implement deterministic ECDSA sign (RFC6979)
This PR is based off the contributions in PR #9223 by Jemmy1228.
It has been modified and reworked to:
(1) Work with providers
(2) Support ECDSA and DSA
(3) Add a KDF HMAC_DRBG implementation that shares code with the RAND HMAC_DRBG.
A nonce_type is passed around inside the Signing API's, in order to support any
future deterministic algorithms.
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Hugo Landau <hlandau@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/18809)
Diffstat (limited to 'crypto/ec')
-rw-r--r-- | crypto/ec/ecdsa_ossl.c | 73 |
1 files changed, 61 insertions, 12 deletions
diff --git a/crypto/ec/ecdsa_ossl.c b/crypto/ec/ecdsa_ossl.c index 96dab38adf..30e130dbba 100644 --- a/crypto/ec/ecdsa_ossl.c +++ b/crypto/ec/ecdsa_ossl.c @@ -19,6 +19,13 @@ #include <openssl/rand.h> #include "crypto/bn.h" #include "ec_local.h" +#include "internal/deterministic_nonce.h" + +static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, + BIGNUM **kinvp, BIGNUM **rp, + const unsigned char *dgst, int dlen, + unsigned int nonce_type, const char *digestname, + OSSL_LIB_CTX *libctx, const char *propq); int ossl_ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) @@ -71,9 +78,39 @@ int ossl_ecdsa_sign(int type, const unsigned char *dgst, int dlen, return 1; } +int ossl_ecdsa_deterministic_sign(const unsigned char *dgst, int dlen, + unsigned char *sig, unsigned int *siglen, + EC_KEY *eckey, unsigned int nonce_type, + const char *digestname, + OSSL_LIB_CTX *libctx, const char *propq) +{ + ECDSA_SIG *s; + BIGNUM *kinv = NULL, *r = NULL; + int ret = 0; + + *siglen = 0; + if (!ecdsa_sign_setup(eckey, NULL, &kinv, &r, dgst, dlen, + nonce_type, digestname, libctx, propq)) + return 0; + + s = ECDSA_do_sign_ex(dgst, dlen, kinv, r, eckey); + if (s == NULL) + goto end; + + *siglen = i2d_ECDSA_SIG(s, &sig); + ECDSA_SIG_free(s); + ret = 1; +end: + BN_clear_free(kinv); + BN_clear_free(r); + return ret; +} + static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp, - const unsigned char *dgst, int dlen) + const unsigned char *dgst, int dlen, + unsigned int nonce_type, const char *digestname, + OSSL_LIB_CTX *libctx, const char *propq) { BN_CTX *ctx = NULL; BIGNUM *k = NULL, *r = NULL, *X = NULL; @@ -126,19 +163,29 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, goto err; do { - /* get random k */ + /* get random or determinstic value of k */ do { + int res = 0; + if (dgst != NULL) { - if (!BN_generate_dsa_nonce(k, order, priv_key, - dgst, dlen, ctx)) { - ERR_raise(ERR_LIB_EC, EC_R_RANDOM_NUMBER_GENERATION_FAILED); - goto err; + if (nonce_type == 1) { +#ifndef FIPS_MODULE + res = ossl_gen_deterministic_nonce_rfc6979(k, order, + priv_key, + dgst, dlen, + digestname, + libctx, propq); +#endif + } else { + res = BN_generate_dsa_nonce(k, order, priv_key, dgst, dlen, + ctx); } } else { - if (!BN_priv_rand_range_ex(k, order, 0, ctx)) { - ERR_raise(ERR_LIB_EC, EC_R_RANDOM_NUMBER_GENERATION_FAILED); - goto err; - } + res = BN_priv_rand_range_ex(k, order, 0, ctx); + } + if (!res) { + ERR_raise(ERR_LIB_EC, EC_R_RANDOM_NUMBER_GENERATION_FAILED); + goto err; } } while (BN_is_zero(k)); @@ -187,7 +234,8 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, int ossl_ecdsa_simple_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) { - return ecdsa_sign_setup(eckey, ctx_in, kinvp, rp, NULL, 0); + return ecdsa_sign_setup(eckey, ctx_in, kinvp, rp, NULL, 0, + 0, NULL, NULL, NULL); } ECDSA_SIG *ossl_ecdsa_simple_sign_sig(const unsigned char *dgst, int dgst_len, @@ -256,7 +304,8 @@ ECDSA_SIG *ossl_ecdsa_simple_sign_sig(const unsigned char *dgst, int dgst_len, } do { if (in_kinv == NULL || in_r == NULL) { - if (!ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, dgst, dgst_len)) { + if (!ecdsa_sign_setup(eckey, ctx, &kinv, &ret->r, dgst, dgst_len, + 0, NULL, NULL, NULL)) { ERR_raise(ERR_LIB_EC, ERR_R_ECDSA_LIB); goto err; } |