Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 45 additions & 8 deletions hw/ip/keymgr_dpe/data/keymgr_dpe.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -77,17 +77,29 @@
act: "req",
package: "kmac_pkg", // Origin package (only needs for the requester)
},
{ struct: "otp_keymgr_key",
{ struct: "keymgr_dpe_creator_root_key",
type: "uni",
name: "otp_key",
name: "creator_root_key",
act: "rcv",
package: "otp_ctrl_pkg",
package: "keymgr_dpe_pkg",
},
{ struct: "otp_device_id",
{ struct: "keymgr_dpe_creator_seed",
type: "uni",
name: "otp_device_id",
name: "creator_seed",
act: "rcv",
package: "otp_ctrl_pkg",
package: "keymgr_dpe_pkg",
},
{ struct: "keymgr_dpe_owner_seed",
type: "uni",
name: "owner_seed",
act: "rcv",
package: "keymgr_dpe_pkg",
},
{ struct: "keymgr_dpe_device_id",
type: "uni",
name: "device_id",
act: "rcv",
package: "keymgr_dpe_pkg",
},
{ struct: "lc_tx",
type: "uni",
Expand Down Expand Up @@ -216,11 +228,33 @@
default: "1",
local: "true"
},
{ name: "NumMaxHwSlot",
desc: '''
Number of maximum supported HW slots. If this value is changed then the
bit width in SLOT_SRC_SEL / SLOT_DST_SEL in the
"CONTROL_SHADOWED" register needs to be updated too.
''',
type: "int",
default: "8",
local: "true"
},
{ name: "NumInstHwSlot",
desc: "Number of instantiated HW slots",
type: "int",
default: "4",
expose: "true"
},
{ name: "NumBootStages",
desc: "Number of available boot stage",
type: "int",
default: "3",
expose: "true"
},
{ name: "NumRomDigestInputs",
desc: "Number of digest inputs from ROM_CTRL",
type: "int",
default: "2",
local: "true"
default: "1",
expose: "true"
},
],

Expand Down Expand Up @@ -539,6 +573,9 @@ countermeasures: [
'''
}
],
// TODO(#30682): Remove this label as soon as the RTL raises an
// error instead of a assertion.
tags: ["excl:CsrAllTests:CsrExclWrite"]
},

{ name: "SIDELOAD_CLEAR",
Expand Down
30 changes: 16 additions & 14 deletions hw/ip/keymgr_dpe/doc/interfaces.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,22 @@ Referring to the [Comportable guideline for peripheral device functionality](htt

## [Inter-Module Signals](https://opentitan.org/book/doc/contributing/hw/comportability/index.html#inter-signal-handling)

| Port Name | Package::Struct | Type | Act | Width | Description |
|:----------------|:-----------------------------|:--------|:------|--------:|:--------------|
| edn | edn_pkg::edn | req_rsp | req | 1 | |
| aes_key | keymgr_pkg::hw_key_req | uni | req | 1 | |
| kmac_key | keymgr_pkg::hw_key_req | uni | req | 1 | |
| otbn_key | keymgr_pkg::otbn_key_req | uni | req | 1 | |
| kmac_data | kmac_pkg::app | req_rsp | req | 1 | |
| otp_key | otp_ctrl_pkg::otp_keymgr_key | uni | rcv | 1 | |
| otp_device_id | otp_ctrl_pkg::otp_device_id | uni | rcv | 1 | |
| lc_keymgr_en | lc_ctrl_pkg::lc_tx | uni | rcv | 1 | |
| lc_keymgr_div | lc_ctrl_pkg::lc_keymgr_div | uni | rcv | 1 | |
| rom_digest | rom_ctrl_pkg::keymgr_data | uni | rcv | 2 | |
| kmac_en_masking | logic | uni | rcv | 1 | |
| tl | tlul_pkg::tl | req_rsp | rsp | 1 | |
| Port Name | Package::Struct | Type | Act | Width | Description |
|:-----------------|:--------------------------------------------|:--------|:------|--------:|:--------------|
| edn | edn_pkg::edn | req_rsp | req | 1 | |
| aes_key | keymgr_pkg::hw_key_req | uni | req | 1 | |
| kmac_key | keymgr_pkg::hw_key_req | uni | req | 1 | |
| otbn_key | keymgr_pkg::otbn_key_req | uni | req | 1 | |
| kmac_data | kmac_pkg::app | req_rsp | req | 1 | |
| creator_root_key | keymgr_dpe_pkg::keymgr_dpe_creator_root_key | uni | rcv | 1 | |
| creator_seed | keymgr_dpe_pkg::keymgr_dpe_creator_seed | uni | rcv | 1 | |
| owner_seed | keymgr_dpe_pkg::keymgr_dpe_owner_seed | uni | rcv | 1 | |
| device_id | keymgr_dpe_pkg::keymgr_dpe_device_id | uni | rcv | 1 | |
| lc_keymgr_en | lc_ctrl_pkg::lc_tx | uni | rcv | 1 | |
| lc_keymgr_div | lc_ctrl_pkg::lc_keymgr_div | uni | rcv | 1 | |
| rom_digest | rom_ctrl_pkg::keymgr_data | uni | rcv | 2 | |
| kmac_en_masking | logic | uni | rcv | 1 | |
| tl | tlul_pkg::tl | req_rsp | rsp | 1 | |

## Interrupts

Expand Down
1 change: 1 addition & 0 deletions hw/ip/keymgr_dpe/dv/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ Here's how to run a smoke test:
```console
$ dvsim $REPO_TOP/hw/ip/keymgr_dpe/dv/keymgr_dpe_sim_cfg.hjson -i keymgr_dpe_smoke
```
With the configurations `keymgr_dpe_earlgrey_sim_cfg.hjson` / `keymgr_dpe_darjeeling_sim_cfg.hjson` it is possible to test the top dependent default configurations.

## Testplan
[Testplan](../data/keymgr_dpe_testplan.hjson)
28 changes: 28 additions & 0 deletions hw/ip/keymgr_dpe/dv/env/keymgr_dpe_ctrl_if.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
// An interface that should be bound into an instance of keymgr_dpe_ctrl (and can access RTL signals
// through upwards hierarchical references).
interface keymgr_dpe_ctrl_if (input clk_i, input rst_ni);
import uvm_pkg::*;

// Function to access the key of one slot via backdoor.
// Required to load the UDS after XORing with generated randomness.
function automatic keymgr_dpe_env_pkg::key_shares_t get_key_of_slot(int unsigned slot);
import keymgr_dpe_env_pkg::DvNumInstHwSlot;

// Check that the slot index is in range. The key_slots_q array has length DvNumInstHwSlot,
// which is a global parameter.
if (slot >= DvNumInstHwSlot) begin
`uvm_error($sformatf("%m"),
$sformatf("Slot index out of range: index is %0d but DvNumInstHwSlot is %0d",
slot, DvNumInstHwSlot))
return '0;
end

// This is an upwards hierarchical reference through the keymgr_dpe_ctrl module (into an
// instance of which this interface is bound)
return keymgr_dpe_ctrl.key_slots_q[slot].key;
endfunction
endinterface
1 change: 1 addition & 0 deletions hw/ip/keymgr_dpe/dv/env/keymgr_dpe_env.core
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ filesets:
- lowrisc:ip:kmac_pkg
files:
- keymgr_dpe_env_pkg.sv
- keymgr_dpe_ctrl_if.sv
- keymgr_dpe_if.sv
- keymgr_dpe_env_cfg.sv: {is_include_file: true}
- keymgr_dpe_env_cov.sv: {is_include_file: true}
Expand Down
4 changes: 4 additions & 0 deletions hw/ip/keymgr_dpe/dv/env/keymgr_dpe_env.sv
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ class keymgr_dpe_env extends cip_base_env #(
`uvm_fatal(`gfn, "failed to get keymgr_dpe_vif from uvm_config_db")
end
cfg.scb = scoreboard;
if (!uvm_config_db#(virtual keymgr_dpe_ctrl_if)::get(
this, "", "keymgr_dpe_ctrl_vif", cfg.keymgr_dpe_ctrl_vif)) begin
`uvm_fatal(get_full_name(), "Could not get keymgr_dpe_ctrl_vif from uvm_config_db.")
end
endfunction

function void connect_phase(uvm_phase phase);
Expand Down
3 changes: 3 additions & 0 deletions hw/ip/keymgr_dpe/dv/env/keymgr_dpe_env_cfg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ class keymgr_dpe_env_cfg extends cip_base_env_cfg #(.RAL_T(keymgr_dpe_reg_block)

`uvm_object_new

// Interface that is bound into the keymgr_dpe_ctrl instance
virtual keymgr_dpe_ctrl_if keymgr_dpe_ctrl_vif;

virtual function void initialize();
list_of_alerts = keymgr_dpe_env_pkg::LIST_OF_ALERTS;
tl_intg_alert_name = "fatal_fault_err";
Expand Down
37 changes: 35 additions & 2 deletions hw/ip/keymgr_dpe/dv/env/keymgr_dpe_env_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,39 @@ package keymgr_dpe_env_pkg;
`include "uvm_macros.svh"
`include "dv_macros.svh"

// Define default values for all blocklevel dv parameter
`ifndef DEF_DV_BOOT_STAGES
`define DEF_DV_BOOT_STAGES 3
`endif
`ifndef DEF_DV_DPE_NUM_SLOT
`define DEF_DV_DPE_NUM_SLOT 4
`endif
`ifndef DEF_DV_NUM_ROM_DIGEST
`define DEF_DV_NUM_ROM_DIGEST 1
`endif

// Avoid using defines throughout the DV code by introducing the following
// parameters.
parameter int DvBootStages = `DEF_DV_BOOT_STAGES;
parameter int DvNumInstHwSlot = `DEF_DV_DPE_NUM_SLOT;
parameter int DvNumRomDigestInputs = `DEF_DV_NUM_ROM_DIGEST;

// Advance width calculation
// When deriving from the UDS the following data are consumed (Not ordered):
// - Software binding
// - Revision seed
// - OTP device ID
// - LC keymgr diversification value
// - ROM digests
// - Creator seed (only if boot stage equals two)
parameter int DvDpeAdvDataWidth = keymgr_pkg::SwBindingWidth +
keymgr_pkg::KeyWidth + keymgr_pkg::KeyWidth * (DvBootStages == 2) +
lc_ctrl_pkg::LcKeymgrDivWidth + keymgr_dpe_pkg::DeviceIdWidth +
keymgr_pkg::KeyWidth * DvNumRomDigestInputs;

localparam int DvNumInstHwSlotWidth = prim_util_pkg::vbits(DvNumInstHwSlot);
typedef logic [DvNumInstHwSlotWidth-1:0] dv_keymgr_dpe_slot_idx_e;

// parameters and types
parameter uint NUM_ALERTS = 2;
parameter string LIST_OF_ALERTS[NUM_ALERTS] = {"recov_operation_err", "fatal_fault_err"};
Expand Down Expand Up @@ -64,8 +97,8 @@ package keymgr_dpe_env_pkg;
} keymgr_dpe_fault_inject_type_e;

typedef struct{
keymgr_dpe_pkg::keymgr_dpe_slot_idx_e src_slot;
keymgr_dpe_pkg::keymgr_dpe_slot_idx_e dst_slot;
dv_keymgr_dpe_slot_idx_e src_slot;
dv_keymgr_dpe_slot_idx_e dst_slot;
} keymgr_dpe_key_slot_t;

string msg_id = "keymgr_dpe_env_pkg";
Expand Down
55 changes: 29 additions & 26 deletions hw/ip/keymgr_dpe/dv/env/keymgr_dpe_if.sv
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ interface keymgr_dpe_if(input clk, input rst_n);

import uvm_pkg::*;
import keymgr_dpe_env_pkg::*;
import keymgr_dpe_reg_pkg::NumRomDigestInputs;

// Represents the keymgr_dpe sideload state for each sideload interface.
//
Expand All @@ -16,11 +15,13 @@ interface keymgr_dpe_if(input clk, input rst_n);
// Status can't be directly changed from SideLoadClear to SideLoadAvail.
// When status is SideLoadClear due to SIDELOAD_CLEAR programmed, need to write CSR to 0 to reset
// it so that status is changed to SideLoadNotAvail, then we may set it to SideLoadAvail again
lc_ctrl_pkg::lc_tx_t keymgr_dpe_en;
lc_ctrl_pkg::lc_keymgr_div_t keymgr_dpe_div;
otp_ctrl_pkg::otp_device_id_t otp_device_id;
otp_ctrl_pkg::otp_keymgr_key_t otp_key;
rom_ctrl_pkg::keymgr_data_t[NumRomDigestInputs-1:0] rom_digests;
lc_ctrl_pkg::lc_tx_t keymgr_dpe_en;
lc_ctrl_pkg::lc_keymgr_div_t keymgr_dpe_div;
keymgr_dpe_pkg::keymgr_dpe_device_id_t otp_device_id;
keymgr_dpe_pkg::keymgr_dpe_creator_root_key_t creator_root_key;
keymgr_dpe_pkg::keymgr_dpe_creator_seed_t creator_seed;
keymgr_dpe_pkg::keymgr_dpe_owner_seed_t owner_seed;
rom_ctrl_pkg::keymgr_data_t[DvNumRomDigestInputs-1:0] rom_digests;

keymgr_pkg::hw_key_req_t kmac_key;
keymgr_pkg::hw_key_req_t aes_key;
Expand Down Expand Up @@ -101,38 +102,40 @@ interface keymgr_dpe_if(input clk, input rst_n);

// assigned from the keymgr_dpe.keymgr_dpe_ctrl.key_slots_q signal, which should hold the
// current value of the keyslots in the dut.
keymgr_dpe_pkg::keymgr_dpe_slot_t [keymgr_dpe_pkg::DpeNumSlots-1:0] internal_key_slots;
keymgr_dpe_pkg::keymgr_dpe_slot_t [DvNumInstHwSlot-1:0] internal_key_slots;

task automatic init(bit rand_otp_key, bit invalid_otp_key);
// Keymgr_dpe only latches OTP key once, so this scb does not support change OTP key on the
// fly. Will write a direct sequence to cover otp key change on the fly.
otp_ctrl_pkg::otp_keymgr_key_t local_otp_key;
keymgr_dpe_pkg::keymgr_dpe_creator_root_key_t local_creator_root_key;

// async delay as these signals are from different clock domain
#($urandom_range(1000, 0) * 1ns);
keymgr_dpe_en = lc_ctrl_pkg::On;
keymgr_dpe_div = 64'h5CFBD765CE33F34E;
otp_device_id = 'hF0F0;
otp_key = otp_ctrl_pkg::OTP_KEYMGR_KEY_DEFAULT;
for (int i = 0; i < NumRomDigestInputs; ++i) begin
for (int i = 0; i < DvNumRomDigestInputs; ++i) begin
rom_digests[i].data = 256'hA20A046CF42E6EAC560A3F82BFA76285B5C1D4AEA7C915E49A32D1C89BE0F507;
rom_digests[i].valid = '1;
end
// Load the default value for all seed's
local_creator_root_key = keymgr_dpe_pkg::KEYMGR_DPE_CREATOR_ROOT_KEY_DEFAULT;
creator_seed = keymgr_dpe_pkg::KEYMGR_DPE_CREATOR_SEED_DEFAULT;
owner_seed = keymgr_dpe_pkg::KEYMGR_DPE_OWNER_SEED_DEFAULT;
// If requested randomize the creator_root_key
if (rand_otp_key) begin
`DV_CHECK_STD_RANDOMIZE_WITH_FATAL(local_otp_key,
local_otp_key.creator_root_key_share0_valid == 1;
local_otp_key.creator_root_key_share1_valid == 1;
!(local_otp_key.creator_root_key_share0 inside {0, '1});
!(local_otp_key.creator_root_key_share1 inside {0, '1});
`DV_CHECK_STD_RANDOMIZE_WITH_FATAL(local_creator_root_key,
local_creator_root_key.share0_valid == 1;
local_creator_root_key.share1_valid == 1;
!(local_creator_root_key.share0 inside {0, '1});
!(local_creator_root_key.share1 inside {0, '1});
, , msg_id)
end else begin
local_otp_key = otp_ctrl_pkg::OTP_KEYMGR_KEY_DEFAULT;
end
if (invalid_otp_key) begin
local_otp_key.creator_root_key_share0_valid = 0;
local_otp_key.creator_root_key_share1_valid = 0;
local_creator_root_key.share0_valid = 0;
local_creator_root_key.share1_valid = 0;
end
otp_key = local_otp_key;
creator_root_key = local_creator_root_key;
endtask

// reset local exp variables when reset is issued
Expand Down Expand Up @@ -189,14 +192,14 @@ interface keymgr_dpe_if(input clk, input rst_n);
// as a set of flags / counters.
bit bad_keymgr_dpe_div = 1'b0;
bit bad_otp_device_id = 1'b0;
bit [NumRomDigestInputs-1:0] bad_rom_data = '0, bad_rom_valid = '0;
bit [DvNumRomDigestInputs-1:0] bad_rom_data = '0, bad_rom_valid = '0;

repeat (num_invalid_input) begin
randcase
1: bad_keymgr_dpe_div = 1'b1;
1: bad_otp_device_id = 1'b1;
1: bad_rom_data[$urandom % NumRomDigestInputs] = 1'b1;
1: bad_rom_valid[$urandom % NumRomDigestInputs] = 1'b1;
1: bad_rom_data[$urandom % DvNumRomDigestInputs] = 1'b1;
1: bad_rom_valid[$urandom % DvNumRomDigestInputs] = 1'b1;
endcase
end

Expand All @@ -217,7 +220,7 @@ interface keymgr_dpe_if(input clk, input rst_n);

// rom_digests
begin
for (int i = 0; i < NumRomDigestInputs; i++)
for (int i = 0; i < DvNumRomDigestInputs; i++)
fork
automatic int local_i = i;
#($urandom_range(1000, 0) * 1ns);
Expand All @@ -235,8 +238,8 @@ interface keymgr_dpe_if(input clk, input rst_n);
function automatic void compare_internal_key_slot(
keymgr_dpe_pkg::keymgr_dpe_slot_t dst_key_slot,
keymgr_dpe_pkg::keymgr_dpe_slot_t src_key_slot,
keymgr_dpe_pkg::keymgr_dpe_slot_idx_e dst_slot_index,
keymgr_dpe_pkg::keymgr_dpe_slot_idx_e src_slot_index,
dv_keymgr_dpe_slot_idx_e dst_slot_index,
dv_keymgr_dpe_slot_idx_e src_slot_index,
bit check_parent_retained
);
`DV_CHECK_EQ(dst_key_slot, internal_key_slots[dst_slot_index],
Expand Down
Loading
Loading