summaryrefslogtreecommitdiffstats
path: root/crypto/ec
diff options
context:
space:
mode:
authorslontis <shane.lontis@oracle.com>2022-07-15 21:22:01 +1000
committerHugo Landau <hlandau@openssl.org>2022-11-30 07:31:53 +0000
commitf3090fc710e30a749acaf9e5dfbe20dd163cf15d (patch)
tree720d4b3cada6e81a69a2b2b68f6e8cf592c3e003 /crypto/ec
parent9ba4f489ecd30901603d66a8ec578cbca08fac06 (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.c73
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;
}