Skip to content

Commit

Permalink
[dif, keymgr] Add CDI type option to dif_keymgr
Browse files Browse the repository at this point in the history
The keymgr IP supports both the sealing and attestation CDI flows,
which is controlled by the `CDI_SEL` field in the `CONTROL_SHADOWED`
register. So far, this field was hardcoded to the sealing type in the
keymgr DIF. This commit parametrizes the field, making it possible to
also invoke the attestation flow through the DIF. In particular, the
commit comprises the following changes:

  - A new `dif_keymgr_cdi_type_t` enumeration type.
  - A new `dif_keymgr_identity_seed_params_t` struct such that the CDI
    flow can be chosen for the identity derivations.
  - A new `cdi_type` field in `dif_keymgr_versioned_key_params_t` to
    chose the CDI flow for software and sideload key derivations.
  - Added unit tests pertaining to the CDI type.
  - Updated some calls to this new API in other files.

Signed-off-by: Andrea Caforio <[email protected]>
(cherry picked from commit 24bbbe6)
  • Loading branch information
andrea-caforio committed Nov 5, 2024
1 parent da7695a commit ed9a230
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 20 deletions.
25 changes: 19 additions & 6 deletions sw/device/lib/dif/dif_keymgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,13 @@ typedef struct start_operation_params {
* Operation to start.
*/
uint32_t op;
/**
* Compound Device Identifier type (sealing or attestation).
*
* Only relevant for the creation of identities, software and sideload keys,
* otherwise the key manager operations are identical for both types.
*/
dif_keymgr_cdi_type_t cdi_type;
} start_operation_params_t;

/**
Expand All @@ -233,6 +240,11 @@ static void start_operation(const dif_keymgr_t *keymgr,
0, KEYMGR_CONTROL_SHADOWED_DEST_SEL_FIELD, params.dest);
reg_control = bitfield_field32_write(
reg_control, KEYMGR_CONTROL_SHADOWED_OPERATION_FIELD, params.op);
reg_control = bitfield_field32_write(
reg_control,
(bitfield_field32_t){.mask = 0x1u,
.index = KEYMGR_CONTROL_SHADOWED_CDI_SEL_BIT},
params.cdi_type);
mmio_region_write32_shadowed(keymgr->base_addr,
KEYMGR_CONTROL_SHADOWED_REG_OFFSET, reg_control);
mmio_region_write32(keymgr->base_addr, KEYMGR_START_REG_OFFSET,
Expand Down Expand Up @@ -461,7 +473,8 @@ dif_result_t dif_keymgr_get_state(const dif_keymgr_t *keymgr,
}
}

dif_result_t dif_keymgr_generate_identity_seed(const dif_keymgr_t *keymgr) {
dif_result_t dif_keymgr_generate_identity_seed(
const dif_keymgr_t *keymgr, dif_keymgr_identity_seed_params_t params) {
if (keymgr == NULL) {
return kDifBadArg;
}
Expand All @@ -474,7 +487,7 @@ dif_result_t dif_keymgr_generate_identity_seed(const dif_keymgr_t *keymgr) {
(start_operation_params_t){
.dest = KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_NONE,
.op = KEYMGR_CONTROL_SHADOWED_OPERATION_VALUE_GENERATE_ID,
});
.cdi_type = params.cdi_type});

return kDifOk;
}
Expand All @@ -491,25 +504,25 @@ dif_result_t dif_keymgr_generate_versioned_key(
hw_op_params = (start_operation_params_t){
.dest = KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_NONE,
.op = KEYMGR_CONTROL_SHADOWED_OPERATION_VALUE_GENERATE_SW_OUTPUT,
};
.cdi_type = params.cdi_type};
break;
case kDifKeymgrVersionedKeyDestAes:
hw_op_params = (start_operation_params_t){
.dest = KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_AES,
.op = KEYMGR_CONTROL_SHADOWED_OPERATION_VALUE_GENERATE_HW_OUTPUT,
};
.cdi_type = params.cdi_type};
break;
case kDifKeymgrVersionedKeyDestKmac:
hw_op_params = (start_operation_params_t){
.dest = KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_KMAC,
.op = KEYMGR_CONTROL_SHADOWED_OPERATION_VALUE_GENERATE_HW_OUTPUT,
};
.cdi_type = params.cdi_type};
break;
case kDifKeymgrVersionedKeyDestOtbn:
hw_op_params = (start_operation_params_t){
.dest = KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_OTBN,
.op = KEYMGR_CONTROL_SHADOWED_OPERATION_VALUE_GENERATE_HW_OUTPUT,
};
.cdi_type = params.cdi_type};
break;
default:
return kDifBadArg;
Expand Down
46 changes: 45 additions & 1 deletion sw/device/lib/dif/dif_keymgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/dif/dif_base.h"

#include "keymgr_regs.h"
#include "sw/device/lib/dif/autogen/dif_keymgr_autogen.h"

#ifdef __cplusplus
Expand Down Expand Up @@ -151,6 +152,33 @@ typedef enum dif_keymgr_state {
kDifKeymgrStateInvalid,
} dif_keymgr_state_t;

/**
* Compound Device Identifier type.
*
* The key manager supports the DICE open profile consisting of two Compound
* Device Identifiers (CDI):
*
* - Sealing
* - Attestation
*
* In every operational state of the key manager, it is possible to derive
* either sealing or attestation identifiers, software or hardware keys by
* setting the `CDI_SEL` bit in the `CONTROL_SHADOWED` register.
*/
typedef enum dif_keymgr_cdi_type {
/**
* Sealing CDI.
*
* This is the default configuration, corresponding to an unset bit.
*/
kDifKeymgrSealingCdi = KEYMGR_CONTROL_SHADOWED_CDI_SEL_VALUE_SEALING_CDI,
/**
* Attestation CDI.
*/
kDifKeymgrAttestationCdi =
KEYMGR_CONTROL_SHADOWED_CDI_SEL_VALUE_ATTESTATION_CDI
} dif_keymgr_cdi_type_t;

/**
* Configures key manager with runtime information.
*
Expand Down Expand Up @@ -334,6 +362,16 @@ OT_WARN_UNUSED_RESULT
dif_result_t dif_keymgr_get_state(const dif_keymgr_t *keymgr,
dif_keymgr_state_t *state);

/**
* Parameters for generating an identity seed.
*/
typedef struct dif_keymgr_identity_seed_params {
/**
* Compound Device Identifier type (sealing or attestation).
*/
dif_keymgr_cdi_type_t cdi_type;
} dif_keymgr_identity_seed_params_t;

/**
* Generates an identity seed.
*
Expand All @@ -346,10 +384,12 @@ dif_result_t dif_keymgr_get_state(const dif_keymgr_t *keymgr,
* KDF.
*
* @param keymgr A key manager handle.
* @param params Identity seed generation params.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
dif_result_t dif_keymgr_generate_identity_seed(const dif_keymgr_t *keymgr);
dif_result_t dif_keymgr_generate_identity_seed(
const dif_keymgr_t *keymgr, dif_keymgr_identity_seed_params_t params);

/**
* Destination of a versioned key generation operation.
Expand Down Expand Up @@ -405,6 +445,10 @@ typedef struct dif_keymgr_versioned_key_params {
* Version value to use for key generation.
*/
uint32_t version;
/**
* Coumpund Device Identifier type (sealing or attestation).
*/
dif_keymgr_cdi_type_t cdi_type;
} dif_keymgr_versioned_key_params_t;

/**
Expand Down
57 changes: 52 additions & 5 deletions sw/device/lib/dif/dif_keymgr_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ class DifKeymgrInitialized : public DifKeymgrTest {
struct OperationStartParams {
uint32_t dest_sel;
uint32_t operation;
dif_keymgr_cdi_type_t cdi_type;
};

/**
Expand All @@ -188,6 +189,10 @@ class DifKeymgrInitialized : public DifKeymgrTest {
{
.offset = KEYMGR_CONTROL_SHADOWED_OPERATION_OFFSET,
.value = params.operation,
},
{
.offset = KEYMGR_CONTROL_SHADOWED_CDI_SEL_BIT,
.value = params.cdi_type,
}});

EXPECT_WRITE32(KEYMGR_START_REG_OFFSET, {{
Expand Down Expand Up @@ -607,29 +612,43 @@ TEST_F(GetStateTest, UnexpectedState) {
class GenerateIdentityTest : public DifKeymgrInitialized {};

TEST_F(GenerateIdentityTest, BadArgs) {
EXPECT_DIF_BADARG(dif_keymgr_generate_identity_seed(nullptr));
EXPECT_DIF_BADARG(dif_keymgr_generate_identity_seed(nullptr, {}));
}

TEST_F(GenerateIdentityTest, LockedBusy) {
ExpectBusy();

EXPECT_EQ(dif_keymgr_generate_identity_seed(&keymgr_), kDifLocked);
EXPECT_EQ(dif_keymgr_generate_identity_seed(&keymgr_, {}), kDifLocked);
}

TEST_F(GenerateIdentityTest, LockedConfig) {
ExpectLockedConfig();

EXPECT_EQ(dif_keymgr_generate_identity_seed(&keymgr_), kDifLocked);
EXPECT_EQ(dif_keymgr_generate_identity_seed(&keymgr_, {}), kDifLocked);
}

TEST_F(GenerateIdentityTest, Generate) {
TEST_F(GenerateIdentityTest, GenerateSealing) {
ExpectIdle();
ExpectOperationStart({
.dest_sel = KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_NONE,
.operation = KEYMGR_CONTROL_SHADOWED_OPERATION_VALUE_GENERATE_ID,
.cdi_type = kDifKeymgrSealingCdi,
});

EXPECT_DIF_OK(dif_keymgr_generate_identity_seed(&keymgr_));
EXPECT_DIF_OK(dif_keymgr_generate_identity_seed(
&keymgr_, {.cdi_type = kDifKeymgrSealingCdi}));
}

TEST_F(GenerateIdentityTest, GenerateAttestation) {
ExpectIdle();
ExpectOperationStart({
.dest_sel = KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_NONE,
.operation = KEYMGR_CONTROL_SHADOWED_OPERATION_VALUE_GENERATE_ID,
.cdi_type = kDifKeymgrAttestationCdi,
});

EXPECT_DIF_OK(dif_keymgr_generate_identity_seed(
&keymgr_, {.cdi_type = kDifKeymgrAttestationCdi}));
}

class GenerateVersionedKeyTest : public DifKeymgrInitialized {};
Expand Down Expand Up @@ -667,6 +686,10 @@ struct GenerateVersionedKeyTestCase {
* Expected OPERATION values to be written to the CONTROL register.
*/
uint32_t exp_operation;
/**
* Expected CDI_SEL value to be written to the CONTROL register.
*/
dif_keymgr_cdi_type_t cdi_type;
};

class GenerateVersionedKey
Expand Down Expand Up @@ -702,18 +725,42 @@ INSTANTIATE_TEST_SUITE_P(
.exp_dest_sel = KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_NONE,
.exp_operation =
KEYMGR_CONTROL_SHADOWED_OPERATION_VALUE_GENERATE_SW_OUTPUT,
.cdi_type = kDifKeymgrSealingCdi,
},
GenerateVersionedKeyTestCase{
.dest = kDifKeymgrVersionedKeyDestAes,
.exp_dest_sel = KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_AES,
.exp_operation =
KEYMGR_CONTROL_SHADOWED_OPERATION_VALUE_GENERATE_HW_OUTPUT,
.cdi_type = kDifKeymgrSealingCdi,
},
GenerateVersionedKeyTestCase{
.dest = kDifKeymgrVersionedKeyDestKmac,
.exp_dest_sel = KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_KMAC,
.exp_operation =
KEYMGR_CONTROL_SHADOWED_OPERATION_VALUE_GENERATE_HW_OUTPUT,
.cdi_type = kDifKeymgrSealingCdi,
},
GenerateVersionedKeyTestCase{
.dest = kDifKeymgrVersionedKeyDestSw,
.exp_dest_sel = KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_NONE,
.exp_operation =
KEYMGR_CONTROL_SHADOWED_OPERATION_VALUE_GENERATE_SW_OUTPUT,
.cdi_type = kDifKeymgrAttestationCdi,
},
GenerateVersionedKeyTestCase{
.dest = kDifKeymgrVersionedKeyDestAes,
.exp_dest_sel = KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_AES,
.exp_operation =
KEYMGR_CONTROL_SHADOWED_OPERATION_VALUE_GENERATE_HW_OUTPUT,
.cdi_type = kDifKeymgrAttestationCdi,
},
GenerateVersionedKeyTestCase{
.dest = kDifKeymgrVersionedKeyDestKmac,
.exp_dest_sel = KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_KMAC,
.exp_operation =
KEYMGR_CONTROL_SHADOWED_OPERATION_VALUE_GENERATE_HW_OUTPUT,
.cdi_type = kDifKeymgrAttestationCdi,
}));

class SideloadClearTest : public DifKeymgrInitialized {};
Expand Down
14 changes: 10 additions & 4 deletions sw/device/lib/testing/keymgr_testutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,9 @@ status_t keymgr_initialize_sim_dv(dif_keymgr_t *keymgr, dif_kmac_t *kmac) {
LOG_INFO("Keymgr entered CreatorRootKey State");
// Generate identity at CreatorRootKey (to follow same sequence and reuse
// chip_sw_keymgr_key_derivation_vseq.sv).
TRY(keymgr_testutils_generate_identity(keymgr));
TRY(keymgr_testutils_generate_identity(
keymgr,
(dif_keymgr_identity_seed_params_t){.cdi_type = kDifKeymgrSealingCdi}));
LOG_INFO("Keymgr generated identity at CreatorRootKey State");

// Advance to OwnerIntermediateKey state and check that the state is correct.
Expand Down Expand Up @@ -271,7 +273,9 @@ status_t keymgr_testutils_startup(dif_keymgr_t *keymgr, dif_kmac_t *kmac) {
// Identity generation is not really necessary for all tests, but it is
// added to make sure each test using this function is also compatible with
// the DV_WAIT sequences from keymgr_key_derivation vseq
TRY(keymgr_testutils_generate_identity(keymgr));
TRY(keymgr_testutils_generate_identity(
keymgr,
(dif_keymgr_identity_seed_params_t){.cdi_type = kDifKeymgrSealingCdi}));
LOG_INFO("Keymgr generated identity at CreatorRootKey State");

return OK_STATUS();
Expand All @@ -293,8 +297,10 @@ status_t keymgr_testutils_check_state(const dif_keymgr_t *keymgr,
return OK_STATUS();
}

status_t keymgr_testutils_generate_identity(const dif_keymgr_t *keymgr) {
TRY(dif_keymgr_generate_identity_seed(keymgr));
status_t keymgr_testutils_generate_identity(
const dif_keymgr_t *keymgr,
const dif_keymgr_identity_seed_params_t params) {
TRY(dif_keymgr_generate_identity_seed(keymgr, params));
return keymgr_testutils_wait_for_operation_done(keymgr);
}

Expand Down
3 changes: 2 additions & 1 deletion sw/device/lib/testing/keymgr_testutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,8 @@ status_t keymgr_testutils_check_state(const dif_keymgr_t *keymgr,
* @param keymgr A key manager handle.
*/
OT_WARN_UNUSED_RESULT
status_t keymgr_testutils_generate_identity(const dif_keymgr_t *keymgr);
status_t keymgr_testutils_generate_identity(
const dif_keymgr_t *keymgr, const dif_keymgr_identity_seed_params_t params);

/**
* Issues a keymgr HW/SW versioned key generation and wait for it to complete
Expand Down
6 changes: 4 additions & 2 deletions sw/device/tests/keymgr_key_derivation_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@ bool test_main(void) {
&keymgr, kDifKeymgrStateOwnerIntermediateKey));
LOG_INFO("Keymgr entered OwnerIntKey State");

CHECK_STATUS_OK(keymgr_testutils_generate_identity(&keymgr));
LOG_INFO("Keymgr generated identity at OwnerIntKey State");
CHECK_STATUS_OK(keymgr_testutils_generate_identity(
&keymgr,
(dif_keymgr_identity_seed_params_t){.cdi_type = kDifKeymgrSealingCdi}));
LOG_INFO("Keymgr generated identity at %s State", state_name);

CHECK_STATUS_OK(
keymgr_testutils_generate_versioned_key(&keymgr, kKeyVersionedParams));
Expand Down
4 changes: 3 additions & 1 deletion sw/device/tests/penetrationtests/firmware/sca/ibex_sca.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ status_t handle_ibex_sca_key_sideloading(ujson_t *uj) {

// Generate identity at CreatorRootKey (to follow same sequence and reuse
// chip_sw_keymgr_key_derivation_vseq.sv).
TRY(keymgr_testutils_generate_identity(&keymgr));
TRY(keymgr_testutils_generate_identity(
&keymgr,
(dif_keymgr_identity_seed_params_t){.cdi_type = kDifKeymgrSealingCdi}));

// Advance to OwnerIntermediateKey state.
TRY(keymgr_testutils_advance_state(&keymgr, &kOwnerIntParams));
Expand Down

0 comments on commit ed9a230

Please sign in to comment.