fix for larger curve sizes with deterministic ECC sign

This commit is contained in:
Jacob Barthelmeh
2022-02-14 09:55:38 -07:00
parent 2fa542eb28
commit f0a0cd1078
2 changed files with 107 additions and 15 deletions

View File

@@ -6287,7 +6287,7 @@ int wc_ecc_gen_deterministic_k(const byte* hash, word32 hashSz,
{ {
int ret = 0, qbits = 0; int ret = 0, qbits = 0;
#ifndef WOLFSSL_SMALL_STACK #ifndef WOLFSSL_SMALL_STACK
byte h1[WC_MAX_DIGEST_SIZE]; byte h1[MAX_ECC_BYTES];
byte V[WC_MAX_DIGEST_SIZE]; byte V[WC_MAX_DIGEST_SIZE];
byte K[WC_MAX_DIGEST_SIZE]; byte K[WC_MAX_DIGEST_SIZE];
byte x[MAX_ECC_BYTES]; byte x[MAX_ECC_BYTES];
@@ -6317,7 +6317,7 @@ int wc_ecc_gen_deterministic_k(const byte* hash, word32 hashSz,
} }
#ifdef WOLFSSL_SMALL_STACK #ifdef WOLFSSL_SMALL_STACK
h1 = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, heap, DYNAMIC_TYPE_DIGEST); h1 = (byte*)XMALLOC(MAX_ECC_BYTES, heap, DYNAMIC_TYPE_DIGEST);
if (h1 == NULL) { if (h1 == NULL) {
ret = MEMORY_E; ret = MEMORY_E;
} }
@@ -6360,7 +6360,8 @@ int wc_ecc_gen_deterministic_k(const byte* hash, word32 hashSz,
} }
#endif #endif
VSz = KSz = h1len = xSz = hashSz; VSz = KSz = hashSz;
xSz = h1len = mp_unsigned_bin_size(order);
/* 3.2 b. Set V = 0x01 0x01 ... */ /* 3.2 b. Set V = 0x01 0x01 ... */
XMEMSET(V, 0x01, VSz); XMEMSET(V, 0x01, VSz);
@@ -6369,7 +6370,7 @@ int wc_ecc_gen_deterministic_k(const byte* hash, word32 hashSz,
XMEMSET(K, 0x00, KSz); XMEMSET(K, 0x00, KSz);
mp_init(z1); /* always init z1 and free z1 */ mp_init(z1); /* always init z1 and free z1 */
ret = mp_to_unsigned_bin_len(priv, x, hashSz); ret = mp_to_unsigned_bin_len(priv, x, xSz);
if (ret == 0) { if (ret == 0) {
qbits = mp_count_bits(order); qbits = mp_count_bits(order);
ret = mp_read_unsigned_bin(z1, hash, hashSz); ret = mp_read_unsigned_bin(z1, hash, hashSz);
@@ -6377,9 +6378,7 @@ int wc_ecc_gen_deterministic_k(const byte* hash, word32 hashSz,
/* bits2octets on h1 */ /* bits2octets on h1 */
if (ret == 0) { if (ret == 0) {
/* right shift by bits in hash minus bits in order */ XMEMSET(h1, 0, MAX_ECC_BYTES);
mp_rshb(z1, (hashSz * WOLFSSL_BIT_SIZE) - qbits);
XMEMSET(h1, 0, WC_MAX_DIGEST_SIZE);
#if !defined(WOLFSSL_ECDSA_DETERMINISTIC_K_VARIANT) #if !defined(WOLFSSL_ECDSA_DETERMINISTIC_K_VARIANT)
/* mod reduce by order using conditional subtract /* mod reduce by order using conditional subtract
@@ -6391,20 +6390,18 @@ int wc_ecc_gen_deterministic_k(const byte* hash, word32 hashSz,
mp_sub(z1, order, z1); mp_sub(z1, order, z1);
z1Sz = mp_unsigned_bin_size(z1); z1Sz = mp_unsigned_bin_size(z1);
if (z1Sz < 0 || z1Sz > WC_MAX_DIGEST_SIZE) { if (z1Sz < 0 || z1Sz > MAX_ECC_BYTES) {
ret = BUFFER_E; ret = BUFFER_E;
} }
else { else {
h1len = (word32)z1Sz; ret = mp_to_unsigned_bin_len(z1, h1, h1len);
ret = mp_to_unsigned_bin(z1, h1);
} }
} }
else else
#endif #endif
{ {
/* use original hash and keep leading 0's */ /* use original hash and keep leading 0's */
h1len = hashSz; mp_to_unsigned_bin_len(z1, h1, h1len);
XMEMCPY(h1, hash, hashSz);
} }
} }
mp_free(z1); mp_free(z1);
@@ -6438,18 +6435,37 @@ int wc_ecc_gen_deterministic_k(const byte* hash, word32 hashSz,
/* 3.2 step h. loop through the next steps until a valid value is found */ /* 3.2 step h. loop through the next steps until a valid value is found */
if (ret == 0 ) { if (ret == 0 ) {
word32 qLen = (qbits+7)/8;
int err; int err;
intOct = 0x00; intOct = 0x00;
do { do {
xSz = 0; /* used as tLen */
err = 0; /* start as good until generated k is tested */ err = 0; /* start as good until generated k is tested */
/* 3.2 step h.2 when tlen < qlen do V = HMAC_K(V); T = T || V */ /* 3.2 step h.2 when tlen < qlen do V = HMAC_K(V); T = T || V */
ret = _HMAC_K(K, KSz, V, VSz, NULL, 0, NULL, 0, NULL, V, hashType, while (xSz < qLen) {
heap); ret = _HMAC_K(K, KSz, V, VSz, NULL, 0, NULL, 0, NULL, V,
hashType, heap);
if (ret == 0) {
int sz;
sz = (qLen - xSz < VSz) ? qLen-xSz : VSz;
if (xSz + sz > qLen) {
ret = BUFFER_E;
break;
}
XMEMCPY(x + xSz, V, sz);
xSz += sz;
}
else {
break; /* error case */
}
}
if (ret == 0) { if (ret == 0) {
mp_clear(k); /* 3.2 step h.1 clear T */ mp_clear(k); /* 3.2 step h.1 clear T */
ret = mp_read_unsigned_bin(k, V, VSz); ret = mp_read_unsigned_bin(k, x, xSz);
} }
if ((ret == 0) && ((int)(VSz * WOLFSSL_BIT_SIZE) != qbits)) { if ((ret == 0) && ((int)(VSz * WOLFSSL_BIT_SIZE) != qbits)) {

View File

@@ -20869,6 +20869,77 @@ static int ecc_test_deterministic_k(WC_RNG* rng)
} }
TEST_SLEEP(); TEST_SLEEP();
done:
wc_ecc_free(&key);
return ret;
}
/* KAT from RFC6979 */
static int ecc384_test_deterministic_k(WC_RNG* rng)
{
int ret;
ecc_key key;
byte sig[72];
word32 sigSz;
unsigned char msg[] = "sample";
unsigned char hash[32];
const char* dIUT =
"6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D8"
"96D5724E4C70A825F872C9EA60D2EDF5";
const char* QIUTx =
"EC3A4E415B4E19A4568618029F427FA5DA9A8BC4AE92E02E06AAE5286B300C64"
"DEF8F0EA9055866064A254515480BC13";
const char* QIUTy =
"8015D9B72D7D57244EA8EF9AC0C621896708A59367F9DFB9F54CA84B3F1C9DB1"
"288B231C3AE0D4FE7344FD2533264720";
const char* expRstr =
"21B13D1E013C7FA1392D03C5F99AF8B30C570C6F98D4EA8E354B63A21D3DAA33"
"BDE1E888E63355D92FA2B3C36D8FB2CD";
const char* expSstr =
"F3AA443FB107745BF4BD77CB3891674632068A10CA67E3D45DB2266FA7D1FEEB"
"EFDC63ECCD1AC42EC0CB8668A4FA0AB0";
mp_int r,s, expR, expS;
mp_init_multi(&r, &s, &expR, &expS, NULL, NULL);
ret = wc_ecc_init_ex(&key, HEAP_HINT, devId);
if (ret != 0) {
return ret;
}
ret = wc_ecc_import_raw(&key, QIUTx, QIUTy, dIUT, "SECP384R1");
if (ret != 0) {
goto done;
}
ret = wc_Hash(WC_HASH_TYPE_SHA256, msg,
(word32)XSTRLEN((const char*)msg), hash, sizeof(hash));
if (ret != 0) {
goto done;
}
ret = wc_ecc_set_deterministic(&key, 1);
if (ret != 0) {
goto done;
}
sigSz = sizeof(sig);
do {
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &key.asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);
#endif
if (ret == 0)
ret = wc_ecc_sign_hash_ex(hash, sizeof(hash), rng, &key, &r, &s);
} while (ret == WC_PENDING_E);
if (ret != 0) {
goto done;
}
TEST_SLEEP();
mp_read_radix(&expR, expRstr, MP_RADIX_HEX);
mp_read_radix(&expS, expSstr, MP_RADIX_HEX);
if (mp_cmp(&r, &expR) != MP_EQ) {
ret = -1;
}
done: done:
wc_ecc_free(&key); wc_ecc_free(&key);
return ret; return ret;
@@ -23812,6 +23883,11 @@ WOLFSSL_TEST_SUBROUTINE int ecc_test(void)
printf("ecc_test_deterministic_k failed! %d\n", ret); printf("ecc_test_deterministic_k failed! %d\n", ret);
goto done; goto done;
} }
ret = ecc384_test_deterministic_k(&rng);
if (ret != 0) {
printf("ecc384_test_deterministic_k failed! %d\n", ret);
goto done;
}
#endif #endif
#if defined(HAVE_ECC_SIGN) && defined(WOLFSSL_ECDSA_SET_K) #if defined(HAVE_ECC_SIGN) && defined(WOLFSSL_ECDSA_SET_K)