mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-08 08:30:48 +02:00
Even more missing ForceZero in ML-KEM / ML-DSA
Ensure that all sensitive private key (derived) data is zeroed.
This commit is contained in:
@@ -3628,6 +3628,8 @@ static int mldsa_rej_bound_poly(wc_Shake* shake256, byte* seed, sword32* s,
|
||||
while (j < MLDSA_N);
|
||||
}
|
||||
|
||||
/* z holds the secret s1/s2 bytes. */
|
||||
ForceZero(z, sizeof(z));
|
||||
return ret;
|
||||
#else
|
||||
int ret;
|
||||
@@ -3656,6 +3658,8 @@ static int mldsa_rej_bound_poly(wc_Shake* shake256, byte* seed, sword32* s,
|
||||
}
|
||||
}
|
||||
|
||||
/* z holds the secret s1/s2 bytes. */
|
||||
ForceZero(z, MLDSA_GEN_S_BYTES);
|
||||
WC_FREE_VAR_EX(z, NULL, DYNAMIC_TYPE_MLDSA);
|
||||
return ret;
|
||||
#endif
|
||||
@@ -3760,6 +3764,9 @@ static int wc_mldsa_gen_s_4_4_avx2(sword32* s[2], byte* seed)
|
||||
(ctr3 < MLDSA_N));
|
||||
}
|
||||
|
||||
/* rand/state hold secret s-vector material. */
|
||||
ForceZero(rand, 4 * MLDSA_GEN_S_BLOCK_BYTES);
|
||||
ForceZero(state, sizeof(word64) * 25 * 4);
|
||||
WC_FREE_VAR_EX(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
WC_FREE_VAR_EX(state, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
|
||||
@@ -3913,6 +3920,9 @@ static int wc_mldsa_gen_s_5_6_avx2(sword32* s[2], byte* seed)
|
||||
/* Create more blocks if too many rejected. */
|
||||
while ((ctr0 < MLDSA_N) || (ctr1 < MLDSA_N) || (ctr2 < MLDSA_N));
|
||||
|
||||
/* rand/state hold secret s-vector material. */
|
||||
ForceZero(rand, 4 * MLDSA_GEN_S_BLOCK_BYTES);
|
||||
ForceZero(state, sizeof(word64) * 25 * 4);
|
||||
WC_FREE_VAR_EX(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
WC_FREE_VAR_EX(state, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
|
||||
@@ -4068,6 +4078,9 @@ static int wc_mldsa_gen_s_7_8_avx2(sword32* s[2], byte* seed)
|
||||
/* Create more blocks if too many rejected. */
|
||||
while ((ctr0 < MLDSA_N) || (ctr1 < MLDSA_N) || (ctr2 < MLDSA_N));
|
||||
|
||||
/* rand/state hold secret s-vector material. */
|
||||
ForceZero(rand, 4 * MLDSA_GEN_S_BLOCK_BYTES);
|
||||
ForceZero(state, sizeof(word64) * 25 * 4);
|
||||
WC_FREE_VAR_EX(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
WC_FREE_VAR_EX(state, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
|
||||
@@ -4257,6 +4270,9 @@ static int wc_mldsa_gen_y_4_avx2(sword32* y, byte* seed, word16 kappa)
|
||||
wc_mldsa_decode_gamma1_17_avx2(rand + 3 * MLDSA_MAX_V,
|
||||
y + 3 * MLDSA_N);
|
||||
|
||||
/* rand/state hold the secret mask y. */
|
||||
ForceZero(rand, 4 * MLDSA_MAX_V);
|
||||
ForceZero(state, sizeof(word64) * 25 * 4);
|
||||
WC_FREE_VAR_EX(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
WC_FREE_VAR_EX(state, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
|
||||
@@ -4337,6 +4353,9 @@ static int wc_mldsa_gen_y_5_avx2(sword32* y, byte* seed, word16 kappa,
|
||||
wc_mldsa_decode_gamma1_19_avx2(rand, y + 4 * MLDSA_N);
|
||||
}
|
||||
|
||||
/* rand/state hold the secret mask y. */
|
||||
ForceZero(rand, 4 * MLDSA_MAX_V);
|
||||
ForceZero(state, sizeof(word64) * 25 * 4);
|
||||
WC_FREE_VAR_EX(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
WC_FREE_VAR_EX(state, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
|
||||
@@ -4432,6 +4451,9 @@ static int wc_mldsa_gen_y_7_avx2(sword32* y, byte* seed, word16 kappa)
|
||||
wc_mldsa_decode_gamma1_19_avx2(rand + 2 * MLDSA_MAX_V,
|
||||
y + 6 * MLDSA_N);
|
||||
|
||||
/* rand/state hold the secret mask y. */
|
||||
ForceZero(rand, 4 * MLDSA_MAX_V);
|
||||
ForceZero(state, sizeof(word64) * 25 * 4);
|
||||
WC_FREE_VAR_EX(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
WC_FREE_VAR_EX(state, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
|
||||
@@ -4490,6 +4512,8 @@ static int mldsa_vec_expand_mask_c(wc_Shake* shake256, byte* seed,
|
||||
}
|
||||
}
|
||||
|
||||
/* v holds the secret mask y. */
|
||||
ForceZero(v, MLDSA_MAX_V);
|
||||
WC_FREE_VAR_EX(v, NULL, DYNAMIC_TYPE_MLDSA);
|
||||
return ret;
|
||||
}
|
||||
@@ -10934,6 +10958,9 @@ int wc_MlDsaKey_InitLabel(wc_MlDsaKey* key, const char* label, void* heap,
|
||||
int wc_MlDsaKey_SetParams(wc_MlDsaKey* key, byte level)
|
||||
{
|
||||
int ret = 0;
|
||||
#if !defined(WC_MLDSA_FIXED_ARRAY) && defined(WC_MLDSA_CACHE_PRIV_VECTORS)
|
||||
const wc_MlDsaParams* oldParams = NULL;
|
||||
#endif
|
||||
|
||||
/* Validate parameters. */
|
||||
if (key == NULL) {
|
||||
@@ -10954,6 +10981,11 @@ int wc_MlDsaKey_SetParams(wc_MlDsaKey* key, byte level)
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
#if !defined(WC_MLDSA_FIXED_ARRAY) && defined(WC_MLDSA_CACHE_PRIV_VECTORS)
|
||||
/* Save old params to size the cached-vector wipe below (key->params
|
||||
* is about to change to the new level). */
|
||||
oldParams = key->params;
|
||||
#endif
|
||||
/* Get the parameters for level into key. */
|
||||
ret = mldsa_get_params(level, &key->params);
|
||||
}
|
||||
@@ -10966,6 +10998,11 @@ int wc_MlDsaKey_SetParams(wc_MlDsaKey* key, byte level)
|
||||
key->aSet = 0;
|
||||
#endif
|
||||
#ifdef WC_MLDSA_CACHE_PRIV_VECTORS
|
||||
/* Cached buffer holds secret s1/s2/t0; zeroize before free. */
|
||||
if ((key->s1 != NULL) && (oldParams != NULL)) {
|
||||
ForceZero(key->s1, (word32)oldParams->s1Sz +
|
||||
2U * (word32)oldParams->s2Sz);
|
||||
}
|
||||
XFREE(key->s1, key->heap, DYNAMIC_TYPE_MLDSA);
|
||||
key->s1 = NULL;
|
||||
key->s2 = NULL;
|
||||
@@ -11050,6 +11087,12 @@ void wc_MlDsaKey_Free(wc_MlDsaKey* key)
|
||||
XFREE(key->t1, key->heap, DYNAMIC_TYPE_MLDSA);
|
||||
#endif
|
||||
#ifdef WC_MLDSA_CACHE_PRIV_VECTORS
|
||||
/* Cached buffer holds secret s1/s2/t0; zeroize before free (the
|
||||
* ForceZero(key) below only clears the pointer). */
|
||||
if ((key->s1 != NULL) && (key->params != NULL)) {
|
||||
ForceZero(key->s1, (word32)key->params->s1Sz +
|
||||
2U * (word32)key->params->s2Sz);
|
||||
}
|
||||
XFREE(key->s1, key->heap, DYNAMIC_TYPE_MLDSA);
|
||||
#endif
|
||||
#ifdef WC_MLDSA_CACHE_MATRIX_A
|
||||
@@ -11433,6 +11476,10 @@ int wc_MlDsaKey_CheckKey(wc_MlDsaKey* key)
|
||||
}
|
||||
|
||||
if (key != NULL) {
|
||||
/* Zeroize secret s1/s2/t0 at the front (trailing t/t1/A are public). */
|
||||
if ((s1 != NULL) && (params != NULL)) {
|
||||
ForceZero(s1, (word32)params->s1Sz + 2U * (word32)params->s2Sz);
|
||||
}
|
||||
/* Dispose of allocated memory. */
|
||||
XFREE(s1, key->heap, DYNAMIC_TYPE_MLDSA);
|
||||
}
|
||||
|
||||
@@ -3101,6 +3101,8 @@ static int mlkem_prf(wc_Shake* shake256, byte* out, unsigned int outLen,
|
||||
outLen -= len;
|
||||
}
|
||||
|
||||
/* state holds secret PRF output. */
|
||||
ForceZero(state, sizeof(state));
|
||||
return 0;
|
||||
#else
|
||||
int ret;
|
||||
@@ -3152,6 +3154,8 @@ int mlkem_kdf(const byte* seed, int seedLen, byte* out, int outLen)
|
||||
}
|
||||
XMEMCPY(out, state, outLen);
|
||||
|
||||
/* state holds secret KDF output. */
|
||||
ForceZero(state, sizeof(state));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -3178,6 +3182,8 @@ int mlkem_kdf(const byte* seed, int seedLen, byte* out, int outLen)
|
||||
BlockSha3(state);
|
||||
XMEMCPY(out, state, outLen);
|
||||
|
||||
/* state holds secret KDF output. */
|
||||
ForceZero(state, sizeof(state));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -4038,6 +4044,8 @@ static int mlkem_get_noise_eta1_c(MLKEM_PRF_T* prf, sword16* p,
|
||||
/* Sample for values in range -3..3 from 3 bits of random. */
|
||||
mlkem_cbd_eta3(p, rand);
|
||||
}
|
||||
/* rand holds secret noise. */
|
||||
ForceZero(rand, sizeof(rand));
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -4050,6 +4058,8 @@ static int mlkem_get_noise_eta1_c(MLKEM_PRF_T* prf, sword16* p,
|
||||
/* Sample for values in range -2..2 from 2 bits of random. */
|
||||
mlkem_cbd_eta2(p, rand);
|
||||
}
|
||||
/* rand holds secret noise. */
|
||||
ForceZero(rand, sizeof(rand));
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -4082,6 +4092,8 @@ static int mlkem_get_noise_eta2_c(MLKEM_PRF_T* prf, sword16* p,
|
||||
mlkem_cbd_eta2(p, rand);
|
||||
}
|
||||
|
||||
/* rand holds secret noise. */
|
||||
ForceZero(rand, sizeof(rand));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -4118,6 +4130,9 @@ static void mlkem_get_noise_x4_eta2_avx2(byte* rand, byte* seed, byte o)
|
||||
mlkem_redistribute_16_rand_avx2(state, rand + 0 * ETA2_RAND_SIZE,
|
||||
rand + 1 * ETA2_RAND_SIZE, rand + 2 * ETA2_RAND_SIZE,
|
||||
rand + 3 * ETA2_RAND_SIZE);
|
||||
|
||||
/* state is secret-seeded; caller zeroizes rand. */
|
||||
ForceZero(state, sizeof(state));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -4171,6 +4186,8 @@ static int mlkem_get_noise_eta2_avx2(MLKEM_PRF_T* prf, sword16* p,
|
||||
}
|
||||
mlkem_cbd_eta2_avx2(p, (byte*)state);
|
||||
|
||||
/* state holds secret noise. */
|
||||
ForceZero(state, sizeof(state));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -4211,6 +4228,9 @@ static void mlkem_get_noise_x4_eta3_avx2(byte* rand, byte* seed)
|
||||
mlkem_redistribute_8_rand_avx2(state, rand + i + 0 * PRF_RAND_SZ,
|
||||
rand + i + 1 * PRF_RAND_SZ, rand + i + 2 * PRF_RAND_SZ,
|
||||
rand + i + 3 * PRF_RAND_SZ);
|
||||
|
||||
/* state is secret-seeded; caller zeroizes rand. */
|
||||
ForceZero(state, sizeof(state));
|
||||
}
|
||||
|
||||
/* Get the noise/error by calculating random bytes and sampling to a binomial
|
||||
@@ -4249,6 +4269,8 @@ static int mlkem_get_noise_k2_avx2(MLKEM_PRF_T* prf, sword16* vec1,
|
||||
ret = mlkem_get_noise_eta2_avx2(prf, poly, seed);
|
||||
}
|
||||
|
||||
/* rand holds secret noise. */
|
||||
ForceZero(rand, 4 * PRF_RAND_SZ);
|
||||
WC_FREE_VAR_EX(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
|
||||
return ret;
|
||||
@@ -4282,6 +4304,8 @@ static int mlkem_get_noise_k3_avx2(sword16* vec1, sword16* vec2, sword16* poly,
|
||||
mlkem_cbd_eta2_avx2(poly, rand + 2 * ETA2_RAND_SIZE);
|
||||
}
|
||||
|
||||
/* rand holds secret noise. */
|
||||
ForceZero(rand, sizeof(rand));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -4320,6 +4344,8 @@ static int mlkem_get_noise_k4_avx2(MLKEM_PRF_T* prf, sword16* vec1,
|
||||
ret = mlkem_get_noise_eta2_avx2(prf, poly, seed);
|
||||
}
|
||||
|
||||
/* rand holds secret noise. */
|
||||
ForceZero(rand, sizeof(rand));
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
@@ -4391,6 +4417,9 @@ static void mlkem_get_noise_x3_eta3_aarch64(byte* rand, byte* seed, byte o)
|
||||
ETA3_RAND_SIZE - SHA3_256_BYTES);
|
||||
XMEMCPY(rand + 2 * ETA3_RAND_SIZE, state + 2*25,
|
||||
ETA3_RAND_SIZE - SHA3_256_BYTES);
|
||||
|
||||
/* state is secret-seeded; caller zeroizes rand. */
|
||||
ForceZero(state, sizeof(state));
|
||||
}
|
||||
|
||||
/* Get the noise/error by calculating random bytes.
|
||||
@@ -4419,6 +4448,9 @@ static void mlkem_get_noise_eta3_aarch64(byte* rand, byte* seed, byte o)
|
||||
XMEMCPY(rand , state, SHA3_256_BYTES);
|
||||
BlockSha3(state);
|
||||
XMEMCPY(rand + SHA3_256_BYTES, state, ETA3_RAND_SIZE - SHA3_256_BYTES);
|
||||
|
||||
/* state is secret-seeded; caller zeroizes rand. */
|
||||
ForceZero(state, sizeof(state));
|
||||
}
|
||||
|
||||
/* Get the noise/error by calculating random bytes and sampling to a binomial
|
||||
@@ -4451,6 +4483,8 @@ static int mlkem_get_noise_k2_aarch64(sword16* vec1, sword16* vec2,
|
||||
mlkem_cbd_eta2(poly , rand + 2 * 25 * 8);
|
||||
}
|
||||
|
||||
/* rand holds secret noise. */
|
||||
ForceZero(rand, sizeof(rand));
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
@@ -4511,6 +4545,8 @@ static int mlkem_get_noise_k3_aarch64(sword16* vec1, sword16* vec2,
|
||||
mlkem_cbd_eta2(poly , rand + 0 * 25 * 8);
|
||||
}
|
||||
|
||||
/* rand holds secret noise. */
|
||||
ForceZero(rand, sizeof(rand));
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
@@ -4546,6 +4582,8 @@ static int mlkem_get_noise_k4_aarch64(sword16* vec1, sword16* vec2,
|
||||
mlkem_cbd_eta2(poly, rand + 2 * 25 * 8);
|
||||
}
|
||||
|
||||
/* rand holds secret noise. */
|
||||
ForceZero(rand, sizeof(rand));
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user