Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/configs/os-check-linux.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
{"name": "all-dtls13-frag-ch-no-mlkem", "minutes": 8.2,
"configure": ["--enable-all", "--enable-dtls13", "--enable-dtls-frag-ch",
"--disable-mlkem"]},
{"name": "all-ecc-blind-k", "minutes": 8.0,
"comment": "Only entry that sets WOLFSSL_ECC_BLIND_K (the blind-private-key entry sets WOLFSSL_BLIND_PRIVATE_KEY, which does not imply it). Keeps the read-only wc_ecc_key_get_priv() contract exercised in CI. pkcs11 is on because wc_pkcs11.c is not compiled anywhere else in this matrix.",
"configure": ["--enable-all", "--enable-pkcs11",
"CPPFLAGS=-DWOLFSSL_ECC_BLIND_K"]},
{"name": "all-check-mem-zero", "minutes": 7.9,
"configure": ["--enable-all", "CPPFLAGS=-DWOLFSSL_CHECK_MEM_ZERO"]},
{"name": "all-faultharden-pk-privkey", "minutes": 7.8,
Expand Down
24 changes: 19 additions & 5 deletions src/pk_ec.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@
#endif
#ifndef WOLFSSL_HAVE_ECC_KEY_GET_PRIV
/* FIPS build has replaced ecc.h. */
#define wc_ecc_key_get_priv(key) (&((key)->k))
#define wc_ecc_key_get_priv(key) (&((key)->k))
#define ecc_get_k_raw(key) (&((key)->k))
#define ecc_blind_k_rng(key, rng) 0
#define WOLFSSL_HAVE_ECC_KEY_GET_PRIV
#endif

Expand Down Expand Up @@ -3161,9 +3163,15 @@ static int wolfssl_ec_key_int_copy(ecc_key* dst, const ecc_key* src)
}

if (ret == 0) {
/* Copy private key. */
ret = mp_copy(wc_ecc_key_get_priv((ecc_key*)src),
wc_ecc_key_get_priv(dst));
/* Copy the stored private scalar, and its blind where the build
* keeps one. The wc_ecc_key_get_priv() accessor cannot be used
* here: it is read-only, and reading needs dst->dp, not set yet. */
ret = mp_copy(ecc_get_k_raw((ecc_key*)src), ecc_get_k_raw(dst));
#ifdef WOLFSSL_ECC_BLIND_K
if (ret == MP_OKAY) {
ret = mp_copy(((ecc_key*)src)->kb, dst->kb);
}
#endif
if (ret != MP_OKAY) {
WOLFSSL_MSG("mp_copy error");
}
Expand Down Expand Up @@ -4446,11 +4454,17 @@ int SetECKeyInternal(WOLFSSL_EC_KEY* eckey)

/* set privkey */
if ((ret == 1) && (eckey->priv_key != NULL)) {
/* Write the stored scalar, then install a fresh blind so any
* blind left from a previous use of this key is replaced. */
if (wolfssl_bn_get_value(eckey->priv_key,
wc_ecc_key_get_priv(key)) != 1) {
ecc_get_k_raw(key)) != 1) {
WOLFSSL_MSG("ec key priv error");
ret = WOLFSSL_FATAL_ERROR;
}
if ((ret == 1) && (ecc_blind_k_rng(key, NULL) != 0)) {
WOLFSSL_MSG("ec key priv blind error");
ret = WOLFSSL_FATAL_ERROR;
}
/* private key */
if ((ret == 1) && (!mp_iszero(wc_ecc_key_get_priv(key)))) {
if (pubSet) {
Expand Down
41 changes: 36 additions & 5 deletions wolfcrypt/src/ecc.c
Original file line number Diff line number Diff line change
Expand Up @@ -378,15 +378,33 @@ ECC Curve Sizes:
#endif

#ifdef WOLFSSL_ECC_BLIND_K
/* Number of digits covered by the fixed-width XORs below. */
#define ECC_BLIND_K_DIGITS(key) \
((int)(((key)->dp->size + sizeof(mp_digit) - 1) / sizeof(mp_digit)))

/* The XORs read this many whole digits regardless of each operand's current
* length, so operands written at partial width (e.g. by mp_copy()) must be
* zero-extended first or stale digits fold into the value. mp_grow() cannot
* fail for a curve-sized key; fail closed if it ever does. */
mp_int* ecc_get_k(ecc_key* key)
{
mp_xor_ct(key->k, key->kb, key->dp->size, key->ku);
if ((mp_grow(key->k, ECC_BLIND_K_DIGITS(key)) != MP_OKAY) ||
(mp_grow(key->kb, ECC_BLIND_K_DIGITS(key)) != MP_OKAY)) {
mp_forcezero(key->ku);
}
else {
mp_xor_ct(key->k, key->kb, key->dp->size, key->ku);
}
return key->ku;
}
void ecc_blind_k(ecc_key* key, mp_int* b)
{
mp_xor_ct(key->k, b, key->dp->size, key->k);
mp_xor_ct(key->kb, b, key->dp->size, key->kb);
if ((mp_grow(key->k, ECC_BLIND_K_DIGITS(key)) == MP_OKAY) &&
(mp_grow(key->kb, ECC_BLIND_K_DIGITS(key)) == MP_OKAY) &&
(mp_grow(b, ECC_BLIND_K_DIGITS(key)) == MP_OKAY)) {
mp_xor_ct(key->k, b, key->dp->size, key->k);
mp_xor_ct(key->kb, b, key->dp->size, key->kb);
}
}
int ecc_blind_k_rng(ecc_key* key, WC_RNG* rng)
{
Expand All @@ -405,11 +423,17 @@ int ecc_blind_k_rng(ecc_key* key, WC_RNG* rng)
}
}
if (ret == 0) {
ret = mp_rand(key->kb, (key->dp->size + sizeof(mp_digit) - 1) /
sizeof(mp_digit), rng);
ret = mp_rand(key->kb, ECC_BLIND_K_DIGITS(key), rng);
if (ret == 0) {
ret = mp_grow(key->k, ECC_BLIND_K_DIGITS(key));
}
if (ret == 0) {
mp_xor_ct(key->k, key->kb, key->dp->size, key->k);
}
else {
/* No blind installed - keep the stored pair consistent. */
mp_forcezero(key->kb);
}
}

if (rng == &local_rng) {
Expand All @@ -418,6 +442,13 @@ int ecc_blind_k_rng(ecc_key* key, WC_RNG* rng)
return ret;
}

void ecc_forcezero_k(ecc_key* key)
{
mp_forcezero(key->k);
mp_forcezero(key->kb);
mp_forcezero(key->ku);
}

mp_int* wc_ecc_key_get_priv(ecc_key* key)
{
return ecc_get_k(key);
Expand Down
21 changes: 15 additions & 6 deletions wolfcrypt/src/eccsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@

#ifndef WOLFSSL_HAVE_ECC_KEY_GET_PRIV
/* FIPS build has replaced ecc.h. */
#define wc_ecc_key_get_priv(key) (&((key)->k))
#define wc_ecc_key_get_priv(key) (&((key)->k))
#define ecc_get_k_raw(key) (&((key)->k))
#define ecc_blind_k_rng(key, rng) 0
#define ecc_forcezero_k(key) mp_forcezero(&((key)->k))
#define WOLFSSL_HAVE_ECC_KEY_GET_PRIV
#endif

Expand Down Expand Up @@ -679,8 +682,11 @@ static int eccsi_decode_key(EccsiKey* key, const byte* data)
int err;

/* Read the secret value from key size bytes. */
err = mp_read_unsigned_bin(wc_ecc_key_get_priv(&key->ecc), data,
err = mp_read_unsigned_bin(ecc_get_k_raw(&key->ecc), data,
(word32)key->ecc.dp->size);
if (err == 0) {
err = ecc_blind_k_rng(&key->ecc, NULL);
}
if (err == 0) {
data += key->ecc.dp->size;
/* Read public key. */
Expand Down Expand Up @@ -809,9 +815,12 @@ int wc_ImportEccsiPrivateKey(EccsiKey* key, const byte* data, word32 sz)
}

if (err == 0) {
err = mp_read_unsigned_bin(wc_ecc_key_get_priv(&key->ecc), data,
err = mp_read_unsigned_bin(ecc_get_k_raw(&key->ecc), data,
(word32)key->ecc.dp->size);
}
if (err == 0) {
err = ecc_blind_k_rng(&key->ecc, NULL);
}

return err;
}
Expand Down Expand Up @@ -926,7 +935,7 @@ static int eccsi_make_pair(EccsiKey* key, WC_RNG* rng,
/* Step 5: ensure SSK and HS are non-zero (code lines above) */

/* Step 6: Copy out SSK (done during calc) and PVT. Erase v */
mp_forcezero(wc_ecc_key_get_priv(&key->pubkey));
ecc_forcezero_k(&key->pubkey);

return err;
}
Expand Down Expand Up @@ -2010,10 +2019,10 @@ int wc_SignEccsiHash(EccsiKey* key, WC_RNG* rng, enum wc_HashType hashType,
if (err == 0) {
j = wc_ecc_key_get_priv(&key->pubkey);
err = mp_mulmod(s, j, &key->params.order, s);
/* Erase j on the failure path too. */
ecc_forcezero_k(&key->pubkey);
}
if (err == 0) {
mp_forcezero(j);

/* Step 6: s = s' fitted */
err = eccsi_fit_to_octets(s, &key->params.order, (int)sz, s);
}
Expand Down
22 changes: 15 additions & 7 deletions wolfcrypt/src/port/silabs/silabs_ecc.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ static sl_se_key_descriptor_t private_device_key =

#ifndef WOLFSSL_HAVE_ECC_KEY_GET_PRIV
/* FIPS build has replaced ecc.h. */
#define wc_ecc_key_get_priv(key) (&((key)->k))
#define wc_ecc_key_get_priv(key) (&((key)->k))
#define ecc_get_k_raw(key) (&((key)->k))
#define ecc_blind_k_rng(key, rng) 0
#define WOLFSSL_HAVE_ECC_KEY_GET_PRIV
#endif

Expand Down Expand Up @@ -209,12 +211,18 @@ int silabs_ecc_make_key(ecc_key* key, int keysize)
key->type = ECC_PRIVATEKEY;

/* copy key to mp components */
mp_read_unsigned_bin(key->pubkey.x,
key->key.storage.location.buffer.pointer, keysize);
mp_read_unsigned_bin(key->pubkey.y,
key->key.storage.location.buffer.pointer + keysize, keysize);
mp_read_unsigned_bin(wc_ecc_key_get_priv(key),
key->key.storage.location.buffer.pointer + (2 * keysize), keysize);
if ((mp_read_unsigned_bin(key->pubkey.x,
key->key.storage.location.buffer.pointer,
keysize) != MP_OKAY) ||
(mp_read_unsigned_bin(key->pubkey.y,
key->key.storage.location.buffer.pointer + keysize,
keysize) != MP_OKAY) ||
(mp_read_unsigned_bin(ecc_get_k_raw(key),
key->key.storage.location.buffer.pointer + (2 * keysize),
keysize) != MP_OKAY) ||
(ecc_blind_k_rng(key, NULL) != 0)) {
return WC_HW_E;
}
}

return (sl_stat == SL_STATUS_OK) ? 0 : WC_HW_E;
Expand Down
26 changes: 19 additions & 7 deletions wolfcrypt/src/sakke.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,9 @@

#ifndef WOLFSSL_HAVE_ECC_KEY_GET_PRIV
/* FIPS build has replaced ecc.h. */
#define wc_ecc_key_get_priv(key) (&((key)->k))
#define wc_ecc_key_get_priv(key) (&((key)->k))
#define ecc_get_k_raw(key) (&((key)->k))
#define ecc_blind_k_rng(key, rng) 0
#define WOLFSSL_HAVE_ECC_KEY_GET_PRIV
#endif

Expand Down Expand Up @@ -533,14 +535,18 @@ int wc_MakeSakkeKey(SakkeKey* key, WC_RNG* rng)
err = RNG_FAILURE_E;
}
if (err == 0) {
err = mp_rand(wc_ecc_key_get_priv(&key->ecc), digits, rng);
err = mp_rand(ecc_get_k_raw(&key->ecc), digits, rng);
}
if (err == 0) {
err = mp_mod(wc_ecc_key_get_priv(&key->ecc), &key->params.q,
wc_ecc_key_get_priv(&key->ecc));
err = mp_mod(ecc_get_k_raw(&key->ecc), &key->params.q,
ecc_get_k_raw(&key->ecc));
}
}
while ((err == 0) && mp_iszero(wc_ecc_key_get_priv(&key->ecc)));
while ((err == 0) && mp_iszero(ecc_get_k_raw(&key->ecc)));

if (err == 0) {
err = ecc_blind_k_rng(&key->ecc, rng);
}
}
if (err == 0) {
/* Calculate public key by multiply master secret by base point. */
Expand Down Expand Up @@ -672,9 +678,12 @@ int wc_ImportSakkeKey(SakkeKey* key, const byte* data, word32 sz)

if (err == 0) {
/* Read the secret value from key size bytes. */
err = mp_read_unsigned_bin(wc_ecc_key_get_priv(&key->ecc), data,
err = mp_read_unsigned_bin(ecc_get_k_raw(&key->ecc), data,
(word32)key->ecc.dp->size);
}
if (err == 0) {
err = ecc_blind_k_rng(&key->ecc, NULL);
}
if (err == 0) {
data += key->ecc.dp->size;
/* Read the public key point's x value from key size bytes. */
Expand Down Expand Up @@ -770,9 +779,12 @@ int wc_ImportSakkePrivateKey(SakkeKey* key, const byte* data, word32 sz)

if (err == 0) {
/* Read the secret value from key size bytes. */
err = mp_read_unsigned_bin(wc_ecc_key_get_priv(&key->ecc), data,
err = mp_read_unsigned_bin(ecc_get_k_raw(&key->ecc), data,
(word32)key->ecc.dp->size);
}
if (err == 0) {
err = ecc_blind_k_rng(&key->ecc, NULL);
}

return err;
}
Expand Down
5 changes: 3 additions & 2 deletions wolfcrypt/src/wc_pkcs11.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@

#ifndef WOLFSSL_HAVE_ECC_KEY_GET_PRIV
/* FIPS build has replaced ecc.h. */
#define wc_ecc_key_get_priv(key) (&((key)->k))
#define wc_ecc_key_get_priv(key) (&((key)->k))
#define ecc_forcezero_k(key) mp_forcezero(&((key)->k))
#define WOLFSSL_HAVE_ECC_KEY_GET_PRIV
#endif

Expand Down Expand Up @@ -2186,7 +2187,7 @@ int wc_Pkcs11StoreKey(Pkcs11Token* token, int type, int clear, void* key)
ret = ret2;
}
if (ret == 0 && clear)
mp_forcezero(wc_ecc_key_get_priv(eccKey));
ecc_forcezero_k(eccKey);
break;
}
#endif
Expand Down
8 changes: 8 additions & 0 deletions wolfssl/wolfcrypt/ecc.h
Original file line number Diff line number Diff line change
Expand Up @@ -687,15 +687,23 @@ struct ecc_key {
#define ecc_get_k(key) (key)->k
#define ecc_blind_k(key, b) (void)b
#define ecc_blind_k_rng(key, rng) 0
#define ecc_forcezero_k(key) mp_forcezero((key)->k)

#define wc_ecc_key_get_priv(key) (key)->k
#else
mp_int* ecc_get_k(ecc_key* key);
void ecc_blind_k(ecc_key* key, mp_int* b);
int ecc_blind_k_rng(ecc_key* key, WC_RNG* rng);
WOLFSSL_LOCAL void ecc_forcezero_k(ecc_key* key);

WOLFSSL_API mp_int* wc_ecc_key_get_priv(ecc_key* key);
#endif
/* Writable handle on the stored private scalar. With blinding enabled,
* wc_ecc_key_get_priv() returns a value regenerated into scratch, so it is
* read-only: writes through it are discarded and erasing it leaves the
* secret in place. Write a new scalar through this instead, then install a
* fresh blind with ecc_blind_k_rng(); erase with ecc_forcezero_k(). */
#define ecc_get_k_raw(key) (key)->k

#define WOLFSSL_HAVE_ECC_KEY_GET_PRIV

Expand Down
Loading