Merge pull request #10697 from Frauschi/zd21977

Even more missing ForceZero in ML-KEM / ML-DSA
This commit is contained in:
Daniel Pouzzner
2026-07-03 00:47:57 -05:00
committed by GitHub
2 changed files with 85 additions and 0 deletions
+47
View File
@@ -3642,6 +3642,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;
@@ -3670,6 +3672,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
@@ -3774,6 +3778,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);
@@ -3927,6 +3934,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);
@@ -4082,6 +4092,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);
@@ -4271,6 +4284,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);
@@ -4351,6 +4367,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);
@@ -4446,6 +4465,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);
@@ -4504,6 +4526,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;
}
@@ -10948,6 +10972,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) {
@@ -10968,6 +10995,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);
}
@@ -10980,6 +11012,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;
@@ -11064,6 +11101,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
@@ -11447,6 +11490,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);
}
+38
View File
@@ -3106,6 +3106,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;
@@ -3157,6 +3159,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
@@ -3183,6 +3187,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
@@ -4043,6 +4049,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
@@ -4055,6 +4063,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;
@@ -4087,6 +4097,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;
}
@@ -4123,6 +4135,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
@@ -4176,6 +4191,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
@@ -4216,6 +4233,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
@@ -4254,6 +4274,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;
@@ -4287,6 +4309,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
@@ -4325,6 +4349,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
@@ -4396,6 +4422,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.
@@ -4424,6 +4453,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
@@ -4456,6 +4488,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
@@ -4516,6 +4550,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
@@ -4551,6 +4587,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