Skip to content

Commit 24321ec

Browse files
committed
Even more missing ForceZero in ML-KEM / ML-DSA
Ensure that all sensitive private key (derived) data is zeroed.
1 parent c685293 commit 24321ec

2 files changed

Lines changed: 85 additions & 0 deletions

File tree

wolfcrypt/src/wc_mldsa.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3628,6 +3628,8 @@ static int mldsa_rej_bound_poly(wc_Shake* shake256, byte* seed, sword32* s,
36283628
while (j < MLDSA_N);
36293629
}
36303630

3631+
/* z holds the secret s1/s2 bytes. */
3632+
ForceZero(z, sizeof(z));
36313633
return ret;
36323634
#else
36333635
int ret;
@@ -3656,6 +3658,8 @@ static int mldsa_rej_bound_poly(wc_Shake* shake256, byte* seed, sword32* s,
36563658
}
36573659
}
36583660

3661+
/* z holds the secret s1/s2 bytes. */
3662+
ForceZero(z, MLDSA_GEN_S_BYTES);
36593663
WC_FREE_VAR_EX(z, NULL, DYNAMIC_TYPE_MLDSA);
36603664
return ret;
36613665
#endif
@@ -3760,6 +3764,9 @@ static int wc_mldsa_gen_s_4_4_avx2(sword32* s[2], byte* seed)
37603764
(ctr3 < MLDSA_N));
37613765
}
37623766

3767+
/* rand/state hold secret s-vector material. */
3768+
ForceZero(rand, 4 * MLDSA_GEN_S_BLOCK_BYTES);
3769+
ForceZero(state, sizeof(word64) * 25 * 4);
37633770
WC_FREE_VAR_EX(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
37643771
WC_FREE_VAR_EX(state, NULL, DYNAMIC_TYPE_TMP_BUFFER);
37653772

@@ -3913,6 +3920,9 @@ static int wc_mldsa_gen_s_5_6_avx2(sword32* s[2], byte* seed)
39133920
/* Create more blocks if too many rejected. */
39143921
while ((ctr0 < MLDSA_N) || (ctr1 < MLDSA_N) || (ctr2 < MLDSA_N));
39153922

3923+
/* rand/state hold secret s-vector material. */
3924+
ForceZero(rand, 4 * MLDSA_GEN_S_BLOCK_BYTES);
3925+
ForceZero(state, sizeof(word64) * 25 * 4);
39163926
WC_FREE_VAR_EX(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
39173927
WC_FREE_VAR_EX(state, NULL, DYNAMIC_TYPE_TMP_BUFFER);
39183928

@@ -4068,6 +4078,9 @@ static int wc_mldsa_gen_s_7_8_avx2(sword32* s[2], byte* seed)
40684078
/* Create more blocks if too many rejected. */
40694079
while ((ctr0 < MLDSA_N) || (ctr1 < MLDSA_N) || (ctr2 < MLDSA_N));
40704080

4081+
/* rand/state hold secret s-vector material. */
4082+
ForceZero(rand, 4 * MLDSA_GEN_S_BLOCK_BYTES);
4083+
ForceZero(state, sizeof(word64) * 25 * 4);
40714084
WC_FREE_VAR_EX(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
40724085
WC_FREE_VAR_EX(state, NULL, DYNAMIC_TYPE_TMP_BUFFER);
40734086

@@ -4257,6 +4270,9 @@ static int wc_mldsa_gen_y_4_avx2(sword32* y, byte* seed, word16 kappa)
42574270
wc_mldsa_decode_gamma1_17_avx2(rand + 3 * MLDSA_MAX_V,
42584271
y + 3 * MLDSA_N);
42594272

4273+
/* rand/state hold the secret mask y. */
4274+
ForceZero(rand, 4 * MLDSA_MAX_V);
4275+
ForceZero(state, sizeof(word64) * 25 * 4);
42604276
WC_FREE_VAR_EX(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
42614277
WC_FREE_VAR_EX(state, NULL, DYNAMIC_TYPE_TMP_BUFFER);
42624278

@@ -4337,6 +4353,9 @@ static int wc_mldsa_gen_y_5_avx2(sword32* y, byte* seed, word16 kappa,
43374353
wc_mldsa_decode_gamma1_19_avx2(rand, y + 4 * MLDSA_N);
43384354
}
43394355

4356+
/* rand/state hold the secret mask y. */
4357+
ForceZero(rand, 4 * MLDSA_MAX_V);
4358+
ForceZero(state, sizeof(word64) * 25 * 4);
43404359
WC_FREE_VAR_EX(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
43414360
WC_FREE_VAR_EX(state, NULL, DYNAMIC_TYPE_TMP_BUFFER);
43424361

@@ -4432,6 +4451,9 @@ static int wc_mldsa_gen_y_7_avx2(sword32* y, byte* seed, word16 kappa)
44324451
wc_mldsa_decode_gamma1_19_avx2(rand + 2 * MLDSA_MAX_V,
44334452
y + 6 * MLDSA_N);
44344453

4454+
/* rand/state hold the secret mask y. */
4455+
ForceZero(rand, 4 * MLDSA_MAX_V);
4456+
ForceZero(state, sizeof(word64) * 25 * 4);
44354457
WC_FREE_VAR_EX(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
44364458
WC_FREE_VAR_EX(state, NULL, DYNAMIC_TYPE_TMP_BUFFER);
44374459

@@ -4490,6 +4512,8 @@ static int mldsa_vec_expand_mask_c(wc_Shake* shake256, byte* seed,
44904512
}
44914513
}
44924514

4515+
/* v holds the secret mask y. */
4516+
ForceZero(v, MLDSA_MAX_V);
44934517
WC_FREE_VAR_EX(v, NULL, DYNAMIC_TYPE_MLDSA);
44944518
return ret;
44954519
}
@@ -10934,6 +10958,9 @@ int wc_MlDsaKey_InitLabel(wc_MlDsaKey* key, const char* label, void* heap,
1093410958
int wc_MlDsaKey_SetParams(wc_MlDsaKey* key, byte level)
1093510959
{
1093610960
int ret = 0;
10961+
#if !defined(WC_MLDSA_FIXED_ARRAY) && defined(WC_MLDSA_CACHE_PRIV_VECTORS)
10962+
const wc_MlDsaParams* oldParams = NULL;
10963+
#endif
1093710964

1093810965
/* Validate parameters. */
1093910966
if (key == NULL) {
@@ -10954,6 +10981,11 @@ int wc_MlDsaKey_SetParams(wc_MlDsaKey* key, byte level)
1095410981
}
1095510982

1095610983
if (ret == 0) {
10984+
#if !defined(WC_MLDSA_FIXED_ARRAY) && defined(WC_MLDSA_CACHE_PRIV_VECTORS)
10985+
/* Save old params to size the cached-vector wipe below (key->params
10986+
* is about to change to the new level). */
10987+
oldParams = key->params;
10988+
#endif
1095710989
/* Get the parameters for level into key. */
1095810990
ret = mldsa_get_params(level, &key->params);
1095910991
}
@@ -10966,6 +10998,11 @@ int wc_MlDsaKey_SetParams(wc_MlDsaKey* key, byte level)
1096610998
key->aSet = 0;
1096710999
#endif
1096811000
#ifdef WC_MLDSA_CACHE_PRIV_VECTORS
11001+
/* Cached buffer holds secret s1/s2/t0; zeroize before free. */
11002+
if ((key->s1 != NULL) && (oldParams != NULL)) {
11003+
ForceZero(key->s1, (word32)oldParams->s1Sz +
11004+
2U * (word32)oldParams->s2Sz);
11005+
}
1096911006
XFREE(key->s1, key->heap, DYNAMIC_TYPE_MLDSA);
1097011007
key->s1 = NULL;
1097111008
key->s2 = NULL;
@@ -11050,6 +11087,12 @@ void wc_MlDsaKey_Free(wc_MlDsaKey* key)
1105011087
XFREE(key->t1, key->heap, DYNAMIC_TYPE_MLDSA);
1105111088
#endif
1105211089
#ifdef WC_MLDSA_CACHE_PRIV_VECTORS
11090+
/* Cached buffer holds secret s1/s2/t0; zeroize before free (the
11091+
* ForceZero(key) below only clears the pointer). */
11092+
if ((key->s1 != NULL) && (key->params != NULL)) {
11093+
ForceZero(key->s1, (word32)key->params->s1Sz +
11094+
2U * (word32)key->params->s2Sz);
11095+
}
1105311096
XFREE(key->s1, key->heap, DYNAMIC_TYPE_MLDSA);
1105411097
#endif
1105511098
#ifdef WC_MLDSA_CACHE_MATRIX_A
@@ -11433,6 +11476,10 @@ int wc_MlDsaKey_CheckKey(wc_MlDsaKey* key)
1143311476
}
1143411477

1143511478
if (key != NULL) {
11479+
/* Zeroize secret s1/s2/t0 at the front (trailing t/t1/A are public). */
11480+
if ((s1 != NULL) && (params != NULL)) {
11481+
ForceZero(s1, (word32)params->s1Sz + 2U * (word32)params->s2Sz);
11482+
}
1143611483
/* Dispose of allocated memory. */
1143711484
XFREE(s1, key->heap, DYNAMIC_TYPE_MLDSA);
1143811485
}

wolfcrypt/src/wc_mlkem_poly.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3101,6 +3101,8 @@ static int mlkem_prf(wc_Shake* shake256, byte* out, unsigned int outLen,
31013101
outLen -= len;
31023102
}
31033103

3104+
/* state holds secret PRF output. */
3105+
ForceZero(state, sizeof(state));
31043106
return 0;
31053107
#else
31063108
int ret;
@@ -3152,6 +3154,8 @@ int mlkem_kdf(const byte* seed, int seedLen, byte* out, int outLen)
31523154
}
31533155
XMEMCPY(out, state, outLen);
31543156

3157+
/* state holds secret KDF output. */
3158+
ForceZero(state, sizeof(state));
31553159
return 0;
31563160
}
31573161
#endif
@@ -3178,6 +3182,8 @@ int mlkem_kdf(const byte* seed, int seedLen, byte* out, int outLen)
31783182
BlockSha3(state);
31793183
XMEMCPY(out, state, outLen);
31803184

3185+
/* state holds secret KDF output. */
3186+
ForceZero(state, sizeof(state));
31813187
return 0;
31823188
}
31833189
#endif
@@ -4038,6 +4044,8 @@ static int mlkem_get_noise_eta1_c(MLKEM_PRF_T* prf, sword16* p,
40384044
/* Sample for values in range -3..3 from 3 bits of random. */
40394045
mlkem_cbd_eta3(p, rand);
40404046
}
4047+
/* rand holds secret noise. */
4048+
ForceZero(rand, sizeof(rand));
40414049
}
40424050
else
40434051
#endif
@@ -4050,6 +4058,8 @@ static int mlkem_get_noise_eta1_c(MLKEM_PRF_T* prf, sword16* p,
40504058
/* Sample for values in range -2..2 from 2 bits of random. */
40514059
mlkem_cbd_eta2(p, rand);
40524060
}
4061+
/* rand holds secret noise. */
4062+
ForceZero(rand, sizeof(rand));
40534063
}
40544064

40554065
return ret;
@@ -4082,6 +4092,8 @@ static int mlkem_get_noise_eta2_c(MLKEM_PRF_T* prf, sword16* p,
40824092
mlkem_cbd_eta2(p, rand);
40834093
}
40844094

4095+
/* rand holds secret noise. */
4096+
ForceZero(rand, sizeof(rand));
40854097
return ret;
40864098
}
40874099

@@ -4118,6 +4130,9 @@ static void mlkem_get_noise_x4_eta2_avx2(byte* rand, byte* seed, byte o)
41184130
mlkem_redistribute_16_rand_avx2(state, rand + 0 * ETA2_RAND_SIZE,
41194131
rand + 1 * ETA2_RAND_SIZE, rand + 2 * ETA2_RAND_SIZE,
41204132
rand + 3 * ETA2_RAND_SIZE);
4133+
4134+
/* state is secret-seeded; caller zeroizes rand. */
4135+
ForceZero(state, sizeof(state));
41214136
}
41224137
#endif
41234138

@@ -4171,6 +4186,8 @@ static int mlkem_get_noise_eta2_avx2(MLKEM_PRF_T* prf, sword16* p,
41714186
}
41724187
mlkem_cbd_eta2_avx2(p, (byte*)state);
41734188

4189+
/* state holds secret noise. */
4190+
ForceZero(state, sizeof(state));
41744191
return 0;
41754192
}
41764193
#endif
@@ -4211,6 +4228,9 @@ static void mlkem_get_noise_x4_eta3_avx2(byte* rand, byte* seed)
42114228
mlkem_redistribute_8_rand_avx2(state, rand + i + 0 * PRF_RAND_SZ,
42124229
rand + i + 1 * PRF_RAND_SZ, rand + i + 2 * PRF_RAND_SZ,
42134230
rand + i + 3 * PRF_RAND_SZ);
4231+
4232+
/* state is secret-seeded; caller zeroizes rand. */
4233+
ForceZero(state, sizeof(state));
42144234
}
42154235

42164236
/* 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,
42494269
ret = mlkem_get_noise_eta2_avx2(prf, poly, seed);
42504270
}
42514271

4272+
/* rand holds secret noise. */
4273+
ForceZero(rand, 4 * PRF_RAND_SZ);
42524274
WC_FREE_VAR_EX(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
42534275

42544276
return ret;
@@ -4282,6 +4304,8 @@ static int mlkem_get_noise_k3_avx2(sword16* vec1, sword16* vec2, sword16* poly,
42824304
mlkem_cbd_eta2_avx2(poly, rand + 2 * ETA2_RAND_SIZE);
42834305
}
42844306

4307+
/* rand holds secret noise. */
4308+
ForceZero(rand, sizeof(rand));
42854309
return 0;
42864310
}
42874311
#endif
@@ -4320,6 +4344,8 @@ static int mlkem_get_noise_k4_avx2(MLKEM_PRF_T* prf, sword16* vec1,
43204344
ret = mlkem_get_noise_eta2_avx2(prf, poly, seed);
43214345
}
43224346

4347+
/* rand holds secret noise. */
4348+
ForceZero(rand, sizeof(rand));
43234349
return ret;
43244350
}
43254351
#endif
@@ -4391,6 +4417,9 @@ static void mlkem_get_noise_x3_eta3_aarch64(byte* rand, byte* seed, byte o)
43914417
ETA3_RAND_SIZE - SHA3_256_BYTES);
43924418
XMEMCPY(rand + 2 * ETA3_RAND_SIZE, state + 2*25,
43934419
ETA3_RAND_SIZE - SHA3_256_BYTES);
4420+
4421+
/* state is secret-seeded; caller zeroizes rand. */
4422+
ForceZero(state, sizeof(state));
43944423
}
43954424

43964425
/* 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)
44194448
XMEMCPY(rand , state, SHA3_256_BYTES);
44204449
BlockSha3(state);
44214450
XMEMCPY(rand + SHA3_256_BYTES, state, ETA3_RAND_SIZE - SHA3_256_BYTES);
4451+
4452+
/* state is secret-seeded; caller zeroizes rand. */
4453+
ForceZero(state, sizeof(state));
44224454
}
44234455

44244456
/* 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,
44514483
mlkem_cbd_eta2(poly , rand + 2 * 25 * 8);
44524484
}
44534485

4486+
/* rand holds secret noise. */
4487+
ForceZero(rand, sizeof(rand));
44544488
return ret;
44554489
}
44564490
#endif
@@ -4511,6 +4545,8 @@ static int mlkem_get_noise_k3_aarch64(sword16* vec1, sword16* vec2,
45114545
mlkem_cbd_eta2(poly , rand + 0 * 25 * 8);
45124546
}
45134547

4548+
/* rand holds secret noise. */
4549+
ForceZero(rand, sizeof(rand));
45144550
return 0;
45154551
}
45164552
#endif
@@ -4546,6 +4582,8 @@ static int mlkem_get_noise_k4_aarch64(sword16* vec1, sword16* vec2,
45464582
mlkem_cbd_eta2(poly, rand + 2 * 25 * 8);
45474583
}
45484584

4585+
/* rand holds secret noise. */
4586+
ForceZero(rand, sizeof(rand));
45494587
return ret;
45504588
}
45514589
#endif

0 commit comments

Comments
 (0)