Skip to content

Commit

Permalink
[sw/silicon_creator] enable OTBN boot services to gen TPM keys
Browse files Browse the repository at this point in the history
This refactors the OTBN boot services library, and silicon_creator
keymgr driver to enable generating two types attestation keys:
1. DICE keys, that are based on the attestation side of the key ladder,
   and
2. TPM keys, that are based on the sealing side of the key ladder.

This fixes #22622.

Signed-off-by: Tim Trippel <[email protected]>
(cherry picked from commit 641d4e0)
  • Loading branch information
timothytrippel committed May 4, 2024
1 parent bd7451a commit 6c45e24
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 40 deletions.
15 changes: 10 additions & 5 deletions sw/device/silicon_creator/lib/dice.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,15 @@ static void curr_pubkey_le_to_be_convert(attestation_public_key_t *pubkey) {
* generated public key is saved at pubkey.
*/
static rom_error_t common_attestation_keygen(
otbn_boot_attestation_key_type_t key_type,
const keymgr_diversification_t *diversifier, attestation_key_seed_t seed,
keymgr_state_t desired_keymgr_state, hmac_digest_t *pubkey_id,
attestation_public_key_t *pubkey) {
HARDENED_RETURN_IF_ERROR(keymgr_state_check(desired_keymgr_state));

// Generate / sideload key material into OTBN, and generate the ECC keypair.
HARDENED_RETURN_IF_ERROR(
otbn_boot_attestation_keygen(seed, *diversifier, pubkey));
otbn_boot_attestation_keygen(seed, key_type, *diversifier, pubkey));

// Keys are represented in certificates in big endian format, but the key is
// output from OTBN in little endian format, so we convert the key to
Expand Down Expand Up @@ -149,7 +150,8 @@ rom_error_t dice_attestation_keygen(dice_key_t desired_key,
default:
return kErrorDiceInvalidArgument;
};
return common_attestation_keygen(keymgr_diversifier, otbn_ecc_keygen_seed,
return common_attestation_keygen(kOtbnBootAttestationKeyTypeDice,
keymgr_diversifier, otbn_ecc_keygen_seed,
desired_state, pubkey_id, pubkey);
}

Expand Down Expand Up @@ -177,7 +179,8 @@ rom_error_t tpm_cert_keygen(tpm_key_t desired_key, hmac_digest_t *pubkey_id,
default:
return kErrorDiceInvalidArgument;
};
return common_attestation_keygen(keymgr_diversifier, otbn_ecc_keygen_seed,
return common_attestation_keygen(kOtbnBootAttestationKeyTypeTpm,
keymgr_diversifier, otbn_ecc_keygen_seed,
kKeymgrStateOwnerKey, pubkey_id, pubkey);
}

Expand Down Expand Up @@ -291,7 +294,8 @@ rom_error_t dice_cdi_0_cert_build(hmac_digest_t *rom_ext_measurement,

// Save the CDI_0 private key to OTBN DMEM so it can endorse the next stage.
HARDENED_RETURN_IF_ERROR(otbn_boot_attestation_key_save(
kCdi0AttestationKeySeed, kCdi0KeymgrDiversifier));
kCdi0AttestationKeySeed, kOtbnBootAttestationKeyTypeDice,
kCdi0KeymgrDiversifier));

return kErrorOk;
}
Expand Down Expand Up @@ -339,7 +343,8 @@ rom_error_t dice_cdi_1_cert_build(hmac_digest_t *owner_measurement,

// Save the CDI_1 private key to OTBN DMEM so it can endorse the next stage.
HARDENED_RETURN_IF_ERROR(otbn_boot_attestation_key_save(
kCdi1AttestationKeySeed, kCdi1KeymgrDiversifier));
kCdi1AttestationKeySeed, kOtbnBootAttestationKeyTypeDice,
kCdi1KeymgrDiversifier));

return kErrorOk;
}
Expand Down
16 changes: 10 additions & 6 deletions sw/device/silicon_creator/lib/drivers/keymgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,17 +201,21 @@ static rom_error_t keymgr_wait_until_done(void) {
return kErrorKeymgrInternal;
}

rom_error_t keymgr_generate_attestation_key_otbn(
keymgr_diversification_t diversification) {
rom_error_t keymgr_generate_key_otbn(keymgr_key_type_t key_type,
keymgr_diversification_t diversification) {
HARDENED_RETURN_IF_ERROR(keymgr_is_idle());

uint32_t ctrl = 0;

// Select OTBN as the destination.
uint32_t ctrl =
bitfield_field32_write(0, KEYMGR_CONTROL_SHADOWED_DEST_SEL_FIELD,
KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_OTBN);
ctrl = bitfield_field32_write(0, KEYMGR_CONTROL_SHADOWED_DEST_SEL_FIELD,
KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_OTBN);

// Select the attestation CDI.
ctrl = bitfield_bit32_write(ctrl, KEYMGR_CONTROL_SHADOWED_CDI_SEL_BIT, true);
if (key_type == kKeymgrKeyTypeAttestation) {
ctrl =
bitfield_bit32_write(ctrl, KEYMGR_CONTROL_SHADOWED_CDI_SEL_BIT, true);
}

// Select the "generate" operation.
ctrl = bitfield_field32_write(
Expand Down
19 changes: 14 additions & 5 deletions sw/device/silicon_creator/lib/drivers/keymgr.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,18 +184,27 @@ OT_WARN_UNUSED_RESULT
rom_error_t keymgr_state_check(keymgr_state_t expected_state);

/**
* Derive a key manager key for the OTBN block.
* Keymgr output-generate key types (attestation or sealing).
*/
typedef enum keymgr_key_type {
kKeymgrKeyTypeAttestation = 0,
kKeymgrKeyTypeSealing = 1,
} keymgr_key_type_t;

/**
* Generate a key manager key and sideload to the OTBN block.
*
* Calls the key manager to sideload a key into the OTBN hardware block and
* waits until the operation is complete before returning. Always uses the
* attestation (not sealing) CDI; call this only for attestation keys.
* waits until the operation is complete before returning. Can sideload an
* attestation or sealing key based on user input.
*
* @param key_type Key type: attestation or sealing.
* @param diversification Diversification input for the key derivation.
* @return OK or error.
*/
OT_WARN_UNUSED_RESULT
rom_error_t keymgr_generate_attestation_key_otbn(
const keymgr_diversification_t diversification);
rom_error_t keymgr_generate_key_otbn(keymgr_key_type_t key_type,
keymgr_diversification_t diversification);

/**
* Clear OTBN's sideloaded key slot.
Expand Down
61 changes: 48 additions & 13 deletions sw/device/silicon_creator/lib/drivers/keymgr_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ TEST_F(KeymgrTest, CheckStateInvalidResponse) {
kErrorKeymgrInternal);
}

TEST_F(KeymgrTest, GenAttestationKey) {
TEST_F(KeymgrTest, GenOtbnAttestationKey) {
keymgr_diversification_t test_diversification = {
.salt = {0xf0f1f2f3, 0xf4f5f6f7, 0xf8f9fafb, 0xfcfdfeff, 0xd0d1d2d3,
0xd4d5d6d7, 0xd8d9dadb, 0xdcdddedf},
Expand All @@ -236,29 +236,63 @@ TEST_F(KeymgrTest, GenAttestationKey) {
ExpectWaitUntilDone(/*busy_cycles=*/2,
KEYMGR_OP_STATUS_STATUS_VALUE_DONE_SUCCESS);

EXPECT_EQ(keymgr_generate_attestation_key_otbn(test_diversification),
kErrorOk);
EXPECT_EQ(
keymgr_generate_key_otbn(kKeymgrKeyTypeAttestation, test_diversification),
kErrorOk);
}

TEST_F(KeymgrTest, GenOtbnSealingKey) {
keymgr_diversification_t test_diversification = {
.salt = {0xf0f1f2f3, 0xf4f5f6f7, 0xf8f9fafb, 0xfcfdfeff, 0xd0d1d2d3,
0xd4d5d6d7, 0xd8d9dadb, 0xdcdddedf},
.version = cfg_.max_key_ver - 1,
};

ExpectIdleCheck(KEYMGR_OP_STATUS_STATUS_VALUE_IDLE);
EXPECT_ABS_WRITE32_SHADOWED(
base_ + KEYMGR_CONTROL_SHADOWED_REG_OFFSET,
{
{KEYMGR_CONTROL_SHADOWED_DEST_SEL_OFFSET,
KEYMGR_CONTROL_SHADOWED_DEST_SEL_VALUE_OTBN},
{KEYMGR_CONTROL_SHADOWED_CDI_SEL_BIT, false},
{KEYMGR_CONTROL_SHADOWED_OPERATION_OFFSET,
KEYMGR_CONTROL_SHADOWED_OPERATION_VALUE_GENERATE_HW_OUTPUT},
});
ExpectDiversificationWrite(test_diversification);
EXPECT_ABS_WRITE32(base_ + KEYMGR_START_REG_OFFSET,
{
{KEYMGR_START_EN_BIT, true},
});
ExpectWaitUntilDone(/*busy_cycles=*/2,
KEYMGR_OP_STATUS_STATUS_VALUE_DONE_SUCCESS);

EXPECT_EQ(
keymgr_generate_key_otbn(kKeymgrKeyTypeSealing, test_diversification),
kErrorOk);
}

TEST_F(KeymgrTest, GenAttestationKeyNotIdle) {
TEST_F(KeymgrTest, GenOtbnKeyNotIdle) {
keymgr_diversification_t test_diversification = {
.salt = {0xf0f1f2f3, 0xf4f5f6f7, 0xf8f9fafb, 0xfcfdfeff, 0xd0d1d2d3,
0xd4d5d6d7, 0xd8d9dadb, 0xdcdddedf},
.version = cfg_.max_key_ver - 1,
};

ExpectIdleCheck(KEYMGR_OP_STATUS_STATUS_VALUE_WIP);
EXPECT_EQ(keymgr_generate_attestation_key_otbn(test_diversification),
kErrorKeymgrInternal);
EXPECT_EQ(
keymgr_generate_key_otbn(kKeymgrKeyTypeAttestation, test_diversification),
kErrorKeymgrInternal);
ExpectIdleCheck(KEYMGR_OP_STATUS_STATUS_VALUE_DONE_ERROR);
EXPECT_EQ(keymgr_generate_attestation_key_otbn(test_diversification),
kErrorKeymgrInternal);
EXPECT_EQ(
keymgr_generate_key_otbn(kKeymgrKeyTypeAttestation, test_diversification),
kErrorKeymgrInternal);
ExpectIdleCheck(KEYMGR_OP_STATUS_STATUS_VALUE_DONE_SUCCESS);
EXPECT_EQ(keymgr_generate_attestation_key_otbn(test_diversification),
kErrorKeymgrInternal);
EXPECT_EQ(
keymgr_generate_key_otbn(kKeymgrKeyTypeAttestation, test_diversification),
kErrorKeymgrInternal);
}

TEST_F(KeymgrTest, GenAttestationKeyError) {
TEST_F(KeymgrTest, GenOtbnKeyError) {
keymgr_diversification_t test_diversification = {
.salt = {0xf0f1f2f3, 0xf4f5f6f7, 0xf8f9fafb, 0xfcfdfeff, 0xd0d1d2d3,
0xd4d5d6d7, 0xd8d9dadb, 0xdcdddedf},
Expand Down Expand Up @@ -286,8 +320,9 @@ TEST_F(KeymgrTest, GenAttestationKeyError) {
EXPECT_ABS_READ32(base_ + KEYMGR_ERR_CODE_REG_OFFSET, err_code);
EXPECT_ABS_WRITE32(base_ + KEYMGR_ERR_CODE_REG_OFFSET, err_code);

EXPECT_EQ(keymgr_generate_attestation_key_otbn(test_diversification),
kErrorKeymgrInternal);
EXPECT_EQ(
keymgr_generate_key_otbn(kKeymgrKeyTypeAttestation, test_diversification),
kErrorKeymgrInternal);
}

TEST_F(KeymgrTest, SideloadClearOtbn) {
Expand Down
6 changes: 4 additions & 2 deletions sw/device/silicon_creator/lib/otbn_boot_services.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,12 @@ rom_error_t otbn_boot_app_load(void) { return otbn_load_app(kOtbnAppBoot); }

rom_error_t otbn_boot_attestation_keygen(
attestation_key_seed_t additional_seed,
otbn_boot_attestation_key_type_t key_type,
keymgr_diversification_t diversification,
attestation_public_key_t *public_key) {
// Trigger key manager to sideload the attestation key into OTBN.
HARDENED_RETURN_IF_ERROR(
keymgr_generate_attestation_key_otbn(diversification));
keymgr_generate_key_otbn((keymgr_key_type_t)key_type, diversification));

// Write the mode.
uint32_t mode = kOtbnBootModeAttestationKeygen;
Expand Down Expand Up @@ -172,10 +173,11 @@ rom_error_t otbn_boot_attestation_keygen(

rom_error_t otbn_boot_attestation_key_save(
attestation_key_seed_t additional_seed,
otbn_boot_attestation_key_type_t key_type,
keymgr_diversification_t diversification) {
// Trigger key manager to sideload the attestation key into OTBN.
HARDENED_RETURN_IF_ERROR(
keymgr_generate_attestation_key_otbn(diversification));
keymgr_generate_key_otbn((keymgr_key_type_t)key_type, diversification));

// Write the mode.
uint32_t mode = kOtbnBootModeAttestationKeySave;
Expand Down
16 changes: 16 additions & 0 deletions sw/device/silicon_creator/lib/otbn_boot_services.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ extern "C" {
OT_WARN_UNUSED_RESULT
rom_error_t otbn_boot_app_load(void);

/**
* OTBN attestation key types (DICE or TPM).
*/
typedef enum otbn_boot_attestation_key_type {
kOtbnBootAttestationKeyTypeDice = kKeymgrKeyTypeAttestation,
kOtbnBootAttestationKeyTypeTpm = kKeymgrKeyTypeSealing,
} otbn_boot_attestation_key_type_t;

/**
* Generate an attestation public key from a keymgr-derived secret.
*
Expand All @@ -47,13 +55,17 @@ rom_error_t otbn_boot_app_load(void);
* `otbn_boot_app_load`.
*
* @param additional_seed The attestation key generation seed to load.
* @param key_type OTBN attestation key type to generate. "DICE" attestation
* keys are based on "attestation" keys from the keymgr; "TPM"
* attestation keys are based on "sealing keys from the keymgr.
* @param diversification Salt and version information for key manager.
* @param[out] public_key Attestation public key.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
rom_error_t otbn_boot_attestation_keygen(
attestation_key_seed_t additional_seed,
otbn_boot_attestation_key_type_t key_type,
keymgr_diversification_t diversification,
attestation_public_key_t *public_key);

Expand All @@ -68,12 +80,16 @@ rom_error_t otbn_boot_attestation_keygen(
* `otbn_boot_app_load`.
*
* @param additional_seed The attestation key generation seed to load.
* @param key_type OTBN attestation key type to generate. "DICE" attestation
* keys are based on "attestation" keys from the keymgr; "TPM"
* attestation keys are based on "sealing keys from the keymgr.
* @param diversification Salt and version information for key manager.
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
rom_error_t otbn_boot_attestation_key_save(
attestation_key_seed_t additional_seed,
otbn_boot_attestation_key_type_t key_type,
keymgr_diversification_t diversification);

/**
Expand Down
31 changes: 23 additions & 8 deletions sw/device/silicon_creator/lib/otbn_boot_services_functest.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,24 +159,34 @@ rom_error_t attestation_keygen_test(void) {
// Check that key generations with different seeds result in different keys.
attestation_public_key_t pk_uds;
RETURN_IF_ERROR(otbn_boot_attestation_keygen(kUdsAttestationKeySeed,
kOtbnBootAttestationKeyTypeDice,
kDiversification, &pk_uds));
attestation_public_key_t pk_cdi0;
RETURN_IF_ERROR(otbn_boot_attestation_keygen(kCdi0AttestationKeySeed,
kOtbnBootAttestationKeyTypeDice,
kDiversification, &pk_cdi0));
attestation_public_key_t pk_cdi1;
RETURN_IF_ERROR(otbn_boot_attestation_keygen(kCdi1AttestationKeySeed,
kOtbnBootAttestationKeyTypeDice,
kDiversification, &pk_cdi1));
attestation_public_key_t pk_tpm_ek;
RETURN_IF_ERROR(otbn_boot_attestation_keygen(kTpmEkAttestationKeySeed,
kOtbnBootAttestationKeyTypeTpm,
kDiversification, &pk_tpm_ek));
CHECK_ARRAYS_NE((unsigned char *)&pk_uds, (unsigned char *)&pk_cdi0,
sizeof(pk_uds));
CHECK_ARRAYS_NE((unsigned char *)&pk_uds, (unsigned char *)&pk_cdi1,
sizeof(pk_uds));
CHECK_ARRAYS_NE((unsigned char *)&pk_cdi0, (unsigned char *)&pk_cdi1,
sizeof(pk_uds));
CHECK_ARRAYS_NE((unsigned char *)&pk_tpm_ek, (unsigned char *)&pk_cdi1,
sizeof(pk_uds));

// Check that running the same key generation twice results in the same key.
attestation_public_key_t pk_uds_again;
RETURN_IF_ERROR(otbn_boot_attestation_keygen(
kUdsAttestationKeySeed, kDiversification, &pk_uds_again));
kUdsAttestationKeySeed, kOtbnBootAttestationKeyTypeDice, kDiversification,
&pk_uds_again));
CHECK_ARRAYS_EQ((unsigned char *)&pk_uds_again, (unsigned char *)&pk_uds,
sizeof(pk_uds));

Expand All @@ -188,7 +198,8 @@ rom_error_t attestation_keygen_test(void) {
diversification_modified.salt[0] ^= 1;
attestation_public_key_t pk_uds_div;
RETURN_IF_ERROR(otbn_boot_attestation_keygen(
kUdsAttestationKeySeed, diversification_modified, &pk_uds_div));
kUdsAttestationKeySeed, kOtbnBootAttestationKeyTypeDice,
diversification_modified, &pk_uds_div));
CHECK_ARRAYS_NE((unsigned char *)&pk_uds_div, (unsigned char *)&pk_uds,
sizeof(pk_uds));
return kErrorOk;
Expand All @@ -198,9 +209,11 @@ rom_error_t attestation_advance_and_endorse_test(void) {
// Generate and save the a keypair.
attestation_public_key_t pk;
RETURN_IF_ERROR(otbn_boot_attestation_keygen(kUdsAttestationKeySeed,
kOtbnBootAttestationKeyTypeDice,
kDiversification, &pk));
RETURN_IF_ERROR(
otbn_boot_attestation_key_save(kUdsAttestationKeySeed, kDiversification));
RETURN_IF_ERROR(otbn_boot_attestation_key_save(
kUdsAttestationKeySeed, kOtbnBootAttestationKeyTypeDice,
kDiversification));

// Advance keymgr to the next stage.
CHECK_STATUS_OK(
Expand Down Expand Up @@ -246,13 +259,15 @@ rom_error_t attestation_advance_and_endorse_test(void) {
// N.B. This test will lock OTBN, so it needs to be the last test that runs.
rom_error_t attestation_save_clear_key_test(void) {
// Save and then clear a private key.
RETURN_IF_ERROR(
otbn_boot_attestation_key_save(kUdsAttestationKeySeed, kDiversification));
RETURN_IF_ERROR(otbn_boot_attestation_key_save(
kUdsAttestationKeySeed, kOtbnBootAttestationKeyTypeDice,
kDiversification));
RETURN_IF_ERROR(otbn_boot_attestation_key_clear());

// Save the private key again and check that endorsing succeeds.
RETURN_IF_ERROR(
otbn_boot_attestation_key_save(kUdsAttestationKeySeed, kDiversification));
RETURN_IF_ERROR(otbn_boot_attestation_key_save(
kUdsAttestationKeySeed, kOtbnBootAttestationKeyTypeDice,
kDiversification));
hmac_digest_t digest;
hmac_sha256(kEndorseTestMessage, kEndorseTestMessageLen, &digest);
attestation_signature_t sig;
Expand Down
3 changes: 2 additions & 1 deletion sw/device/silicon_creator/rom_ext/rom_ext.c
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,8 @@ static rom_error_t rom_ext_attestation_keygen(
HARDENED_RETURN_IF_ERROR(dice_attestation_keygen(kDiceKeyUds, &uds_pubkey_id,
&curr_attestation_pubkey));
HARDENED_RETURN_IF_ERROR(otbn_boot_attestation_key_save(
kUdsAttestationKeySeed, kUdsKeymgrDiversifier));
kUdsAttestationKeySeed, kOtbnBootAttestationKeyTypeDice,
kUdsKeymgrDiversifier));
// TODO(#22921): fix cert updating check and re-enable checks below.
curr_cert_valid = kHardenedBoolTrue;
/*HARDENED_RETURN_IF_ERROR(cert_x509_asn1_check_serial_number(*/
Expand Down

0 comments on commit 6c45e24

Please sign in to comment.