deterministic ECC sign edge case fix and add variant

This commit is contained in:
Jacob Barthelmeh
2021-12-08 09:54:47 -07:00
parent 8609d98122
commit dfce101b5b
2 changed files with 47 additions and 16 deletions

View File

@ -70,6 +70,18 @@ Possible ECC enable options:
* signing. If the value is invalid then an error is
* returned rather than generating a new 'k'. (For testing)
* default: off
* WOLFSSL_ECDSA_DETERMINISTIC_K: Enables RFC6979 implementation of
* deterministic ECC signatures. The following function
* can be used to set the deterministic signing flag in the
* ecc key structure.
* int wc_ecc_set_deterministic(ecc_key* key, byte flag)
* default: off
*
* WOLFSSL_ECDSA_DETERMINISTIC_K_VARIANT: RFC6979 lists a variant that uses the
* hash directly instead of doing bits2octets(H(m)), when
* the variant macro is used the bits2octets operation on
* the hash is removed.
* default: off
*/
/*
@ -5479,7 +5491,8 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen,
}
#endif /* !NO_ASN */
#if defined(WOLFSSL_ECDSA_DETERMINISTIC_K)
#if defined(WOLFSSL_ECDSA_DETERMINISTIC_K) || \
defined(WOLFSSL_ECDSA_DETERMINISTIC_K_VARIANT)
/* returns MP_OKAY on success */
static int deterministic_sign_helper(const byte* in, word32 inlen, ecc_key* key)
{
@ -5522,7 +5535,8 @@ static int deterministic_sign_helper(const byte* in, word32 inlen, ecc_key* key)
FREE_CURVE_SPECS();
return err;
}
#endif /* WOLFSSL_ECDSA_DETERMINISTIC_K */
#endif /* WOLFSSL_ECDSA_DETERMINISTIC_K ||
WOLFSSL_ECDSA_DETERMINISTIC_K_VARIANT */
#if defined(WOLFSSL_STM32_PKA)
int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng,
@ -5582,7 +5596,8 @@ static int ecc_sign_hash_sw(ecc_key* key, ecc_key* pubkey, WC_RNG* rng,
break;
}
#if defined(WOLFSSL_ECDSA_SET_K) || defined(WOLFSSL_ECDSA_SET_K_ONE_LOOP) || \
defined(WOLFSSL_ECDSA_DETERMINISTIC_K)
defined(WOLFSSL_ECDSA_DETERMINISTIC_K) || \
defined(WOLFSSL_ECDSA_DETERMINISTIC_K_VARIANT)
if (key->sign_k != NULL) {
if (loop_check > 1) {
err = RNG_FAILURE_E;
@ -5601,7 +5616,8 @@ static int ecc_sign_hash_sw(ecc_key* key, ecc_key* pubkey, WC_RNG* rng,
#ifdef WOLFSSL_ECDSA_SET_K_ONE_LOOP
loop_check = 64;
#endif
#ifdef WOLFSSL_ECDSA_DETERMINISTIC_K
#if defined(WOLFSSL_ECDSA_DETERMINISTIC_K) || \
defined(WOLFSSL_ECDSA_DETERMINISTIC_K_VARIANT)
if (key->deterministic == 1) {
/* sign_k generated earlier in function for SP calls.
* Only go through the loop once and fail if error */
@ -5708,6 +5724,7 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng,
#if defined(WOLFSSL_ECDSA_SET_K) || defined(WOLFSSL_ECDSA_SET_K_ONE_LOOP) || \
defined(WOLFSSL_ECDSA_DETERMINISTIC_K) || \
defined(WOLFSSL_ECDSA_DETERMINISTIC_K_VARIANT) || \
(defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \
(defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA)))
DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT);
@ -5738,7 +5755,8 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng,
}
#endif
#if defined(WOLFSSL_ECDSA_DETERMINISTIC_K)
#if defined(WOLFSSL_ECDSA_DETERMINISTIC_K) || \
defined(WOLFSSL_ECDSA_DETERMINISTIC_K_VARIANT)
/* generate deterministic 'k' value to be used either with SP or normal */
if (key->deterministic == 1) {
if (deterministic_sign_helper(in, inlen, key)) {
@ -5755,7 +5773,8 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng,
#endif
) {
#if defined(WOLFSSL_ECDSA_SET_K) || defined(WOLFSSL_ECDSA_SET_K_ONE_LOOP) \
|| defined(WOLFSSL_ECDSA_DETERMINISTIC_K)
|| defined(WOLFSSL_ECDSA_DETERMINISTIC_K) || \
defined(WOLFSSL_ECDSA_DETERMINISTIC_K_VARIANT)
mp_int* sign_k = key->sign_k;
#else
mp_int* sign_k = NULL;
@ -5869,7 +5888,8 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng,
/* load curve info */
#if defined(WOLFSSL_ECDSA_SET_K) || defined(WOLFSSL_ECDSA_SET_K_ONE_LOOP) || \
defined(WOLFSSL_ECDSA_DETERMINISTIC_K)
defined(WOLFSSL_ECDSA_DETERMINISTIC_K) || \
defined(WOLFSSL_ECDSA_DETERMINISTIC_K_VARIANT)
ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT, err);
if (err == MP_OKAY)
err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL);
@ -6017,13 +6037,15 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng,
return err;
}
#if defined(WOLFSSL_ECDSA_DETERMINISTIC_K)
#if defined(WOLFSSL_ECDSA_DETERMINISTIC_K) || \
defined(WOLFSSL_ECDSA_DETERMINISTIC_K_VARIANT)
/* helper function to do HMAC operations
* returns 0 on success and updates "out" buffer
*/
static int _HMAC_K(byte* K, word32 KSz, byte* V, word32 VSz,
const byte* h1, word32 h1Sz, byte* x, word32 xSz, byte* oct,
byte* out, enum wc_HashType hashType, void* heap) {
byte* out, enum wc_HashType hashType, void* heap)
{
Hmac hmac;
int ret, init;
@ -6135,7 +6157,7 @@ int wc_ecc_gen_deterministic_k(const byte* hash, word32 hashSz,
}
#endif
VSz = KSz = h1len = hashSz;
VSz = KSz = h1len = xSz = hashSz;
/* 3.2 b. Set V = 0x01 0x01 ... */
XMEMSET(V, 0x01, VSz);
@ -6144,7 +6166,7 @@ int wc_ecc_gen_deterministic_k(const byte* hash, word32 hashSz,
XMEMSET(K, 0x00, KSz);
mp_init(&z1); /* always init z1 and free z1 */
ret = mp_to_unsigned_bin(priv, x);
ret = mp_to_unsigned_bin_len(priv, x, hashSz);
if (ret == 0) {
qbits = mp_count_bits(order);
ret = mp_read_unsigned_bin(&z1, hash, hashSz);
@ -6156,7 +6178,11 @@ int wc_ecc_gen_deterministic_k(const byte* hash, word32 hashSz,
mp_rshb(&z1, (hashSz * WOLFSSL_BIT_SIZE) - qbits);
XMEMSET(h1, 0, WC_MAX_DIGEST_SIZE);
/* mod reduce by order using conditional subtract */
#if !defined(WOLFSSL_ECDSA_DETERMINISTIC_K_VARIANT)
/* mod reduce by order using conditional subtract
* RFC6979 lists a variant that uses the hash directly instead of
* doing bits2octets(H(m)), when variant macro is used avoid this
* bits2octets operation */
if (mp_cmp(&z1, order) == MP_GT) {
mp_sub(&z1, order, &z1);
h1len = mp_unsigned_bin_size(&z1);
@ -6167,7 +6193,9 @@ int wc_ecc_gen_deterministic_k(const byte* hash, word32 hashSz,
ret = mp_to_unsigned_bin(&z1, h1);
}
}
else {
else
#endif
{
/* use original hash and keep leading 0's */
h1len = hashSz;
XMEMCPY(h1, hash, hashSz);

View File

@ -489,10 +489,12 @@ struct ecc_key {
#endif
#if defined(WOLFSSL_ECDSA_SET_K) || defined(WOLFSSL_ECDSA_SET_K_ONE_LOOP) || \
defined(WOLFSSL_ECDSA_DETERMINISTIC_K)
defined(WOLFSSL_ECDSA_DETERMINISTIC_K) || \
defined(WOLFSSL_ECDSA_DETERMINISTIC_K_VARIANT)
mp_int *sign_k;
#endif
#if defined(WOLFSSL_ECDSA_DETERMINISTIC_K)
#if defined(WOLFSSL_ECDSA_DETERMINISTIC_K) || \
defined(WOLFSSL_ECDSA_DETERMINISTIC_K_VARIANT)
byte deterministic:1;
#endif
@ -598,7 +600,8 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen,
WOLFSSL_API
int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng,
ecc_key* key, mp_int *r, mp_int *s);
#ifdef WOLFSSL_ECDSA_DETERMINISTIC_K
#if defined(WOLFSSL_ECDSA_DETERMINISTIC_K) || \
defined(WOLFSSL_ECDSA_DETERMINISTIC_K_VARIANT)
WOLFSSL_API
int wc_ecc_set_deterministic(ecc_key* key, byte flag);
WOLFSSL_API