From cc880e39aefaba8d50e561e9414dcc561628bbb7 Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Mon, 11 Nov 2019 09:03:19 +1000 Subject: [PATCH 1/2] Add deterministic ECDSA sig gen. Fix corner cases for add point. In verify, two points are added and they may either be the same point (different z) or result in infinity. If they are the same point then a double needs to be performed instead. Detection of infinity added. Calculation of wc_ecc_sig_size fixed to handle wehn there are more bits in the order than in the modulus. --- wolfcrypt/src/ecc.c | 304 +++++++++++++++++++++++++++++------- wolfcrypt/src/sp_arm32.c | 33 +++- wolfcrypt/src/sp_arm64.c | 29 +++- wolfcrypt/src/sp_armthumb.c | 33 +++- wolfcrypt/src/sp_c32.c | 37 ++++- wolfcrypt/src/sp_c64.c | 32 +++- wolfcrypt/src/sp_cortexm.c | 33 +++- wolfcrypt/src/sp_int.c | 10 +- wolfcrypt/src/sp_x86_64.c | 48 +++++- wolfcrypt/test/test.c | 88 ++++++++++- wolfssl/wolfcrypt/ecc.h | 8 + wolfssl/wolfcrypt/sp.h | 2 +- 12 files changed, 568 insertions(+), 89 deletions(-) diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 8321837cf..58404ba4f 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -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; } } @@ -4319,13 +4318,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 @@ -4679,7 +4681,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 @@ -4691,11 +4699,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 @@ -4704,11 +4707,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) { @@ -4721,20 +4729,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 */ @@ -4785,7 +4806,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) { @@ -4939,8 +4964,25 @@ 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; + } + mp_copy(key->sign_k, &pubkey->k); + 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 */ @@ -5019,8 +5061,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 @@ -5055,6 +5124,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); @@ -5255,10 +5332,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) @@ -5347,8 +5426,24 @@ 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 { + mp_set(C->x, 0); + mp_set(C->y, 0); + mp_set(C->z, 1); + first = 1; + } + } } } } @@ -5861,38 +5956,60 @@ 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 { + mp_set(mG->x, 0); + mp_set(mG->y, 0); + 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 */ @@ -7491,6 +7608,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) { @@ -8414,17 +8534,33 @@ 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 { + mp_set(R->x, 0); + mp_set(R->y, 0); + mp_copy(&fp_cache[idx].mu, R->z); + 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) || @@ -8432,7 +8568,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; } } } @@ -8635,21 +8771,56 @@ 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 { + mp_set(R->x, 0); + mp_set(R->y, 0); + mp_copy(&fp_cache[idx1].mu, R->z); + 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 { + mp_set(R->x, 0); + mp_set(R->y, 0); + mp_copy(&fp_cache[idx2].mu, R->z); + 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; } @@ -8658,14 +8829,31 @@ 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 { + mp_set(R->x, 0); + mp_set(R->y, 0); + mp_copy(&fp_cache[idx2].mu, R->z); + 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; } diff --git a/wolfcrypt/src/sp_arm32.c b/wolfcrypt/src/sp_arm32.c index de6f0fb77..1b2c1a12c 100644 --- a/wolfcrypt/src/sp_arm32.c +++ b/wolfcrypt/src/sp_arm32.c @@ -26980,7 +26980,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; @@ -27046,7 +27046,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); } @@ -27205,7 +27211,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) { @@ -27223,7 +27231,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. */ @@ -27253,7 +27280,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); } } } diff --git a/wolfcrypt/src/sp_arm64.c b/wolfcrypt/src/sp_arm64.c index 672580068..69a784181 100644 --- a/wolfcrypt/src/sp_arm64.c +++ b/wolfcrypt/src/sp_arm64.c @@ -30018,7 +30018,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; @@ -30084,7 +30084,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); } @@ -30243,7 +30249,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) { @@ -30261,7 +30269,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. */ @@ -30291,7 +30314,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); } } } diff --git a/wolfcrypt/src/sp_armthumb.c b/wolfcrypt/src/sp_armthumb.c index bbab4605d..b0c885abe 100644 --- a/wolfcrypt/src/sp_armthumb.c +++ b/wolfcrypt/src/sp_armthumb.c @@ -16358,7 +16358,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; @@ -16424,7 +16424,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); } @@ -16583,7 +16589,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) { @@ -16601,7 +16609,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. */ @@ -16631,7 +16658,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); } } } diff --git a/wolfcrypt/src/sp_c32.c b/wolfcrypt/src/sp_c32.c index 743b33b93..40c29bcb0 100644 --- a/wolfcrypt/src/sp_c32.c +++ b/wolfcrypt/src/sp_c32.c @@ -8441,13 +8441,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) || \ @@ -12856,7 +12854,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; @@ -12922,7 +12920,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); } @@ -13081,7 +13085,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) { @@ -13099,7 +13105,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. */ @@ -13129,7 +13156,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); } } } diff --git a/wolfcrypt/src/sp_c64.c b/wolfcrypt/src/sp_c64.c index 1bd086eb9..3702eefa5 100644 --- a/wolfcrypt/src/sp_c64.c +++ b/wolfcrypt/src/sp_c64.c @@ -8011,13 +8011,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) || \ @@ -12201,7 +12199,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; @@ -12267,7 +12265,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); } @@ -12426,7 +12430,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) { @@ -12444,7 +12450,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. */ @@ -12474,7 +12496,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); } } } diff --git a/wolfcrypt/src/sp_cortexm.c b/wolfcrypt/src/sp_cortexm.c index d760cc097..c2925beed 100644 --- a/wolfcrypt/src/sp_cortexm.c +++ b/wolfcrypt/src/sp_cortexm.c @@ -16429,7 +16429,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; @@ -16495,7 +16495,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); } @@ -16654,7 +16660,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) { @@ -16672,7 +16680,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. */ @@ -16702,7 +16729,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); } } } diff --git a/wolfcrypt/src/sp_int.c b/wolfcrypt/src/sp_int.c index 4b9ab4eb1..063d10c17 100644 --- a/wolfcrypt/src/sp_int.c +++ b/wolfcrypt/src/sp_int.c @@ -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; } diff --git a/wolfcrypt/src/sp_x86_64.c b/wolfcrypt/src/sp_x86_64.c index 9473b4332..17f630052 100644 --- a/wolfcrypt/src/sp_x86_64.c +++ b/wolfcrypt/src/sp_x86_64.c @@ -21130,7 +21130,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; @@ -21199,7 +21199,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)) @@ -21387,11 +21393,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) { @@ -21428,11 +21437,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. */ @@ -21462,7 +21500,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); } } } diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 6b7397973..4069a85c1 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -16645,6 +16645,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) { @@ -16667,7 +16746,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); @@ -18494,6 +18573,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) { diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index ac34e2bd0..41bb8ddf4 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -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; @@ -467,6 +471,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 diff --git a/wolfssl/wolfcrypt/sp.h b/wolfssl/wolfcrypt/sp.h index ed1db955c..f6009c9cd 100644 --- a/wolfssl/wolfcrypt/sp.h +++ b/wolfssl/wolfcrypt/sp.h @@ -96,7 +96,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); From 13c63461580161479ec1d74692162c5616151e6d Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Wed, 20 Nov 2019 11:07:04 +1000 Subject: [PATCH 2/2] Check error returns from mp calls --- wolfcrypt/src/ecc.c | 85 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 66 insertions(+), 19 deletions(-) diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 58404ba4f..1e2da1675 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -4970,7 +4970,10 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, err = RNG_FAILURE_E; break; } - mp_copy(key->sign_k, &pubkey->k); + + 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); @@ -5438,9 +5441,15 @@ int ecc_mul2add(ecc_point* A, mp_int* kA, } /* When only Z zero then result is infinity */ else { - mp_set(C->x, 0); - mp_set(C->y, 0); - mp_set(C->z, 1); + 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; } } @@ -5985,9 +5994,11 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, } /* When only Z zero then result is infinity */ else { - mp_set(mG->x, 0); - mp_set(mG->y, 0); - mp_set(mG->z, 1); + 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); } } } @@ -8555,9 +8566,18 @@ static int accel_fp_mul(int idx, mp_int* k, ecc_point *R, mp_int* a, } /* When only Z zero then result is infinity */ else { - mp_set(R->x, 0); - mp_set(R->y, 0); - mp_copy(&fp_cache[idx].mu, R->z); + 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; } } @@ -8785,9 +8805,18 @@ static int accel_fp_mul2add(int idx1, int idx2, } /* When only Z zero then result is infinity */ else { - mp_set(R->x, 0); - mp_set(R->y, 0); - mp_copy(&fp_cache[idx1].mu, R->z); + 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; } } @@ -8809,9 +8838,18 @@ static int accel_fp_mul2add(int idx1, int idx2, } /* When only Z zero then result is infinity */ else { - mp_set(R->x, 0); - mp_set(R->y, 0); - mp_copy(&fp_cache[idx2].mu, R->z); + 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; } } @@ -8843,9 +8881,18 @@ static int accel_fp_mul2add(int idx1, int idx2, } /* When only Z zero then result is infinity */ else { - mp_set(R->x, 0); - mp_set(R->y, 0); - mp_copy(&fp_cache[idx2].mu, R->z); + 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; } }