[keymgr] Detect spurious done's from kmac as a fault
Signed-off-by: Timothy Chen <timothytim@google.com>
diff --git a/hw/ip/keymgr/data/keymgr.hjson b/hw/ip/keymgr/data/keymgr.hjson
index 7ce6f19..dbc4099 100644
--- a/hw/ip/keymgr/data/keymgr.hjson
+++ b/hw/ip/keymgr/data/keymgr.hjson
@@ -1030,41 +1030,46 @@
desc: "The kmac transfer interface is in an error state, asynchronous fault.",
},
{ bits: "2",
+ name: "KMAC_DONE",
+ resval: "0x0"
+ desc: "The kmac transfer interface encountered unexpected done, asynchronous fault.",
+ },
+ { bits: "3",
name: "KMAC_OP",
resval: "0x0"
desc: "KMAC reported an error during keymgr usage, this should never happen - synchronous fault.",
},
- { bits: "3",
+ { bits: "4",
name: "KMAC_OUT",
resval: "0x0"
desc: "KMAC data returned as all 0's or all 1's - synchronous fault",
},
- { bits: "4",
+ { bits: "5",
name: "REGFILE_INTG",
resval: "0x0"
desc: "Register file integrity error, asynchronous fault",
},
- { bits: "5",
+ { bits: "6",
name: "SHADOW",
resval: "0x0"
desc: "Shadow copy storage error, asynchronous fault",
},
- { bits: "6",
+ { bits: "7",
name: "CTRL_FSM_INTG",
resval: "0x0"
desc: "Control FSM integrity error, asynchronous fault",
},
- { bits: "7",
+ { bits: "8",
name: "CTRL_FSM_CNT",
resval: "0x0"
desc: "Control FSM counter integrity error, asynchronous fault",
},
- { bits: "8",
+ { bits: "9",
name: "RESEED_CNT",
resval: "0x0"
desc: "Reseed counter integrity error, asynchronous fault",
},
- { bits: "9",
+ { bits: "10",
name: "SIDE_CTRL_FSM",
resval: "0x0"
desc: "Sideload control FSM integrity error, asynchronous fault",
diff --git a/hw/ip/keymgr/rtl/keymgr.sv b/hw/ip/keymgr/rtl/keymgr.sv
index a76c360..edf6011 100644
--- a/hw/ip/keymgr/rtl/keymgr.sv
+++ b/hw/ip/keymgr/rtl/keymgr.sv
@@ -261,6 +261,7 @@
logic kmac_cmd_err;
logic kmac_fsm_err;
logic kmac_op_err;
+ logic kmac_done_err;
logic [Shares-1:0][kmac_pkg::AppDigestW-1:0] kmac_data;
logic [Shares-1:0][KeyWidth-1:0] kmac_data_truncated;
logic [ErrLastPos-1:0] err_code;
@@ -314,6 +315,7 @@
.kmac_input_invalid_i(kmac_input_invalid),
.kmac_fsm_err_i(kmac_fsm_err),
.kmac_op_err_i(kmac_op_err),
+ .kmac_done_err_i(kmac_done_err),
.kmac_cmd_err_i(kmac_cmd_err),
.kmac_data_i(kmac_data_truncated)
);
@@ -516,6 +518,7 @@
.entropy_i(data_rand),
.fsm_error_o(kmac_fsm_err),
.kmac_error_o(kmac_op_err),
+ .kmac_done_error_o(kmac_done_err),
.cmd_error_o(kmac_cmd_err)
);
@@ -615,6 +618,7 @@
assign hw2reg.fault_status.cmd.de = fault_code[FaultKmacCmd];
assign hw2reg.fault_status.kmac_fsm.de = fault_code[FaultKmacFsm];
assign hw2reg.fault_status.kmac_op.de = fault_code[FaultKmacOp];
+ assign hw2reg.fault_status.kmac_done.de = fault_code[FaultKmacDone];
assign hw2reg.fault_status.kmac_out.de = fault_code[FaultKmacOut];
assign hw2reg.fault_status.regfile_intg.de = fault_code[FaultRegIntg];
assign hw2reg.fault_status.shadow.de = fault_code[FaultShadow];
@@ -624,6 +628,7 @@
assign hw2reg.fault_status.side_ctrl_fsm.de = fault_code[FaultSideFsm];
assign hw2reg.fault_status.cmd.d = 1'b1;
assign hw2reg.fault_status.kmac_fsm.d = 1'b1;
+ assign hw2reg.fault_status.kmac_done.d = 1'b1;
assign hw2reg.fault_status.kmac_op.d = 1'b1;
assign hw2reg.fault_status.kmac_out.d = 1'b1;
assign hw2reg.fault_status.regfile_intg.d = 1'b1;
diff --git a/hw/ip/keymgr/rtl/keymgr_ctrl.sv b/hw/ip/keymgr/rtl/keymgr_ctrl.sv
index f656ec9..68bad5f 100644
--- a/hw/ip/keymgr/rtl/keymgr_ctrl.sv
+++ b/hw/ip/keymgr/rtl/keymgr_ctrl.sv
@@ -58,6 +58,7 @@
input kmac_input_invalid_i, // asserted when selected data fails criteria check
input kmac_fsm_err_i, // asserted when kmac fsm reaches unexpected state
input kmac_op_err_i, // asserted when kmac itself reports an error
+ input kmac_done_err_i,// asserted when kmac unexpectedly toggles done
input kmac_cmd_err_i, // asserted when more than one command given to kmac
input [Shares-1:0][KeyWidth-1:0] kmac_data_i,
@@ -783,14 +784,15 @@
end
end
assign async_fault = async_fault_q | async_fault_d;
- assign async_fault_d[AsyncFaultKmacCmd] = kmac_cmd_err_i;
- assign async_fault_d[AsyncFaultKmacFsm] = kmac_fsm_err_i;
- assign async_fault_d[AsyncFaultRegIntg] = regfile_intg_err_i;
- assign async_fault_d[AsyncFaultShadow ] = shadowed_storage_err_i;
- assign async_fault_d[AsyncFaultFsmIntg] = state_intg_err_q | data_fsm_err;
- assign async_fault_d[AsyncFaultCntErr ] = cnt_err;
- assign async_fault_d[AsyncFaultRCntErr] = reseed_cnt_err_i;
- assign async_fault_d[AsyncFaultSideErr] = sideload_fsm_err_i;
+ assign async_fault_d[AsyncFaultKmacCmd] = kmac_cmd_err_i;
+ assign async_fault_d[AsyncFaultKmacFsm] = kmac_fsm_err_i;
+ assign async_fault_d[AsyncFaultKmacDone] = kmac_done_err_i;
+ assign async_fault_d[AsyncFaultRegIntg] = regfile_intg_err_i;
+ assign async_fault_d[AsyncFaultShadow ] = shadowed_storage_err_i;
+ assign async_fault_d[AsyncFaultFsmIntg] = state_intg_err_q | data_fsm_err;
+ assign async_fault_d[AsyncFaultCntErr ] = cnt_err;
+ assign async_fault_d[AsyncFaultRCntErr] = reseed_cnt_err_i;
+ assign async_fault_d[AsyncFaultSideErr] = sideload_fsm_err_i;
// output to error code register
assign error_o[ErrInvalidOp] = op_done_o & sync_err[SyncErrInvalidOp];
@@ -802,6 +804,7 @@
assign fault_o[FaultKmacOut] = op_done_o & sync_fault[SyncFaultKmacOut];
assign fault_o[FaultKmacCmd] = async_fault[AsyncFaultKmacCmd];
assign fault_o[FaultKmacFsm] = async_fault[AsyncFaultKmacFsm];
+ assign fault_o[FaultKmacDone] = async_fault[AsyncFaultKmacDone];
assign fault_o[FaultRegIntg] = async_fault[AsyncFaultRegIntg];
assign fault_o[FaultShadow] = async_fault[AsyncFaultShadow];
assign fault_o[FaultCtrlFsm] = async_fault[AsyncFaultFsmIntg];
diff --git a/hw/ip/keymgr/rtl/keymgr_kmac_if.sv b/hw/ip/keymgr/rtl/keymgr_kmac_if.sv
index d25b4ac..77d3946 100644
--- a/hw/ip/keymgr/rtl/keymgr_kmac_if.sv
+++ b/hw/ip/keymgr/rtl/keymgr_kmac_if.sv
@@ -36,6 +36,7 @@
// error outputs
output logic fsm_error_o,
output logic kmac_error_o,
+ output logic kmac_done_error_o,
output logic cmd_error_o
);
@@ -119,6 +120,7 @@
logic start;
logic [3:0] inputs_invalid_d, inputs_invalid_q;
logic clr_err;
+ logic kmac_done_vld;
data_state_e state_q, state_d;
@@ -173,6 +175,9 @@
.state_o ( state_raw_q )
);
+ // kmac done is asserted outside of expected window
+ assign kmac_done_error_o = ~kmac_done_vld & kmac_data_i.done;
+
always_comb begin
cnt_clr = 1'b0;
cnt_set = 1'b0;
@@ -188,6 +193,8 @@
fsm_error_o = '0;
kmac_error_o = '0;
+ kmac_done_vld = '0;
+
unique case (state_q)
StIdle: begin
@@ -243,6 +250,7 @@
end
StOpWait: begin
+ kmac_done_vld = 1'b1;
if (kmac_data_i.done) begin
kmac_error_o = kmac_data_i.error;
done_o = 1'b1;
@@ -271,16 +279,18 @@
endcase // unique case (state_q)
// unconditional error transitions
+ // counter errors may disturb the fsm flow and are
+ // treated like fsm errors
if (cnt_err) begin
state_d = StError;
end
end
- // If an fsm error is detected, there is no guarantee the transaction can completely gracefully.
- // Allow the transaction to terminate early with random data.
- assign data_o = start && done_o && !fsm_error_o ? {kmac_data_i.digest_share1,
- kmac_data_i.digest_share0} :
- {DecoyOutputCopies{entropy_i[0]}};
+ // when transaction is not complete, populate the data with random
+ assign data_o = start && done_o ?
+ {kmac_data_i.digest_share1,
+ kmac_data_i.digest_share0} :
+ {DecoyOutputCopies{entropy_i[0]}};
// The input invalid check is done whenever transactions are ongoing with kmac
// once set, it cannot be unset until transactions are fully complete
diff --git a/hw/ip/keymgr/rtl/keymgr_pkg.sv b/hw/ip/keymgr/rtl/keymgr_pkg.sv
index b28c9ce..b5c98c6 100644
--- a/hw/ip/keymgr/rtl/keymgr_pkg.sv
+++ b/hw/ip/keymgr/rtl/keymgr_pkg.sv
@@ -160,6 +160,7 @@
typedef enum logic [3:0] {
AsyncFaultKmacCmd,
AsyncFaultKmacFsm,
+ AsyncFaultKmacDone,
AsyncFaultRegIntg,
AsyncFaultShadow,
AsyncFaultFsmIntg,
@@ -183,6 +184,7 @@
typedef enum logic [3:0] {
FaultKmacCmd,
FaultKmacFsm,
+ FaultKmacDone,
FaultKmacOp,
FaultKmacOut,
FaultRegIntg,
diff --git a/hw/ip/keymgr/rtl/keymgr_reg_pkg.sv b/hw/ip/keymgr/rtl/keymgr_reg_pkg.sv
index a9a0003..7045a2b 100644
--- a/hw/ip/keymgr/rtl/keymgr_reg_pkg.sv
+++ b/hw/ip/keymgr/rtl/keymgr_reg_pkg.sv
@@ -124,6 +124,9 @@
} kmac_fsm;
struct packed {
logic q;
+ } kmac_done;
+ struct packed {
+ logic q;
} kmac_op;
struct packed {
logic q;
@@ -213,6 +216,10 @@
struct packed {
logic d;
logic de;
+ } kmac_done;
+ struct packed {
+ logic d;
+ logic de;
} kmac_op;
struct packed {
logic d;
@@ -246,37 +253,37 @@
// Register -> HW type
typedef struct packed {
- keymgr_reg2hw_intr_state_reg_t intr_state; // [942:942]
- keymgr_reg2hw_intr_enable_reg_t intr_enable; // [941:941]
- keymgr_reg2hw_intr_test_reg_t intr_test; // [940:939]
- keymgr_reg2hw_alert_test_reg_t alert_test; // [938:935]
- keymgr_reg2hw_start_reg_t start; // [934:934]
- keymgr_reg2hw_control_shadowed_reg_t control_shadowed; // [933:927]
- keymgr_reg2hw_sideload_clear_reg_t sideload_clear; // [926:924]
- keymgr_reg2hw_reseed_interval_shadowed_reg_t reseed_interval_shadowed; // [923:908]
- keymgr_reg2hw_sw_binding_regwen_reg_t sw_binding_regwen; // [907:906]
- keymgr_reg2hw_sealing_sw_binding_mreg_t [7:0] sealing_sw_binding; // [905:650]
- keymgr_reg2hw_attest_sw_binding_mreg_t [7:0] attest_sw_binding; // [649:394]
- keymgr_reg2hw_salt_mreg_t [7:0] salt; // [393:138]
- keymgr_reg2hw_key_version_mreg_t [0:0] key_version; // [137:106]
- keymgr_reg2hw_max_creator_key_ver_shadowed_reg_t max_creator_key_ver_shadowed; // [105:74]
- keymgr_reg2hw_max_owner_int_key_ver_shadowed_reg_t max_owner_int_key_ver_shadowed; // [73:42]
- keymgr_reg2hw_max_owner_key_ver_shadowed_reg_t max_owner_key_ver_shadowed; // [41:10]
- keymgr_reg2hw_fault_status_reg_t fault_status; // [9:0]
+ keymgr_reg2hw_intr_state_reg_t intr_state; // [943:943]
+ keymgr_reg2hw_intr_enable_reg_t intr_enable; // [942:942]
+ keymgr_reg2hw_intr_test_reg_t intr_test; // [941:940]
+ keymgr_reg2hw_alert_test_reg_t alert_test; // [939:936]
+ keymgr_reg2hw_start_reg_t start; // [935:935]
+ keymgr_reg2hw_control_shadowed_reg_t control_shadowed; // [934:928]
+ keymgr_reg2hw_sideload_clear_reg_t sideload_clear; // [927:925]
+ keymgr_reg2hw_reseed_interval_shadowed_reg_t reseed_interval_shadowed; // [924:909]
+ keymgr_reg2hw_sw_binding_regwen_reg_t sw_binding_regwen; // [908:907]
+ keymgr_reg2hw_sealing_sw_binding_mreg_t [7:0] sealing_sw_binding; // [906:651]
+ keymgr_reg2hw_attest_sw_binding_mreg_t [7:0] attest_sw_binding; // [650:395]
+ keymgr_reg2hw_salt_mreg_t [7:0] salt; // [394:139]
+ keymgr_reg2hw_key_version_mreg_t [0:0] key_version; // [138:107]
+ keymgr_reg2hw_max_creator_key_ver_shadowed_reg_t max_creator_key_ver_shadowed; // [106:75]
+ keymgr_reg2hw_max_owner_int_key_ver_shadowed_reg_t max_owner_int_key_ver_shadowed; // [74:43]
+ keymgr_reg2hw_max_owner_key_ver_shadowed_reg_t max_owner_key_ver_shadowed; // [42:11]
+ keymgr_reg2hw_fault_status_reg_t fault_status; // [10:0]
} keymgr_reg2hw_t;
// HW -> register type
typedef struct packed {
- keymgr_hw2reg_intr_state_reg_t intr_state; // [566:565]
- keymgr_hw2reg_cfg_regwen_reg_t cfg_regwen; // [564:564]
- keymgr_hw2reg_start_reg_t start; // [563:562]
- keymgr_hw2reg_sw_binding_regwen_reg_t sw_binding_regwen; // [561:561]
- keymgr_hw2reg_sw_share0_output_mreg_t [7:0] sw_share0_output; // [560:297]
- keymgr_hw2reg_sw_share1_output_mreg_t [7:0] sw_share1_output; // [296:33]
- keymgr_hw2reg_working_state_reg_t working_state; // [32:29]
- keymgr_hw2reg_op_status_reg_t op_status; // [28:26]
- keymgr_hw2reg_err_code_reg_t err_code; // [25:20]
- keymgr_hw2reg_fault_status_reg_t fault_status; // [19:0]
+ keymgr_hw2reg_intr_state_reg_t intr_state; // [568:567]
+ keymgr_hw2reg_cfg_regwen_reg_t cfg_regwen; // [566:566]
+ keymgr_hw2reg_start_reg_t start; // [565:564]
+ keymgr_hw2reg_sw_binding_regwen_reg_t sw_binding_regwen; // [563:563]
+ keymgr_hw2reg_sw_share0_output_mreg_t [7:0] sw_share0_output; // [562:299]
+ keymgr_hw2reg_sw_share1_output_mreg_t [7:0] sw_share1_output; // [298:35]
+ keymgr_hw2reg_working_state_reg_t working_state; // [34:31]
+ keymgr_hw2reg_op_status_reg_t op_status; // [30:28]
+ keymgr_hw2reg_err_code_reg_t err_code; // [27:22]
+ keymgr_hw2reg_fault_status_reg_t fault_status; // [21:0]
} keymgr_hw2reg_t;
// Register offsets
diff --git a/hw/ip/keymgr/rtl/keymgr_reg_top.sv b/hw/ip/keymgr/rtl/keymgr_reg_top.sv
index c6897eb..3edcca3 100644
--- a/hw/ip/keymgr/rtl/keymgr_reg_top.sv
+++ b/hw/ip/keymgr/rtl/keymgr_reg_top.sv
@@ -304,6 +304,7 @@
logic err_code_invalid_shadow_update_wd;
logic fault_status_cmd_qs;
logic fault_status_kmac_fsm_qs;
+ logic fault_status_kmac_done_qs;
logic fault_status_kmac_op_qs;
logic fault_status_kmac_out_qs;
logic fault_status_regfile_intg_qs;
@@ -2141,7 +2142,32 @@
.qs (fault_status_kmac_fsm_qs)
);
- // F[kmac_op]: 2:2
+ // F[kmac_done]: 2:2
+ prim_subreg #(
+ .DW (1),
+ .SwAccess(prim_subreg_pkg::SwAccessRO),
+ .RESVAL (1'h0)
+ ) u_fault_status_kmac_done (
+ .clk_i (clk_i),
+ .rst_ni (rst_ni),
+
+ // from register interface
+ .we (1'b0),
+ .wd ('0),
+
+ // from internal hardware
+ .de (hw2reg.fault_status.kmac_done.de),
+ .d (hw2reg.fault_status.kmac_done.d),
+
+ // to internal hardware
+ .qe (),
+ .q (reg2hw.fault_status.kmac_done.q),
+
+ // to register interface (read)
+ .qs (fault_status_kmac_done_qs)
+ );
+
+ // F[kmac_op]: 3:3
prim_subreg #(
.DW (1),
.SwAccess(prim_subreg_pkg::SwAccessRO),
@@ -2166,7 +2192,7 @@
.qs (fault_status_kmac_op_qs)
);
- // F[kmac_out]: 3:3
+ // F[kmac_out]: 4:4
prim_subreg #(
.DW (1),
.SwAccess(prim_subreg_pkg::SwAccessRO),
@@ -2191,7 +2217,7 @@
.qs (fault_status_kmac_out_qs)
);
- // F[regfile_intg]: 4:4
+ // F[regfile_intg]: 5:5
prim_subreg #(
.DW (1),
.SwAccess(prim_subreg_pkg::SwAccessRO),
@@ -2216,7 +2242,7 @@
.qs (fault_status_regfile_intg_qs)
);
- // F[shadow]: 5:5
+ // F[shadow]: 6:6
prim_subreg #(
.DW (1),
.SwAccess(prim_subreg_pkg::SwAccessRO),
@@ -2241,7 +2267,7 @@
.qs (fault_status_shadow_qs)
);
- // F[ctrl_fsm_intg]: 6:6
+ // F[ctrl_fsm_intg]: 7:7
prim_subreg #(
.DW (1),
.SwAccess(prim_subreg_pkg::SwAccessRO),
@@ -2266,7 +2292,7 @@
.qs (fault_status_ctrl_fsm_intg_qs)
);
- // F[ctrl_fsm_cnt]: 7:7
+ // F[ctrl_fsm_cnt]: 8:8
prim_subreg #(
.DW (1),
.SwAccess(prim_subreg_pkg::SwAccessRO),
@@ -2291,7 +2317,7 @@
.qs (fault_status_ctrl_fsm_cnt_qs)
);
- // F[reseed_cnt]: 8:8
+ // F[reseed_cnt]: 9:9
prim_subreg #(
.DW (1),
.SwAccess(prim_subreg_pkg::SwAccessRO),
@@ -2316,7 +2342,7 @@
.qs (fault_status_reseed_cnt_qs)
);
- // F[side_ctrl_fsm]: 9:9
+ // F[side_ctrl_fsm]: 10:10
prim_subreg #(
.DW (1),
.SwAccess(prim_subreg_pkg::SwAccessRO),
@@ -2929,14 +2955,15 @@
addr_hit[61]: begin
reg_rdata_next[0] = fault_status_cmd_qs;
reg_rdata_next[1] = fault_status_kmac_fsm_qs;
- reg_rdata_next[2] = fault_status_kmac_op_qs;
- reg_rdata_next[3] = fault_status_kmac_out_qs;
- reg_rdata_next[4] = fault_status_regfile_intg_qs;
- reg_rdata_next[5] = fault_status_shadow_qs;
- reg_rdata_next[6] = fault_status_ctrl_fsm_intg_qs;
- reg_rdata_next[7] = fault_status_ctrl_fsm_cnt_qs;
- reg_rdata_next[8] = fault_status_reseed_cnt_qs;
- reg_rdata_next[9] = fault_status_side_ctrl_fsm_qs;
+ reg_rdata_next[2] = fault_status_kmac_done_qs;
+ reg_rdata_next[3] = fault_status_kmac_op_qs;
+ reg_rdata_next[4] = fault_status_kmac_out_qs;
+ reg_rdata_next[5] = fault_status_regfile_intg_qs;
+ reg_rdata_next[6] = fault_status_shadow_qs;
+ reg_rdata_next[7] = fault_status_ctrl_fsm_intg_qs;
+ reg_rdata_next[8] = fault_status_ctrl_fsm_cnt_qs;
+ reg_rdata_next[9] = fault_status_reseed_cnt_qs;
+ reg_rdata_next[10] = fault_status_side_ctrl_fsm_qs;
end
default: begin