Skip to content

Commit

Permalink
[lc_ctrl] Use unique diversification values
Browse files Browse the repository at this point in the history
This makes the diversification values fed to the keymgr
unique for each group of life cycle states.

Fixes #14047

Signed-off-by: Michael Schaffner <[email protected]>
  • Loading branch information
msfschaffner committed Feb 14, 2024
1 parent 3938983 commit 6948d41
Show file tree
Hide file tree
Showing 12 changed files with 338 additions and 227 deletions.
14 changes: 13 additions & 1 deletion hw/ip/lc_ctrl/data/lc_ctrl.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,13 @@
randcount: "128",
randtype: "data",
}
{ name: "RndCnstLcKeymgrDivTestDevRma",
{ name: "RndCnstLcKeymgrDivTestUnlocked",
desc: "Compile-time random bits for lc state group diversification value",
type: "lc_ctrl_pkg::lc_keymgr_div_t",
randcount: "128",
randtype: "data",
}
{ name: "RndCnstLcKeymgrDivDev",
desc: "Compile-time random bits for lc state group diversification value",
type: "lc_ctrl_pkg::lc_keymgr_div_t",
randcount: "128",
Expand All @@ -89,6 +95,12 @@
randcount: "128",
randtype: "data",
}
{ name: "RndCnstLcKeymgrDivRma",
desc: "Compile-time random bits for lc state group diversification value",
type: "lc_ctrl_pkg::lc_keymgr_div_t",
randcount: "128",
randtype: "data",
}
{ name: "RndCnstInvalidTokens",
desc: "Compile-time random bits used for invalid tokens in the token mux",
type: "lc_ctrl_pkg::lc_token_mux_t",
Expand Down
28 changes: 16 additions & 12 deletions hw/ip/lc_ctrl/doc/interfaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@

Note that parameters prefixed with `RndCnst` are random netlist constants that need to be regenerated via topgen before the tapeout (typically by the silicon creator).

Parameter | Default (Max) | Top Earlgrey | Description
-------------------------------|-----------------------|----------------|---------------
`AlertAsyncOn` | 2'b11 | 2'b11 |
`IdcodeValue` | `32'h00000001` | `32'h00000001` | Idcode for the LC JTAG TAP.
`RndCnstLcKeymgrDivInvalid` | (see RTL) | (see RTL) | Life cycle state group diversification value for keymgr.
`RndCnstLcKeymgrDivTestDevRma` | (see RTL) | (see RTL) | Life cycle state group diversification value for keymgr.
`RndCnstLcKeymgrDivProduction` | (see RTL) | (see RTL) | Life cycle state group diversification value for keymgr.
Parameter | Default (Max) | Top Earlgrey | Description
---------------------------------|----------------|----------------|---------------
`AlertAsyncOn` | 2'b11 | 2'b11 |
`IdcodeValue` | `32'h00000001` | `32'h00000001` | Idcode for the LC JTAG TAP.
`RndCnstLcKeymgrDivInvalid` | (see RTL) | (see RTL) | Life cycle state group diversification value for keymgr.
`RndCnstLcKeymgrDivTestUnlocked` | (see RTL) | (see RTL) | Life cycle state group diversification value for keymgr.
`RndCnstLcKeymgrDivDev` | (see RTL) | (see RTL) | Life cycle state group diversification value for keymgr.
`RndCnstLcKeymgrDivProduction` | (see RTL) | (see RTL) | Life cycle state group diversification value for keymgr.
`RndCnstLcKeymgrRma` | (see RTL) | (see RTL) | Life cycle state group diversification value for keymgr.

### Signals

Expand Down Expand Up @@ -182,11 +184,13 @@ For all signals except ESCALATE_EN, it is recommended to structure the design su
The `lc_keymgr_div_o` signal is a 128bit diversification constant that is output to the key manager once the life cycle controller has initialized, and is asserted at the same time as `lc_keymgr_en_o`.
Depending on which group the life cycle state is in, this signal is assigned a different random netlist constant as defined in the table below.

Life Cycle State Group | Assigned Diversification Constant
---------------------------|----------------------------------
TEST_UNLOCKED\*, DEV, RMA | `LcKeymgrDivTestDevRma`
PROD, PROD_END | `LcKeymgrDivProduction`
All Other States | `LcKeymgrDivInvalid`
Life Cycle State Group | Assigned Diversification Constant
-----------------------|----------------------------------
TEST_UNLOCKED\* | `LcKeymgrDivTestUnlocked`
DEV | `LcKeymgrDivTestDev`
PROD, PROD_END | `LcKeymgrDivProduction`
RMA | `LcKeymgrDivTestRma`
All Other States | `LcKeymgrDivInvalid`

Note that this signal is quasistatic.
It is hence recommended to place a max-delay constraint on it and leverage the synchronized version of `lc_keymgr_en_o` to enable any downstream register in different clock domains than the life cycle controller.
18 changes: 18 additions & 0 deletions hw/ip/lc_ctrl/dv/env/lc_ctrl_env_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,24 @@ package lc_ctrl_env_pkg;
`DV_CHECK_STD_RANDOMIZE_FATAL(get_random_token,, "lc_ctrl_env_pkg");
endfunction

function automatic lc_keymgr_div_t get_exp_div(dec_lc_state_e state, lc_ctrl_parameters_cfg cfg);
unique case (state) begin
DecLcStTestUnlocked0,
DecLcStTestUnlocked1,
DecLcStTestUnlocked2,
DecLcStTestUnlocked3,
DecLcStTestUnlocked4,
DecLcStTestUnlocked5,
DecLcStTestUnlocked6,
DecLcStTestUnlocked7: return cfg.keymgr_div_test_unlocked;
DecLcStDev: return cfg.keymgr_div_dev;
DecLcStProd,
DecLcStProdEnd: return cfg.keymgr_div_production;
DecLcStRma: return cfg.keymgr_div_rma;
default: return cfg.keymgr_div_invalid;
endcase
endfunction

// package sources
`include "lc_ctrl_parameters_cfg.sv"
`include "lc_ctrl_env_cfg.sv"
Expand Down
16 changes: 10 additions & 6 deletions hw/ip/lc_ctrl/dv/env/lc_ctrl_parameters_cfg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,23 @@
class lc_ctrl_parameters_cfg extends uvm_object;
// LC_CTRL parameters
// Enable asynchronous transitions on alerts.
logic [NUM_ALERTS-1:0] alert_async_on = {NUM_ALERTS{1'b1}};
logic [NUM_ALERTS-1:0] alert_async_on = {NUM_ALERTS{1'b1}};
// Idcode value for the JTAG.
logic [ 31:0] id_code_value = 32'h00000001;
logic [ 31:0] id_code_value = 32'h00000001;
// Random netlist constants
lc_keymgr_div_t keymgr_div_invalid = LcKeymgrDivWidth'(0);
lc_keymgr_div_t keymgr_div_test_dev_rma = LcKeymgrDivWidth'(1);
lc_keymgr_div_t keymgr_div_production = LcKeymgrDivWidth'(2);
lc_keymgr_div_t keymgr_div_invalid = LcKeymgrDivWidth'(0);
lc_keymgr_div_t keymgr_div_test_unlocked = LcKeymgrDivWidth'(1);
lc_keymgr_div_t keymgr_div_dev = LcKeymgrDivWidth'(2);
lc_keymgr_div_t keymgr_div_production = LcKeymgrDivWidth'(3);
lc_keymgr_div_t keymgr_div_rma = LcKeymgrDivWidth'(4);
`uvm_object_utils_begin(lc_ctrl_parameters_cfg)
`uvm_field_int(alert_async_on, UVM_DEFAULT)
`uvm_field_int(id_code_value, UVM_DEFAULT)
`uvm_field_int(keymgr_div_invalid, UVM_DEFAULT)
`uvm_field_int(keymgr_div_test_dev_rma, UVM_DEFAULT)
`uvm_field_int(keymgr_div_test_unlocked, UVM_DEFAULT)
`uvm_field_int(keymgr_div_dev, UVM_DEFAULT)
`uvm_field_int(keymgr_div_production, UVM_DEFAULT)
`uvm_field_int(keymgr_div_rma, UVM_DEFAULT)
`uvm_object_utils_end

`uvm_object_new
Expand Down
24 changes: 15 additions & 9 deletions hw/ip/lc_ctrl/dv/env/lc_ctrl_scoreboard.sv
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,9 @@ class lc_ctrl_scoreboard extends cip_base_scoreboard #(
forever begin
@(posedge cfg.pwr_lc_vif.pins[LcPwrDoneRsp] && cfg.en_scb) begin
dec_lc_state_e lc_state = dec_lc_state(lc_state_e'(cfg.lc_ctrl_vif.otp_i.state));
lc_outputs_t exp_lc_o = EXP_LC_OUTPUTS[int'(lc_state)];
string err_msg = $sformatf("LC_St %0s", lc_state.name);
lc_outputs_t exp_lc_o = EXP_LC_OUTPUTS[int'(lc_state)];
lc_keymgr_div_t exp_div_o = get_exp_div(lc_state, cfg.parameters_cfg);
string err_msg = $sformatf("LC_St %0s", lc_state.name);
cfg.clk_rst_vif.wait_n_clks(1);

// lc_creator_seed_sw_rw_en_o is ON only when device has NOT been personalized or RMA state
Expand All @@ -87,14 +88,16 @@ class lc_ctrl_scoreboard extends cip_base_scoreboard #(

if (cfg.escalate_injected) begin
exp_lc_o = EXP_LC_OUTPUTS[int'(DecLcStEscalate)];
exp_div_o = cfg.parameters_cfg.keymgr_div_invalid;
end

fork
begin
// Delay a some of cycles to allow escalate to be recognised
if (cfg.escalate_injected) cfg.clk_rst_vif.wait_clks(5);
->check_lc_output_ev;
check_lc_outputs(exp_lc_o, {$sformatf("Called from line: %0d, ", `__LINE__), err_msg});
check_lc_outputs(exp_lc_o, exp_div_o,
{$sformatf("Called from line: %0d, ", `__LINE__), err_msg});
end
join_none

Expand Down Expand Up @@ -230,6 +233,7 @@ class lc_ctrl_scoreboard extends cip_base_scoreboard #(

// check lc outputs, default all off
virtual function void check_lc_outputs(lc_outputs_t exp_o = '{default: lc_ctrl_pkg::Off},
lc_keymgr_div_t exp_div_o = '0,
string msg = "expect all output OFF");
`DV_CHECK_EQ(cfg.lc_ctrl_vif.lc_dft_en_o, exp_o.lc_dft_en_o, msg)
`DV_CHECK_EQ(cfg.lc_ctrl_vif.lc_nvm_debug_en_o, exp_o.lc_nvm_debug_en_o, msg)
Expand All @@ -243,14 +247,16 @@ class lc_ctrl_scoreboard extends cip_base_scoreboard #(
`DV_CHECK_EQ(cfg.lc_ctrl_vif.lc_seed_hw_rd_en_o, exp_o.lc_seed_hw_rd_en_o, msg)
`DV_CHECK_EQ(cfg.lc_ctrl_vif.lc_creator_seed_sw_rw_en_o, exp_o.lc_creator_seed_sw_rw_en_o, msg)
`DV_CHECK_EQ(cfg.lc_ctrl_vif.clk_byp_req_o, exp_clk_byp_req, msg)
`DV_CHECK_EQ(cfg.lc_ctrl_vif.keymgr_div_o, exp_div_o, msg)
endfunction

virtual task process_tl_access(tl_seq_item item, tl_channels_e channel, string ral_name);
uvm_reg csr;
bit do_read_check = 1'b0;
bit write = item.is_write();
uvm_reg_addr_t csr_addr = cfg.ral_models[ral_name].get_word_aligned_addr(item.a_addr);
lc_outputs_t exp = '{default: lc_ctrl_pkg::Off};
uvm_reg csr;
bit do_read_check = 1'b0;
bit write = item.is_write();
uvm_reg_addr_t csr_addr = cfg.ral_models[ral_name].get_word_aligned_addr(item.a_addr);
lc_outputs_t exp = '{default: lc_ctrl_pkg::Off};
lc_keymgr_div_t exp_div = cfg.parameters_cfg.keymgr_div_invalid;

bit addr_phase_read = (!write && channel == AddrChannel);
bit addr_phase_write = (write && channel == AddrChannel);
Expand Down Expand Up @@ -398,7 +404,7 @@ class lc_ctrl_scoreboard extends cip_base_scoreboard #(
begin
// Wait for escalate to be recognise
if (cfg.err_inj.security_escalation_err) cfg.clk_rst_vif.wait_clks(5);
check_lc_outputs(exp, $sformatf("Called from line: %0d", `__LINE__));
check_lc_outputs(exp, exp_div, $sformatf("Called from line: %0d", `__LINE__));
end
join_none
end
Expand Down
16 changes: 12 additions & 4 deletions hw/ip/lc_ctrl/dv/tb.sv
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,14 @@ module tb;
// Random netlist constants
parameter lc_keymgr_div_t RndCnstLcKeymgrDivInvalid =
LcKeymgrDivWidth'({(LcKeymgrDivWidth/8){32'h00000000}});
parameter lc_keymgr_div_t RndCnstLcKeymgrDivTestDevRma =
parameter lc_keymgr_div_t RndCnstLcKeymgrDivTestUnlocked =
LcKeymgrDivWidth'({(LcKeymgrDivWidth/8){8'h5a}});
parameter lc_keymgr_div_t RndCnstLcKeymgrDivProduction =
parameter lc_keymgr_div_t RndCnstLcKeymgrDivDev =
LcKeymgrDivWidth'({(LcKeymgrDivWidth/8){8'ha5}});
parameter lc_keymgr_div_t RndCnstLcKeymgrDivProduction =
LcKeymgrDivWidth'({(LcKeymgrDivWidth/8){8'ha69}});

Check warning on line 30 in hw/ip/lc_ctrl/dv/tb.sv

View workflow job for this annotation

GitHub Actions / verible-verilog-lint

[verible-verilog-lint] hw/ip/lc_ctrl/dv/tb.sv#L30

Number 8'ha69 occupies 12 bits, truncated to 8 bits. [Style: number-literals] [truncated-numeric-literal]
Raw output
message:"Number 8'ha69 occupies 12 bits, truncated to 8 bits. [Style: number-literals] [truncated-numeric-literal]"  location:{path:"./hw/ip/lc_ctrl/dv/tb.sv"  range:{start:{line:30  column:48}}}  severity:WARNING  source:{name:"verible-verilog-lint"  url:"https://github.com/chipsalliance/verible"}
parameter lc_keymgr_div_t RndCnstLcKeymgrDivRma =
LcKeymgrDivWidth'({(LcKeymgrDivWidth/8){8'h96}});
// ---------- VOLATILE_TEST_UNLOCKED CODE SECTION START ----------
// NOTE THAT THIS IS A FEATURE FOR TEST CHIPS ONLY TO MITIGATE
// THE RISK OF A BROKEN OTP MACRO. THIS WILL BE DISABLED VIA
Expand Down Expand Up @@ -103,8 +107,10 @@ module tb;
.IdcodeValue(IdcodeValue),
// Random netlist constants
.RndCnstLcKeymgrDivInvalid(RndCnstLcKeymgrDivInvalid),
.RndCnstLcKeymgrDivTestDevRma(RndCnstLcKeymgrDivTestDevRma),
.RndCnstLcKeymgrDivTestUnlocked(RndCnstLcKeymgrDivTestUnlocked),
.RndCnstLcKeymgrDivTestDev(RndCnstLcKeymgrDivTestDev),
.RndCnstLcKeymgrDivProduction(RndCnstLcKeymgrDivProduction),
.RndCnstLcKeymgrDivTestRma(RndCnstLcKeymgrDivTestRma),
.SiliconCreatorId(LcCtrlSiliconCreatorId[lc_ctrl_reg_pkg::SiliconCreatorIdWidth-1:0]),
.ProductId(LcCtrlProductId[lc_ctrl_reg_pkg::ProductIdWidth-1:0]),
.RevisionId(LcCtrlRevisionId[lc_ctrl_reg_pkg::RevisionIdWidth-1:0]),
Expand Down Expand Up @@ -234,8 +240,10 @@ module tb;
parameters_cfg.alert_async_on = AlertAsyncOn;
parameters_cfg.id_code_value = IdcodeValue;
parameters_cfg.keymgr_div_invalid = RndCnstLcKeymgrDivInvalid;
parameters_cfg.keymgr_div_test_dev_rma = RndCnstLcKeymgrDivTestDevRma;
parameters_cfg.keymgr_div_test_unlocked = RndCnstLcKeymgrDivTestUnlocked;
parameters_cfg.keymgr_div_dev = RndCnstLcKeymgrDivDev;
parameters_cfg.keymgr_div_production = RndCnstLcKeymgrDivProduction;
parameters_cfg.keymgr_div_rma = RndCnstLcKeymgrDivRma;
uvm_config_db#(lc_ctrl_parameters_cfg)::set(null, "*", "parameters_cfg", parameters_cfg);

// verilog_format: on
Expand Down
24 changes: 14 additions & 10 deletions hw/ip/lc_ctrl/rtl/lc_ctrl.sv
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ module lc_ctrl
// Idcode value for the JTAG.
parameter logic [31:0] IdcodeValue = 32'h00000001,
// Random netlist constants
parameter lc_keymgr_div_t RndCnstLcKeymgrDivInvalid = LcKeymgrDivWidth'(0),
parameter lc_keymgr_div_t RndCnstLcKeymgrDivTestDevRma = LcKeymgrDivWidth'(1),
parameter lc_keymgr_div_t RndCnstLcKeymgrDivProduction = LcKeymgrDivWidth'(2),
parameter lc_token_mux_t RndCnstInvalidTokens = {TokenMuxBits{1'b1}},
parameter bit SecVolatileRawUnlockEn = 0
parameter lc_keymgr_div_t RndCnstLcKeymgrDivInvalid = LcKeymgrDivWidth'(0),
parameter lc_keymgr_div_t RndCnstLcKeymgrDivTestUnlocked = LcKeymgrDivWidth'(1),
parameter lc_keymgr_div_t RndCnstLcKeymgrDivTestDev = LcKeymgrDivWidth'(2),
parameter lc_keymgr_div_t RndCnstLcKeymgrDivProduction = LcKeymgrDivWidth'(3),
parameter lc_keymgr_div_t RndCnstLcKeymgrDivTestRma = LcKeymgrDivWidth'(4),
parameter lc_token_mux_t RndCnstInvalidTokens = {TokenMuxBits{1'b1}},
parameter bit SecVolatileRawUnlockEn = 0
) (
// Life cycle controller clock
input clk_i,
Expand Down Expand Up @@ -700,11 +702,13 @@ module lc_ctrl
////////////

lc_ctrl_fsm #(
.RndCnstLcKeymgrDivInvalid ( RndCnstLcKeymgrDivInvalid ),
.RndCnstLcKeymgrDivTestDevRma ( RndCnstLcKeymgrDivTestDevRma ),
.RndCnstLcKeymgrDivProduction ( RndCnstLcKeymgrDivProduction ),
.RndCnstInvalidTokens ( RndCnstInvalidTokens ),
.SecVolatileRawUnlockEn ( SecVolatileRawUnlockEn )
.RndCnstLcKeymgrDivInvalid ( RndCnstLcKeymgrDivInvalid ),
.RndCnstLcKeymgrDivTestUnlocked( RndCnstLcKeymgrDivTestUnlocked ),
.RndCnstLcKeymgrDivTestDev ( RndCnstLcKeymgrDivTestDev ),
.RndCnstLcKeymgrDivProduction ( RndCnstLcKeymgrDivProduction ),
.RndCnstLcKeymgrDivTestRma ( RndCnstLcKeymgrDivTestRma ),
.RndCnstInvalidTokens ( RndCnstInvalidTokens ),
.SecVolatileRawUnlockEn ( SecVolatileRawUnlockEn )
) u_lc_ctrl_fsm (
.clk_i,
.rst_ni,
Expand Down
20 changes: 12 additions & 8 deletions hw/ip/lc_ctrl/rtl/lc_ctrl_fsm.sv
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,13 @@ module lc_ctrl_fsm
import lc_ctrl_reg_pkg::*;
import lc_ctrl_state_pkg::*;
#(// Random netlist constants
parameter lc_keymgr_div_t RndCnstLcKeymgrDivInvalid = LcKeymgrDivWidth'(0),
parameter lc_keymgr_div_t RndCnstLcKeymgrDivTestDevRma = LcKeymgrDivWidth'(1),
parameter lc_keymgr_div_t RndCnstLcKeymgrDivProduction = LcKeymgrDivWidth'(2),
parameter lc_token_mux_t RndCnstInvalidTokens = {TokenMuxBits{1'b1}},
parameter bit SecVolatileRawUnlockEn = 0
parameter lc_keymgr_div_t RndCnstLcKeymgrDivInvalid = LcKeymgrDivWidth'(0),
parameter lc_keymgr_div_t RndCnstLcKeymgrDivTestUnlocked = LcKeymgrDivWidth'(1),
parameter lc_keymgr_div_t RndCnstLcKeymgrDivTestDev = LcKeymgrDivWidth'(2),
parameter lc_keymgr_div_t RndCnstLcKeymgrDivProduction = LcKeymgrDivWidth'(3),
parameter lc_keymgr_div_t RndCnstLcKeymgrDivTestRma = LcKeymgrDivWidth'(4)
parameter lc_token_mux_t RndCnstInvalidTokens = {TokenMuxBits{1'b1}},
parameter bit SecVolatileRawUnlockEn = 0
) (
// This module is combinational, but we
// need the clock and reset for the assertions.
Expand Down Expand Up @@ -784,9 +786,11 @@ module lc_ctrl_fsm

// LC signal decoder and broadcasting logic.
lc_ctrl_signal_decode #(
.RndCnstLcKeymgrDivInvalid ( RndCnstLcKeymgrDivInvalid ),
.RndCnstLcKeymgrDivTestDevRma ( RndCnstLcKeymgrDivTestDevRma ),
.RndCnstLcKeymgrDivProduction ( RndCnstLcKeymgrDivProduction )
.RndCnstLcKeymgrDivInvalid ( RndCnstLcKeymgrDivInvalid ),
.RndCnstLcKeymgrDivTestUnlocked( RndCnstLcKeymgrDivTestUnlocked ),
.RndCnstLcKeymgrDivTestDev ( RndCnstLcKeymgrDivTestDev ),
.RndCnstLcKeymgrDivProduction ( RndCnstLcKeymgrDivProduction ),
.RndCnstLcKeymgrDivTestRma ( RndCnstLcKeymgrDivTestRma )
) u_lc_ctrl_signal_decode (
.clk_i,
.rst_ni,
Expand Down
Loading

0 comments on commit 6948d41

Please sign in to comment.