@@ -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,
1094810972int 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 }
0 commit comments