From f0dc2e2e9cc3b36124817049b7de845d9086cd3e Mon Sep 17 00:00:00 2001
From: Martin Velay <mvelay@lowrisc.org>
Date: Tue, 17 Dec 2024 09:30:57 +0000
Subject: [PATCH 1/2] [hmac,doc] Wipe secret doc update

- fix doc to be aligned with the RTL as the FSMs are not affected by the
wipe secret triggering. But this is not a security issue.

Signed-off-by: Martin Velay <mvelay@lowrisc.org>
(cherry picked from commit ee236383d73df6cb477bbeb5a566f3bd77dd52ea)
---
 hw/ip/hmac/data/hmac.hjson  | 2 +-
 hw/ip/hmac/doc/registers.md | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/ip/hmac/data/hmac.hjson b/hw/ip/hmac/data/hmac.hjson
index 94dbc4f44ab53..8fe65f6c387a4 100644
--- a/hw/ip/hmac/data/hmac.hjson
+++ b/hw/ip/hmac/data/hmac.hjson
@@ -414,7 +414,7 @@
     { name: "WIPE_SECRET",
       desc: '''Clear internal secret registers.
 
-            If CPU writes a value into the register, the value is used to clear the internal variables such as the secret key, internal state machine, or hash value.
+            If CPU writes a value into the register, the value is used to clear the internal variables such as the secret key, intermediate hash results, digest and the internal message scheduling array.
             The clear secret operation overwrites the internal variables with the provided 32-bit value.
             For SHA-2 384/512 that work with 64-bit words, the 32-bit value is duplicated and concatenated to generate the 64-bit value.
             It is recommended to use a value extracted from an entropy source.
diff --git a/hw/ip/hmac/doc/registers.md b/hw/ip/hmac/doc/registers.md
index 2ca2180f2fe91..b7a9b9b9f19f5 100644
--- a/hw/ip/hmac/doc/registers.md
+++ b/hw/ip/hmac/doc/registers.md
@@ -320,7 +320,7 @@ HMAC Error Code
 ## WIPE_SECRET
 Clear internal secret registers.
 
-If CPU writes a value into the register, the value is used to clear the internal variables such as the secret key, internal state machine, or hash value.
+If CPU writes a value into the register, the value is used to clear the internal variables such as the secret key, intermediate hash results, digest and the internal message scheduling array.
 The clear secret operation overwrites the internal variables with the provided 32-bit value.
 For SHA-2 384/512 that work with 64-bit words, the 32-bit value is duplicated and concatenated to generate the 64-bit value.
 It is recommended to use a value extracted from an entropy source.

From b3066f10732539110fc1aca0662d242957e00215 Mon Sep 17 00:00:00 2001
From: Martin Velay <mvelay@lowrisc.org>
Date: Tue, 17 Dec 2024 09:35:17 +0000
Subject: [PATCH 2/2] [hmac,dv] Wipe secret assertions

- add multiple assertions to ensure that the specified internal
variables are cleared when a wipe secret operation is triggered.

Signed-off-by: Martin Velay <mvelay@lowrisc.org>
(cherry picked from commit 905b3d1ce4729a50fa1faabbcee889cf8815d973)
---
 hw/ip/hmac/data/hmac.hjson  |  2 +-
 hw/ip/hmac/doc/registers.md |  2 +-
 hw/ip/hmac/rtl/hmac.sv      |  5 +++++
 hw/ip/prim/rtl/prim_sha2.sv | 17 +++++++++++++++++
 4 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/hw/ip/hmac/data/hmac.hjson b/hw/ip/hmac/data/hmac.hjson
index 8fe65f6c387a4..7161d2df5bcd6 100644
--- a/hw/ip/hmac/data/hmac.hjson
+++ b/hw/ip/hmac/data/hmac.hjson
@@ -414,7 +414,7 @@
     { name: "WIPE_SECRET",
       desc: '''Clear internal secret registers.
 
-            If CPU writes a value into the register, the value is used to clear the internal variables such as the secret key, intermediate hash results, digest and the internal message scheduling array.
+            If the CPU writes a value into the register, the value is used to clear some internal variables such as the secret key, intermediate hash results, digest and internal message scheduling array.
             The clear secret operation overwrites the internal variables with the provided 32-bit value.
             For SHA-2 384/512 that work with 64-bit words, the 32-bit value is duplicated and concatenated to generate the 64-bit value.
             It is recommended to use a value extracted from an entropy source.
diff --git a/hw/ip/hmac/doc/registers.md b/hw/ip/hmac/doc/registers.md
index b7a9b9b9f19f5..be716c1eaa204 100644
--- a/hw/ip/hmac/doc/registers.md
+++ b/hw/ip/hmac/doc/registers.md
@@ -320,7 +320,7 @@ HMAC Error Code
 ## WIPE_SECRET
 Clear internal secret registers.
 
-If CPU writes a value into the register, the value is used to clear the internal variables such as the secret key, intermediate hash results, digest and the internal message scheduling array.
+If the CPU writes a value into the register, the value is used to clear some internal variables such as the secret key, intermediate hash results, digest and internal message scheduling array.
 The clear secret operation overwrites the internal variables with the provided 32-bit value.
 For SHA-2 384/512 that work with 64-bit words, the 32-bit value is duplicated and concatenated to generate the 64-bit value.
 It is recommended to use a value extracted from an entropy source.
diff --git a/hw/ip/hmac/rtl/hmac.sv b/hw/ip/hmac/rtl/hmac.sv
index ba4c7d5c92737..9867356da30b8 100644
--- a/hw/ip/hmac/rtl/hmac.sv
+++ b/hw/ip/hmac/rtl/hmac.sv
@@ -935,6 +935,11 @@ module hmac
   `ASSERT(ValidHmacEnConditionAssert,
           hmac_en != $past(hmac_en) |-> !in_process && !initiated)
 
+  // When wipe_secret is high, sensitive internal variables are cleared by extending the wipe
+  // value specifed in the register
+  `ASSERT(WipeSecretKeyAssert,
+          wipe_secret |=> (secret_key == {($bits(secret_key)/$bits(wipe_v)){$past(wipe_v)}}))
+
   // All outputs should be known value after reset
   `ASSERT_KNOWN(IntrHmacDoneOKnown, intr_hmac_done_o)
   `ASSERT_KNOWN(IntrFifoEmptyOKnown, intr_fifo_empty_o)
diff --git a/hw/ip/prim/rtl/prim_sha2.sv b/hw/ip/prim/rtl/prim_sha2.sv
index 27cf8d298800a..f1578c673abc1 100644
--- a/hw/ip/prim/rtl/prim_sha2.sv
+++ b/hw/ip/prim/rtl/prim_sha2.sv
@@ -178,6 +178,14 @@ module prim_sha2 import prim_sha2_pkg::*;
     // assign digest to output
     assign digest_o = digest_q;
 
+    // When wipe_secret is high, sensitive internal variables are cleared by extending the wipe
+    // value specifed in the register
+    `ASSERT(WipeHashAssert,
+            wipe_secret_i |=> (hash_q == {($bits(hash_q)/$bits(wipe_v_i)){$past(wipe_v_i)}}))
+    `ASSERT(WipeMsgSchArrAssert,
+            wipe_secret_i |=> (w_q == {($bits(w_q)/$bits(wipe_v_i)){$past(wipe_v_i)}}))
+    `ASSERT(WipeDigestAssert,
+            wipe_secret_i |=> (digest_q == {($bits(digest_q)/$bits(wipe_v_i)){$past(wipe_v_i)}}))
   end else begin : gen_256 // MultimodeEn = 0
     // datapath signal definitions for SHA-2 256 only
     sha_word32_t        shaf_rdata256;
@@ -264,6 +272,15 @@ module prim_sha2 import prim_sha2_pkg::*;
       assign digest_o[i][31:0]  = digest256_q[i];
       assign digest_o[i][63:32] = 32'b0;
     end
+
+    // When wipe_secret is high, sensitive internal variables are cleared by extending the wipe
+    // value specifed in the register
+    `ASSERT(WipeHashAssert,
+      wipe_secret_i |=> (hash256_q == {($bits(hash256_q)/$bits(wipe_v_i)){$past(wipe_v_i)}}))
+    `ASSERT(WipeMsgSchArrAssert,
+      wipe_secret_i |=> (w256_q == {($bits(w256_q)/$bits(wipe_v_i)){$past(wipe_v_i)}}))
+    `ASSERT(WipeDigestAssert,
+      wipe_secret_i |=> (digest256_q == {($bits(digest256_q)/$bits(wipe_v_i)){$past(wipe_v_i)}}))
   end
 
   // compute round counter (shared)