Merge pull request #2581 from SparkiDev/ecc_fixes_add

Add deterministic ECDSA sig gen. Fix corner cases for add point.
pull/2611/head
toddouska 2019-11-20 09:12:28 -08:00 committed by GitHub
commit 1ba366920c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 615 additions and 89 deletions

View File

@ -2640,8 +2640,8 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R,
/* now find (8+k)G for k=1..7 */
if (err == MP_OKAY)
for (j = 9; j < 16; j++) {
err = ecc_projective_add_point(M[j-9], tG, M[j-M_POINTS], a,
modulus, mp);
err = ecc_projective_add_point(M[j-9], tG, M[j-M_POINTS], a, modulus,
mp);
if (err != MP_OKAY) break;
}
@ -2709,7 +2709,7 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R,
/* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */
err = ecc_projective_add_point(R, M[bitbuf-M_POINTS], R, a,
modulus, mp);
modulus, mp);
}
if (err != MP_OKAY) break;
/* empty window and reset */
@ -2745,8 +2745,7 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R,
first = 0;
} else {
/* then add */
err = ecc_projective_add_point(R, tG, R, a, modulus,
mp);
err = ecc_projective_add_point(R, tG, R, a, modulus, mp);
if (err != MP_OKAY) break;
}
}
@ -4353,13 +4352,16 @@ int wc_ecc_init_ex(ecc_key* key, void* heap, int devId)
alt_fp_init(key->pubkey.y);
alt_fp_init(key->pubkey.z);
ret = mp_init(&key->k);
#else
ret = mp_init_multi(&key->k, key->pubkey.x, key->pubkey.y, key->pubkey.z,
NULL, NULL);
#endif /* ALT_ECC_SIZE */
if (ret != MP_OKAY) {
return MEMORY_E;
}
#else
ret = mp_init_multi(&key->k, key->pubkey.x, key->pubkey.y, key->pubkey.z,
NULL, NULL);
if (ret != MP_OKAY) {
return MEMORY_E;
}
#endif /* ALT_ECC_SIZE */
#endif /* WOLFSSL_ATECC508A */
#ifdef WOLFSSL_HEAP_TEST
@ -4714,7 +4716,13 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen,
}
#endif /* !NO_ASN */
#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL)
#if defined(WOLFSSL_STM32_PKA)
int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng,
ecc_key* key, mp_int *r, mp_int *s)
{
return stm32_ecc_sign_hash_ex(in, inlen, rng, key, r, s);
}
#elif !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL)
/**
Sign a message digest
in The message digest to sign
@ -4726,11 +4734,6 @@ int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen,
*/
int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng,
ecc_key* key, mp_int *r, mp_int *s)
#if defined(WOLFSSL_STM32_PKA)
{
return stm32_ecc_sign_hash_ex(in, inlen, rng, key, r, s);
}
#else
{
int err = 0;
#ifndef WOLFSSL_SP_MATH
@ -4739,11 +4742,16 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng,
!defined(WOLFSSL_SMALL_STACK)
mp_int e_lcl;
#endif
#ifndef WOLFSSL_ECDSA_SET_K
DECLARE_CURVE_SPECS(curve, 1);
#else
DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT);
#endif
#endif /* !WOLFSSL_SP_MATH */
if (in == NULL || r == NULL || s == NULL || key == NULL || rng == NULL)
if (in == NULL || r == NULL || s == NULL || key == NULL || rng == NULL) {
return ECC_BAD_ARG_E;
}
/* is this a private key? */
if (key->type != ECC_PRIVATEKEY && key->type != ECC_PRIVATEKEY_ONLY) {
@ -4756,20 +4764,33 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng,
}
#ifdef WOLFSSL_SP_MATH
if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1)
return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, key->heap);
else
if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) {
#ifndef WOLFSSL_ECDSA_SET_K
return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, NULL, key->heap);
#else
return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, key->sign_k,
key->heap);
#endif
}
else {
return WC_KEY_SIZE_E;
}
#else
#ifdef WOLFSSL_HAVE_SP_ECC
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
if (key->asyncDev.marker != WOLFSSL_ASYNC_MARKER_ECC)
#endif
{
#ifndef WOLFSSL_SP_NO_256
#ifndef WOLFSSL_SP_NO_256
if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1)
return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, key->heap);
#endif
#ifndef WOLFSSL_ECDSA_SET_K
return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, NULL,
key->heap);
#else
return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, key->sign_k,
key->heap);
#endif
#endif
}
#endif /* WOLFSSL_HAVE_SP_ECC */
@ -4820,7 +4841,11 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng,
}
/* load curve info */
#ifndef WOLFSSL_ECDSA_SET_K
err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ORDER);
#else
err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL);
#endif
/* load digest into e */
if (err == MP_OKAY) {
@ -4974,8 +4999,28 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng,
err = RNG_FAILURE_E;
break;
}
err = wc_ecc_make_key_ex(rng, key->dp->size, pubkey,
#ifdef WOLFSSL_ECDSA_SET_K
if (key->sign_k != NULL) {
if (loop_check > 1) {
err = RNG_FAILURE_E;
break;
}
err = mp_copy(key->sign_k, &pubkey->k);
if (err != MP_OKAY) break;
mp_forcezero(key->sign_k);
mp_free(key->sign_k);
XFREE(key->sign_k, key->heap, DYNAMIC_TYPE_ECC);
key->sign_k = NULL;
err = wc_ecc_make_pub_ex(pubkey, curve, NULL);
}
else
#endif
{
err = wc_ecc_make_key_ex(rng, key->dp->size, pubkey,
key->dp->id);
}
if (err != MP_OKAY) break;
/* find r = x1 mod n */
@ -5054,8 +5099,35 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng,
return err;
}
#endif /* WOLFSSL_STM32_PKA */
#ifdef WOLFSSL_ECDSA_SET_K
int wc_ecc_sign_set_k(const byte* k, word32 klen, ecc_key* key)
{
int ret = 0;
if (k == NULL || klen <= 0 || key == NULL) {
ret = BAD_FUNC_ARG;
}
if (ret == 0) {
if (key->sign_k == NULL) {
key->sign_k = (mp_int*)XMALLOC(sizeof(mp_int), key->heap,
DYNAMIC_TYPE_ECC);
if (key->sign_k == NULL) {
ret = MEMORY_E;
}
}
}
if (ret == 0) {
ret = mp_read_unsigned_bin(key->sign_k, k, klen);
}
return ret;
}
#endif /* WOLFSSL_ECDSA_SET_K */
#endif /* WOLFSSL_ATECC508A && WOLFSSL_CRYPTOCELL*/
#endif /* HAVE_ECC_SIGN */
#ifdef WOLFSSL_CUSTOM_CURVES
@ -5091,6 +5163,14 @@ int wc_ecc_free(ecc_key* key)
return 0;
}
#ifdef WOLFSSL_ECDSA_SET_K
if (key->sign_k != NULL) {
mp_forcezero(key->sign_k);
mp_free(key->sign_k);
XFREE(key->sign_k, key->heap, DYNAMIC_TYPE_ECC);
}
#endif
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC)
#ifdef WC_ASYNC_ENABLE_ECC
wolfAsync_DevCtxFree(&key->asyncDev, WOLFSSL_ASYNC_MARKER_ECC);
@ -5291,10 +5371,12 @@ int ecc_mul2add(ecc_point* A, mp_int* kA,
/* done with mu */
mp_clear(mu);
#ifdef WOLFSSL_SMALL_STACK
XFREE(mu, heap, DYNAMIC_TYPE_ECC);
#endif
}
#ifdef WOLFSSL_SMALL_STACK
if (mu != NULL) {
XFREE(mu, heap, DYNAMIC_TYPE_ECC);
}
#endif
}
if (err == MP_OKAY)
@ -5383,8 +5465,30 @@ int ecc_mul2add(ecc_point* A, mp_int* kA,
if (err == MP_OKAY)
err = ecc_projective_add_point(C, precomp[nA + (nB<<2)], C,
a, modulus, mp);
else
if (err != MP_OKAY)
break;
if (mp_iszero(C->z)) {
/* When all zero then should have done an add */
if (mp_iszero(C->x) && mp_iszero(C->y)) {
err = ecc_projective_dbl_point(precomp[nA + (nB<<2)], C,
a, modulus, mp);
if (err != MP_OKAY)
break;
}
/* When only Z zero then result is infinity */
else {
err = mp_set(C->x, 0);
if (err != MP_OKAY)
break;
err = mp_set(C->y, 0);
if (err != MP_OKAY)
break;
err = mp_set(C->z, 1);
if (err != MP_OKAY)
break;
first = 1;
}
}
}
}
}
@ -5897,38 +6001,62 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash,
err = wc_ecc_point_add(mG, mQ, mG, curve->prime);
#else
#ifndef ECC_SHAMIR
if (err == MP_OKAY)
{
mp_digit mp = 0;
/* compute u1*mG + u2*mQ = mG */
if (err == MP_OKAY) {
if (!mp_iszero(u1)) {
/* compute u1*mG + u2*mQ = mG */
err = wc_ecc_mulmod_ex(u1, mG, mG, curve->Af, curve->prime, 0,
key->heap);
}
if (err == MP_OKAY) {
err = wc_ecc_mulmod_ex(u2, mQ, mQ, curve->Af, curve->prime, 0,
if (err == MP_OKAY) {
err = wc_ecc_mulmod_ex(u2, mQ, mQ, curve->Af, curve->prime, 0,
key->heap);
}
/* find the montgomery mp */
if (err == MP_OKAY)
err = mp_montgomery_setup(curve->prime, &mp);
/* add them */
if (err == MP_OKAY)
err = ecc_projective_add_point(mQ, mG, mG, curve->Af,
curve->prime, mp);
if (err == MP_OKAY && mp_iszero(mG->z)) {
/* When all zero then should have done an add */
if (mp_iszero(mG->x) && mp_iszero(mG->y)) {
err = ecc_projective_dbl_point(mQ, mG, curve->Af,
curve->prime, mp);
}
/* When only Z zero then result is infinity */
else {
err = mp_set(mG->x, 0);
if (err == MP_OKAY)
err = mp_set(mG->y, 0);
if (err == MP_OKAY)
err = mp_set(mG->z, 1);
}
}
}
else {
/* compute 0*mG + u2*mQ = mG */
err = wc_ecc_mulmod_ex(u2, mQ, mG, curve->Af, curve->prime, 0,
key->heap);
/* find the montgomery mp */
if (err == MP_OKAY)
err = mp_montgomery_setup(curve->prime, &mp);
}
/* find the montgomery mp */
if (err == MP_OKAY)
err = mp_montgomery_setup(curve->prime, &mp);
/* add them */
if (err == MP_OKAY)
err = ecc_projective_add_point(mQ, mG, mG, curve->Af,
curve->prime, mp);
/* reduce */
if (err == MP_OKAY)
err = ecc_map(mG, curve->prime, mp);
}
#else
/* use Shamir's trick to compute u1*mG + u2*mQ using half the doubles */
if (err == MP_OKAY) {
err = ecc_mul2add(mG, u1, mQ, u2, mG, curve->Af, curve->prime,
key->heap);
}
/* use Shamir's trick to compute u1*mG + u2*mQ using half the doubles */
if (err == MP_OKAY) {
err = ecc_mul2add(mG, u1, mQ, u2, mG, curve->Af, curve->prime,
key->heap);
}
#endif /* ECC_SHAMIR */
#endif /* FREESCALE_LTC_ECC */
/* v = X_x1 mod n */
@ -7527,6 +7655,9 @@ int wc_ecc_sig_size(ecc_key* key)
extra byte for r and s, so add 2 */
keySz = key->dp->size;
orderBits = wc_ecc_get_curve_order_bit_count(key->dp);
if (orderBits > keySz * 8) {
keySz = (orderBits + 7) / 8;
}
/* maximum possible signature header size is 7 bytes */
maxSigSz = (keySz * 2) + SIG_HEADER_SZ;
if ((orderBits % 8) == 0) {
@ -8450,17 +8581,42 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* a,
/* double if not first */
if (!first) {
if ((err = ecc_projective_dbl_point(R, R, a, modulus,
mp)) != MP_OKAY) {
mp)) != MP_OKAY) {
break;
}
}
/* add if not first, otherwise copy */
if (!first && z) {
if ((err = ecc_projective_add_point(R, fp_cache[idx].LUT[z], R,
a, modulus, mp)) != MP_OKAY) {
if ((err = ecc_projective_add_point(R, fp_cache[idx].LUT[z], R, a,
modulus, mp)) != MP_OKAY) {
break;
}
if (mp_iszero(R->z)) {
/* When all zero then should have done an add */
if (mp_iszero(R->x) && mp_iszero(R->y)) {
if ((err = ecc_projective_dbl_point(fp_cache[idx].LUT[z],
R, a, modulus, mp)) != MP_OKAY) {
break;
}
}
/* When only Z zero then result is infinity */
else {
err = mp_set(R->x, 0);
if (err != MP_OKAY) {
break;
}
err = mp_set(R->y, 0);
if (err != MP_OKAY) {
break;
}
err = mp_copy(&fp_cache[idx].mu, R->z);
if (err != MP_OKAY) {
break;
}
first = 1;
}
}
} else if (z) {
if ((mp_copy(fp_cache[idx].LUT[z]->x, R->x) != MP_OKAY) ||
(mp_copy(fp_cache[idx].LUT[z]->y, R->y) != MP_OKAY) ||
@ -8468,7 +8624,7 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* a,
err = GEN_MEM_ERR;
break;
}
first = 0;
first = 0;
}
}
}
@ -8671,21 +8827,74 @@ static int accel_fp_mul2add(int idx1, int idx2,
if (!first) {
if (zA) {
if ((err = ecc_projective_add_point(R, fp_cache[idx1].LUT[zA],
R, a, modulus, mp)) != MP_OKAY) {
R, a, modulus, mp)) != MP_OKAY) {
break;
}
if (mp_iszero(R->z)) {
/* When all zero then should have done an add */
if (mp_iszero(R->x) && mp_iszero(R->y)) {
if ((err = ecc_projective_dbl_point(
fp_cache[idx1].LUT[zA], R,
a, modulus, mp)) != MP_OKAY) {
break;
}
}
/* When only Z zero then result is infinity */
else {
err = mp_set(R->x, 0);
if (err != MP_OKAY) {
break;
}
err = mp_set(R->y, 0);
if (err != MP_OKAY) {
break;
}
err = mp_copy(&fp_cache[idx1].mu, R->z);
if (err != MP_OKAY) {
break;
}
first = 1;
}
}
}
if (zB) {
if ((err = ecc_projective_add_point(R, fp_cache[idx2].LUT[zB],
R, a, modulus, mp)) != MP_OKAY) {
R, a, modulus, mp)) != MP_OKAY) {
break;
}
if (mp_iszero(R->z)) {
/* When all zero then should have done an add */
if (mp_iszero(R->x) && mp_iszero(R->y)) {
if ((err = ecc_projective_dbl_point(
fp_cache[idx2].LUT[zB], R,
a, modulus, mp)) != MP_OKAY) {
break;
}
}
/* When only Z zero then result is infinity */
else {
err = mp_set(R->x, 0);
if (err != MP_OKAY) {
break;
}
err = mp_set(R->y, 0);
if (err != MP_OKAY) {
break;
}
err = mp_copy(&fp_cache[idx2].mu, R->z);
if (err != MP_OKAY) {
break;
}
first = 1;
}
}
}
} else {
if (zA) {
if ((mp_copy(fp_cache[idx1].LUT[zA]->x, R->x) != MP_OKAY) ||
(mp_copy(fp_cache[idx1].LUT[zA]->y, R->y) != MP_OKAY) ||
(mp_copy(&fp_cache[idx1].mu, R->z) != MP_OKAY)) {
(mp_copy(fp_cache[idx1].LUT[zA]->y, R->y) != MP_OKAY) ||
(mp_copy(&fp_cache[idx1].mu, R->z) != MP_OKAY)) {
err = GEN_MEM_ERR;
break;
}
@ -8694,14 +8903,40 @@ static int accel_fp_mul2add(int idx1, int idx2,
if (zB && first == 0) {
if (zB) {
if ((err = ecc_projective_add_point(R,
fp_cache[idx2].LUT[zB], R, a, modulus, mp)) != MP_OKAY){
fp_cache[idx2].LUT[zB], R, a, modulus, mp)) != MP_OKAY){
break;
}
if (mp_iszero(R->z)) {
/* When all zero then should have done an add */
if (mp_iszero(R->x) && mp_iszero(R->y)) {
if ((err = ecc_projective_dbl_point(
fp_cache[idx2].LUT[zB], R,
a, modulus, mp)) != MP_OKAY) {
break;
}
}
/* When only Z zero then result is infinity */
else {
err = mp_set(R->x, 0);
if (err != MP_OKAY) {
break;
}
err = mp_set(R->y, 0);
if (err != MP_OKAY) {
break;
}
err = mp_copy(&fp_cache[idx2].mu, R->z);
if (err != MP_OKAY) {
break;
}
first = 1;
}
}
}
} else if (zB && first == 1) {
if ((mp_copy(fp_cache[idx2].LUT[zB]->x, R->x) != MP_OKAY) ||
(mp_copy(fp_cache[idx2].LUT[zB]->y, R->y) != MP_OKAY) ||
(mp_copy(&fp_cache[idx2].mu, R->z) != MP_OKAY)) {
(mp_copy(fp_cache[idx2].LUT[zB]->y, R->y) != MP_OKAY) ||
(mp_copy(&fp_cache[idx2].mu, R->z) != MP_OKAY)) {
err = GEN_MEM_ERR;
break;
}

View File

@ -79395,7 +79395,7 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a,
* MP_OKAY on success.
*/
int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
mp_int* rm, mp_int* sm, void* heap)
mp_int* rm, mp_int* sm, mp_int* km, void* heap)
{
#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
sp_digit* d = NULL;
@ -79461,7 +79461,13 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
sp_256_from_mp(x, 8, priv);
/* New random point. */
err = sp_256_ecc_gen_k_8(rng, k);
if (km == NULL || mp_iszero(km)) {
err = sp_256_ecc_gen_k_8(rng, k);
}
else {
sp_256_from_mp(k, 8, km);
mp_zero(km);
}
if (err == MP_OKAY) {
err = sp_256_ecc_mulmod_base_8(point, k, 1, NULL);
}
@ -79620,7 +79626,9 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
sp_256_from_mp(p2->y, 8, pY);
sp_256_from_mp(p2->z, 8, pZ);
{
sp_256_mul_8(s, s, p256_norm_order);
}
err = sp_256_mod_8(s, s, p256_order);
}
if (err == MP_OKAY) {
@ -79638,7 +79646,26 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
}
if (err == MP_OKAY) {
{
sp_256_proj_point_add_8(p1, p1, p2, tmp);
if (sp_256_iszero_8(p1->z)) {
if (sp_256_iszero_8(p1->x) && sp_256_iszero_8(p1->y)) {
sp_256_proj_point_dbl_8(p1, p2, tmp);
}
else {
/* Y ordinate is not used from here - don't set. */
p1->x[0] = 0;
p1->x[1] = 0;
p1->x[2] = 0;
p1->x[3] = 0;
p1->x[4] = 0;
p1->x[5] = 0;
p1->x[6] = 0;
p1->x[7] = 0;
XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod));
}
}
}
/* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
/* Reload r and convert to Montgomery form. */
@ -79668,7 +79695,7 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
/* u1 = (r + 1*order).z'.z' mod prime */
sp_256_mont_mul_8(u1, u2, p1->z, p256_mod,
p256_mp_mod);
*res = (int)(sp_256_cmp_8(p1->x, u2) == 0);
*res = (int)(sp_256_cmp_8(p1->x, u1) == 0);
}
}
}

View File

@ -47453,7 +47453,7 @@ static void sp_256_mont_inv_order_4(sp_digit* r, const sp_digit* a,
* MP_OKAY on success.
*/
int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
mp_int* rm, mp_int* sm, void* heap)
mp_int* rm, mp_int* sm, mp_int* km, void* heap)
{
#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
sp_digit* d = NULL;
@ -47519,7 +47519,13 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
sp_256_from_mp(x, 4, priv);
/* New random point. */
err = sp_256_ecc_gen_k_4(rng, k);
if (km == NULL || mp_iszero(km)) {
err = sp_256_ecc_gen_k_4(rng, k);
}
else {
sp_256_from_mp(k, 4, km);
mp_zero(km);
}
if (err == MP_OKAY) {
err = sp_256_ecc_mulmod_base_4(point, k, 1, NULL);
}
@ -47678,7 +47684,9 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
sp_256_from_mp(p2->y, 4, pY);
sp_256_from_mp(p2->z, 4, pZ);
{
sp_256_mul_4(s, s, p256_norm_order);
}
err = sp_256_mod_4(s, s, p256_order);
}
if (err == MP_OKAY) {
@ -47696,7 +47704,22 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
}
if (err == MP_OKAY) {
{
sp_256_proj_point_add_4(p1, p1, p2, tmp);
if (sp_256_iszero_4(p1->z)) {
if (sp_256_iszero_4(p1->x) && sp_256_iszero_4(p1->y)) {
sp_256_proj_point_dbl_4(p1, p2, tmp);
}
else {
/* Y ordinate is not used from here - don't set. */
p1->x[0] = 0;
p1->x[1] = 0;
p1->x[2] = 0;
p1->x[3] = 0;
XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod));
}
}
}
/* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
/* Reload r and convert to Montgomery form. */
@ -47726,7 +47749,7 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
/* u1 = (r + 1*order).z'.z' mod prime */
sp_256_mont_mul_4(u1, u2, p1->z, p256_mod,
p256_mp_mod);
*res = (int)(sp_256_cmp_4(p1->x, u2) == 0);
*res = (int)(sp_256_cmp_4(p1->x, u1) == 0);
}
}
}

View File

@ -20862,7 +20862,7 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a,
* MP_OKAY on success.
*/
int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
mp_int* rm, mp_int* sm, void* heap)
mp_int* rm, mp_int* sm, mp_int* km, void* heap)
{
#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
sp_digit* d = NULL;
@ -20928,7 +20928,13 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
sp_256_from_mp(x, 8, priv);
/* New random point. */
err = sp_256_ecc_gen_k_8(rng, k);
if (km == NULL || mp_iszero(km)) {
err = sp_256_ecc_gen_k_8(rng, k);
}
else {
sp_256_from_mp(k, 8, km);
mp_zero(km);
}
if (err == MP_OKAY) {
err = sp_256_ecc_mulmod_base_8(point, k, 1, NULL);
}
@ -21087,7 +21093,9 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
sp_256_from_mp(p2->y, 8, pY);
sp_256_from_mp(p2->z, 8, pZ);
{
sp_256_mul_8(s, s, p256_norm_order);
}
err = sp_256_mod_8(s, s, p256_order);
}
if (err == MP_OKAY) {
@ -21105,7 +21113,26 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
}
if (err == MP_OKAY) {
{
sp_256_proj_point_add_8(p1, p1, p2, tmp);
if (sp_256_iszero_8(p1->z)) {
if (sp_256_iszero_8(p1->x) && sp_256_iszero_8(p1->y)) {
sp_256_proj_point_dbl_8(p1, p2, tmp);
}
else {
/* Y ordinate is not used from here - don't set. */
p1->x[0] = 0;
p1->x[1] = 0;
p1->x[2] = 0;
p1->x[3] = 0;
p1->x[4] = 0;
p1->x[5] = 0;
p1->x[6] = 0;
p1->x[7] = 0;
XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod));
}
}
}
/* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
/* Reload r and convert to Montgomery form. */
@ -21135,7 +21162,7 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
/* u1 = (r + 1*order).z'.z' mod prime */
sp_256_mont_mul_8(u1, u2, p1->z, p256_mod,
p256_mp_mod);
*res = (int)(sp_256_cmp_8(p1->x, u2) == 0);
*res = (int)(sp_256_cmp_8(p1->x, u1) == 0);
}
}
}

View File

@ -12452,13 +12452,11 @@ static const sp_digit p256_mod[10] = {
0x3ffffff,0x3ffffff,0x3ffffff,0x003ffff,0x0000000,0x0000000,0x0000000,
0x0000400,0x3ff0000,0x03fffff
};
#ifndef WOLFSSL_SP_SMALL
/* The Montogmery normalizer for modulus of the curve P256. */
static const sp_digit p256_norm_mod[10] = {
0x0000001,0x0000000,0x0000000,0x3fc0000,0x3ffffff,0x3ffffff,0x3ffffff,
0x3fffbff,0x000ffff,0x0000000
};
#endif /* WOLFSSL_SP_SMALL */
/* The Montogmery multiplier for modulus of the curve P256. */
static const sp_digit p256_mp_mod = 0x000001;
#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
@ -16867,7 +16865,7 @@ static void sp_256_mont_inv_order_10(sp_digit* r, const sp_digit* a,
* MP_OKAY on success.
*/
int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
mp_int* rm, mp_int* sm, void* heap)
mp_int* rm, mp_int* sm, mp_int* km, void* heap)
{
#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
sp_digit* d = NULL;
@ -16933,7 +16931,13 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
sp_256_from_mp(x, 10, priv);
/* New random point. */
err = sp_256_ecc_gen_k_10(rng, k);
if (km == NULL || mp_iszero(km)) {
err = sp_256_ecc_gen_k_10(rng, k);
}
else {
sp_256_from_mp(k, 10, km);
mp_zero(km);
}
if (err == MP_OKAY) {
err = sp_256_ecc_mulmod_base_10(point, k, 1, NULL);
}
@ -17092,7 +17096,9 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
sp_256_from_mp(p2->y, 10, pY);
sp_256_from_mp(p2->z, 10, pZ);
{
sp_256_mul_10(s, s, p256_norm_order);
}
err = sp_256_mod_10(s, s, p256_order);
}
if (err == MP_OKAY) {
@ -17110,7 +17116,28 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
}
if (err == MP_OKAY) {
{
sp_256_proj_point_add_10(p1, p1, p2, tmp);
if (sp_256_iszero_10(p1->z)) {
if (sp_256_iszero_10(p1->x) && sp_256_iszero_10(p1->y)) {
sp_256_proj_point_dbl_10(p1, p2, tmp);
}
else {
/* Y ordinate is not used from here - don't set. */
p1->x[0] = 0;
p1->x[1] = 0;
p1->x[2] = 0;
p1->x[3] = 0;
p1->x[4] = 0;
p1->x[5] = 0;
p1->x[6] = 0;
p1->x[7] = 0;
p1->x[8] = 0;
p1->x[9] = 0;
XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod));
}
}
}
/* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
/* Reload r and convert to Montgomery form. */
@ -17140,7 +17167,7 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
/* u1 = (r + 1*order).z'.z' mod prime */
sp_256_mont_mul_10(u1, u2, p1->z, p256_mod,
p256_mp_mod);
*res = (int)(sp_256_cmp_10(p1->x, u2) == 0);
*res = (int)(sp_256_cmp_10(p1->x, u1) == 0);
}
}
}

View File

@ -12270,13 +12270,11 @@ static const sp_digit p256_mod[5] = {
0xfffffffffffffL,0x00fffffffffffL,0x0000000000000L,0x0001000000000L,
0x0ffffffff0000L
};
#ifndef WOLFSSL_SP_SMALL
/* The Montogmery normalizer for modulus of the curve P256. */
static const sp_digit p256_norm_mod[5] = {
0x0000000000001L,0xff00000000000L,0xfffffffffffffL,0xfffefffffffffL,
0x000000000ffffL
};
#endif /* WOLFSSL_SP_SMALL */
/* The Montogmery multiplier for modulus of the curve P256. */
static const sp_digit p256_mp_mod = 0x0000000000001;
#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \
@ -16460,7 +16458,7 @@ static void sp_256_mont_inv_order_5(sp_digit* r, const sp_digit* a,
* MP_OKAY on success.
*/
int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
mp_int* rm, mp_int* sm, void* heap)
mp_int* rm, mp_int* sm, mp_int* km, void* heap)
{
#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
sp_digit* d = NULL;
@ -16526,7 +16524,13 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
sp_256_from_mp(x, 5, priv);
/* New random point. */
err = sp_256_ecc_gen_k_5(rng, k);
if (km == NULL || mp_iszero(km)) {
err = sp_256_ecc_gen_k_5(rng, k);
}
else {
sp_256_from_mp(k, 5, km);
mp_zero(km);
}
if (err == MP_OKAY) {
err = sp_256_ecc_mulmod_base_5(point, k, 1, NULL);
}
@ -16685,7 +16689,9 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
sp_256_from_mp(p2->y, 5, pY);
sp_256_from_mp(p2->z, 5, pZ);
{
sp_256_mul_5(s, s, p256_norm_order);
}
err = sp_256_mod_5(s, s, p256_order);
}
if (err == MP_OKAY) {
@ -16703,7 +16709,23 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
}
if (err == MP_OKAY) {
{
sp_256_proj_point_add_5(p1, p1, p2, tmp);
if (sp_256_iszero_5(p1->z)) {
if (sp_256_iszero_5(p1->x) && sp_256_iszero_5(p1->y)) {
sp_256_proj_point_dbl_5(p1, p2, tmp);
}
else {
/* Y ordinate is not used from here - don't set. */
p1->x[0] = 0;
p1->x[1] = 0;
p1->x[2] = 0;
p1->x[3] = 0;
p1->x[4] = 0;
XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod));
}
}
}
/* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
/* Reload r and convert to Montgomery form. */
@ -16733,7 +16755,7 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
/* u1 = (r + 1*order).z'.z' mod prime */
sp_256_mont_mul_5(u1, u2, p1->z, p256_mod,
p256_mp_mod);
*res = (int)(sp_256_cmp_5(p1->x, u2) == 0);
*res = (int)(sp_256_cmp_5(p1->x, u1) == 0);
}
}
}

View File

@ -20604,7 +20604,7 @@ static void sp_256_mont_inv_order_8(sp_digit* r, const sp_digit* a,
* MP_OKAY on success.
*/
int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
mp_int* rm, mp_int* sm, void* heap)
mp_int* rm, mp_int* sm, mp_int* km, void* heap)
{
#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
sp_digit* d = NULL;
@ -20670,7 +20670,13 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
sp_256_from_mp(x, 8, priv);
/* New random point. */
err = sp_256_ecc_gen_k_8(rng, k);
if (km == NULL || mp_iszero(km)) {
err = sp_256_ecc_gen_k_8(rng, k);
}
else {
sp_256_from_mp(k, 8, km);
mp_zero(km);
}
if (err == MP_OKAY) {
err = sp_256_ecc_mulmod_base_8(point, k, 1, NULL);
}
@ -20829,7 +20835,9 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
sp_256_from_mp(p2->y, 8, pY);
sp_256_from_mp(p2->z, 8, pZ);
{
sp_256_mul_8(s, s, p256_norm_order);
}
err = sp_256_mod_8(s, s, p256_order);
}
if (err == MP_OKAY) {
@ -20847,7 +20855,26 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
}
if (err == MP_OKAY) {
{
sp_256_proj_point_add_8(p1, p1, p2, tmp);
if (sp_256_iszero_8(p1->z)) {
if (sp_256_iszero_8(p1->x) && sp_256_iszero_8(p1->y)) {
sp_256_proj_point_dbl_8(p1, p2, tmp);
}
else {
/* Y ordinate is not used from here - don't set. */
p1->x[0] = 0;
p1->x[1] = 0;
p1->x[2] = 0;
p1->x[3] = 0;
p1->x[4] = 0;
p1->x[5] = 0;
p1->x[6] = 0;
p1->x[7] = 0;
XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod));
}
}
}
/* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
/* Reload r and convert to Montgomery form. */
@ -20877,7 +20904,7 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
/* u1 = (r + 1*order).z'.z' mod prime */
sp_256_mont_mul_8(u1, u2, p1->z, p256_mod,
p256_mp_mod);
*res = (int)(sp_256_cmp_8(p1->x, u2) == 0);
*res = (int)(sp_256_cmp_8(p1->x, u1) == 0);
}
}
}

View File

@ -851,8 +851,14 @@ int sp_add(sp_int* a, sp_int* b, sp_int* r)
*/
int sp_set_int(sp_int* a, unsigned long b)
{
a->used = 1;
a->dp[0] = b;
if (b == 0) {
a->used = 0;
a->dp[0] = 0;
}
else {
a->used = 1;
a->dp[0] = b;
}
return MP_OKAY;
}

View File

@ -22700,7 +22700,7 @@ static void sp_256_mont_inv_order_avx2_4(sp_digit* r, const sp_digit* a,
* MP_OKAY on success.
*/
int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
mp_int* rm, mp_int* sm, void* heap)
mp_int* rm, mp_int* sm, mp_int* km, void* heap)
{
#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK)
sp_digit* d = NULL;
@ -22769,7 +22769,13 @@ int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
sp_256_from_mp(x, 4, priv);
/* New random point. */
err = sp_256_ecc_gen_k_4(rng, k);
if (km == NULL || mp_iszero(km)) {
err = sp_256_ecc_gen_k_4(rng, k);
}
else {
sp_256_from_mp(k, 4, km);
mp_zero(km);
}
if (err == MP_OKAY) {
#ifdef HAVE_INTEL_AVX2
if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
@ -22957,11 +22963,14 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
sp_256_from_mp(p2->z, 4, pZ);
#ifdef HAVE_INTEL_AVX2
if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
sp_256_mul_avx2_4(s, s, p256_norm_order);
}
else
#endif
{
sp_256_mul_4(s, s, p256_norm_order);
}
err = sp_256_mod_4(s, s, p256_order);
}
if (err == MP_OKAY) {
@ -22998,11 +23007,40 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
if (err == MP_OKAY) {
#ifdef HAVE_INTEL_AVX2
if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags))
if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) {
sp_256_proj_point_add_avx2_4(p1, p1, p2, tmp);
if (sp_256_iszero_4(p1->z)) {
if (sp_256_iszero_4(p1->x) && sp_256_iszero_4(p1->y)) {
sp_256_proj_point_dbl_avx2_4(p1, p2, tmp);
}
else {
/* Y ordinate is not used from here - don't set. */
p1->x[0] = 0;
p1->x[1] = 0;
p1->x[2] = 0;
p1->x[3] = 0;
XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod));
}
}
}
else
#endif
{
sp_256_proj_point_add_4(p1, p1, p2, tmp);
if (sp_256_iszero_4(p1->z)) {
if (sp_256_iszero_4(p1->x) && sp_256_iszero_4(p1->y)) {
sp_256_proj_point_dbl_4(p1, p2, tmp);
}
else {
/* Y ordinate is not used from here - don't set. */
p1->x[0] = 0;
p1->x[1] = 0;
p1->x[2] = 0;
p1->x[3] = 0;
XMEMCPY(p1->z, p256_norm_mod, sizeof(p256_norm_mod));
}
}
}
/* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */
/* Reload r and convert to Montgomery form. */
@ -23032,7 +23070,7 @@ int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX,
/* u1 = (r + 1*order).z'.z' mod prime */
sp_256_mont_mul_4(u1, u2, p1->z, p256_mod,
p256_mp_mod);
*res = (int)(sp_256_cmp_4(p1->x, u2) == 0);
*res = (int)(sp_256_cmp_4(p1->x, u1) == 0);
}
}
}

View File

@ -16587,6 +16587,85 @@ static int ecc_test_vector(int keySize)
return 0;
}
#if defined(HAVE_ECC_SIGN) && defined(WOLFSSL_ECDSA_SET_K)
static int ecc_test_sign_vectors(WC_RNG* rng)
{
int ret;
ecc_key key;
byte sig[72];
word32 sigSz;
unsigned char hash[32] = "test wolfSSL deterministic sign";
const char* dIUT = "7d7dc5f71eb29ddaf80d6214632eeae03d9058af1fb6d22ed80badb62bc1a534";
const char* QIUTx = "ead218590119e8876b29146ff89ca61770c4edbbf97d38ce385ed281d8a6b230";
const char* QIUTy = "28af61281fd35e2fa7002523acc85a429cb06ee6648325389f59edfce1405141";
const byte k[1] = { 0x02 };
const byte expSig[71] = {
0x30, 0x45, 0x02, 0x20, 0x7c, 0xf2, 0x7b, 0x18,
0x8d, 0x03, 0x4f, 0x7e, 0x8a, 0x52, 0x38, 0x03,
0x04, 0xb5, 0x1a, 0xc3, 0xc0, 0x89, 0x69, 0xe2,
0x77, 0xf2, 0x1b, 0x35, 0xa6, 0x0b, 0x48, 0xfc,
0x47, 0x66, 0x99, 0x78, 0x02, 0x21, 0x00, 0xa8,
0x43, 0xa0, 0xce, 0x6c, 0x5e, 0x17, 0x8a, 0x53,
0x4d, 0xaf, 0xd2, 0x95, 0x78, 0x9f, 0x84, 0x4f,
0x94, 0xb8, 0x75, 0xa3, 0x19, 0xa5, 0xd4, 0xdf,
0xe1, 0xd4, 0x5e, 0x9d, 0x97, 0xfe, 0x81
};
ret = wc_ecc_init_ex(&key, HEAP_HINT, devId);
if (ret != 0) {
return ret;
}
ret = wc_ecc_import_raw(&key, QIUTx, QIUTy, dIUT, "SECP256R1");
if (ret != 0) {
goto done;
}
ret = wc_ecc_sign_set_k(k, sizeof(k), &key);
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(hash, sizeof(hash), sig, &sigSz, rng, &key);
} while (ret == WC_PENDING_E);
if (ret != 0) {
goto done;
}
TEST_SLEEP();
if (sigSz != sizeof(expSig)) {
ret = -8350;
goto done;
}
if (XMEMCMP(sig, expSig, sigSz) != 0) {
ret = -8351;
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(hash, sizeof(hash), sig, &sigSz, rng, &key);
} while (ret == WC_PENDING_E);
if (ret != 0) {
goto done;
}
TEST_SLEEP();
done:
wc_ecc_free(&key);
return ret;
}
#endif
#ifdef HAVE_ECC_CDH
static int ecc_test_cdh_vectors(void)
{
@ -16609,7 +16688,7 @@ static int ecc_test_cdh_vectors(void)
ret = wc_ecc_init_ex(&priv_key, HEAP_HINT, devId);
if (ret != 0) {
wc_ecc_free(&pub_key);
goto done;
return ret;
}
wc_ecc_set_flags(&pub_key, WC_ECC_FLAG_COFACTOR);
wc_ecc_set_flags(&priv_key, WC_ECC_FLAG_COFACTOR);
@ -18459,6 +18538,13 @@ int ecc_test(void)
}
#endif
#if defined(HAVE_ECC_SIGN) && defined(WOLFSSL_ECDSA_SET_K)
ret = ecc_test_sign_vectors(&rng);
if (ret != 0) {
printf("ecc_test_sign_vectors failed! %d\n", ret);
goto done;
}
#endif
#ifdef HAVE_ECC_CDH
ret = ecc_test_cdh_vectors();
if (ret != 0) {

View File

@ -391,6 +391,10 @@ struct ecc_key {
ecc_context_t ctx;
#endif
#ifdef WOLFSSL_ECDSA_SET_K
mp_int *sign_k;
#endif
#ifdef WOLFSSL_SMALL_STACK_CACHE
mp_int* t1;
mp_int* t2;
@ -470,6 +474,10 @@ 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_SET_K
WOLFSSL_API
int wc_ecc_sign_set_k(const byte* k, word32 klen, ecc_key* key);
#endif
#endif /* HAVE_ECC_SIGN */
#ifdef HAVE_ECC_VERIFY

View File

@ -106,7 +106,7 @@ int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap);
int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out,
word32* outlen, void* heap);
int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv,
mp_int* rm, mp_int* sm, void* heap);
mp_int* rm, mp_int* sm, mp_int* km, void* heap);
int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY,
mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap);
int sp_ecc_is_point_256(mp_int* pX, mp_int* pY);