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 18a9fa5 commit 09c1060
Show file tree
Hide file tree
Showing 12 changed files with 344 additions and 232 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.
35 changes: 29 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,20 +5,43 @@
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

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

endclass : lc_ctrl_parameters_cfg
32 changes: 19 additions & 13 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 = cfg.parameters_cfg.get_exp_div(lc_state);
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,18 +247,20 @@ 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};
bit addr_phase_read = (!write && channel == AddrChannel);
bit addr_phase_write = (write && channel == AddrChannel);
bit data_phase_read = (!write && channel == DataChannel);
bit data_phase_write = (write && channel == DataChannel);
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);
bit data_phase_read = (!write && channel == DataChannel);
bit data_phase_write = (write && channel == DataChannel);

// if access was to a valid csr, get the csr handle
if (csr_addr inside {cfg.ral_models[ral_name].csr_addrs}) begin
Expand Down Expand Up @@ -403,7 +409,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'h69}});
parameter lc_keymgr_div_t RndCnstLcKeymgrDivRma =
LcKeymgrDivWidth'({(LcKeymgrDivWidth/8){8'h96}});

// macro includes
`include "uvm_macros.svh"
Expand Down Expand Up @@ -95,8 +99,10 @@ module tb;
.IdcodeValue(IdcodeValue),
// Random netlist constants
.RndCnstLcKeymgrDivInvalid(RndCnstLcKeymgrDivInvalid),
.RndCnstLcKeymgrDivTestDevRma(RndCnstLcKeymgrDivTestDevRma),
.RndCnstLcKeymgrDivTestUnlocked(RndCnstLcKeymgrDivTestUnlocked),
.RndCnstLcKeymgrDivDev(RndCnstLcKeymgrDivDev),
.RndCnstLcKeymgrDivProduction(RndCnstLcKeymgrDivProduction),
.RndCnstLcKeymgrDivRma(RndCnstLcKeymgrDivRma),
.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 @@ -226,8 +232,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 RndCnstLcKeymgrDivDev = LcKeymgrDivWidth'(2),
parameter lc_keymgr_div_t RndCnstLcKeymgrDivProduction = LcKeymgrDivWidth'(3),
parameter lc_keymgr_div_t RndCnstLcKeymgrDivRma = 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 ),
.RndCnstLcKeymgrDivDev ( RndCnstLcKeymgrDivDev ),
.RndCnstLcKeymgrDivProduction ( RndCnstLcKeymgrDivProduction ),
.RndCnstLcKeymgrDivRma ( RndCnstLcKeymgrDivRma ),
.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 RndCnstLcKeymgrDivDev = LcKeymgrDivWidth'(2),
parameter lc_keymgr_div_t RndCnstLcKeymgrDivProduction = LcKeymgrDivWidth'(3),
parameter lc_keymgr_div_t RndCnstLcKeymgrDivRma = 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 ),
.RndCnstLcKeymgrDivDev ( RndCnstLcKeymgrDivDev ),
.RndCnstLcKeymgrDivProduction ( RndCnstLcKeymgrDivProduction ),
.RndCnstLcKeymgrDivRma ( RndCnstLcKeymgrDivRma )
) u_lc_ctrl_signal_decode (
.clk_i,
.rst_ni,
Expand Down
Loading

0 comments on commit 09c1060

Please sign in to comment.