Skip to content

Commit f988324

Browse files
Merge pull request #22 from gardenlinux/fix/fips/0052
fix 0052-zeroization-ossl_ml_kem_key_reset.patch
2 parents e4f96d7 + 9071f0d commit f988324

1 file changed

Lines changed: 52 additions & 9 deletions

File tree

Lines changed: 52 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,58 @@
1-
:100644 100644 dd8a39197a 0000000000 M crypto/ml_kem/ml_kem.c
1+
From 2209874540108f88ed2d61f2bf14cce3c538be58 Mon Sep 17 00:00:00 2001
2+
From: nkraetzschmar <9020053+nkraetzschmar@users.noreply.github.com>
3+
Date: Fri, 17 Jul 2026 15:09:20 +0000
4+
Subject: [PATCH] FIPS: ML-KEM zeroize full key allocation in key_reset
5+
6+
ossl_ml_kem_key_reset failed to wipe the public vector |t| and matrix
7+
|m| (only the private |s|/|z|/|d| tail was cleansed), so on freeing a
8+
public key those SSPs survived; the prior fix attempt cleansed |m| with
9+
sizeof(pointer) (8 bytes) *after* OPENSSL_free(key->t), a use-after-free.
10+
11+
|t|, |m|, |s|, |z|/|d| are consecutive slices of the single allocation
12+
starting at key->t (add_storage()), so cleanse the whole allocation
13+
(puballoc/prvalloc) before freeing it. |rho|/|pkhash| alias the in-struct
14+
|seedbuf|, cleansed separately.
15+
---
16+
crypto/ml_kem/ml_kem.c | 23 ++++++++++++++++-------
17+
1 file changed, 16 insertions(+), 7 deletions(-)
218

319
diff --git a/crypto/ml_kem/ml_kem.c b/crypto/ml_kem/ml_kem.c
4-
index dd8a39197a..5c5446435d 100644
20+
index f29912581a..fc528317bb 100644
521
--- a/crypto/ml_kem/ml_kem.c
622
+++ b/crypto/ml_kem/ml_kem.c
7-
@@ -1897,2 +1900,8 @@ void ossl_ml_kem_key_reset(ML_KEM_KEY *key)
23+
@@ -1909,16 +1909,25 @@ void ossl_ml_kem_key_reset(ML_KEM_KEY *key)
24+
if (key->t == NULL)
25+
return;
26+
/*-
27+
- * Cleanse any sensitive data:
28+
- * - The private vector |s| is immediately followed by the FO failure
29+
- * secret |z|, and seed |d|, we can cleanse all three in one call.
30+
+ * Cleanse all key material before releasing it.
31+
*
32+
- * - Otherwise, when key->d is set, cleanse the stashed seed.
33+
+ * |t|, |m|, |s| and |z|/|d| are consecutive slices of the single
34+
+ * allocation that begins at |key->t| (see add_storage()), so a single
35+
+ * cleanse over the whole allocation covers the public vector |t| and
36+
+ * matrix |m| as well as the private vector |s| and the FO failure secret
37+
+ * |z| (plus the optional seed |d|). This must happen *before* the
38+
+ * OPENSSL_free() below, while the memory is still ours.
39+
*/
40+
- if (ossl_ml_kem_have_prvkey(key))
41+
- OPENSSL_cleanse(key->s,
42+
- key->vinfo->rank * sizeof(scalar) + 2 * ML_KEM_RANDOM_BYTES);
43+
+ OPENSSL_cleanse(key->t, ossl_ml_kem_have_prvkey(key)
44+
+ ? key->vinfo->prvalloc
45+
+ : key->vinfo->puballoc);
846
OPENSSL_free(key->t);
9-
+
10-
+ if (key->rho != NULL)
11-
+ OPENSSL_cleanse(key->rho, sizeof(key->rho));
12-
+ OPENSSL_cleanse((void *)key->pkhash, ML_KEM_PKHASH_BYTES);
13-
+ OPENSSL_cleanse(key->m, sizeof(key->m));
14-
+ OPENSSL_cleanse(key->seedbuf, ML_KEM_SEED_BYTES);
47+
+ /*
48+
+ * |rho| and |pkhash| are aliases into the in-struct |seedbuf|, so wiping
49+
+ * |seedbuf| clears both. |seedbuf| is not part of the freed allocation
50+
+ * above, so the order here is immaterial.
51+
+ */
52+
+ OPENSSL_cleanse(key->seedbuf, sizeof(key->seedbuf));
1553
key->d = key->z = (uint8_t *)(key->s = key->m = key->t = NULL);
54+
}
55+
56+
--
57+
2.47.3
58+

0 commit comments

Comments
 (0)