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
1 change: 1 addition & 0 deletions sw/device/lib/crypto/drivers/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ cc_library(
"//hw/top/dt:keymgr_dpe",
"//sw/device/lib/base:abs_mmio",
"//sw/device/lib/base:bitfield",
"//sw/device/lib/base:hardened",
"//sw/device/lib/base:hardened_memory",
"//sw/device/lib/base:macros",
"//sw/device/lib/crypto/impl:status",
Expand Down
45 changes: 45 additions & 0 deletions sw/device/lib/crypto/drivers/keymgr_dpe.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ static_assert(kKeymgrDPEOutputShareNumWords ==
static_assert(kKeymgrDPEOutputShareNumWords ==
KEYMGR_DPE_SW_SHARE1_OUTPUT_MULTIREG_COUNT,
"Number of output share 1 registers does not match.");
static_assert(KEYMGR_DPE_METADATA_LOW_MULTIREG_COUNT ==
KEYMGR_DPE_PARAM_NUM_MAX_HW_SLOT,
"Number of metadata low registers does not match.");
static_assert(KEYMGR_DPE_METADATA_HIGH_MULTIREG_COUNT ==
KEYMGR_DPE_PARAM_NUM_MAX_HW_SLOT,
"Number of metadata high registers does not match.");

/**
* Fails if the keymgr dpe is not idle.
Expand Down Expand Up @@ -334,3 +340,42 @@ status_t keymgr_dpe_sideload_clear_otbn(void) {
status_t keymgr_dpe_sideload_clear_hmac(void) {
return keymgr_dpe_sideload_clear(KEYMGR_DPE_SIDELOAD_CLEAR_VAL_VALUE_HMAC);
}

status_t keymgr_dpe_get_metadata(uint32_t slot,
Comment thread
rroth-lowrisc marked this conversation as resolved.
keymgr_dpe_metadata_t *metadata) {
if (launder32(slot) >= KEYMGR_DPE_PARAM_NUM_MAX_HW_SLOT) {
return OTCRYPTO_BAD_ARGS;
}
HARDENED_CHECK_LT(slot, KEYMGR_DPE_PARAM_NUM_MAX_HW_SLOT);

const uint32_t kBase = keymgr_dpe_base();
metadata->max_key_version = abs_mmio_read32(
kBase + KEYMGR_DPE_METADATA_LOW_0_REG_OFFSET + slot * sizeof(uint32_t));

uint32_t reg_high = abs_mmio_read32(
kBase + KEYMGR_DPE_METADATA_HIGH_0_REG_OFFSET + slot * sizeof(uint32_t));
metadata->valid =
bitfield_bit32_read(reg_high, KEYMGR_DPE_METADATA_HIGH_0_VALID_0_BIT)
Comment thread
andrea-caforio marked this conversation as resolved.
? kHardenedBoolTrue
: kHardenedBoolFalse;
metadata->boot_stage = (keymgr_dpe_boot_stage_t)bitfield_field32_read(
Comment thread
andrea-caforio marked this conversation as resolved.
reg_high, KEYMGR_DPE_METADATA_HIGH_0_BOOT_STAGE_0_FIELD);

metadata->slot_policy.allow_child =
bitfield_bit32_read(reg_high,
KEYMGR_DPE_METADATA_HIGH_0_ALLOW_CHILD_POLICY_0_BIT)
? kHardenedBoolTrue
: kHardenedBoolFalse;
metadata->slot_policy.exportable =
bitfield_bit32_read(reg_high,
KEYMGR_DPE_METADATA_HIGH_0_EXPORTABLE_POLICY_0_BIT)
? kHardenedBoolTrue
: kHardenedBoolFalse;
metadata->slot_policy.retain_parent =
bitfield_bit32_read(reg_high,
KEYMGR_DPE_METADATA_HIGH_0_RETAIN_PARENT_POLICY_0_BIT)
? kHardenedBoolTrue
: kHardenedBoolFalse;

return OTCRYPTO_OK;
}
65 changes: 64 additions & 1 deletion sw/device/lib/crypto/drivers/keymgr_dpe.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
#ifndef OPENTITAN_SW_DEVICE_LIB_CRYPTO_DRIVERS_KEYMGR_DPE_H_
#define OPENTITAN_SW_DEVICE_LIB_CRYPTO_DRIVERS_KEYMGR_DPE_H_

#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

#include "sw/device/lib/base/hardened.h"
#include "sw/device/lib/base/macros.h"
#include "sw/device/lib/crypto/impl/status.h"

Expand Down Expand Up @@ -55,6 +55,57 @@ typedef struct keymgr_dpe_output {
uint32_t share1[kKeymgrDPEOutputShareNumWords];
} keymgr_dpe_output_t;

/**
* Policy bits associated with the DPE context held in one HW slot.
*/
typedef struct keymgr_dpe_policy {
/**
* Set if this DPE context allows deriving further DPE contexts.
*/
hardened_bool_t allow_child;
/**
* Set if the key for this slot is exportable.
*/
hardened_bool_t exportable;
/**
* Set if further advance operations retain (do not erase) this slot.
*/
hardened_bool_t retain_parent;
} keymgr_dpe_policy_t;

/**
* Boot stage associated with a DPE context.
* Mirrors `keymgr_dpe_boot_stage_e` in keymgr_dpe_pkg.sv.
*/
typedef enum keymgr_dpe_boot_stage {
Comment thread
rroth-lowrisc marked this conversation as resolved.
kKeymgrDPEBootStageCreator = 0,
kKeymgrDPEBootStageOwnerInt = 1,
kKeymgrDPEBootStageOwner = 2,
kKeymgrDPEBootStageRuntime = 3,
} keymgr_dpe_boot_stage_t;

/**
* Output metadata from one HW slot.
*/
typedef struct keymgr_dpe_metadata {
/**
* Maximum allowed version for keys to be generated from this DPE context.
*/
uint32_t max_key_version;
Comment thread
andrea-caforio marked this conversation as resolved.
/**
* The current boot_stage of this DPE context.
*/
keymgr_dpe_boot_stage_t boot_stage;
/**
* The current slot policy bits for this DPE context.
*/
keymgr_dpe_policy_t slot_policy;
/**
* Validity of this DPE context.
*/
hardened_bool_t valid;
} keymgr_dpe_metadata_t;

/**
* Derive a key manager dpe key that is visible to software.
*
Expand Down Expand Up @@ -151,6 +202,18 @@ status_t keymgr_dpe_sideload_clear_otbn(void);
OT_WARN_UNUSED_RESULT
status_t keymgr_dpe_sideload_clear_hmac(void);

/**
* Reads back the metadata of a keymgr_dpe HW slot.
*
* @param slot Index of the HW slot to read metadata from. Must be less than
* `KEYMGR_DPE_PARAM_NUM_MAX_HW_SLOT`.
* @param[out] metadata Metadata of the DPE context held in `slot`.
* @return OK, or `OTCRYPTO_BAD_ARGS` if `slot` is out of range.
*/
OT_WARN_UNUSED_RESULT
status_t keymgr_dpe_get_metadata(uint32_t slot,
keymgr_dpe_metadata_t *metadata);

#ifdef __cplusplus
}
#endif
Expand Down
53 changes: 53 additions & 0 deletions sw/device/lib/dif/dif_keymgr_dpe.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,21 @@ static_assert(KEYMGR_DPE_SW_SHARE1_OUTPUT_7_REG_OFFSET ==
KEYMGR_DPE_SW_SHARE1_OUTPUT_0_REG_OFFSET + 28,
"SW_SHARE1_OUTPUT_N registers must be contiguous.");

static_assert(KEYMGR_DPE_METADATA_LOW_1_REG_OFFSET ==
KEYMGR_DPE_METADATA_LOW_0_REG_OFFSET + 4,
"METADATA_LOW_N registers must be contiguous.");
static_assert(KEYMGR_DPE_METADATA_HIGH_1_REG_OFFSET ==
KEYMGR_DPE_METADATA_HIGH_0_REG_OFFSET + 4,
"METADATA_HIGH_N registers must be contiguous.");
static_assert(KEYMGR_DPE_METADATA_LOW_MULTIREG_COUNT ==
KEYMGR_DPE_PARAM_NUM_MAX_HW_SLOT,
"METADATA_LOW_N register count must match the number of HW "
"slots.");
static_assert(KEYMGR_DPE_METADATA_HIGH_MULTIREG_COUNT ==
KEYMGR_DPE_PARAM_NUM_MAX_HW_SLOT,
"METADATA_HIGH_N register count must match the number of HW "
"slots.");

/**
* Error code constants of `dif_keymgr_dpe_status_code_t` are masks for the bits
* of ERR_CODE register shifted left by 1.
Expand Down Expand Up @@ -286,6 +301,44 @@ dif_result_t dif_keymgr_dpe_erase_slot(
return kDifOk;
}

dif_result_t dif_keymgr_dpe_get_metadata(const dif_keymgr_dpe_t *keymgr_dpe,
uint32_t slot,
dif_keymgr_dpe_metadata_t *metadata) {
if (keymgr_dpe == NULL || metadata == NULL ||
slot >= KEYMGR_DPE_PARAM_NUM_MAX_HW_SLOT) {
return kDifBadArg;
}

metadata->max_key_version = mmio_region_read32(
keymgr_dpe->base_addr, (ptrdiff_t)(KEYMGR_DPE_METADATA_LOW_0_REG_OFFSET +
slot * sizeof(uint32_t)));

uint32_t reg_high = mmio_region_read32(
keymgr_dpe->base_addr, (ptrdiff_t)(KEYMGR_DPE_METADATA_HIGH_0_REG_OFFSET +
slot * sizeof(uint32_t)));
metadata->valid =
bitfield_bit32_read(reg_high, KEYMGR_DPE_METADATA_HIGH_0_VALID_0_BIT);
metadata->boot_stage = bitfield_field32_read(
reg_high, KEYMGR_DPE_METADATA_HIGH_0_BOOT_STAGE_0_FIELD);

uint32_t slot_policy = 0;
slot_policy = bitfield_bit32_write(
slot_policy, KEYMGR_DPE_SLOT_POLICY_ALLOW_CHILD_BIT,
bitfield_bit32_read(reg_high,
KEYMGR_DPE_METADATA_HIGH_0_ALLOW_CHILD_POLICY_0_BIT));
slot_policy = bitfield_bit32_write(
slot_policy, KEYMGR_DPE_SLOT_POLICY_EXPORTABLE_BIT,
bitfield_bit32_read(reg_high,
KEYMGR_DPE_METADATA_HIGH_0_EXPORTABLE_POLICY_0_BIT));
slot_policy = bitfield_bit32_write(
slot_policy, KEYMGR_DPE_SLOT_POLICY_RETAIN_PARENT_BIT,
bitfield_bit32_read(
reg_high, KEYMGR_DPE_METADATA_HIGH_0_RETAIN_PARENT_POLICY_0_BIT));
metadata->slot_policy = slot_policy;

return kDifOk;
}

dif_result_t dif_keymgr_dpe_disable(const dif_keymgr_dpe_t *keymgr_dpe) {
if (keymgr_dpe == NULL) {
return kDifBadArg;
Expand Down
40 changes: 40 additions & 0 deletions sw/device/lib/dif/dif_keymgr_dpe.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,32 @@ typedef struct dif_keymgr_dpe_advance_params {
uint32_t slot_policy;
} dif_keymgr_dpe_advance_params_t;

/**
* Output metadata from one HW slot
*/
typedef struct dif_keymgr_dpe_metadata {
/**
* Maximum allowed version for keys to be generated from this DPE context
*/
uint32_t max_key_version;

/**
* The current boot_stage of this DPE context.
*/
uint32_t boot_stage;

/**
* The current slot policy bits for this DPE context, using the same bit
* layout as the `SLOT_POLICY` register.
*/
uint32_t slot_policy;

/**
* Validity of this DPE context.
*/
uint32_t valid;
} dif_keymgr_dpe_metadata_t;

/**
* Key destination of a versioned key generation operation.
*
Expand Down Expand Up @@ -285,6 +311,20 @@ dif_result_t dif_keymgr_dpe_erase_slot(
const dif_keymgr_dpe_t *keymgr_dpe,
const dif_keymgr_dpe_erase_params_t *params);

/**
* Reads back the metadata of a keymgr_dpe HW slot.
*
* @param keymgr_dpe A key manager handle.
* @param slot Index of the HW slot to read metadata from.
* @param[out] metadata The maximum key version, boot stage, slot policy and
* validity of the DPE context held in `slot`.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_keymgr_dpe_get_metadata(const dif_keymgr_dpe_t *keymgr_dpe,
uint32_t slot,
dif_keymgr_dpe_metadata_t *metadata);

/**
* Disables key manager dpe.
*
Expand Down
22 changes: 22 additions & 0 deletions sw/device/lib/testing/keymgr_dpe_testutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,28 @@ status_t keymgr_dpe_testutils_check_state(
return OK_STATUS();
}

status_t keymgr_dpe_testutils_check_metadata(const dif_keymgr_dpe_t *keymgr_dpe,
uint32_t slot,
uint32_t exp_max_key_version,
uint32_t exp_boot_stage,
uint32_t exp_policy) {
dif_keymgr_dpe_metadata_t metadata;
TRY(dif_keymgr_dpe_get_metadata(keymgr_dpe, slot, &metadata));
TRY_CHECK(metadata.valid, "Keymgr DPE slot %d is not valid", slot);
TRY_CHECK(metadata.max_key_version == exp_max_key_version,
"Keymgr DPE slot %d has unexpected max key version: %x, expected "
"to be %x",
slot, metadata.max_key_version, exp_max_key_version);
TRY_CHECK(
metadata.boot_stage == exp_boot_stage,
"Keymgr DPE slot %d in unexpected boot stage: %x, expected to be %x",
slot, metadata.boot_stage, exp_boot_stage);
TRY_CHECK(metadata.slot_policy == exp_policy,
"Keymgr DPE slot %d has unexpected policy: %x, expected to be %x",
slot, metadata.slot_policy, exp_policy);
return OK_STATUS();
}

status_t keymgr_dpe_testutils_generate_key(
const dif_keymgr_dpe_t *keymgr_dpe,
const dif_keymgr_dpe_generate_params_t *params) {
Expand Down
20 changes: 20 additions & 0 deletions sw/device/lib/testing/keymgr_dpe_testutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,26 @@ OT_WARN_UNUSED_RESULT
status_t keymgr_dpe_testutils_check_state(
const dif_keymgr_dpe_t *keymgr_dpe, const dif_keymgr_dpe_state_t exp_state);

/**
* Checks that a keymgr dpe HW slot holds a valid DPE context with the expected
* maximum key version, boot stage and slot policy.
*
* @param keymgr_dpe A key manager dpe handle.
* @param slot The HW slot to check.
* @param exp_max_key_version The expected maximum key version for the DPE
* context in `slot`.
* @param exp_boot_stage The expected boot stage for the DPE context in
* `slot`.
* @param exp_policy The expected policy bits for the DPE context in `slot`,
* using the same bit layout as the `SLOT_POLICY` register.
*/
OT_WARN_UNUSED_RESULT
status_t keymgr_dpe_testutils_check_metadata(const dif_keymgr_dpe_t *keymgr_dpe,
uint32_t slot,
uint32_t exp_max_key_version,
uint32_t exp_boot_stage,
uint32_t exp_policy);

/**
* Issues a keymgr dpe HW/SW versioned key generation and wait for it
* to complete.
Expand Down
2 changes: 2 additions & 0 deletions sw/device/silicon_creator/lib/drivers/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ cc_library(
"//hw/top:keymgr_dpe_c_regs",
"//hw/top/dt",
"//sw/device/lib/base:abs_mmio",
"//sw/device/lib/base:hardened",
"//sw/device/lib/base:hardened_memory",
"//sw/device/lib/base:macros",
"//sw/device/lib/runtime:hart",
Expand Down Expand Up @@ -398,6 +399,7 @@ opentitan_test(
"//sw/device/lib/testing/test_framework:ottf_main",
"//sw/device/silicon_creator/lib:error",
"//sw/device/silicon_creator/lib:keymgr_dpe_binding",
"//sw/device/silicon_creator/lib:manifest",
"//sw/device/silicon_creator/lib/base:chip",
"//sw/device/silicon_creator/lib/base:sec_mmio",
],
Expand Down
Loading
Loading