Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[silicon_creator] refactor OTBN boot services to enable generating TPM or DICE keys #22810

Merged
merged 3 commits into from
Apr 30, 2024
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
27 changes: 11 additions & 16 deletions sw/device/silicon_creator/lib/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,12 @@ cc_test(
opentitan_test(
name = "boot_data_functest",
srcs = ["boot_data_functest.c"],
broken = cw310_params(tags = ["broken"]),
exec_env = dicts.add(
EARLGREY_TEST_ENVS,
{
# FIXME broken in sival ROM_EXT, remove this line when fixed. See #21706.
"//hw/top_earlgrey:fpga_cw310_sival_rom_ext": "broken",
},
),
exec_env = {
"//hw/top_earlgrey:fpga_cw310_rom_with_fake_keys": None,
"//hw/top_earlgrey:fpga_cw310_sival": None,
"//hw/top_earlgrey:sim_dv": None,
"//hw/top_earlgrey:sim_verilator": None,
},
verilator = verilator_params(
timeout = "eternal",
tags = ["flaky"],
Expand Down Expand Up @@ -491,14 +489,11 @@ cc_library(
opentitan_test(
name = "otbn_boot_services_functest",
srcs = ["otbn_boot_services_functest.c"],
broken = cw310_params(tags = ["broken"]),
exec_env = dicts.add(
EARLGREY_TEST_ENVS,
{
# FIXME broken in sival ROM_EXT, remove this line when fixed. See #21706.
"//hw/top_earlgrey:fpga_cw310_sival_rom_ext": "broken",
},
),
exec_env = {
"//hw/top_earlgrey:fpga_cw310_sival": None,
"//hw/top_earlgrey:sim_dv": None,
"//hw/top_earlgrey:sim_verilator": None,
},
# This target uses OTBN pointers internally, so it cannot work host-side.
deps = [
":otbn_boot_services",
Expand Down
109 changes: 47 additions & 62 deletions sw/device/silicon_creator/lib/dice.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,90 +98,70 @@ static void curr_pubkey_le_to_be_convert(attestation_public_key_t *pubkey) {
le_be_buf_format((unsigned char *)pubkey->y, kAttestationPublicKeyCoordBytes);
}

/**
* Function generating a DICE or TPM certificate key pair. If successful, the
* generated public key is saved at pubkey.
*/
static rom_error_t common_attestation_keygen(
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));

// 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
// big endian format.
curr_pubkey_le_to_be_convert(pubkey);

// Generate the key ID.
hmac_sha256(pubkey, kAttestationPublicKeyCoordBytes * 2, pubkey_id);

return kErrorOk;
}

/**
* Function preparing parameters for generating DICE attestation keys.
*/
rom_error_t dice_attestation_keygen(dice_key_t desired_key,
hmac_digest_t *pubkey_id,
attestation_public_key_t *pubkey) {
otbn_boot_attestation_key_type_t key_type;
attestation_key_seed_t otbn_ecc_keygen_seed;
const sc_keymgr_diversification_t *keymgr_diversifier;
sc_keymgr_state_t desired_state;
sc_keymgr_state_t desired_keymgr_state;

switch (desired_key) {
case kDiceKeyUds:
desired_state = kScKeymgrStateCreatorRootKey;
desired_keymgr_state = kScKeymgrStateCreatorRootKey;
key_type = kOtbnBootAttestationKeyTypeDice;
keymgr_diversifier = &kUdsKeymgrDiversifier;
otbn_ecc_keygen_seed = kUdsAttestationKeySeed;
break;
case kDiceKeyCdi0:
desired_state = kScKeymgrStateOwnerIntermediateKey;
desired_keymgr_state = kScKeymgrStateOwnerIntermediateKey;
key_type = kOtbnBootAttestationKeyTypeDice;
keymgr_diversifier = &kCdi0KeymgrDiversifier;
otbn_ecc_keygen_seed = kCdi0AttestationKeySeed;
break;
case kDiceKeyCdi1:
desired_state = kScKeymgrStateOwnerKey;
desired_keymgr_state = kScKeymgrStateOwnerKey;
key_type = kOtbnBootAttestationKeyTypeDice;
keymgr_diversifier = &kCdi1KeymgrDiversifier;
otbn_ecc_keygen_seed = kCdi1AttestationKeySeed;
break;
default:
return kErrorDiceInvalidArgument;
};
return common_attestation_keygen(keymgr_diversifier, otbn_ecc_keygen_seed,
desired_state, pubkey_id, pubkey);
}

/**
* Function preparing parameters for generating TPM keys.
*/
rom_error_t tpm_cert_keygen(tpm_key_t desired_key, hmac_digest_t *pubkey_id,
attestation_public_key_t *pubkey) {
attestation_key_seed_t otbn_ecc_keygen_seed;
const sc_keymgr_diversification_t *keymgr_diversifier;

switch (desired_key) {
case kTpmKeyEk:
case kDiceKeyTpmEk:
desired_keymgr_state = kScKeymgrStateOwnerKey;
key_type = kOtbnBootAttestationKeyTypeTpm;
keymgr_diversifier = &kTpmEkKeymgrDiversifier;
otbn_ecc_keygen_seed = kTpmEkAttestationKeySeed;
break;
case kTpmKeyCek:
case kDiceKeyTpmCek:
desired_keymgr_state = kScKeymgrStateOwnerKey;
key_type = kOtbnBootAttestationKeyTypeTpm;
keymgr_diversifier = &kTpmCekKeymgrDiversifier;
otbn_ecc_keygen_seed = kTpmCekAttestationKeySeed;
break;
case kTpmKeyCik:
case kDiceKeyTpmCik:
desired_keymgr_state = kScKeymgrStateOwnerKey;
key_type = kOtbnBootAttestationKeyTypeTpm;
keymgr_diversifier = &kTpmCikKeymgrDiversifier;
otbn_ecc_keygen_seed = kTpmCikAttestationKeySeed;
break;
default:
return kErrorDiceInvalidArgument;
return kErrorDiceInvalidKeyType;
};
return common_attestation_keygen(keymgr_diversifier, otbn_ecc_keygen_seed,
kScKeymgrStateOwnerKey, pubkey_id, 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(
otbn_ecc_keygen_seed, key_type, *keymgr_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
// big endian format.
curr_pubkey_le_to_be_convert(pubkey);

// Generate the key ID.
hmac_sha256(pubkey, kAttestationPublicKeyCoordBytes * 2, pubkey_id);

return kErrorOk;
}

/**
Expand Down Expand Up @@ -311,7 +291,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,14 +340,16 @@ 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;
}

rom_error_t dice_tpm_ek_cert_build(manuf_certgen_inputs_t *inputs,
attestation_public_key_t *tpm_ek_pubkey,
hmac_digest_t *digest, uint8_t *tpm_ek_tbs,
hmac_digest_t *pubkey_id,
uint8_t *tpm_ek_tbs,
size_t *tpm_ek_tbs_size) {
tpm_ek_tbs_values_t tpm_ek_tbs_params = {
.auth_key_key_id = inputs->auth_key_key_id,
Expand All @@ -375,7 +358,7 @@ rom_error_t dice_tpm_ek_cert_build(manuf_certgen_inputs_t *inputs,
.tpm_ek_pub_key_ec_x_size = kAttestationPublicKeyCoordBytes,
.tpm_ek_pub_key_ec_y = (unsigned char *)tpm_ek_pubkey->y,
.tpm_ek_pub_key_ec_y_size = kAttestationPublicKeyCoordBytes,
.tpm_ek_pub_key_id = (unsigned char *)digest->digest, // Nobody cares.
.tpm_ek_pub_key_id = (unsigned char *)pubkey_id->digest,
.tpm_ek_pub_key_id_size = kDiceCertKeyIdSizeInBytes,
.tpm_version = "0.0.1",
.tpm_version_len = 5,
Expand All @@ -393,7 +376,8 @@ rom_error_t dice_tpm_ek_cert_build(manuf_certgen_inputs_t *inputs,

rom_error_t dice_tpm_cek_cert_build(manuf_certgen_inputs_t *inputs,
attestation_public_key_t *tpm_cek_pubkey,
hmac_digest_t *digest, uint8_t *tpm_cek_tbs,
hmac_digest_t *pubkey_id,
uint8_t *tpm_cek_tbs,
size_t *tpm_cek_tbs_size) {
tpm_cek_tbs_values_t tpm_cek_tbs_params = {
.auth_key_key_id = inputs->auth_key_key_id,
Expand All @@ -402,7 +386,7 @@ rom_error_t dice_tpm_cek_cert_build(manuf_certgen_inputs_t *inputs,
.tpm_cek_pub_key_ec_x_size = kAttestationPublicKeyCoordBytes,
.tpm_cek_pub_key_ec_y = (unsigned char *)tpm_cek_pubkey->y,
.tpm_cek_pub_key_ec_y_size = kAttestationPublicKeyCoordBytes,
.tpm_cek_pub_key_id = (unsigned char *)digest->digest,
.tpm_cek_pub_key_id = (unsigned char *)pubkey_id->digest,
.tpm_cek_pub_key_id_size = kDiceCertKeyIdSizeInBytes,
};

Expand All @@ -414,7 +398,8 @@ rom_error_t dice_tpm_cek_cert_build(manuf_certgen_inputs_t *inputs,

rom_error_t dice_tpm_cik_cert_build(manuf_certgen_inputs_t *inputs,
attestation_public_key_t *tpm_cik_pubkey,
hmac_digest_t *digest, uint8_t *tpm_cik_tbs,
hmac_digest_t *pubkey_id,
uint8_t *tpm_cik_tbs,
size_t *tpm_cik_tbs_size) {
tpm_cik_tbs_values_t tpm_cik_tbs_params = {
.auth_key_key_id = inputs->auth_key_key_id,
Expand All @@ -423,7 +408,7 @@ rom_error_t dice_tpm_cik_cert_build(manuf_certgen_inputs_t *inputs,
.tpm_cik_pub_key_ec_x_size = kAttestationPublicKeyCoordBytes,
.tpm_cik_pub_key_ec_y = (unsigned char *)tpm_cik_pubkey->y,
.tpm_cik_pub_key_ec_y_size = kAttestationPublicKeyCoordBytes,
.tpm_cik_pub_key_id = (unsigned char *)digest->digest,
.tpm_cik_pub_key_id = (unsigned char *)pubkey_id->digest,
.tpm_cik_pub_key_id_size = kDiceCertKeyIdSizeInBytes,
};

Expand Down
50 changes: 24 additions & 26 deletions sw/device/silicon_creator/lib/dice.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,33 @@ enum {
};

/**
* Supported DICE attestation keys.
* Supported DICE/TPM attestation keys.
*/
typedef enum dice_key {
/**
* DICE UDS key.
*/
kDiceKeyUds = 0,
/**
* DICE CDI0 key.
*/
kDiceKeyCdi0 = 1,
/**
* DICE CDI1 key.
*/
kDiceKeyCdi1 = 2,
/**
* TPM EK key.
*/
kDiceKeyTpmEk = 3,
/**
* TPM CEK key.
*/
kDiceKeyTpmCek = 4,
/**
* TPM CIK key.
*/
kDiceKeyTpmCik = 5,
} dice_key_t;

/**
Expand All @@ -50,17 +71,8 @@ typedef struct dice_cert_key_id_pair {
} dice_cert_key_id_pair_t;

/**
* Supported TPM attestation keys.
*/
typedef enum tpm_key {
kTpmKeyEk = 0,
kTpmKeyCek = 1,
kTpmKeyCik = 2,
} tpm_key_t;

/**
* Generates the requested attestation ECC keypair, returning the public key and
* a key ID (which is a SHA256 digest of the public key).
* Generates the requested attestation ECC P256 keypair, returning the public
* key and a key ID (which is a SHA256 digest of the public key).
*
* Preconditions: keymgr has been initialized and cranked to the desired stage.
*
Expand Down Expand Up @@ -131,20 +143,6 @@ rom_error_t dice_cdi_1_cert_build(hmac_digest_t *owner_measurement,
attestation_public_key_t *cdi_1_pubkey,
uint8_t *cert, size_t *cert_size);

/**
* Generates the requested TPM ECC keypair, returning the public key and
* a key ID (which is a SHA256 digest of the public key).
*
* Preconditions: keymgr has been initialized and cranked to the desired stage.
*
* @param desired_key The desired attestation key to generate.
* @param[out] pubkey_id The public key ID (for embedding into certificates).
* @param[out] pubkey The public key.
*/
OT_WARN_UNUSED_RESULT
rom_error_t tpm_cert_keygen(tpm_key_t desired_key, hmac_digest_t *pubkey_id,
attestation_public_key_t *pubkey);

/**
* Generates an X.509 TBS section of a TPM EK certificate.
*
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
Loading
Loading