Skip to content
Merged
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
93 changes: 93 additions & 0 deletions hw/ip/keymgr_dpe/data/keymgr_dpe.hjson
Original file line number Diff line number Diff line change
Expand Up @@ -1002,6 +1002,99 @@ countermeasures: [
]
},

{ multireg: {
cname: "KEYMGR",
name: "METADATA_LOW",
desc: '''
Read metadata (low word) for each HW slot.

Only the first `NumInstHwSlot` slots are instantiated.
Entries at index `NumInstHwSlot` and above always read as 0.
Together with !!METADATA_HIGH, this register lets software inspect the non-secret
metadata of the DPE context.
''',
count: "NumMaxHwSlot",
swaccess: "ro",
hwaccess: "hwo",
Comment thread
rroth-lowrisc marked this conversation as resolved.
hwext: "true",
fields: [
{ bits: "31:0",
name: "MAX_KEY_VERSION",
desc: '''
Maximum key version allowed for key derived from this DPE context.
''',
resval: "0"
},
],
},
},

{ multireg: {
cname: "KEYMGR",
name: "METADATA_HIGH",
desc: '''
Read metadata (high word) for each HW slot.

Only the first `NumInstHwSlot` slots are instantiated.
Entries at index `NumInstHwSlot` and above always read as 0.
Together with !!METADATA_LOW, this register lets software inspect the non-secret
metadata of the DPE context.
''',
count: "NumMaxHwSlot",
swaccess: "ro",
hwaccess: "hwo",
hwext: "true",
fields: [
{ bits: "0",
name: "VALID",
desc: '''
Set if the DPE context held in this slot is valid.
''',
resval: "0"
},
{ bits: "2:1",
name: "BOOT_STAGE",
desc: '''
Boot stage associated with the DPE context held in this slot.
Comment thread
rroth-lowrisc marked this conversation as resolved.

| Value | Boot stage |
|:-----:|:------------------|
| 0 | BootStageCreator |
| 1 | BootStageOwnerInt |
| 2 | BootStageOwner |
| 3 | BootStageRuntime |

The naming indicates the next bootstage after a successful key derivation
e.g. boot stage 1 means the context is the _CreatorRootKey_ and will be
derived into the _OwnerIntKey_.
''',
resval: "0"
},
{ bits: "3",
name: "ALLOW_CHILD_POLICY",
resval: "0"
desc: '''
Read the `allow_child` policy applied to the DPE context in this slot.
'''
},
{ bits: "4",
name: "EXPORTABLE_POLICY",
resval: "0"
desc: '''
Read the `exportable` policy applied to the DPE context in this slot.
'''
},
{ bits: "5",
name: "RETAIN_PARENT_POLICY",
resval: "0"
desc: '''
Read the `retain_parent` policy applied to the DPE context in this slot.
'''
},
],
},
},

{ name: "ERR_CODE",
desc: '''
Key manager error code.
Expand Down
13 changes: 13 additions & 0 deletions hw/ip/keymgr_dpe/doc/programmers_guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,19 @@ SW needs to configure the following registers to erase a slot:

At the end of a successful erase operation, the secret of the destination slot is removed and the slot is marked as invalid.

## Read Slot Metadata

Software can read back a slot's `valid`, `boot_stage`, `max_key_version` and `key_policy` fields at any time by reading the `METADATA_LOW` and `METADATA_HIGH` registers at the corresponding slot index:
* `METADATA_LOW[i].MAX_KEY_VERSION` reports `max_key_version` of slot `i`.
* `METADATA_HIGH[i].VALID` reports whether slot `i` currently holds a valid DPE context.
* `METADATA_HIGH[i].BOOT_STAGE` reports the `boot_stage` of slot `i`.
* `METADATA_HIGH[i].ALLOW_CHILD_POLICY` reports the `allow_child` policy applied to slot `i`.
* `METADATA_HIGH[i].EXPORTABLE_POLICY` reports the `exportable` policy applied to slot `i`.
* `METADATA_HIGH[i].RETAIN_PARENT_POLICY` reports the `retain_parent` policy applied to slot `i`.

The secret key itself is never exposed through these registers.
Both registers are replicated `NumMaxHwSlot` times but only indices below `NumInstHwSlot` correspond to an actual hardware slot, the remaining slots are bound to `0`.

# Disable

SW needs to configure the following registers to disable keymgr_dpe:
Expand Down
131 changes: 123 additions & 8 deletions hw/ip/keymgr_dpe/doc/registers.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,26 @@
| keymgr_dpe.[`SW_SHARE1_OUTPUT_7`](#sw_share1_output) | 0xbc | 4 | Key manager software output. |
| keymgr_dpe.[`WORKING_STATE`](#working_state) | 0xc0 | 4 | Key manager working state. |
| keymgr_dpe.[`OP_STATUS`](#op_status) | 0xc4 | 4 | Key manager status. |
| keymgr_dpe.[`ERR_CODE`](#err_code) | 0xc8 | 4 | Key manager error code. |
| keymgr_dpe.[`FAULT_STATUS`](#fault_status) | 0xcc | 4 | This register represents both synchronous and asynchronous fatal faults. |
| keymgr_dpe.[`DEBUG`](#debug) | 0xd0 | 4 | The register holds some debug information that may be convenient if keymgr |
| keymgr_dpe.[`LOAD_KEY_LOCK`](#load_key_lock) | 0xd4 | 4 | Register write lock for the LOAD_KEY command |
| keymgr_dpe.[`METADATA_LOW_0`](#metadata_low) | 0xc8 | 4 | Read metadata (low word) for each HW slot. |
| keymgr_dpe.[`METADATA_LOW_1`](#metadata_low) | 0xcc | 4 | Read metadata (low word) for each HW slot. |
| keymgr_dpe.[`METADATA_LOW_2`](#metadata_low) | 0xd0 | 4 | Read metadata (low word) for each HW slot. |
| keymgr_dpe.[`METADATA_LOW_3`](#metadata_low) | 0xd4 | 4 | Read metadata (low word) for each HW slot. |
| keymgr_dpe.[`METADATA_LOW_4`](#metadata_low) | 0xd8 | 4 | Read metadata (low word) for each HW slot. |
| keymgr_dpe.[`METADATA_LOW_5`](#metadata_low) | 0xdc | 4 | Read metadata (low word) for each HW slot. |
| keymgr_dpe.[`METADATA_LOW_6`](#metadata_low) | 0xe0 | 4 | Read metadata (low word) for each HW slot. |
| keymgr_dpe.[`METADATA_LOW_7`](#metadata_low) | 0xe4 | 4 | Read metadata (low word) for each HW slot. |
| keymgr_dpe.[`METADATA_HIGH_0`](#metadata_high) | 0xe8 | 4 | Read metadata (high word) for each HW slot. |
| keymgr_dpe.[`METADATA_HIGH_1`](#metadata_high) | 0xec | 4 | Read metadata (high word) for each HW slot. |
| keymgr_dpe.[`METADATA_HIGH_2`](#metadata_high) | 0xf0 | 4 | Read metadata (high word) for each HW slot. |
| keymgr_dpe.[`METADATA_HIGH_3`](#metadata_high) | 0xf4 | 4 | Read metadata (high word) for each HW slot. |
| keymgr_dpe.[`METADATA_HIGH_4`](#metadata_high) | 0xf8 | 4 | Read metadata (high word) for each HW slot. |
| keymgr_dpe.[`METADATA_HIGH_5`](#metadata_high) | 0xfc | 4 | Read metadata (high word) for each HW slot. |
| keymgr_dpe.[`METADATA_HIGH_6`](#metadata_high) | 0x100 | 4 | Read metadata (high word) for each HW slot. |
| keymgr_dpe.[`METADATA_HIGH_7`](#metadata_high) | 0x104 | 4 | Read metadata (high word) for each HW slot. |
| keymgr_dpe.[`ERR_CODE`](#err_code) | 0x108 | 4 | Key manager error code. |
| keymgr_dpe.[`FAULT_STATUS`](#fault_status) | 0x10c | 4 | This register represents both synchronous and asynchronous fatal faults. |
| keymgr_dpe.[`DEBUG`](#debug) | 0x110 | 4 | The register holds some debug information that may be convenient if keymgr |
| keymgr_dpe.[`LOAD_KEY_LOCK`](#load_key_lock) | 0x114 | 4 | Register write lock for the LOAD_KEY command |

## INTR_STATE
Interrupt State Register
Expand Down Expand Up @@ -605,6 +621,105 @@ Operation status.
| 0x3 | DONE_ERROR | Operation finished with errors, please see ERR_CODE register. |


## METADATA_LOW
Read metadata (low word) for each HW slot.

Only the first `NumInstHwSlot` slots are instantiated.
Entries at index `NumInstHwSlot` and above always read as 0.
Together with [`METADATA_HIGH`](#metadata_high), this register lets software inspect the non-secret
metadata of the DPE context.
- Reset default: `0x0`
- Reset mask: `0xffffffff`

### Instances

| Name | Offset |
|:---------------|:---------|
| METADATA_LOW_0 | 0xc8 |
| METADATA_LOW_1 | 0xcc |
| METADATA_LOW_2 | 0xd0 |
| METADATA_LOW_3 | 0xd4 |
| METADATA_LOW_4 | 0xd8 |
| METADATA_LOW_5 | 0xdc |
| METADATA_LOW_6 | 0xe0 |
| METADATA_LOW_7 | 0xe4 |


### Fields

```wavejson
{"reg": [{"name": "MAX_KEY_VERSION", "bits": 32, "attr": ["ro"], "rotate": 0}], "config": {"lanes": 1, "fontsize": 10, "vspace": 80}}
```

| Bits | Type | Reset | Name | Description |
|:------:|:------:|:-------:|:----------------|:-------------------------------------------------------------------|
| 31:0 | ro | 0x0 | MAX_KEY_VERSION | Maximum key version allowed for key derived from this DPE context. |

## METADATA_HIGH
Read metadata (high word) for each HW slot.

Only the first `NumInstHwSlot` slots are instantiated.
Entries at index `NumInstHwSlot` and above always read as 0.
Together with [`METADATA_LOW`](#metadata_low), this register lets software inspect the non-secret
metadata of the DPE context.
- Reset default: `0x0`
- Reset mask: `0x3f`

### Instances

| Name | Offset |
|:----------------|:---------|
| METADATA_HIGH_0 | 0xe8 |
| METADATA_HIGH_1 | 0xec |
| METADATA_HIGH_2 | 0xf0 |
| METADATA_HIGH_3 | 0xf4 |
| METADATA_HIGH_4 | 0xf8 |
| METADATA_HIGH_5 | 0xfc |
| METADATA_HIGH_6 | 0x100 |
| METADATA_HIGH_7 | 0x104 |


### Fields

```wavejson
{"reg": [{"name": "VALID", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "BOOT_STAGE", "bits": 2, "attr": ["ro"], "rotate": -90}, {"name": "ALLOW_CHILD_POLICY", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "EXPORTABLE_POLICY", "bits": 1, "attr": ["ro"], "rotate": -90}, {"name": "RETAIN_PARENT_POLICY", "bits": 1, "attr": ["ro"], "rotate": -90}, {"bits": 26}], "config": {"lanes": 1, "fontsize": 10, "vspace": 220}}
```

| Bits | Type | Reset | Name |
|:------:|:------:|:-------:|:-------------------------------------------------------------|
| 31:6 | | | Reserved |
| 5 | ro | 0x0 | [RETAIN_PARENT_POLICY](#metadata_high--retain_parent_policy) |
| 4 | ro | 0x0 | [EXPORTABLE_POLICY](#metadata_high--exportable_policy) |
| 3 | ro | 0x0 | [ALLOW_CHILD_POLICY](#metadata_high--allow_child_policy) |
| 2:1 | ro | 0x0 | [BOOT_STAGE](#metadata_high--boot_stage) |
| 0 | ro | 0x0 | [VALID](#metadata_high--valid) |

### METADATA_HIGH . RETAIN_PARENT_POLICY
Read the `retain_parent` policy applied to the DPE context in this slot.

### METADATA_HIGH . EXPORTABLE_POLICY
Read the `exportable` policy applied to the DPE context in this slot.

### METADATA_HIGH . ALLOW_CHILD_POLICY
Read the `allow_child` policy applied to the DPE context in this slot.

### METADATA_HIGH . BOOT_STAGE
Boot stage associated with the DPE context held in this slot.

| Value | Boot stage |
|:-----:|:------------------|
| 0 | BootStageCreator |
| 1 | BootStageOwnerInt |
| 2 | BootStageOwner |
| 3 | BootStageRuntime |

The naming indicates the next bootstage after a successful key derivation
e.g. boot stage 1 means the context is the _CreatorRootKey_ and will be
derived into the _OwnerIntKey_.

### METADATA_HIGH . VALID
Set if the DPE context held in this slot is valid.

## ERR_CODE
Key manager error code.
This register must be explicitly cleared by software.
Expand All @@ -614,7 +729,7 @@ errors.

Synchronous errors refer to those that only happen when a keymgr operation is
invoked, while asynchronous refers to errors that can happen at any time.
- Offset: `0xc8`
- Offset: `0x108`
- Reset default: `0x0`
- Reset mask: `0x7`

Expand All @@ -637,7 +752,7 @@ This register represents both synchronous and asynchronous fatal faults.
Synchronous faults refer to those that only happen when a keymgr operation is
invoked, while asynchronous refers to faults that can happen at any time.

- Offset: `0xcc`
- Offset: `0x10c`
- Reset default: `0x0`
- Reset mask: `0x3fff`

Expand Down Expand Up @@ -668,7 +783,7 @@ invoked, while asynchronous refers to faults that can happen at any time.
## DEBUG
The register holds some debug information that may be convenient if keymgr
misbehaves.
- Offset: `0xd0`
- Offset: `0x110`
- Reset default: `0x0`
- Reset mask: `0x1ff`

Expand All @@ -693,7 +808,7 @@ misbehaves.

## LOAD_KEY_LOCK
Register write lock for the LOAD_KEY command
- Offset: `0xd4`
- Offset: `0x114`
- Reset default: `0x0`
- Reset mask: `0x1`

Expand Down
4 changes: 4 additions & 0 deletions hw/ip/keymgr_dpe/doc/theory_of_operation.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ Otherwise all advance requests are rejected that specify this slot as its source
* If `retain_parent` is set to `true`/`1`, then the parent slot remains valid after an advance call.
Otherwise, after the derivation of a child slot, the DPE context of the parent slot is removed automatically.

With the exception of the secret key itself, software can read back a slot's `valid`, `boot_stage`, `max_key_version` and `key_policy` subfields at any time through the `METADATA_LOW` and `METADATA_HIGH` registers.
Both registers are replicated `NumMaxHwSlot` times but only indices below `NumInstHwSlot` correspond to an actual hardware slot, the remaining slots are bound to `0`.
`METADATA_LOW.MAX_KEY_VERSION` reports `max_key_version`, while `METADATA_HIGH` reports `valid`, `boot_stage` and `key_policy` subfields respectively.

## Key Manager State

The key manager working state represents the current working state of the key manager and it is decoupled from the DICE hierarchy.
Expand Down
22 changes: 22 additions & 0 deletions hw/ip/keymgr_dpe/rtl/keymgr_dpe.sv
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,24 @@ module keymgr_dpe
logic sideload_sel_err;
logic key_version_vld;

keymgr_dpe_metadata_slot_t [NumInstHwSlot-1:0] metadata;
for (genvar i = 0; i < NumMaxHwSlot; i++) begin : gen_metadata_read_data
if (i < NumInstHwSlot) begin : gen_inst_slot
assign hw2reg.metadata_high[i].valid.d = metadata[i].valid;
assign hw2reg.metadata_high[i].exportable_policy.d = metadata[i].key_policy.exportable;
assign hw2reg.metadata_high[i].retain_parent_policy.d = metadata[i].key_policy.retain_parent;
assign hw2reg.metadata_high[i].allow_child_policy.d = metadata[i].key_policy.allow_child;
assign hw2reg.metadata_high[i].boot_stage.d = metadata[i].boot_stage;
assign hw2reg.metadata_low[i].d = metadata[i].max_key_version;
end else begin : gen_tieoff_slot
assign hw2reg.metadata_high[i].valid.d = '0;
assign hw2reg.metadata_high[i].exportable_policy.d = '0;
assign hw2reg.metadata_high[i].retain_parent_policy.d = '0;
assign hw2reg.metadata_high[i].allow_child_policy.d = '0;
assign hw2reg.metadata_high[i].boot_stage.d = '0;
assign hw2reg.metadata_low[i].d = '0;
end
end

for (genvar i = 0; i < Shares; i++) begin : gen_truncate_data
assign kmac_data_truncated[i] = kmac_data[i][KeyWidth-1:0];
Expand Down Expand Up @@ -364,6 +382,7 @@ module keymgr_dpe
.max_key_version_i(reg2hw.max_key_ver_shadowed),
.key_version_i(reg2hw.key_version),
.key_version_vld_o(key_version_vld),
.metadata_o(metadata),
.op_start_i(op_start),
.op_done_o(op_done),
.init_o(init),
Expand Down Expand Up @@ -926,6 +945,9 @@ module keymgr_dpe
// Verify supported number of boot stage
`ASSERT_INIT(InvalidNumOfBootStage_A, NumBootStages inside {2, 3})

// Verify the metadata do not exceed the width of the sw registers
`ASSERT_INIT(MetadataExceedSwReg_A, $bits(keymgr_dpe_metadata_slot_t) <= 2*top_pkg::TL_DW)
Comment thread
rroth-lowrisc marked this conversation as resolved.

// Verify the number of instanciated HW slots
`ASSERT_INIT(InvalidNumHwSlot_A, NumInstHwSlot <= NumMaxHwSlot)
// Only a power-of-two for the NumInstHwSlot is supported
Expand Down
6 changes: 6 additions & 0 deletions hw/ip/keymgr_dpe/rtl/keymgr_dpe_ctrl.sv
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ module keymgr_dpe_ctrl
input [KeyVersionWidth-1:0] max_key_version_i,
input [KeyVersionWidth-1:0] key_version_i,
output key_version_vld_o,
output keymgr_dpe_metadata_slot_t [NumInstHwSlot-1:0] metadata_o,

output logic op_done_o,
output keymgr_dpe_op_status_e status_o,
Expand Down Expand Up @@ -140,6 +141,11 @@ module keymgr_dpe_ctrl
assign gen_hw_key_cmd = op_start_i & (op_i == OpDpeGenHwOut) & en_i;
assign disable_cmd = op_start_i & (op_i == OpDpeDisable) & en_i;

// Forward all metadata to the sw register
for (genvar i = 0; i < NumInstHwSlot; i++) begin : gen_metadata_output
assign metadata_o[i] = extract_metadata_from_slot(key_slots_q[i]);
end

///////////////////////////
// interaction between main control fsm and operation fsm
///////////////////////////
Expand Down
20 changes: 20 additions & 0 deletions hw/ip/keymgr_dpe/rtl/keymgr_dpe_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,14 @@ package keymgr_dpe_pkg;
keymgr_dpe_policy_t key_policy;
} keymgr_dpe_slot_t;

// Internal metadata for each slot
typedef struct packed {
keymgr_dpe_policy_t key_policy;
keymgr_dpe_boot_stage_e boot_stage;
logic valid;
logic [KeyVersionWidth-1:0] max_key_version;
} keymgr_dpe_metadata_slot_t;

typedef enum logic [2:0] {
SlotUpdateIdle,
SlotDestRandomize,
Expand Down Expand Up @@ -406,4 +414,16 @@ package keymgr_dpe_pkg;
return |value & ~&value;
endfunction

// extract all metadata from a slot
function automatic keymgr_dpe_metadata_slot_t extract_metadata_from_slot (keymgr_dpe_slot_t slot);
// read unused signal to avoid linter warnings
logic [Shares-1:0][KeyWidth-1:0] unused_key = slot.key;
return keymgr_dpe_metadata_slot_t'{
slot.key_policy,
slot.boot_stage,
slot.valid,
slot.max_key_version
};
endfunction

endpackage : keymgr_dpe_pkg
Loading
Loading