Skip to content

Commit ec37935

Browse files
authored
Merge pull request #10697 from Frauschi/zd21977
Even more missing ForceZero in ML-KEM / ML-DSA
2 parents 3c72ada + 24321ec commit ec37935

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
@@ -3642,6 +3642,8 @@ static int mldsa_rej_bound_poly(wc_Shake* shake256, byte* seed, sword32* s,
36423642
while (j < MLDSA_N);
36433643
}
36443644

3645+
/* z holds the secret s1/s2 bytes. */
3646+
ForceZero(z, sizeof(z));
36453647
return ret;
36463648
#else
36473649
int ret;
@@ -3670,6 +3672,8 @@ static int mldsa_rej_bound_poly(wc_Shake* shake256, byte* seed, sword32* s,
36703672
}
36713673
}
36723674

3675+
/* z holds the secret s1/s2 bytes. */
3676+
ForceZero(z, MLDSA_GEN_S_BYTES);
36733677
WC_FREE_VAR_EX(z, NULL, DYNAMIC_TYPE_MLDSA);
36743678
return ret;
36753679
#endif
@@ -3774,6 +3778,9 @@ static int wc_mldsa_gen_s_4_4_avx2(sword32* s[2], byte* seed)
37743778
(ctr3 < MLDSA_N));
37753779
}
37763780

3781+
/* rand/state hold secret s-vector material. */
3782+
ForceZero(rand, 4 * MLDSA_GEN_S_BLOCK_BYTES);
3783+
ForceZero(state, sizeof(word64) * 25 * 4);
37773784
WC_FREE_VAR_EX(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
37783785
WC_FREE_VAR_EX(state, NULL, DYNAMIC_TYPE_TMP_BUFFER);
37793786

@@ -3927,6 +3934,9 @@ static int wc_mldsa_gen_s_5_6_avx2(sword32* s[2], byte* seed)
39273934
/* Create more blocks if too many rejected. */
39283935
while ((ctr0 < MLDSA_N) || (ctr1 < MLDSA_N) || (ctr2 < MLDSA_N));
39293936

3937+
/* rand/state hold secret s-vector material. */
3938+
ForceZero(rand, 4 * MLDSA_GEN_S_BLOCK_BYTES);
3939+
ForceZero(state, sizeof(word64) * 25 * 4);
39303940
WC_FREE_VAR_EX(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
39313941
WC_FREE_VAR_EX(state, NULL, DYNAMIC_TYPE_TMP_BUFFER);
39323942

@@ -4082,6 +4092,9 @@ static int wc_mldsa_gen_s_7_8_avx2(sword32* s[2], byte* seed)
40824092
/* Create more blocks if too many rejected. */
40834093
while ((ctr0 < MLDSA_N) || (ctr1 < MLDSA_N) || (ctr2 < MLDSA_N));
40844094

4095+
/* rand/state hold secret s-vector material. */
4096+
ForceZero(rand, 4 * MLDSA_GEN_S_BLOCK_BYTES);
4097+
ForceZero(state, sizeof(word64) * 25 * 4);
40854098
WC_FREE_VAR_EX(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
40864099
WC_FREE_VAR_EX(state, NULL, DYNAMIC_TYPE_TMP_BUFFER);
40874100

@@ -4271,6 +4284,9 @@ static int wc_mldsa_gen_y_4_avx2(sword32* y, byte* seed, word16 kappa)
42714284
wc_mldsa_decode_gamma1_17_avx2(rand + 3 * MLDSA_MAX_V,
42724285
y + 3 * MLDSA_N);
42734286

4287+
/* rand/state hold the secret mask y. */
4288+
ForceZero(rand, 4 * MLDSA_MAX_V);
4289+
ForceZero(state, sizeof(word64) * 25 * 4);
42744290
WC_FREE_VAR_EX(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
42754291
WC_FREE_VAR_EX(state, NULL, DYNAMIC_TYPE_TMP_BUFFER);
42764292

@@ -4351,6 +4367,9 @@ static int wc_mldsa_gen_y_5_avx2(sword32* y, byte* seed, word16 kappa,
43514367
wc_mldsa_decode_gamma1_19_avx2(rand, y + 4 * MLDSA_N);
43524368
}
43534369

4370+
/* rand/state hold the secret mask y. */
4371+
ForceZero(rand, 4 * MLDSA_MAX_V);
4372+
ForceZero(state, sizeof(word64) * 25 * 4);
43544373
WC_FREE_VAR_EX(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
43554374
WC_FREE_VAR_EX(state, NULL, DYNAMIC_TYPE_TMP_BUFFER);
43564375

@@ -4446,6 +4465,9 @@ static int wc_mldsa_gen_y_7_avx2(sword32* y, byte* seed, word16 kappa)
44464465
wc_mldsa_decode_gamma1_19_avx2(rand + 2 * MLDSA_MAX_V,
44474466
y + 6 * MLDSA_N);
44484467

4468+
/* rand/state hold the secret mask y. */
4469+
ForceZero(rand, 4 * MLDSA_MAX_V);
4470+
ForceZero(state, sizeof(word64) * 25 * 4);
44494471
WC_FREE_VAR_EX(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
44504472
WC_FREE_VAR_EX(state, NULL, DYNAMIC_TYPE_TMP_BUFFER);
44514473

@@ -4504,6 +4526,8 @@ static int mldsa_vec_expand_mask_c(wc_Shake* shake256, byte* seed,
45044526
}
45054527
}
45064528

4529+
/* v holds the secret mask y. */
4530+
ForceZero(v, MLDSA_MAX_V);
45074531
WC_FREE_VAR_EX(v, NULL, DYNAMIC_TYPE_MLDSA);
45084532
return ret;
45094533
}
@@ -10948,6 +10972,9 @@ int wc_MlDsaKey_InitLabel(wc_MlDsaKey* key, const char* label, void* heap,
1094810972
int wc_MlDsaKey_SetParams(wc_MlDsaKey* key, byte level)
1094910973
{
1095010974
int ret = 0;
10975+
#if !defined(WC_MLDSA_FIXED_ARRAY) && defined(WC_MLDSA_CACHE_PRIV_VECTORS)
10976+
const wc_MlDsaParams* oldParams = NULL;
10977+
#endif
1095110978

1095210979
/* Validate parameters. */
1095310980
if (key == NULL) {
@@ -10968,6 +10995,11 @@ int wc_MlDsaKey_SetParams(wc_MlDsaKey* key, byte level)
1096810995
}
1096910996

1097010997
if (ret == 0) {
10998+
#if !defined(WC_MLDSA_FIXED_ARRAY) && defined(WC_MLDSA_CACHE_PRIV_VECTORS)
10999+
/* Save old params to size the cached-vector wipe below (key->params
11000+
* is about to change to the new level). */
11001+
oldParams = key->params;
11002+
#endif
1097111003
/* Get the parameters for level into key. */
1097211004
ret = mldsa_get_params(level, &key->params);
1097311005
}
@@ -10980,6 +11012,11 @@ int wc_MlDsaKey_SetParams(wc_MlDsaKey* key, byte level)
1098011012
key->aSet = 0;
1098111013
#endif
1098211014
#ifdef WC_MLDSA_CACHE_PRIV_VECTORS
11015+
/* Cached buffer holds secret s1/s2/t0; zeroize before free. */
11016+
if ((key->s1 != NULL) && (oldParams != NULL)) {
11017+
ForceZero(key->s1, (word32)oldParams->s1Sz +
11018+
2U * (word32)oldParams->s2Sz);
11019+
}
1098311020
XFREE(key->s1, key->heap, DYNAMIC_TYPE_MLDSA);
1098411021
key->s1 = NULL;
1098511022
key->s2 = NULL;
@@ -11064,6 +11101,12 @@ void wc_MlDsaKey_Free(wc_MlDsaKey* key)
1106411101
XFREE(key->t1, key->heap, DYNAMIC_TYPE_MLDSA);
1106511102
#endif
1106611103
#ifdef WC_MLDSA_CACHE_PRIV_VECTORS
11104+
/* Cached buffer holds secret s1/s2/t0; zeroize before free (the
11105+
* ForceZero(key) below only clears the pointer). */
11106+
if ((key->s1 != NULL) && (key->params != NULL)) {
11107+
ForceZero(key->s1, (word32)key->params->s1Sz +
11108+
2U * (word32)key->params->s2Sz);
11109+
}
1106711110
XFREE(key->s1, key->heap, DYNAMIC_TYPE_MLDSA);
1106811111
#endif
1106911112
#ifdef WC_MLDSA_CACHE_MATRIX_A
@@ -11447,6 +11490,10 @@ int wc_MlDsaKey_CheckKey(wc_MlDsaKey* key)
1144711490
}
1144811491

1144911492
if (key != NULL) {
11493+
/* Zeroize secret s1/s2/t0 at the front (trailing t/t1/A are public). */
11494+
if ((s1 != NULL) && (params != NULL)) {
11495+
ForceZero(s1, (word32)params->s1Sz + 2U * (word32)params->s2Sz);
11496+
}
1145011497
/* Dispose of allocated memory. */
1145111498
XFREE(s1, key->heap, DYNAMIC_TYPE_MLDSA);
1145211499
}

wolfcrypt/src/wc_mlkem_poly.c

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

3109+
/* state holds secret PRF output. */
3110+
ForceZero(state, sizeof(state));
31093111
return 0;
31103112
#else
31113113
int ret;
@@ -3157,6 +3159,8 @@ int mlkem_kdf(const byte* seed, int seedLen, byte* out, int outLen)
31573159
}
31583160
XMEMCPY(out, state, outLen);
31593161

3162+
/* state holds secret KDF output. */
3163+
ForceZero(state, sizeof(state));
31603164
return 0;
31613165
}
31623166
#endif
@@ -3183,6 +3187,8 @@ int mlkem_kdf(const byte* seed, int seedLen, byte* out, int outLen)
31833187
BlockSha3(state);
31843188
XMEMCPY(out, state, outLen);
31853189

3190+
/* state holds secret KDF output. */
3191+
ForceZero(state, sizeof(state));
31863192
return 0;
31873193
}
31883194
#endif
@@ -4043,6 +4049,8 @@ static int mlkem_get_noise_eta1_c(MLKEM_PRF_T* prf, sword16* p,
40434049
/* Sample for values in range -3..3 from 3 bits of random. */
40444050
mlkem_cbd_eta3(p, rand);
40454051
}
4052+
/* rand holds secret noise. */
4053+
ForceZero(rand, sizeof(rand));
40464054
}
40474055
else
40484056
#endif
@@ -4055,6 +4063,8 @@ static int mlkem_get_noise_eta1_c(MLKEM_PRF_T* prf, sword16* p,
40554063
/* Sample for values in range -2..2 from 2 bits of random. */
40564064
mlkem_cbd_eta2(p, rand);
40574065
}
4066+
/* rand holds secret noise. */
4067+
ForceZero(rand, sizeof(rand));
40584068
}
40594069

40604070
return ret;
@@ -4087,6 +4097,8 @@ static int mlkem_get_noise_eta2_c(MLKEM_PRF_T* prf, sword16* p,
40874097
mlkem_cbd_eta2(p, rand);
40884098
}
40894099

4100+
/* rand holds secret noise. */
4101+
ForceZero(rand, sizeof(rand));
40904102
return ret;
40914103
}
40924104

@@ -4123,6 +4135,9 @@ static void mlkem_get_noise_x4_eta2_avx2(byte* rand, byte* seed, byte o)
41234135
mlkem_redistribute_16_rand_avx2(state, rand + 0 * ETA2_RAND_SIZE,
41244136
rand + 1 * ETA2_RAND_SIZE, rand + 2 * ETA2_RAND_SIZE,
41254137
rand + 3 * ETA2_RAND_SIZE);
4138+
4139+
/* state is secret-seeded; caller zeroizes rand. */
4140+
ForceZero(state, sizeof(state));
41264141
}
41274142
#endif
41284143

@@ -4176,6 +4191,8 @@ static int mlkem_get_noise_eta2_avx2(MLKEM_PRF_T* prf, sword16* p,
41764191
}
41774192
mlkem_cbd_eta2_avx2(p, (byte*)state);
41784193

4194+
/* state holds secret noise. */
4195+
ForceZero(state, sizeof(state));
41794196
return 0;
41804197
}
41814198
#endif
@@ -4216,6 +4233,9 @@ static void mlkem_get_noise_x4_eta3_avx2(byte* rand, byte* seed)
42164233
mlkem_redistribute_8_rand_avx2(state, rand + i + 0 * PRF_RAND_SZ,
42174234
rand + i + 1 * PRF_RAND_SZ, rand + i + 2 * PRF_RAND_SZ,
42184235
rand + i + 3 * PRF_RAND_SZ);
4236+
4237+
/* state is secret-seeded; caller zeroizes rand. */
4238+
ForceZero(state, sizeof(state));
42194239
}
42204240

42214241
/* 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,
42544274
ret = mlkem_get_noise_eta2_avx2(prf, poly, seed);
42554275
}
42564276

4277+
/* rand holds secret noise. */
4278+
ForceZero(rand, 4 * PRF_RAND_SZ);
42574279
WC_FREE_VAR_EX(rand, NULL, DYNAMIC_TYPE_TMP_BUFFER);
42584280

42594281
return ret;
@@ -4287,6 +4309,8 @@ static int mlkem_get_noise_k3_avx2(sword16* vec1, sword16* vec2, sword16* poly,
42874309
mlkem_cbd_eta2_avx2(poly, rand + 2 * ETA2_RAND_SIZE);
42884310
}
42894311

4312+
/* rand holds secret noise. */
4313+
ForceZero(rand, sizeof(rand));
42904314
return 0;
42914315
}
42924316
#endif
@@ -4325,6 +4349,8 @@ static int mlkem_get_noise_k4_avx2(MLKEM_PRF_T* prf, sword16* vec1,
43254349
ret = mlkem_get_noise_eta2_avx2(prf, poly, seed);
43264350
}
43274351

4352+
/* rand holds secret noise. */
4353+
ForceZero(rand, sizeof(rand));
43284354
return ret;
43294355
}
43304356
#endif
@@ -4396,6 +4422,9 @@ static void mlkem_get_noise_x3_eta3_aarch64(byte* rand, byte* seed, byte o)
43964422
ETA3_RAND_SIZE - SHA3_256_BYTES);
43974423
XMEMCPY(rand + 2 * ETA3_RAND_SIZE, state + 2*25,
43984424
ETA3_RAND_SIZE - SHA3_256_BYTES);
4425+
4426+
/* state is secret-seeded; caller zeroizes rand. */
4427+
ForceZero(state, sizeof(state));
43994428
}
44004429

44014430
/* 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)
44244453
XMEMCPY(rand , state, SHA3_256_BYTES);
44254454
BlockSha3(state);
44264455
XMEMCPY(rand + SHA3_256_BYTES, state, ETA3_RAND_SIZE - SHA3_256_BYTES);
4456+
4457+
/* state is secret-seeded; caller zeroizes rand. */
4458+
ForceZero(state, sizeof(state));
44274459
}
44284460

44294461
/* 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,
44564488
mlkem_cbd_eta2(poly , rand + 2 * 25 * 8);
44574489
}
44584490

4491+
/* rand holds secret noise. */
4492+
ForceZero(rand, sizeof(rand));
44594493
return ret;
44604494
}
44614495
#endif
@@ -4516,6 +4550,8 @@ static int mlkem_get_noise_k3_aarch64(sword16* vec1, sword16* vec2,
45164550
mlkem_cbd_eta2(poly , rand + 0 * 25 * 8);
45174551
}
45184552

4553+
/* rand holds secret noise. */
4554+
ForceZero(rand, sizeof(rand));
45194555
return 0;
45204556
}
45214557
#endif
@@ -4551,6 +4587,8 @@ static int mlkem_get_noise_k4_aarch64(sword16* vec1, sword16* vec2,
45514587
mlkem_cbd_eta2(poly, rand + 2 * 25 * 8);
45524588
}
45534589

4590+
/* rand holds secret noise. */
4591+
ForceZero(rand, sizeof(rand));
45544592
return ret;
45554593
}
45564594
#endif

0 commit comments

Comments
 (0)