[lc_ctrl] Add life cycle state diversification output
Signed-off-by: Michael Schaffner <msf@opentitan.org>
diff --git a/hw/ip/lc_ctrl/rtl/lc_ctrl.sv b/hw/ip/lc_ctrl/rtl/lc_ctrl.sv
index c45af38..a9e7f5e 100644
--- a/hw/ip/lc_ctrl/rtl/lc_ctrl.sv
+++ b/hw/ip/lc_ctrl/rtl/lc_ctrl.sv
@@ -14,7 +14,13 @@
// Enable asynchronous transitions on alerts.
parameter logic [NumAlerts-1:0] AlertAsyncOn = {NumAlerts{1'b1}},
// Idcode value for the JTAG.
- parameter logic [31:0] IdcodeValue = 32'h00000001
+ parameter logic [31:0] IdcodeValue = 32'h00000001,
+ // Random netlist constants
+ parameter lc_keymgr_div_t RndCnstLcKeymgrDivInv = LcKeymgrDivWidth'(0),
+ parameter lc_keymgr_div_t RndCnstLcKeymgrDivTest = LcKeymgrDivWidth'(1),
+ parameter lc_keymgr_div_t RndCnstLcKeymgrDivProd = LcKeymgrDivWidth'(2),
+ parameter lc_keymgr_div_t RndCnstLcKeymgrDivDev = LcKeymgrDivWidth'(3),
+ parameter lc_keymgr_div_t RndCnstLcKeymgrDivRma = LcKeymgrDivWidth'(4)
) (
input clk_i,
input rst_ni,
@@ -67,7 +73,9 @@
// The ack is synced to the lc clock domain using prim_lc_sync.
output lc_flash_rma_seed_t lc_flash_rma_seed_o,
output lc_tx_t lc_flash_rma_req_o,
- input lc_tx_t lc_flash_rma_ack_i
+ input lc_tx_t lc_flash_rma_ack_i,
+ // State group diversification value for keymgr
+ output lc_keymgr_div_t lc_keymgr_div_o
);
////////////////////////
@@ -446,7 +454,13 @@
assign lc_otp_token_o.token_input = transition_token_q;
assign lc_flash_rma_seed_o = transition_token_q[RmaSeedWidth-1:0];
- lc_ctrl_fsm u_lc_ctrl_fsm (
+ lc_ctrl_fsm #(
+ .RndCnstLcKeymgrDivInv ( RndCnstLcKeymgrDivInv ),
+ .RndCnstLcKeymgrDivTest ( RndCnstLcKeymgrDivTest ),
+ .RndCnstLcKeymgrDivProd ( RndCnstLcKeymgrDivProd ),
+ .RndCnstLcKeymgrDivDev ( RndCnstLcKeymgrDivDev ),
+ .RndCnstLcKeymgrDivRma ( RndCnstLcKeymgrDivRma )
+ ) u_lc_ctrl_fsm (
.clk_i,
.rst_ni,
.init_req_i ( lc_init ),
@@ -492,7 +506,8 @@
.lc_clk_byp_req_o,
.lc_clk_byp_ack_i ( lc_clk_byp_ack ),
.lc_flash_rma_req_o,
- .lc_flash_rma_ack_i ( lc_flash_rma_ack )
+ .lc_flash_rma_ack_i ( lc_flash_rma_ack ),
+ .lc_keymgr_div_o
);
////////////////
@@ -515,5 +530,6 @@
`ASSERT_KNOWN(LcClkBypReqKnown_A, lc_clk_byp_req_o )
`ASSERT_KNOWN(LcFlashRmaSeedKnown_A, lc_flash_rma_seed_o )
`ASSERT_KNOWN(LcFlashRmaReqKnown_A, lc_flash_rma_req_o )
+ `ASSERT_KNOWN(LcKeymgrDiv_A, lc_keymgr_div_o )
endmodule : lc_ctrl
diff --git a/hw/ip/lc_ctrl/rtl/lc_ctrl_fsm.sv b/hw/ip/lc_ctrl/rtl/lc_ctrl_fsm.sv
index 9da0b3c..b66c9a8 100644
--- a/hw/ip/lc_ctrl/rtl/lc_ctrl_fsm.sv
+++ b/hw/ip/lc_ctrl/rtl/lc_ctrl_fsm.sv
@@ -6,7 +6,13 @@
module lc_ctrl_fsm
import lc_ctrl_pkg::*;
-(
+#(// Random netlist constants
+ parameter lc_keymgr_div_t RndCnstLcKeymgrDivInv = LcKeymgrDivWidth'(0),
+ parameter lc_keymgr_div_t RndCnstLcKeymgrDivTest = LcKeymgrDivWidth'(1),
+ parameter lc_keymgr_div_t RndCnstLcKeymgrDivProd = LcKeymgrDivWidth'(2),
+ parameter lc_keymgr_div_t RndCnstLcKeymgrDivDev = LcKeymgrDivWidth'(3),
+ parameter lc_keymgr_div_t RndCnstLcKeymgrDivRma = LcKeymgrDivWidth'(4)
+) (
// This module is combinational, but we
// need the clock and reset for the assertions.
input clk_i,
@@ -66,7 +72,9 @@
input lc_tx_t lc_clk_byp_ack_i,
// Request and feedback to/from flash controller
output lc_tx_t lc_flash_rma_req_o,
- input lc_tx_t lc_flash_rma_ack_i
+ input lc_tx_t lc_flash_rma_ack_i,
+ // State group diversification value for keymgr
+ output lc_keymgr_div_t lc_keymgr_div_o
);
///////////////
@@ -413,7 +421,13 @@
);
// LC signal decoder and broadcasting logic.
- lc_ctrl_signal_decode u_lc_ctrl_signal_decode (
+ lc_ctrl_signal_decode #(
+ .RndCnstLcKeymgrDivInv ( RndCnstLcKeymgrDivInv ),
+ .RndCnstLcKeymgrDivTest ( RndCnstLcKeymgrDivTest ),
+ .RndCnstLcKeymgrDivProd ( RndCnstLcKeymgrDivProd ),
+ .RndCnstLcKeymgrDivDev ( RndCnstLcKeymgrDivDev ),
+ .RndCnstLcKeymgrDivRma ( RndCnstLcKeymgrDivRma )
+ ) u_lc_ctrl_signal_decode (
.clk_i,
.rst_ni,
.lc_state_valid_i ( lc_state_valid_q ),
@@ -428,7 +442,8 @@
.lc_provision_wr_en_o,
.lc_provision_rd_en_o,
.lc_keymgr_en_o,
- .lc_escalate_en_o
+ .lc_escalate_en_o,
+ .lc_keymgr_div_o
);
// Conditional signals set by main FSM.
diff --git a/hw/ip/lc_ctrl/rtl/lc_ctrl_pkg.sv b/hw/ip/lc_ctrl/rtl/lc_ctrl_pkg.sv
index 4821692..3f76149 100644
--- a/hw/ip/lc_ctrl/rtl/lc_ctrl_pkg.sv
+++ b/hw/ip/lc_ctrl/rtl/lc_ctrl_pkg.sv
@@ -205,6 +205,9 @@
parameter int RmaSeedWidth = 32;
typedef logic [RmaSeedWidth-1:0] lc_flash_rma_seed_t;
+ parameter int LcKeymgrDivWidth = 64;
+ typedef logic [LcKeymgrDivWidth-1:0] lc_keymgr_div_t;
+
////////////////////
// Main FSM State //
////////////////////
diff --git a/hw/ip/lc_ctrl/rtl/lc_ctrl_signal_decode.sv b/hw/ip/lc_ctrl/rtl/lc_ctrl_signal_decode.sv
index 75507d3..5e68738 100644
--- a/hw/ip/lc_ctrl/rtl/lc_ctrl_signal_decode.sv
+++ b/hw/ip/lc_ctrl/rtl/lc_ctrl_signal_decode.sv
@@ -6,7 +6,19 @@
module lc_ctrl_signal_decode
import lc_ctrl_pkg::*;
-(
+#(
+ // Random netlist constants
+ // SCRAP, RAW, TEST_LOCKED*, INVALID
+ parameter lc_keymgr_div_t RndCnstLcKeymgrDivInv = LcKeymgrDivWidth'(0),
+ // TEST_UNLOCKED*
+ parameter lc_keymgr_div_t RndCnstLcKeymgrDivTest = LcKeymgrDivWidth'(1),
+ // PROD, PROD_END
+ parameter lc_keymgr_div_t RndCnstLcKeymgrDivProd = LcKeymgrDivWidth'(2),
+ // DEV
+ parameter lc_keymgr_div_t RndCnstLcKeymgrDivDev = LcKeymgrDivWidth'(3),
+ // RMA
+ parameter lc_keymgr_div_t RndCnstLcKeymgrDivRma = LcKeymgrDivWidth'(4)
+) (
input clk_i,
input rst_ni,
// Life cycle state vector.
@@ -24,7 +36,9 @@
output lc_tx_t lc_provision_wr_en_o,
output lc_tx_t lc_provision_rd_en_o,
output lc_tx_t lc_keymgr_en_o,
- output lc_tx_t lc_escalate_en_o
+ output lc_tx_t lc_escalate_en_o,
+ // State group diversification value for keymgr
+ output lc_keymgr_div_t lc_keymgr_div_o
);
//////////////////////////
@@ -39,6 +53,7 @@
lc_tx_t lc_provision_rd_en_d, lc_provision_rd_en_q;
lc_tx_t lc_keymgr_en_d, lc_keymgr_en_q;
lc_tx_t lc_escalate_en_d, lc_escalate_en_q;
+ lc_keymgr_div_t lc_keymgr_div_d, lc_keymgr_div_q;
always_comb begin : p_lc_signal_decode
// Life cycle control signal defaults
@@ -50,7 +65,8 @@
lc_provision_rd_en_d = Off;
lc_keymgr_en_d = Off;
lc_escalate_en_d = Off;
-
+ // Set to invalid diversification value by default.
+ lc_keymgr_div_d = RndCnstLcKeymgrDivInv;
// The escalation life cycle signal is always decoded, no matter
// which state we currently are in.
if (esc_wipe_secrets_i) begin
@@ -66,8 +82,7 @@
FlashRmaSt,
TokenHashSt,
TokenCheck0St,
- TokenCheck1St,
- TransProgSt}) begin
+ TokenCheck1St}) begin
unique case (lc_state_i)
///////////////////////////////////////////////////////////////////
// Enable DFT and debug functionality, including the CPU in the
@@ -80,6 +95,7 @@
lc_nvm_debug_en_d = On;
lc_hw_debug_en_d = On;
lc_cpu_en_d = On;
+ lc_keymgr_div_d = RndCnstLcKeymgrDivTest;
end
///////////////////////////////////////////////////////////////////
// Enable production functions
@@ -87,6 +103,7 @@
lc_cpu_en_d = On;
lc_keymgr_en_d = On;
lc_provision_rd_en_d = On;
+ lc_keymgr_div_d = RndCnstLcKeymgrDivProd;
// Only allow provisioning if the defice has not yet been personalized.
if (lc_id_state_i == LcIdBlank) begin
lc_provision_wr_en_d = On;
@@ -99,6 +116,7 @@
lc_cpu_en_d = On;
lc_keymgr_en_d = On;
lc_provision_rd_en_d = On;
+ lc_keymgr_div_d = RndCnstLcKeymgrDivDev;
// Only allow provisioning if the defice has not yet been personalized.
if (lc_id_state_i == LcIdBlank) begin
lc_provision_wr_en_d = On;
@@ -113,6 +131,7 @@
lc_cpu_en_d = On;
lc_keymgr_en_d = On;
lc_provision_rd_en_d = On;
+ lc_keymgr_div_d = RndCnstLcKeymgrDivRma;
// Only allow provisioning if the defice has not yet been personalized.
if (lc_id_state_i == LcIdBlank) begin
lc_provision_wr_en_d = On;
@@ -138,6 +157,7 @@
assign lc_provision_rd_en_o = lc_provision_rd_en_q;
assign lc_keymgr_en_o = lc_keymgr_en_q;
assign lc_escalate_en_o = lc_escalate_en_q;
+ assign lc_keymgr_div_o = lc_keymgr_div_q;
always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
if (!rst_ni) begin
@@ -149,6 +169,7 @@
lc_provision_rd_en_q <= Off;
lc_keymgr_en_q <= Off;
lc_escalate_en_q <= Off;
+ lc_keymgr_div_q <= RndCnstLcKeymgrDivInv;
end else begin
lc_dft_en_q <= lc_dft_en_d;
lc_nvm_debug_en_q <= lc_nvm_debug_en_d;
@@ -158,6 +179,7 @@
lc_provision_rd_en_q <= lc_provision_rd_en_d;
lc_keymgr_en_q <= lc_keymgr_en_d;
lc_escalate_en_q <= lc_escalate_en_d;
+ lc_keymgr_div_q <= lc_keymgr_div_d;
end
end
@@ -165,6 +187,19 @@
// Assertions //
////////////////
+ // Need to make sure that the random netlist constants
+ // are unique.
+ `ASSERT_INIT(LcKeymgrDivUnique0_A, !(RndCnstLcKeymgrDivInvalid inside {RndCnstLcKeymgrDivTest,
+ RndCnstLcKeymgrDivProd,
+ RndCnstLcKeymgrDivDev,
+ RndCnstLcKeymgrDivRma}))
+ `ASSERT_INIT(LcKeymgrDivUnique1_A, !(RndCnstLcKeymgrDivTest inside {RndCnstLcKeymgrDivProd,
+ RndCnstLcKeymgrDivDev,
+ RndCnstLcKeymgrDivRma}))
+ `ASSERT_INIT(LcKeymgrDivUnique2_A, !(RndCnstLcKeymgrDivProd inside {RndCnstLcKeymgrDivDev,
+ RndCnstLcKeymgrDivRma}))
+ `ASSERT_INIT(LcKeymgrDivUnique3_A, !(RndCnstLcKeymgrDivDev inside {RndCnstLcKeymgrDivRma}))
+
`ASSERT(SignalsAreOffWhenNotEnabled_A,
!lc_state_valid_i
|=>
@@ -175,7 +210,8 @@
lc_provision_wr_en_o == Off &&
lc_provision_rd_en_o == Off &&
lc_keymgr_en_o == Off &&
- lc_dft_en_o == Off)
+ lc_dft_en_o == Off &&
+ lc_keymgr_div_o == RndCnstLcKeymgrDivInv)
`ASSERT(EscalationAlwaysDecoded_A,
(lc_escalate_en_o == On) == $past(esc_wipe_secrets_i))