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 lowRISC#22622.

Signed-off-by: Tim Trippel <[email protected]>
  • Loading branch information
timothytrippel committed Apr 25, 2024
1 parent b938dde commit bda5118
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 36 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 @@ -103,14 +103,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 sc_keymgr_diversification_t *diversifier, attestation_key_seed_t seed,
sc_keymgr_state_t desired_keymgr_state, hmac_digest_t *pubkey_id,
attestation_public_key_t *pubkey) {
HARDENED_RETURN_IF_ERROR(sc_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 @@ -152,7 +153,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 @@ -180,7 +182,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,
kScKeymgrStateOwnerKey, pubkey_id, pubkey);
}

Expand Down Expand Up @@ -311,7 +314,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 @@ -359,7 +363,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
15 changes: 10 additions & 5 deletions sw/device/silicon_creator/lib/drivers/keymgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,17 +203,22 @@ static rom_error_t keymgr_wait_until_done(void) {
return kErrorKeymgrInternal;
}

rom_error_t sc_keymgr_generate_attestation_key_otbn(
rom_error_t sc_keymgr_generate_key_otbn(
sc_keymgr_key_type_t key_type,
sc_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 == kScKeymgrKeyTypeAttestation) {
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 sc_keymgr_state_check(sc_keymgr_state_t expected_state);

/**
* Derive a key manager key for the OTBN block.
* Keymgr output-generate key types (attestation or sealing).
*/
typedef enum sc_keymgr_key_type {
kScKeymgrKeyTypeAttestation = 0,
kScKeymgrKeyTypeSealing = 1,
} sc_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 sc_keymgr_generate_attestation_key_otbn(
const sc_keymgr_diversification_t diversification);
rom_error_t sc_keymgr_generate_key_otbn(
sc_keymgr_key_type_t key_type, sc_keymgr_diversification_t diversification);

/**
* Clear OTBN's sideloaded key slot.
Expand Down
51 changes: 43 additions & 8 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) {
sc_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(sc_keymgr_generate_attestation_key_otbn(test_diversification),
EXPECT_EQ(sc_keymgr_generate_key_otbn(kScKeymgrKeyTypeAttestation,
test_diversification),
kErrorOk);
}

TEST_F(KeymgrTest, GenAttestationKeyNotIdle) {
TEST_F(KeymgrTest, GenOtbnSealingKey) {
sc_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(sc_keymgr_generate_key_otbn(kScKeymgrKeyTypeSealing,
test_diversification),
kErrorOk);
}

TEST_F(KeymgrTest, GenOtbnKeyNotIdle) {
sc_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(sc_keymgr_generate_attestation_key_otbn(test_diversification),
EXPECT_EQ(sc_keymgr_generate_key_otbn(kScKeymgrKeyTypeAttestation,
test_diversification),
kErrorKeymgrInternal);
ExpectIdleCheck(KEYMGR_OP_STATUS_STATUS_VALUE_DONE_ERROR);
EXPECT_EQ(sc_keymgr_generate_attestation_key_otbn(test_diversification),
EXPECT_EQ(sc_keymgr_generate_key_otbn(kScKeymgrKeyTypeAttestation,
test_diversification),
kErrorKeymgrInternal);
ExpectIdleCheck(KEYMGR_OP_STATUS_STATUS_VALUE_DONE_SUCCESS);
EXPECT_EQ(sc_keymgr_generate_attestation_key_otbn(test_diversification),
EXPECT_EQ(sc_keymgr_generate_key_otbn(kScKeymgrKeyTypeAttestation,
test_diversification),
kErrorKeymgrInternal);
}

TEST_F(KeymgrTest, GenAttestationKeyError) {
TEST_F(KeymgrTest, GenOtbnKeyError) {
sc_keymgr_diversification_t test_diversification = {
.salt = {0xf0f1f2f3, 0xf4f5f6f7, 0xf8f9fafb, 0xfcfdfeff, 0xd0d1d2d3,
0xd4d5d6d7, 0xd8d9dadb, 0xdcdddedf},
Expand Down Expand Up @@ -286,7 +320,8 @@ 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(sc_keymgr_generate_attestation_key_otbn(test_diversification),
EXPECT_EQ(sc_keymgr_generate_key_otbn(kScKeymgrKeyTypeAttestation,
test_diversification),
kErrorKeymgrInternal);
}

Expand Down
10 changes: 6 additions & 4 deletions sw/device/silicon_creator/lib/otbn_boot_services.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,11 +125,12 @@ rom_error_t otbn_boot_app_load(void) { return sc_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,
sc_keymgr_diversification_t diversification,
attestation_public_key_t *public_key) {
// Trigger key manager to sideload the attestation key into OTBN.
HARDENED_RETURN_IF_ERROR(
sc_keymgr_generate_attestation_key_otbn(diversification));
HARDENED_RETURN_IF_ERROR(sc_keymgr_generate_key_otbn(
(sc_keymgr_key_type_t)key_type, diversification));

// Write the mode.
uint32_t mode = kOtbnBootModeAttestationKeygen;
Expand Down Expand Up @@ -168,10 +169,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,
sc_keymgr_diversification_t diversification) {
// Trigger key manager to sideload the attestation key into OTBN.
HARDENED_RETURN_IF_ERROR(
sc_keymgr_generate_attestation_key_otbn(diversification));
HARDENED_RETURN_IF_ERROR(sc_keymgr_generate_key_otbn(
(sc_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 = kScKeymgrKeyTypeAttestation,
kOtbnBootAttestationKeyTypeTpm = kScKeymgrKeyTypeSealing,
} 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,
sc_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,
sc_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 @@ -74,24 +74,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 @@ -103,7 +113,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 @@ -113,9 +124,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 @@ -147,13 +160,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(kTestMessage, kTestMessageLen, &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 @@ -286,7 +286,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));
curr_cert_valid = kHardenedBoolFalse;
HARDENED_RETURN_IF_ERROR(cert_x509_asn1_check_serial_number(
&kFlashCtrlInfoPageUdsCertificate, uds_pubkey_id.digest,
Expand Down

0 comments on commit bda5118

Please sign in to comment.