Skip to content

Commit 2547524

Browse files
committed
[keymgr_dpe, dv] Introduce backdoor load for UDS
The scoreboard loads the UDS directly from the DUT via interface. The problem is the keymgr_dpe initializes the slot for the UDS with randomness. The initally loaded UDS is xored with the randomness already present in the destination slot as countermeasure for SCA. The scoreboard however can currently not recreate this randomness thus the backdoor load. Signed-off-by: Raphael Roth <rroth@lowrisc.org>
1 parent c8fa723 commit 2547524

6 files changed

Lines changed: 69 additions & 0 deletions

File tree

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright lowRISC contributors (OpenTitan project).
2+
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3+
// SPDX-License-Identifier: Apache-2.0
4+
//
5+
// An interface that should be bound into an instance of keymgr_dpe_ctrl (and can access RTL signals
6+
// through upwards hierarchical references).
7+
interface keymgr_dpe_ctrl_if (input clk_i, input rst_ni);
8+
import uvm_pkg::*;
9+
10+
// Function to access the key of one slot via backdoor.
11+
// Required to load the UDS after XORing with generated randomness.
12+
function automatic keymgr_dpe_env_pkg::key_shares_t get_key_of_slot(int unsigned slot);
13+
import keymgr_dpe_pkg::DpeNumSlots;
14+
15+
// Check that the slot index is in range. The key_slots_q array has length DpeNumSlots, which is
16+
// a global parameter.
17+
if (slot >= DpeNumSlots) begin
18+
`uvm_error($sformatf("%m"),
19+
$sformatf("Slot index out of range: index is %0d but DpeNumSlots is %0d",
20+
slot, DpeNumSlots))
21+
return '0;
22+
end
23+
24+
// This is an upwards hierarchical reference through the keymgr_dpe_ctrl module (into an
25+
// instance of which this interface is bound)
26+
return keymgr_dpe_ctrl.key_slots_q[slot].key;
27+
endfunction
28+
endinterface

hw/ip/keymgr_dpe/dv/env/keymgr_dpe_env.core

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ filesets:
1414
- lowrisc:ip:kmac_pkg
1515
files:
1616
- keymgr_dpe_env_pkg.sv
17+
- keymgr_dpe_ctrl_if.sv
1718
- keymgr_dpe_if.sv
1819
- keymgr_dpe_env_cfg.sv: {is_include_file: true}
1920
- keymgr_dpe_env_cov.sv: {is_include_file: true}

hw/ip/keymgr_dpe/dv/env/keymgr_dpe_env.sv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ class keymgr_dpe_env extends cip_base_env #(
2626
`uvm_fatal(`gfn, "failed to get keymgr_dpe_vif from uvm_config_db")
2727
end
2828
cfg.scb = scoreboard;
29+
if (!uvm_config_db#(virtual keymgr_dpe_ctrl_if)::get(
30+
this, "", "keymgr_dpe_ctrl_vif", cfg.keymgr_dpe_ctrl_vif)) begin
31+
`uvm_fatal(get_full_name(), "Could not get keymgr_dpe_ctrl_vif from uvm_config_db.")
32+
end
2933
endfunction
3034

3135
function void connect_phase(uvm_phase phase);

hw/ip/keymgr_dpe/dv/env/keymgr_dpe_env_cfg.sv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ class keymgr_dpe_env_cfg extends cip_base_env_cfg #(.RAL_T(keymgr_dpe_reg_block)
1515

1616
`uvm_object_new
1717

18+
// Interface that is bound into the keymgr_dpe_ctrl instance
19+
virtual keymgr_dpe_ctrl_if keymgr_dpe_ctrl_vif;
20+
1821
virtual function void initialize();
1922
list_of_alerts = keymgr_dpe_env_pkg::LIST_OF_ALERTS;
2023
tl_intg_alert_name = "fatal_fault_err";

hw/ip/keymgr_dpe/dv/env/keymgr_dpe_scoreboard.sv

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ class keymgr_dpe_scoreboard extends cip_base_scoreboard #(
6868
bit is_kmac_rsp_err;
6969
bit is_kmac_invalid_data;
7070
bit is_sw_share_corrupted;
71+
// Indicates if the UDS was fetched by the keymgr_dpe for the first time.
72+
// The UDS needs to be xored with randomness to counter SCA, however the
73+
// current dv environment cannot replicate this randomness. As a workaround
74+
// the generated value (UDS xored with randomness) is loaded by a backdoor
75+
// directly from the DUT.
76+
bit load_uds_with_randomness;
7177

7278
// HW internal key, used for OP in current state
7379
keymgr_dpe_env_pkg::keymgr_dpe_key_slot_t current_key_slot;
@@ -990,6 +996,12 @@ class keymgr_dpe_scoreboard extends cip_base_scoreboard #(
990996
current_internal_key[current_key_slot.dst_slot].valid = 1;
991997
current_internal_key[current_key_slot.dst_slot].boot_stage = keymgr_dpe_pkg::BootStageCreator;
992998
current_internal_key[current_key_slot.dst_slot].max_key_version = max_key_version;
999+
// This call load the "true" UDS without the randomness present in the
1000+
// hw slot. The problem is that when this function is called (when writing
1001+
// the first time into the start register) the randomness in the hw slot
1002+
// is not yet generated.
1003+
// The current workaround is to backdoor load on the first advance call
1004+
// in the available state as the src_slot has the UDS loaded.
9931005
current_internal_key[current_key_slot.dst_slot].key = otp_key;
9941006
current_internal_key[current_key_slot.dst_slot].key_policy =
9951007
keymgr_dpe_pkg::DEFAULT_UDS_POLICY;
@@ -1004,6 +1016,15 @@ class keymgr_dpe_scoreboard extends cip_base_scoreboard #(
10041016
);
10051017
endfunction
10061018

1019+
// Directly access the slot which holds the UDS with the xored randmoness
1020+
// Otherwise the scorebord would need to manually replicate the randomness
1021+
// generation.
1022+
virtual function void backdoor_load_uds(int slot);
1023+
`uvm_info(`gfn, "Load UDS with randomness via backdoor", UVM_MEDIUM)
1024+
current_internal_key[slot].key =
1025+
cfg.keymgr_dpe_ctrl_vif.get_key_of_slot(slot);
1026+
endfunction
1027+
10071028
virtual function bit [TL_DW-1:0] get_current_max_version(
10081029
keymgr_dpe_pkg::keymgr_dpe_exposed_working_state_e state = current_state);
10091030
// design change this to 0 if LC turns off keymgr_dpe.
@@ -1127,6 +1148,13 @@ class keymgr_dpe_scoreboard extends cip_base_scoreboard #(
11271148
"src_slot valid == 0 err"}, op.name, current_state.name), UVM_MEDIUM)
11281149
return 1;
11291150
end
1151+
// Workaround to load the UDS with the xored randomness into the
1152+
// correct internal slot. The first (successful) advance call will
1153+
// use the UDS per default.
1154+
if (load_uds_with_randomness == 1'b0) begin
1155+
load_uds_with_randomness = 1'b1;
1156+
backdoor_load_uds(current_key_slot.src_slot);
1157+
end
11301158
return 0;
11311159
end
11321160
keymgr_dpe_pkg::OpDpeGenSwOut, keymgr_dpe_pkg::OpDpeGenHwOut: begin
@@ -1534,6 +1562,7 @@ class keymgr_dpe_scoreboard extends cip_base_scoreboard #(
15341562
is_kmac_rsp_err = 0;
15351563
is_kmac_invalid_data = 0;
15361564
is_sw_share_corrupted = 0;
1565+
load_uds_with_randomness = 0;
15371566
req_fifo.flush();
15381567
rsp_fifo.flush();
15391568
foreach (current_internal_key[slot]) begin

hw/ip/keymgr_dpe/dv/tb.sv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ module tb;
2626
keymgr_dpe_if keymgr_dpe_if(.clk(clk), .rst_n(rst_n));
2727
kmac_app_intf keymgr_dpe_kmac_intf(.clk(clk), .rst_n(rst_n));
2828

29+
bind dut.u_ctrl keymgr_dpe_ctrl_if u_if (.clk_i, .rst_ni);
30+
2931
// connect KDF interface for assertion check
3032
assign keymgr_dpe_if.kmac_data_req = keymgr_dpe_kmac_intf.kmac_data_req;
3133
assign keymgr_dpe_if.kmac_data_rsp = keymgr_dpe_kmac_intf.kmac_data_rsp;
@@ -83,6 +85,8 @@ module tb;
8385
uvm_config_db#(intr_vif)::set(null, "*.env", "intr_vif", intr_if);
8486
uvm_config_db#(virtual tl_if)::set(null, "*.env.m_tl_agent*", "vif", tl_if);
8587
uvm_config_db#(virtual keymgr_dpe_if)::set(null, "*.env", "keymgr_dpe_vif", keymgr_dpe_if);
88+
uvm_config_db#(virtual keymgr_dpe_ctrl_if)::set(null, "*.env", "keymgr_dpe_ctrl_vif",
89+
dut.u_ctrl.u_if);
8690
uvm_config_db#(virtual kmac_app_intf)::set(null,
8791
"*env.m_keymgr_dpe_kmac_agent*", "vif", keymgr_dpe_kmac_intf);
8892
$timeformat(-12, 0, " ps", 12);

0 commit comments

Comments
 (0)