Randomize z ordinates in scalar mult when timing resistant

An RNG is required for shared secret calculation now.
Use wc_ecc_set_rng() to set an RNG against the ECC object.
ECC verification does not need timing resistance and does not randomize
z ordinates.
This commit is contained in:
Sean Parkinson 2020-07-13 12:32:57 +10:00
parent 3ce933c90a
commit 6467de5a88
12 changed files with 493 additions and 81 deletions
mcapi
src
tests
wolfcrypt
wolfssl
test.h
wolfcrypt

@ -702,14 +702,32 @@ int CRYPT_ECC_DHE_SharedSecretMake(CRYPT_ECC_CTX* priv, CRYPT_ECC_CTX* pub,
{
int ret;
unsigned int inOut = outSz;
#if defined(ECC_TIMING_RESISTANT)
WC_RNG rng;
#endif
if (priv == NULL || pub == NULL || out == NULL || usedSz == NULL)
return BAD_FUNC_ARG;
#if defined(ECC_TIMING_RESISTANT)
ret = wc_InitRng(&rng);
if (ret != 0)
return ret;
ret = wc_ecc_set_rng((ecc_key*)priv->holder, &rng);
if (ret != 0) {
wc_FreeRng(&rng);
return ret;
}
#endif
ret = wc_ecc_shared_secret((ecc_key*)priv->holder, (ecc_key*)pub->holder,
out, &inOut);
*usedSz = inOut;
#if defined(ECC_TIMING_RESISTANT)
wc_FreeRng(&rng);
#endif
return ret;
}

@ -4243,7 +4243,13 @@ int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, ecc_key* pub_key,
else
#endif
{
ret = wc_ecc_shared_secret(priv_key, pub_key, out, outlen);
#if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) && \
!defined(HAVE_SELFTEST)
ret = wc_ecc_set_rng(priv_key, ssl->rng);
if (ret == 0)
#endif
ret = wc_ecc_shared_secret(priv_key, pub_key, out, outlen);
}
/* Handle async pending response */

@ -7487,6 +7487,15 @@ static int TLSX_KeyShare_ProcessEcc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
}
ssl->ecdhCurveOID = ssl->peerEccKey->dp->oidSum;
#if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) && \
!defined(HAVE_SELFTEST)
ret = wc_ecc_set_rng(keyShareKey, ssl->rng);
if (ret != 0) {
return ret;
}
#endif
do {
#if defined(WOLFSSL_ASYNC_CRYPT)
ret = wc_AsyncWait(ret, &keyShareKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN);

@ -19056,6 +19056,14 @@ static int test_wc_ecc_shared_secret (void)
ret = wc_ecc_make_key(&rng, keySz, &pubKey);
}
#if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) && \
!defined(HAVE_SELFTEST)
if (ret == 0) {
ret = wc_ecc_set_rng(&key, &rng);
}
#endif
printf(testingFmt, "wc_ecc_shared_secret()");
if (ret == 0) {
ret = wc_ecc_shared_secret(&key, &pubKey, out, &outlen);
@ -20021,6 +20029,17 @@ static int test_wc_ecc_encryptDecrypt (void)
}
}
#if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) && \
!defined(HAVE_SELFTEST)
if (ret == 0) {
ret = wc_ecc_set_rng(&srvKey, &rng);
}
if (ret == 0) {
ret = wc_ecc_set_rng(&cliKey, &rng);
}
#endif
printf(testingFmt, "wc_ecc_encrypt()");
if (ret == 0) {
@ -20353,6 +20372,14 @@ static int test_wc_ecc_shared_secret_ssh (void)
printf(testingFmt, "ecc_shared_secret_ssh()");
#if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) && \
!defined(HAVE_SELFTEST)
if (ret == 0) {
ret = wc_ecc_set_rng(&key, &rng);
}
#endif
if (ret == 0) {
ret = wc_ecc_shared_secret_ssh(&key, &key2.pubkey, secret, &secretLen);
}
@ -22203,6 +22230,7 @@ static void test_wc_PKCS7_EncodeDecodeEnvelopedData (void)
{
#if defined(HAVE_PKCS7)
PKCS7* pkcs7;
WC_RNG rng;
word32 tempWrd32 = 0;
byte* tmpBytePtr = NULL;
const char input[] = "Test data to encode.";
@ -22370,6 +22398,10 @@ static void test_wc_PKCS7_EncodeDecodeEnvelopedData (void)
#endif /* END HAVE_ECC */
}; /* END pkcs7EnvelopedVector */
#ifdef ECC_TIMING_RESISTANT
AssertIntEQ(wc_InitRng(&rng), 0);
#endif
printf(testingFmt, "wc_PKCS7_EncodeEnvelopedData()");
AssertNotNull(pkcs7 = wc_PKCS7_New(HEAP_HINT, devId));
@ -22379,6 +22411,9 @@ static void test_wc_PKCS7_EncodeDecodeEnvelopedData (void)
for (i = 0; i < testSz; i++) {
AssertIntEQ(wc_PKCS7_InitWithCert(pkcs7, (testVectors + i)->cert,
(word32)(testVectors + i)->certSz), 0);
#ifdef ECC_TIMING_RESISTANT
pkcs7->rng = &rng;
#endif
pkcs7->content = (byte*)(testVectors + i)->content;
pkcs7->contentSz = (testVectors + i)->contentSz;
@ -22501,6 +22536,10 @@ static void test_wc_PKCS7_EncodeDecodeEnvelopedData (void)
}
#endif /* HAVE_ECC */
#ifdef ECC_TIMING_RESISTANT
wc_FreeRng(&rng);
#endif
#endif /* HAVE_PKCS7 */
} /* END test_wc_PKCS7_EncodeEnvelopedData() */

@ -5311,6 +5311,13 @@ void bench_ecc(int doAsync)
}
#ifdef HAVE_ECC_DHE
#if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) && \
!defined(HAVE_SELFTEST)
for (i = 0; i < BENCH_MAX_PENDING; i++) {
(void)wc_ecc_set_rng(&genKey[i], &gRng);
}
#endif
/* ECC Shared Secret */
bench_stats_start(&count, &start);

@ -2429,7 +2429,7 @@ int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp)
#define M_POINTS 8
static int ecc_mulmod(mp_int* k, ecc_point* tG, ecc_point* R, ecc_point** M,
mp_int* a, mp_int* modulus, mp_digit mp)
mp_int* a, mp_int* modulus, mp_digit mp, WC_RNG* rng)
{
int err = MP_OKAY;
int i;
@ -2437,6 +2437,8 @@ static int ecc_mulmod(mp_int* k, ecc_point* tG, ecc_point* R, ecc_point** M,
int bitcnt = 0, mode = 0, digidx = 0;
mp_digit buf;
(void)rng;
/* calc the M tab, which holds kG for k==8..15 */
/* M[0] == 8G */
if (err == MP_OKAY)
@ -2569,6 +2571,36 @@ static int ecc_mulmod(mp_int* k, ecc_point* tG, ecc_point* R, ecc_point** M,
#else
static int wc_ecc_gen_z(WC_RNG* rng, int size, ecc_point* p,
mp_int* modulus, mp_digit mp, mp_int* tx, mp_int* ty)
{
int err;
err = wc_ecc_gen_k(rng, size, ty, modulus);
if (err == MP_OKAY)
err = mp_mul(p->z, ty, p->z);
if (err == MP_OKAY)
err = mp_montgomery_reduce(p->z, modulus, mp);
if (err == MP_OKAY)
err = mp_sqr(ty, tx);
if (err == MP_OKAY)
err = mp_montgomery_reduce(tx, modulus, mp);
if (err == MP_OKAY)
err = mp_mul(ty, tx, ty);
if (err == MP_OKAY)
err = mp_montgomery_reduce(ty, modulus, mp);
if (err == MP_OKAY)
err = mp_mul(p->x, tx, p->x);
if (err == MP_OKAY)
err = mp_montgomery_reduce(p->x, modulus, mp);
if (err == MP_OKAY)
err = mp_mul(p->y, ty, p->y);
if (err == MP_OKAY)
err = mp_montgomery_reduce(p->y, modulus, mp);
return err;
}
#if defined(WC_NO_CACHE_RESISTANT)
#define M_POINTS 4
#else
@ -2576,7 +2608,7 @@ static int ecc_mulmod(mp_int* k, ecc_point* tG, ecc_point* R, ecc_point** M,
#endif
static int ecc_mulmod(mp_int* k, ecc_point* tG, ecc_point* R, ecc_point** M,
mp_int* a, mp_int* modulus, mp_digit mp)
mp_int* a, mp_int* modulus, mp_digit mp, WC_RNG* rng)
{
int err = MP_OKAY;
int i;
@ -2595,14 +2627,35 @@ static int ecc_mulmod(mp_int* k, ecc_point* tG, ecc_point* R, ecc_point** M,
/* M[1] == 2G */
if (err == MP_OKAY)
err = ecc_projective_dbl_point(tG, M[1], a, modulus, mp);
#ifdef WC_NO_CACHE_RESISTANT
if (err == MP_OKAY)
err = wc_ecc_copy_point(M[0], M[2]);
if (rng != NULL) {
if (err == MP_OKAY) {
err = wc_ecc_gen_z(rng, (mp_count_bits(modulus) + 7) / 8, M[0],
modulus, mp, M[3]->x, M[3]->y);
}
if (err == MP_OKAY) {
err = wc_ecc_gen_z(rng, (mp_count_bits(modulus) + 7) / 8, M[1],
modulus, mp, M[3]->x, M[3]->y);
}
}
#else
if (err == MP_OKAY)
err = wc_ecc_copy_point(M[0], M[3]);
if (err == MP_OKAY)
err = wc_ecc_copy_point(M[1], M[4]);
if (rng != NULL) {
if (err == MP_OKAY) {
err = wc_ecc_gen_z(rng, (mp_count_bits(modulus) + 7) / 8, M[3],
modulus, mp, M[2]->x, M[2]->y);
}
if (err == MP_OKAY) {
err = wc_ecc_gen_z(rng, (mp_count_bits(modulus) + 7) / 8, M[4],
modulus, mp, M[2]->x, M[2]->y);
}
}
#endif
/* setup sliding window */
@ -2638,10 +2691,10 @@ static int ecc_mulmod(mp_int* k, ecc_point* tG, ecc_point* R, ecc_point** M,
if (mode == 0) {
/* timing resistant - dummy operations */
if (err == MP_OKAY)
err = ecc_projective_add_point(M[1], M[2], M[2], a, modulus,
err = ecc_projective_add_point(M[1], M[2], M[3], a, modulus,
mp);
if (err == MP_OKAY)
err = ecc_projective_dbl_point(M[2], M[3], a, modulus, mp);
err = ecc_projective_dbl_point(M[3], M[2], a, modulus, mp);
}
else {
if (err == MP_OKAY)
@ -2842,7 +2895,7 @@ static void ecc_key_tmp_final(ecc_key* key, void* heap)
*/
#ifdef FP_ECC
static int normal_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a,
mp_int* modulus, int map, void* heap)
mp_int* modulus, WC_RNG* rng, int map, void* heap)
#else
int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a,
mp_int* modulus, int map, void* heap)
@ -2898,7 +2951,11 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a,
goto exit;
}
err = ecc_mulmod(k, tG, R, M, a, modulus, mp);
#ifdef FP_ECC
err = ecc_mulmod(k, tG, R, M, a, modulus, mp, rng);
#else
err = ecc_mulmod(k, tG, R, M, a, modulus, mp, NULL);
#endif
/* map R back from projective space */
if (err == MP_OKAY && map)
err = ecc_map(R, modulus, mp);
@ -2953,57 +3010,140 @@ exit:
return MP_OKAY on success
*/
int wc_ecc_mulmod_ex2(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a,
mp_int* modulus, mp_int* order, int map, void* heap)
mp_int* modulus, mp_int* order, WC_RNG* rng, int map,
void* heap)
#ifndef WOLFSSL_SP_MATH
{
#if !defined(WOLFSSL_SP_MATH) && defined(ECC_TIMING_RESISTANT)
int err;
mp_int t;
mp_int o;
mp_digit mask;
int i;
ecc_point *tG, *M[M_POINTS];
int i, err;
#ifdef WOLFSSL_SMALL_STACK_CACHE
ecc_key key;
#endif
mp_digit mp;
#ifdef ECC_TIMING_RESISTANT
mp_int t;
mp_int o;
mp_digit mask;
#endif
if ((err = mp_init(&t)) != MP_OKAY)
return err;
if ((err = mp_init(&o)) != MP_OKAY) {
mp_free(&t);
return err;
}
if (k == NULL || G == NULL || R == NULL || modulus == NULL) {
return ECC_BAD_ARG_E;
}
if (k == NULL || order == NULL) {
err = ECC_BAD_ARG_E;
}
/* init variables */
tG = NULL;
XMEMSET(M, 0, sizeof(M));
/* Make k at 1 bit longer than order. */
if (err == MP_OKAY) {
err = mp_add(k, order, &t);
}
if (err == MP_OKAY) {
err = mp_copy(order, &o);
}
if (err == MP_OKAY) {
/* Only add if order + k has same number of bits as order */
mask = (mp_digit)0 - (mp_count_bits(&t) == mp_count_bits(order));
for (i = 0; i < o.used; i++) {
o.dp[i] &= mask;
}
err = mp_add(&t, &o, &t);
}
#ifdef WOLFSSL_SMALL_STACK_CACHE
err = ecc_key_tmp_init(&key, heap);
if (err != MP_OKAY)
goto exit;
R->key = &key;
#endif /* WOLFSSL_SMALL_STACK_CACHE */
if (err == MP_OKAY) {
err = wc_ecc_mulmod_ex(&t, G, R, a, modulus, map, heap);
}
/* alloc ram for window temps */
for (i = 0; i < M_POINTS; i++) {
M[i] = wc_ecc_new_point_h(heap);
if (M[i] == NULL) {
err = MEMORY_E;
goto exit;
}
#ifdef WOLFSSL_SMALL_STACK_CACHE
M[i]->key = &key;
#endif
}
mp_forcezero(&t);
mp_free(&o);
mp_free(&t);
/* make a copy of G in case R==G */
tG = wc_ecc_new_point_h(heap);
if (tG == NULL) {
err = MEMORY_E;
goto exit;
}
if ((err = ecc_point_to_mont(G, tG, modulus, heap)) != MP_OKAY) {
goto exit;
}
return err;
/* init montgomery reduction */
if ((err = mp_montgomery_setup(modulus, &mp)) != MP_OKAY) {
goto exit;
}
#ifdef ECC_TIMING_RESISTANT
if ((err = mp_init(&t)) != MP_OKAY)
goto exit;
if ((err = mp_init(&o)) != MP_OKAY) {
mp_free(&t);
goto exit;
}
/* Make k at 1 bit longer than order. */
if (err == MP_OKAY) {
err = mp_add(k, order, &t);
}
if (err == MP_OKAY) {
err = mp_copy(order, &o);
}
if (err == MP_OKAY) {
/* Only add if order + k has same number of bits as order */
mask = (mp_digit)0 - (mp_count_bits(&t) == mp_count_bits(order));
for (i = 0; i < o.used; i++) {
o.dp[i] &= mask;
}
err = mp_add(&t, &o, &t);
}
mp_free(&o);
if (err == MP_OKAY)
err = ecc_mulmod(&t, tG, R, M, a, modulus, mp, rng);
mp_forcezero(&t);
mp_free(&t);
#else
(void)order;
err = ecc_mulmod(k, tG, R, M, a, modulus, mp, rng);
return wc_ecc_mulmod_ex(k, G, R, a, modulus, map, heap);
#endif /* !WOLFSSL_SP_MATH && ECC_TIMING_RESISTANT */
(void)order;
#endif
/* map R back from projective space */
if (err == MP_OKAY && map)
err = ecc_map(R, modulus, mp);
exit:
/* done */
wc_ecc_del_point_h(tG, heap);
for (i = 0; i < M_POINTS; i++) {
wc_ecc_del_point_h(M[i], heap);
}
#ifdef WOLFSSL_SMALL_STACK_CACHE
R->key = NULL;
ecc_key_tmp_free(&key, heap);
#endif /* WOLFSSL_SMALL_STACK_CACHE */
return err;
}
#else
{
if (k == NULL || G == NULL || R == NULL || modulus == NULL) {
return ECC_BAD_ARG_E;
}
(void)a;
(void)order;
(void)rng;
#ifndef WOLFSSL_SP_NO_256
if (mp_count_bits(modulus) == 256) {
return sp_ecc_mulmod_256(k, G, R, map, heap);
}
#endif
#ifdef WOLFSSL_SP_384
if (mp_count_bits(modulus) == 384) {
return sp_ecc_mulmod_384(k, G, R, map, heap);
}
#endif
return ECC_BAD_ARG_E;
}
#endif /* !WOLFSSL_SP_MATH */
#endif /* !FP_ECC */
#endif /* !FREESCALE_LTC_ECC && !WOLFSSL_STM32_PKA */
@ -3613,7 +3753,7 @@ int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out,
static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point,
byte* out, word32* outlen, ecc_curve_spec* curve)
{
int err;
int err = MP_OKAY;
#ifndef WOLFSSL_SP_MATH
ecc_point* result = NULL;
word32 x = 0;
@ -3676,9 +3816,23 @@ static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point,
return MEMORY_E;
}
/* Map in a separate call as this should be constant time */
err = wc_ecc_mulmod_ex2(k, point, result, curve->Af, curve->prime,
curve->order, 0, private_key->heap);
#ifdef ECC_TIMING_RESISTANT
if (private_key->rng == NULL) {
err = MISSING_RNG_E;
}
#endif
if (err == MP_OKAY) {
/* Map in a separate call as this should be constant time */
#ifdef ECC_TIMING_RESISTANT
err = wc_ecc_mulmod_ex2(k, point, result, curve->Af, curve->prime,
curve->order, private_key->rng, 0,
private_key->heap);
#else
err = wc_ecc_mulmod_ex2(k, point, result, curve->Af, curve->prime,
curve->order, NULL, 0, private_key->heap);
#endif
}
if (err == MP_OKAY) {
err = mp_montgomery_setup(curve->prime, &mp);
}
@ -3955,7 +4109,6 @@ static WC_INLINE void wc_ecc_reset(ecc_key* key)
key->state = ECC_STATE_NONE;
}
/* create the public ECC key from a private key
*
* key an initialized private key to generate public part from
@ -3969,8 +4122,8 @@ static WC_INLINE void wc_ecc_reset(ecc_key* key)
*
* returns MP_OKAY on success
*/
static int wc_ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn,
ecc_point* pubOut)
static int ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn,
ecc_point* pubOut, WC_RNG* rng)
{
int err = MP_OKAY;
#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A)
@ -3981,6 +4134,8 @@ static int wc_ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn,
DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT);
#endif /* !WOLFSSL_ATECC508A */
(void)rng;
if (key == NULL) {
return BAD_FUNC_ARG;
}
@ -4055,6 +4210,8 @@ static int wc_ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn,
err = mp_copy(curve->Gx, base->x);
if (err == MP_OKAY)
err = mp_copy(curve->Gy, base->y);
if (err == MP_OKAY)
err = mp_montgomery_setup(curve->prime, &mp);
if (err == MP_OKAY)
err = mp_set(base->z, 1);
@ -4062,14 +4219,11 @@ static int wc_ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn,
if (err == MP_OKAY) {
/* Map in a separate call as this should be constant time */
err = wc_ecc_mulmod_ex2(&key->k, base, pub, curve->Af, curve->prime,
curve->order, 0, key->heap);
curve->order, rng, 0, key->heap);
if (err == MP_MEM) {
err = MEMORY_E;
}
}
if (err == MP_OKAY) {
err = mp_montgomery_setup(curve->prime, &mp);
}
if (err == MP_OKAY) {
/* Use constant time map if compiled in */
err = ecc_map_ex(pub, curve->prime, mp, 1);
@ -4128,7 +4282,23 @@ int wc_ecc_make_pub(ecc_key* key, ecc_point* pubOut)
{
WOLFSSL_ENTER("wc_ecc_make_pub");
return wc_ecc_make_pub_ex(key, NULL, pubOut);
return ecc_make_pub_ex(key, NULL, pubOut, NULL);
}
/* create the public ECC key from a private key - mask timing use random z
*
* key an initialized private key to generate public part from
* pubOut [out]ecc_point holding the public key, if NULL then public key part
* is cached in key instead.
*
*
* returns MP_OKAY on success
*/
int wc_ecc_make_pub_ex(ecc_key* key, ecc_point* pubOut, WC_RNG* rng)
{
WOLFSSL_ENTER("wc_ecc_make_pub");
return ecc_make_pub_ex(key, NULL, pubOut, rng);
}
@ -4305,7 +4475,7 @@ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id)
/* generate public key from k */
if (err == MP_OKAY)
err = wc_ecc_make_pub_ex(key, curve, NULL);
err = ecc_make_pub_ex(key, curve, NULL, rng);
if (err == MP_OKAY)
key->type = ECC_PRIVATEKEY;
@ -5188,7 +5358,7 @@ int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng,
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);
err = ecc_make_pub_ex(pubkey, curve, NULL, rng);
}
else
#endif
@ -5992,7 +6162,7 @@ int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash,
/* checking if private key with no public part */
if (key->type == ECC_PRIVATEKEY_ONLY) {
WOLFSSL_MSG("Verify called with private key, generating public part");
err = wc_ecc_make_pub_ex(key, NULL, NULL);
err = ecc_make_pub_ex(key, NULL, NULL, NULL);
if (err != MP_OKAY) {
WOLFSSL_MSG("Unable to extract public key");
return err;
@ -6947,9 +7117,15 @@ static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime)
if (err == MP_OKAY)
err = mp_set(base->z, 1);
#ifdef ECC_TIMING_RESISTANT
if (err == MP_OKAY)
err = wc_ecc_mulmod_ex2(&key->k, base, res, a, prime, curve->order,
1, key->heap);
key->rng, 1, key->heap);
#else
if (err == MP_OKAY)
err = wc_ecc_mulmod_ex2(&key->k, base, res, a, prime, curve->order,
NULL, 1, key->heap);
#endif
}
if (err == MP_OKAY) {
@ -9657,7 +9833,7 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a,
if (err == MP_OKAY)
err = accel_fp_mul(idx, k, R, a, modulus, mp, map);
} else {
err = normal_ecc_mulmod(k, G, R, a, modulus, map, heap);
err = normal_ecc_mulmod(k, G, R, a, modulus, NULL, map, heap);
}
}
@ -9689,7 +9865,7 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a,
#ifndef WOLFSSL_SP_MATH
static int normal_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R,
mp_int* a, mp_int* modulus, mp_int* order,
int map, void* heap)
WC_RNG* rng, int map, void* heap)
{
int err;
mp_int t;
@ -9721,7 +9897,7 @@ static int normal_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R,
}
if (err == MP_OKAY) {
err = normal_ecc_mulmod(&t, G, R, a, modulus, map, heap);
err = normal_ecc_mulmod(&t, G, R, a, modulus, rng, map, heap);
}
mp_forcezero(&t);
@ -9743,7 +9919,7 @@ static int normal_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R,
return MP_OKAY if successful
*/
int wc_ecc_mulmod_ex2(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a,
mp_int* modulus, mp_int* order, int map, void* heap)
mp_int* modulus, mp_int* order, WC_RNG* rng, int map, void* heap)
{
#ifndef WOLFSSL_SP_MATH
int idx, err = MP_OKAY;
@ -9813,7 +9989,8 @@ int wc_ecc_mulmod_ex2(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a,
if (err == MP_OKAY)
err = accel_fp_mul(idx, k, R, a, modulus, mp, map);
} else {
err = normal_ecc_mulmod_ex(k, G, R, a, modulus, order, map, heap);
err = normal_ecc_mulmod_ex(k, G, R, a, modulus, order, rng, map,
heap);
}
}
@ -9908,6 +10085,22 @@ void wc_ecc_fp_free(void)
#endif /* FP_ECC */
#ifdef ECC_TIMING_RESISTANT
int wc_ecc_set_rng(ecc_key* key, WC_RNG* rng)
{
int err = 0;
if (key == NULL) {
err = BAD_FUNC_ARG;
}
else {
key->rng = rng;
}
return err;
}
#endif
#ifdef HAVE_ECC_ENCRYPT

@ -1413,16 +1413,40 @@ int wolfSSL_EVP_PKEY_derive(WOLFSSL_EVP_PKEY_CTX *ctx, unsigned char *key, size_
}
if (key) {
word32 len32 = (word32)len;
#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_FIPS) && \
!defined(HAVE_SELFTEST)
WC_RNG rng;
if (wc_InitRng(&rng) != MP_OKAY) {
WOLFSSL_MSG("Init RNG failed");
return WOLFSSL_FAILURE;
}
((ecc_key*)ctx->pkey->ecc->internal)->rng = &rng;
#endif
if (*keylen < len32) {
WOLFSSL_MSG("buffer too short");
#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_FIPS) && \
!defined(HAVE_SELFTEST)
((ecc_key*)ctx->pkey->ecc->internal)->rng = NULL;
wc_FreeRng(&rng);
#endif
return WOLFSSL_FAILURE;
}
if (wc_ecc_shared_secret_ssh((ecc_key*)ctx->pkey->ecc->internal,
(ecc_point*)ctx->peerKey->ecc->pub_key->internal,
key, &len32) != MP_OKAY) {
WOLFSSL_MSG("wc_ecc_shared_secret failed");
#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_FIPS) && \
!defined(HAVE_SELFTEST)
((ecc_key*)ctx->pkey->ecc->internal)->rng = NULL;
wc_FreeRng(&rng);
#endif
return WOLFSSL_FAILURE;
}
#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_FIPS) && \
!defined(HAVE_SELFTEST)
((ecc_key*)ctx->pkey->ecc->internal)->rng = NULL;
wc_FreeRng(&rng);
#endif
len = (int)len32;
}
*keylen = (size_t)len;

@ -5531,7 +5531,7 @@ static int wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI* kari, int keyWrapOID)
/* create key encryption key (KEK) using key wrap algorithm and key encryption
* algorithm, place in kari->kek. return 0 on success, <0 on error. */
static int wc_PKCS7_KariGenerateKEK(WC_PKCS7_KARI* kari,
static int wc_PKCS7_KariGenerateKEK(WC_PKCS7_KARI* kari, WC_RNG* rng,
int keyWrapOID, int keyEncOID)
{
int ret;
@ -5566,6 +5566,19 @@ static int wc_PKCS7_KariGenerateKEK(WC_PKCS7_KARI* kari,
if (secret == NULL)
return MEMORY_E;
#if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) && \
!defined(HAVE_SELFTEST)
ret = wc_ecc_set_rng(kari->senderKey, rng);
if (ret != 0)
return ret;
ret = wc_ecc_set_rng(kari->recipKey, rng);
if (ret != 0)
return ret;
#else
(void)rng;
#endif
if (kari->direction == WC_PKCS7_ENCODE) {
ret = wc_ecc_shared_secret(kari->senderKey, kari->recipKey,
@ -5797,7 +5810,7 @@ int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz,
}
/* generate KEK (key encryption key) */
ret = wc_PKCS7_KariGenerateKEK(kari, keyWrapOID, keyAgreeOID);
ret = wc_PKCS7_KariGenerateKEK(kari, pkcs7->rng, keyWrapOID, keyAgreeOID);
if (ret != 0) {
wc_PKCS7_KariFree(kari);
#ifdef WOLFSSL_SMALL_STACK
@ -9397,7 +9410,8 @@ static int wc_PKCS7_DecryptKari(PKCS7* pkcs7, byte* in, word32 inSz,
}
else {
/* create KEK */
ret = wc_PKCS7_KariGenerateKEK(kari, keyWrapOID, pkcs7->keyAgreeOID);
ret = wc_PKCS7_KariGenerateKEK(kari, pkcs7->rng, keyWrapOID,
pkcs7->keyAgreeOID);
if (ret != 0) {
wc_PKCS7_KariFree(kari);
#ifdef WOLFSSL_SMALL_STACK

@ -3492,11 +3492,12 @@ int fp_montgomery_reduce_ex(fp_int *a, fp_int *m, fp_digit mp, int ct)
a->used = pa+1;
fp_clamp(a);
#ifdef WOLFSSL_MONT_RED_NCT
#ifndef WOLFSSL_MONT_RED_CT
/* if A >= m then A = A - m */
if (fp_cmp_mag (a, m) != FP_LT) {
s_fp_sub (a, m, a);
}
(void)ct;
#else
if (ct) {
fp_submod_ct(a, m, m, a);

@ -18260,7 +18260,7 @@ done:
#endif
#ifdef HAVE_ECC_CDH
static int ecc_test_cdh_vectors(void)
static int ecc_test_cdh_vectors(WC_RNG* rng)
{
int ret;
ecc_key pub_key, priv_key;
@ -18292,6 +18292,16 @@ static int ecc_test_cdh_vectors(void)
if (ret != 0)
goto done;
#if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) && \
!defined(HAVE_SELFTEST)
ret = wc_ecc_set_rng(&priv_key, rng);
if (ret != 0)
goto done;
#else
(void)rng;
#endif
/* compute ECC Cofactor shared secret */
x = sizeof(sharedA);
do {
@ -18517,6 +18527,14 @@ static int ecc_test_make_pub(WC_RNG* rng)
}
TEST_SLEEP();
#if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) && \
!defined(HAVE_SELFTEST)
ret = wc_ecc_set_rng(&key, rng);
if (ret != 0)
goto done;
#endif
x = sizeof(exportBuf);
do {
#if defined(WOLFSSL_ASYNC_CRYPT)
@ -18766,6 +18784,17 @@ static int ecc_test_curve_size(WC_RNG* rng, int keySize, int testVerifyCount,
}
#ifdef HAVE_ECC_DHE
#if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) && \
!defined(HAVE_SELFTEST)
ret = wc_ecc_set_rng(&userA, rng);
if (ret != 0)
goto done;
ret = wc_ecc_set_rng(&userB, rng);
if (ret != 0)
goto done;
#endif
x = ECC_SHARED_SIZE;
do {
#if defined(WOLFSSL_ASYNC_CRYPT)
@ -19528,7 +19557,7 @@ done:
#endif
#ifdef HAVE_ECC_DHE
static int ecc_ssh_test(ecc_key* key)
static int ecc_ssh_test(ecc_key* key, WC_RNG* rng)
{
int ret;
byte out[128];
@ -19548,6 +19577,16 @@ static int ecc_ssh_test(ecc_key* key)
if (ret != BAD_FUNC_ARG)
return -9747;
#if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) && \
!defined(HAVE_SELFTEST)
ret = wc_ecc_set_rng(key, rng);
if (ret != 0)
return -9748;
#else
(void)rng;
#endif
/* Use API. */
ret = 0;
do {
@ -19558,7 +19597,7 @@ static int ecc_ssh_test(ecc_key* key)
ret = wc_ecc_shared_secret_ssh(key, &key->pubkey, out, &outLen);
} while (ret == WC_PENDING_E);
if (ret != 0)
return -9748;
return -9749;
TEST_SLEEP();
return 0;
}
@ -19613,7 +19652,7 @@ static int ecc_def_curve_test(WC_RNG *rng)
goto done;
#endif
#ifdef HAVE_ECC_DHE
ret = ecc_ssh_test(&key);
ret = ecc_ssh_test(&key, rng);
if (ret < 0)
goto done;
#endif
@ -20667,7 +20706,7 @@ int ecc_test(void)
}
#endif
#ifdef HAVE_ECC_CDH
ret = ecc_test_cdh_vectors();
ret = ecc_test_cdh_vectors(&rng);
if (ret != 0) {
printf("ecc_test_cdh_vectors failed! %d\n", ret);
goto done;
@ -20773,6 +20812,19 @@ int ecc_encrypt_test(void)
for (i = 0; i < (int)sizeof(msg); i++)
msg[i] = i;
#if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) && \
!defined(HAVE_SELFTEST)
ret = wc_ecc_set_rng(&userA, &rng);
if (ret != 0) {
ret = -10011; goto done;
}
ret = wc_ecc_set_rng(&userB, &rng);
if (ret != 0) {
ret = -10012; goto done;
}
#endif
/* encrypt msg to B */
ret = wc_ecc_encrypt(&userA, &userB, msg, sizeof(msg), out, &outSz, NULL);
if (ret != 0) {
@ -20923,6 +20975,15 @@ int ecc_test_buffers(void) {
if (ret != 0)
return -10015;
#if defined(ECC_TIMING_RESISTANT) && (!defined(HAVE_FIPS) || \
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) && \
!defined(HAVE_SELFTEST)
ret = wc_ecc_set_rng(&cliKey, &rng);
if (ret != 0) {
return -10023;
}
#endif
#if defined(HAVE_ECC_ENCRYPT) && defined(HAVE_HKDF)
{
word32 y;
@ -24856,6 +24917,7 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz,
byte enveloped[2048];
byte decoded[2048];
PKCS7* pkcs7;
WC_RNG rng;
#ifdef PKCS7_OUTPUT_TEST_BUNDLES
XFILE pkcs7File;
#endif
@ -25012,6 +25074,17 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz,
testSz = sizeof(testVectors) / sizeof(pkcs7EnvelopedVector);
#ifdef ECC_TIMING_RESISTANT
#ifndef HAVE_FIPS
ret = wc_InitRng_ex(&rng, HEAP_HINT, devId);
#else
ret = wc_InitRng(&rng);
#endif
if (ret != 0) {
return -11760;
}
#endif
for (i = 0; i < testSz; i++) {
pkcs7 = wc_PKCS7_New(HEAP_HINT,
#ifdef WOLFSSL_ASYNC_CRYPT
@ -25172,6 +25245,9 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz,
}
}
#ifdef ECC_TIMING_RESISTANT
pkcs7->rng = &rng;
#endif
/* encode envelopedData */
envelopedSz = wc_PKCS7_EncodeEnvelopedData(pkcs7, enveloped,
sizeof(enveloped));
@ -25233,6 +25309,10 @@ static int pkcs7enveloped_run_vectors(byte* rsaCert, word32 rsaCertSz,
pkcs7 = NULL;
}
#ifdef ECC_TIMING_RESISTANT
wc_FreeRng(&rng);
#endif
(void)eccCert;
(void)eccCertSz;
(void)eccPrivKey;
@ -25633,8 +25713,6 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz,
wc_FreeRng(&rng);
return -11806;
}
wc_FreeRng(&rng);
}
for (i = 0; i < testSz; i++) {
@ -25808,6 +25886,10 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz,
}
}
#ifdef ECC_TIMING_RESISTANT
pkcs7->rng = &rng;
#endif
/* encode envelopedData */
envelopedSz = wc_PKCS7_EncodeAuthEnvelopedData(pkcs7, enveloped,
sizeof(enveloped));
@ -25869,6 +25951,8 @@ static int pkcs7authenveloped_run_vectors(byte* rsaCert, word32 rsaCertSz,
pkcs7 = NULL;
}
wc_FreeRng(&rng);
#if !defined(HAVE_ECC) || defined(NO_AES)
(void)eccCert;
(void)eccCertSz;

@ -2673,6 +2673,13 @@ static WC_INLINE int myEccSharedSecret(WOLFSSL* ssl, ecc_key* otherKey,
ret = BAD_FUNC_ARG;
}
#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_FIPS) && \
!defined(HAVE_SELFTEST)
if (ret == 0) {
ret = wc_ecc_set_rng(privKey, wolfSSL_GetRNG(ssl));
}
#endif
/* generate shared secret and return it */
if (ret == 0) {
ret = wc_ecc_shared_secret(privKey, pubKey, out, outlen);

@ -431,6 +431,9 @@ struct ecc_key {
#ifdef WOLFSSL_DSP
remote_handle64 handle;
#endif
#ifdef ECC_TIMING_RESISTANT
WC_RNG* rng;
#endif
#ifdef WC_ECC_NONBLOCK
ecc_nb_ctx_t* nb_ctx;
#endif
@ -476,6 +479,8 @@ int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id);
WOLFSSL_API
int wc_ecc_make_pub(ecc_key* key, ecc_point* pubOut);
WOLFSSL_API
int wc_ecc_make_pub_ex(ecc_key* key, ecc_point* pubOut, WC_RNG* rng);
WOLFSSL_API
int wc_ecc_check_key(ecc_key* key);
WOLFSSL_API
int wc_ecc_is_point(ecc_point* ecp, mp_int* a, mp_int* b, mp_int* prime);
@ -545,6 +550,10 @@ WOLFSSL_API
void wc_ecc_fp_free(void);
WOLFSSL_LOCAL
void wc_ecc_fp_init(void);
#ifdef ECC_TIMING_RESISTANT
WOLFSSL_API
int wc_ecc_set_rng(ecc_key* key, WC_RNG* rng);
#endif
WOLFSSL_API
int wc_ecc_set_curve(ecc_key* key, int keysize, int curve_id);
@ -602,7 +611,8 @@ int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R,
mp_int* a, mp_int* modulus, int map, void* heap);
WOLFSSL_LOCAL
int wc_ecc_mulmod_ex2(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a,
mp_int* modulus, mp_int* order, int map, void* heap);
mp_int* modulus, mp_int* order, WC_RNG* rng, int map,
void* heap);
#endif /* !WOLFSSL_ATECC508A */