mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-07-30 02:37:28 +02:00
Merge pull request #4861 from JacobBarthelmeh/ECC
Deterministic ECDSA: fix for larger curve sizes
This commit is contained in:
@ -6405,7 +6405,7 @@ int wc_ecc_gen_deterministic_k(const byte* hash, word32 hashSz,
|
||||
{
|
||||
int ret = 0, qbits = 0;
|
||||
#ifndef WOLFSSL_SMALL_STACK
|
||||
byte h1[WC_MAX_DIGEST_SIZE];
|
||||
byte h1[MAX_ECC_BYTES];
|
||||
byte V[WC_MAX_DIGEST_SIZE];
|
||||
byte K[WC_MAX_DIGEST_SIZE];
|
||||
byte x[MAX_ECC_BYTES];
|
||||
@ -6417,7 +6417,7 @@ int wc_ecc_gen_deterministic_k(const byte* hash, word32 hashSz,
|
||||
byte *x = NULL;
|
||||
mp_int *z1 = NULL;
|
||||
#endif
|
||||
word32 xSz, VSz, KSz, h1len;
|
||||
word32 xSz, VSz, KSz, h1len, qLen;
|
||||
byte intOct;
|
||||
|
||||
if (hash == NULL || k == NULL || order == NULL) {
|
||||
@ -6429,13 +6429,18 @@ int wc_ecc_gen_deterministic_k(const byte* hash, word32 hashSz,
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (hashSz != WC_SHA256_DIGEST_SIZE) {
|
||||
WOLFSSL_MSG("Currently only SHA256 digest is supported");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
if (mp_unsigned_bin_size(priv) > MAX_ECC_BYTES) {
|
||||
WOLFSSL_MSG("private key larger than max expected!");
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
#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) {
|
||||
ret = MEMORY_E;
|
||||
}
|
||||
@ -6478,7 +6483,8 @@ int wc_ecc_gen_deterministic_k(const byte* hash, word32 hashSz,
|
||||
}
|
||||
#endif
|
||||
|
||||
VSz = KSz = h1len = xSz = hashSz;
|
||||
VSz = KSz = hashSz;
|
||||
qLen = xSz = h1len = mp_unsigned_bin_size(order);
|
||||
|
||||
/* 3.2 b. Set V = 0x01 0x01 ... */
|
||||
XMEMSET(V, 0x01, VSz);
|
||||
@ -6487,7 +6493,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_len(priv, x, hashSz);
|
||||
ret = mp_to_unsigned_bin_len(priv, x, qLen);
|
||||
if (ret == 0) {
|
||||
qbits = mp_count_bits(order);
|
||||
ret = mp_read_unsigned_bin(z1, hash, hashSz);
|
||||
@ -6495,9 +6501,7 @@ int wc_ecc_gen_deterministic_k(const byte* hash, word32 hashSz,
|
||||
|
||||
/* bits2octets on h1 */
|
||||
if (ret == 0) {
|
||||
/* right shift by bits in hash minus bits in order */
|
||||
mp_rshb(z1, (hashSz * WOLFSSL_BIT_SIZE) - qbits);
|
||||
XMEMSET(h1, 0, WC_MAX_DIGEST_SIZE);
|
||||
XMEMSET(h1, 0, MAX_ECC_BYTES);
|
||||
|
||||
#if !defined(WOLFSSL_ECDSA_DETERMINISTIC_K_VARIANT)
|
||||
/* mod reduce by order using conditional subtract
|
||||
@ -6509,20 +6513,18 @@ int wc_ecc_gen_deterministic_k(const byte* hash, word32 hashSz,
|
||||
|
||||
mp_sub(z1, order, 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;
|
||||
}
|
||||
else {
|
||||
h1len = (word32)z1Sz;
|
||||
ret = mp_to_unsigned_bin(z1, h1);
|
||||
ret = mp_to_unsigned_bin_len(z1, h1, h1len);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* use original hash and keep leading 0's */
|
||||
h1len = hashSz;
|
||||
XMEMCPY(h1, hash, hashSz);
|
||||
mp_to_unsigned_bin_len(z1, h1, h1len);
|
||||
}
|
||||
}
|
||||
mp_free(z1);
|
||||
@ -6560,20 +6562,34 @@ int wc_ecc_gen_deterministic_k(const byte* hash, word32 hashSz,
|
||||
|
||||
intOct = 0x00;
|
||||
do {
|
||||
xSz = 0; /* used as tLen */
|
||||
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 */
|
||||
ret = _HMAC_K(K, KSz, V, VSz, NULL, 0, NULL, 0, NULL, V, hashType,
|
||||
heap);
|
||||
if (ret == 0) {
|
||||
mp_clear(k); /* 3.2 step h.1 clear T */
|
||||
ret = mp_read_unsigned_bin(k, V, VSz);
|
||||
while (xSz < qLen) {
|
||||
ret = _HMAC_K(K, KSz, V, VSz, NULL, 0, NULL, 0, NULL, V,
|
||||
hashType, heap);
|
||||
if (ret == 0) {
|
||||
int sz;
|
||||
|
||||
sz = MIN(qLen - xSz, VSz);
|
||||
XMEMCPY(x + xSz, V, sz);
|
||||
xSz += sz;
|
||||
}
|
||||
else {
|
||||
break; /* error case */
|
||||
}
|
||||
}
|
||||
|
||||
if ((ret == 0) && ((int)(VSz * WOLFSSL_BIT_SIZE) != qbits)) {
|
||||
if (ret == 0) {
|
||||
mp_clear(k); /* 3.2 step h.1 clear T */
|
||||
ret = mp_read_unsigned_bin(k, x, xSz);
|
||||
}
|
||||
|
||||
if ((ret == 0) && ((int)(xSz * WOLFSSL_BIT_SIZE) != qbits)) {
|
||||
/* handle odd case where shift of 'k' is needed with RFC 6979
|
||||
* k = bits2int(T) in section 3.2 h.3 */
|
||||
mp_rshb(k, (VSz * WOLFSSL_BIT_SIZE) - qbits);
|
||||
mp_rshb(k, (xSz * WOLFSSL_BIT_SIZE) - qbits);
|
||||
}
|
||||
|
||||
/* 3.2 step h.3 the key should be smaller than the order of base
|
||||
|
@ -20880,6 +20880,160 @@ done:
|
||||
wc_ecc_free(&key);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef WOLFSSL_PUBLIC_MP
|
||||
#if defined(HAVE_ECC384)
|
||||
/* 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:
|
||||
wc_ecc_free(&key);
|
||||
return ret;
|
||||
}
|
||||
#endif /* HAVE_ECC384 */
|
||||
|
||||
#if defined(HAVE_ECC521)
|
||||
/* KAT from RFC6979 */
|
||||
static int ecc521_test_deterministic_k(WC_RNG* rng)
|
||||
{
|
||||
int ret;
|
||||
ecc_key key;
|
||||
byte sig[ECC_MAX_SIG_SIZE];
|
||||
word32 sigSz;
|
||||
unsigned char msg[] = "sample";
|
||||
unsigned char hash[32];
|
||||
|
||||
const char* dIUT =
|
||||
"0FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75C"
|
||||
"AA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B83"
|
||||
"538";
|
||||
const char* QIUTx =
|
||||
"1894550D0785932E00EAA23B694F213F8C3121F86DC97A04E5A7167DB4E5BCD3"
|
||||
"71123D46E45DB6B5D5370A7F20FB633155D38FFA16D2BD761DCAC474B9A2F502"
|
||||
"3A4";
|
||||
const char* QIUTy =
|
||||
"0493101C962CD4D2FDDF782285E64584139C2F91B47F87FF82354D6630F746A2"
|
||||
"8A0DB25741B5B34A828008B22ACC23F924FAAFBD4D33F81EA66956DFEAA2BFDF"
|
||||
"CF5";
|
||||
const char* expRstr =
|
||||
"1511BB4D675114FE266FC4372B87682BAECC01D3CC62CF2303C92B3526012659"
|
||||
"D16876E25C7C1E57648F23B73564D67F61C6F14D527D54972810421E7D87589E"
|
||||
"1A7";
|
||||
const char* expSstr =
|
||||
"04A171143A83163D6DF460AAF61522695F207A58B95C0644D87E52AA1A347916"
|
||||
"E4F7A72930B1BC06DBE22CE3F58264AFD23704CBB63B29B931F7DE6C9D949A7E"
|
||||
"CFC";
|
||||
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, "SECP521R1");
|
||||
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:
|
||||
wc_ecc_free(&key);
|
||||
return ret;
|
||||
}
|
||||
#endif /* HAVE_ECC521 */
|
||||
#endif /* WOLFSSL_PUBLIC_MP */
|
||||
#endif
|
||||
|
||||
|
||||
@ -23944,6 +24098,22 @@ WOLFSSL_TEST_SUBROUTINE int ecc_test(void)
|
||||
printf("ecc_test_deterministic_k failed! %d\n", ret);
|
||||
goto done;
|
||||
}
|
||||
#ifdef WOLFSSL_PUBLIC_MP
|
||||
#if defined(HAVE_ECC384)
|
||||
ret = ecc384_test_deterministic_k(&rng);
|
||||
if (ret != 0) {
|
||||
printf("ecc384_test_deterministic_k failed! %d\n", ret);
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
#if defined(HAVE_ECC521)
|
||||
ret = ecc521_test_deterministic_k(&rng);
|
||||
if (ret != 0) {
|
||||
printf("ecc512_test_deterministic_k failed! %d\n", ret);
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_ECC_SIGN) && defined(WOLFSSL_ECDSA_SET_K)
|
||||
|
Reference in New Issue
Block a user