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

Cherry-pick to earlgrey_1.0.0: [manuf] Finalize {Creator,Owner}SwCfg at end of perso flow #24917

Merged
merged 2 commits into from
Oct 29, 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
2 changes: 0 additions & 2 deletions sw/device/silicon_creator/lib/cert/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ cc_library(
hdrs = ["dice.h"],
deps = [
":cert",
"//hw/ip/otp_ctrl/data:otp_ctrl_c_regs",
"//sw/device/lib/base:memory",
"//sw/device/lib/base:status",
"//sw/device/lib/testing/test_framework:check",
Expand All @@ -106,7 +105,6 @@ cc_library(
"//sw/device/silicon_creator/lib/drivers:hmac",
"//sw/device/silicon_creator/lib/drivers:keymgr",
"//sw/device/silicon_creator/lib/drivers:lifecycle",
"//sw/device/silicon_creator/lib/drivers:otp",
"//sw/device/silicon_creator/lib/sigverify:ecdsa_p256_key",
"//sw/device/silicon_creator/manuf/lib:flash_info_fields",
],
Expand Down
82 changes: 11 additions & 71 deletions sw/device/silicon_creator/lib/cert/dice.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,11 @@
#include "sw/device/silicon_creator/lib/drivers/hmac.h"
#include "sw/device/silicon_creator/lib/drivers/keymgr.h"
#include "sw/device/silicon_creator/lib/drivers/lifecycle.h"
#include "sw/device/silicon_creator/lib/drivers/otp.h"
#include "sw/device/silicon_creator/lib/error.h"
#include "sw/device/silicon_creator/lib/otbn_boot_services.h"
#include "sw/device/silicon_creator/lib/sigverify/ecdsa_p256_key.h"
#include "sw/device/silicon_creator/manuf/lib/flash_info_fields.h"

#include "otp_ctrl_regs.h" // Generated.

enum {
/**
* Size of the largest OTP partition to be measured.
*/
kDiceMeasuredOtpPartitionMaxSizeIn32bitWords =
(OTP_CTRL_PARAM_OWNER_SW_CFG_SIZE -
OTP_CTRL_PARAM_OWNER_SW_CFG_DIGEST_SIZE) /
sizeof(uint32_t),
};

static uint32_t otp_state[kDiceMeasuredOtpPartitionMaxSizeIn32bitWords] = {0};
static ecdsa_p256_signature_t curr_tbs_signature = {.r = {0}, .s = {0}};
static uint8_t cdi_0_tbs_buffer[kCdi0MaxTbsSizeBytes];
static cdi_0_sig_values_t cdi_0_cert_params = {
Expand All @@ -47,16 +33,6 @@ static cdi_1_sig_values_t cdi_1_cert_params = {
.tbs_size = kCdi1MaxTbsSizeBytes,
};

// clang-format off
static_assert(
OTP_CTRL_PARAM_OWNER_SW_CFG_SIZE > OTP_CTRL_PARAM_CREATOR_SW_CFG_SIZE &&
OTP_CTRL_PARAM_OWNER_SW_CFG_SIZE > OTP_CTRL_PARAM_ROT_CREATOR_AUTH_CODESIGN_SIZE &&
OTP_CTRL_PARAM_OWNER_SW_CFG_SIZE > OTP_CTRL_PARAM_ROT_CREATOR_AUTH_STATE_SIZE,
"The largest DICE measured OTP partition is no longer the "
"OwnerSwCfg partition. Update the "
"kDiceMeasuredOtpPartitionMaxSizeIn32bitWords constant.");
// clang-format on

static_assert(kDiceMeasurementSizeInBytes == 32,
"The DICE attestation measurement size should equal the size of "
"the keymgr binding registers.");
Expand Down Expand Up @@ -148,62 +124,26 @@ static void curr_tbs_signature_le_to_be_convert(ecdsa_p256_signature_t *sig) {
util_reverse_bytes(sig->s, kEcdsaP256SignatureComponentBytes);
}

/**
* Helper function to compute measurements of various OTP partitions that are to
* be included in attestation certificates.
*/
static void measure_otp_partition(otp_partition_t partition,
hmac_digest_t *measurement) {
// Compute the digest.
otp_dai_read(partition, /*address=*/0, otp_state,
kOtpPartitions[partition].size / sizeof(uint32_t));
hmac_sha256(otp_state, kOtpPartitions[partition].size, measurement);

// Check the digest matches what is stored in OTP.
// TODO(#21554): remove this conditional once the root keys and key policies
// have been provisioned. Until then, these partitions have not been locked.
if (partition == kOtpPartitionCreatorSwCfg ||
partition == kOtpPartitionOwnerSwCfg) {
uint64_t expected_digest = otp_partition_digest_read(partition);
uint32_t digest_hi = expected_digest >> 32;
uint32_t digest_lo = expected_digest & UINT32_MAX;
HARDENED_CHECK_EQ(digest_hi, measurement->digest[1]);
HARDENED_CHECK_EQ(digest_lo, measurement->digest[0]);
}
}

rom_error_t dice_uds_tbs_cert_build(cert_key_id_pair_t *key_ids,
ecdsa_p256_public_key_t *uds_pubkey,
uint8_t *tbs_cert, size_t *tbs_cert_size) {
// Measure OTP partitions.
//
// Note: we do not measure HwCfg0 as this is the Device ID, which is already
// mixed into the keyladder directly via hardware channels.
hmac_digest_t otp_creator_sw_cfg_measurement = {.digest = {0}};
hmac_digest_t otp_owner_sw_cfg_measurement = {.digest = {0}};
hmac_digest_t otp_rot_creator_auth_codesign_measurement = {.digest = {0}};
hmac_digest_t otp_rot_creator_auth_state_measurement = {.digest = {0}};
measure_otp_partition(kOtpPartitionCreatorSwCfg,
&otp_creator_sw_cfg_measurement);
measure_otp_partition(kOtpPartitionOwnerSwCfg, &otp_owner_sw_cfg_measurement);
measure_otp_partition(kOtpPartitionRotCreatorAuthCodesign,
&otp_rot_creator_auth_codesign_measurement);
measure_otp_partition(kOtpPartitionRotCreatorAuthState,
&otp_rot_creator_auth_state_measurement);

rom_error_t dice_uds_tbs_cert_build(
hmac_digest_t *otp_creator_sw_cfg_measurement,
hmac_digest_t *otp_owner_sw_cfg_measurement,
hmac_digest_t *otp_rot_creator_auth_codesign_measurement,
hmac_digest_t *otp_rot_creator_auth_state_measurement,
cert_key_id_pair_t *key_ids, ecdsa_p256_public_key_t *uds_pubkey,
uint8_t *tbs_cert, size_t *tbs_cert_size) {
// Generate the TBS certificate.
uds_tbs_values_t uds_cert_tbs_params = {
.otp_creator_sw_cfg_hash =
(unsigned char *)otp_creator_sw_cfg_measurement.digest,
(unsigned char *)otp_creator_sw_cfg_measurement->digest,
.otp_creator_sw_cfg_hash_size = kHmacDigestNumBytes,
.otp_owner_sw_cfg_hash =
(unsigned char *)otp_owner_sw_cfg_measurement.digest,
(unsigned char *)otp_owner_sw_cfg_measurement->digest,
.otp_owner_sw_cfg_hash_size = kHmacDigestNumBytes,
.otp_rot_creator_auth_codesign_hash =
(unsigned char *)otp_rot_creator_auth_codesign_measurement.digest,
(unsigned char *)otp_rot_creator_auth_codesign_measurement->digest,
.otp_rot_creator_auth_codesign_hash_size = kHmacDigestNumBytes,
.otp_rot_creator_auth_state_hash =
(unsigned char *)otp_rot_creator_auth_state_measurement.digest,
(unsigned char *)otp_rot_creator_auth_state_measurement->digest,
.otp_rot_creator_auth_state_hash_size = kHmacDigestNumBytes,
.debug_flag = is_debug_exposed(),
.creator_pub_key_id = (unsigned char *)key_ids->cert->digest,
Expand Down
17 changes: 14 additions & 3 deletions sw/device/silicon_creator/lib/cert/dice.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,13 @@ extern const sc_keymgr_ecc_key_t kDiceKeyCdi1;
/**
* Generates the UDS attestation keypair and (unendorsed) X.509 TBS certificate.
*
* @param otp_creator_sw_cfg_measurement Pointer to the CreatorSwCfg
* measurement.
* @param otp_owner_sw_cfg_measurement Pointer to the OwnerSwCfg measurement.
* @param otp_rot_creator_auth_codesign_measurement Pointer to the
* RotCreatorAuthCodesign measurement.
* @param otp_rot_creator_auth_state_measurement Pointer to the
* RotCreatorAuthState measurement.
* @param key_ids Pointer to the (current and endorsement) public key IDs.
* @param uds_pubkey Pointer to the (current stage) public key in big endian.
* @param[out] cert Buffer to hold the generated UDS certificate.
Expand All @@ -41,9 +48,13 @@ extern const sc_keymgr_ecc_key_t kDiceKeyCdi1;
* @return The result of the operation.
*/
OT_WARN_UNUSED_RESULT
rom_error_t dice_uds_tbs_cert_build(cert_key_id_pair_t *key_ids,
ecdsa_p256_public_key_t *uds_pubkey,
uint8_t *tbs_cert, size_t *tbs_cert_size);
rom_error_t dice_uds_tbs_cert_build(
hmac_digest_t *otp_creator_sw_cfg_measurement,
hmac_digest_t *otp_owner_sw_cfg_measurement,
hmac_digest_t *otp_rot_creator_auth_codesign_measurement,
hmac_digest_t *otp_rot_creator_auth_state_measurement,
cert_key_id_pair_t *key_ids, ecdsa_p256_public_key_t *uds_pubkey,
uint8_t *tbs_cert, size_t *tbs_cert_size);

/**
* Generates the CDI_0 attestation keypair and X.509 certificate.
Expand Down
10 changes: 7 additions & 3 deletions sw/device/silicon_creator/lib/cert/dice_cwt.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,13 @@ const sc_keymgr_ecc_key_t kDiceKeyCdi1 = {
// -2 : bstr, ; X coordinate, big-endian
// -3 : bstr ; Y coordinate, big-endian
// }
rom_error_t dice_uds_tbs_cert_build(cert_key_id_pair_t *key_ids,
ecdsa_p256_public_key_t *uds_pubkey,
uint8_t *tbs_cert, size_t *tbs_cert_size) {
rom_error_t dice_uds_tbs_cert_build(
hmac_digest_t *otp_creator_sw_cfg_measurement,
hmac_digest_t *otp_owner_sw_cfg_measurement,
hmac_digest_t *otp_rot_creator_auth_codesign_measurement,
hmac_digest_t *otp_rot_creator_auth_state_measurement,
cert_key_id_pair_t *key_ids, ecdsa_p256_public_key_t *uds_pubkey,
uint8_t *tbs_cert, size_t *tbs_cert_size) {
struct CborOut kCborOutHandle;

struct CborOut *pCborOut = &kCborOutHandle;
Expand Down
120 changes: 109 additions & 11 deletions sw/device/silicon_creator/manuf/base/ft_personalize.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "sw/device/silicon_creator/lib/drivers/hmac.h"
#include "sw/device/silicon_creator/lib/drivers/keymgr.h"
#include "sw/device/silicon_creator/lib/drivers/kmac.h"
#include "sw/device/silicon_creator/lib/drivers/otp.h"
#include "sw/device/silicon_creator/lib/error.h"
#include "sw/device/silicon_creator/lib/otbn_boot_services.h"
#include "sw/device/silicon_creator/manuf/base/perso_tlv_data.h"
Expand All @@ -45,6 +46,28 @@ OTTF_DEFINE_TEST_CONFIG(.console.type = kOttfConsoleSpiDevice,
.console.base_addr = TOP_EARLGREY_SPI_DEVICE_BASE_ADDR,
.console.test_may_clobber = false, );

enum {
/**
* Size of the largest OTP partition to be measured.
*/
kDiceMeasuredOtpPartitionMaxSizeIn32bitWords =
(OTP_CTRL_PARAM_OWNER_SW_CFG_SIZE -
OTP_CTRL_PARAM_OWNER_SW_CFG_DIGEST_SIZE) /
sizeof(uint32_t),
};

static uint32_t otp_state[kDiceMeasuredOtpPartitionMaxSizeIn32bitWords] = {0};

// clang-format off
static_assert(
OTP_CTRL_PARAM_OWNER_SW_CFG_SIZE > OTP_CTRL_PARAM_CREATOR_SW_CFG_SIZE &&
OTP_CTRL_PARAM_OWNER_SW_CFG_SIZE > OTP_CTRL_PARAM_ROT_CREATOR_AUTH_CODESIGN_SIZE &&
OTP_CTRL_PARAM_OWNER_SW_CFG_SIZE > OTP_CTRL_PARAM_ROT_CREATOR_AUTH_STATE_SIZE,
"The largest DICE measured OTP partition is no longer the "
"OwnerSwCfg partition. Update the "
"kDiceMeasuredOtpPartitionMaxSizeIn32bitWords constant.");
// clang-format on

/**
* Peripheral handles.
*/
Expand All @@ -62,6 +85,10 @@ static keymgr_binding_value_t sealing_binding_value = {.data = {0}};
/**
* Certificate data.
*/
static hmac_digest_t otp_creator_sw_cfg_measurement;
static hmac_digest_t otp_owner_sw_cfg_measurement;
static hmac_digest_t otp_rot_creator_auth_codesign_measurement;
static hmac_digest_t otp_rot_creator_auth_state_measurement;
static manuf_certgen_inputs_t certgen_inputs;
static hmac_digest_t uds_endorsement_key_id;
static hmac_digest_t uds_pubkey_id;
Expand Down Expand Up @@ -162,6 +189,31 @@ static status_t config_and_erase_certificate_flash_pages(void) {
return OK_STATUS();
}

/**
* Helper function to compute measurements of various OTP partitions that are to
* be included in attestation certificates.
*/
static status_t measure_otp_partition(otp_partition_t partition,
hmac_digest_t *measurement) {
// Compute the digest.
otp_dai_read(partition, /*address=*/0, otp_state,
kOtpPartitions[partition].size / sizeof(uint32_t));

// Sets the expected values for fields in the OTP that are not provisioned
// until the final stages of personalization.
if (partition == kOtpPartitionOwnerSwCfg) {
manuf_individualize_device_partition_expected_read(
kDifOtpCtrlPartitionOwnerSwCfg, (uint8_t *)otp_state);
} else if (partition == kOtpPartitionCreatorSwCfg) {
manuf_individualize_device_partition_expected_read(
kDifOtpCtrlPartitionCreatorSwCfg, (uint8_t *)otp_state);
}

hmac_sha256(otp_state, kOtpPartitions[partition].size, measurement);

return OK_STATUS();
}

/**
* Provision OTP SECRET{1,2} partitions, keymgr flash info pages, enable flash
* scrambling, and reboot.
Expand All @@ -172,20 +224,13 @@ static status_t personalize_otp_and_flash_secrets(ujson_t *uj) {
if (!status_ok(manuf_personalize_device_secret1_check(&otp_ctrl))) {
TRY(manuf_personalize_device_secret1(&lc_ctrl, &otp_ctrl));
}
if (!status_ok(manuf_individualize_device_creator_sw_cfg_check(&otp_ctrl))) {
if (!status_ok(
manuf_individualize_device_flash_data_default_cfg_check(&otp_ctrl))) {
TRY(manuf_individualize_device_flash_data_default_cfg(&otp_ctrl));
TRY(manuf_individualize_device_creator_sw_cfg_lock(&otp_ctrl));
LOG_INFO("Bootstrap requested.");
wait_for_interrupt();
}

// The last bootstrap process in the perso flow is done.
// Complete the provisioning of OTP OwnerSwCfg partition.
if (!status_ok(manuf_individualize_device_owner_sw_cfg_check(&otp_ctrl))) {
TRY(manuf_individualize_device_rom_bootstrap_dis_cfg(&otp_ctrl));
TRY(manuf_individualize_device_owner_sw_cfg_lock(&otp_ctrl));
}

// Provision OTP Secret2 partition and flash info pages 1, 2, and 4 (keymgr
// and DICE keygen seeds).
if (!status_ok(manuf_personalize_device_secrets_check(&otp_ctrl))) {
Expand Down Expand Up @@ -353,6 +398,19 @@ static status_t personalize_gen_dice_certificates(ujson_t *uj) {
TRY(sc_keymgr_state_check(kScKeymgrStateInit));
sc_keymgr_advance_state();

// Measure OTP partitions.
//
// Note: we do not measure HwCfg0 as this is the Device ID, which is already
// mixed into the keyladder directly via hardware channels.
TRY(measure_otp_partition(kOtpPartitionCreatorSwCfg,
&otp_creator_sw_cfg_measurement));
TRY(measure_otp_partition(kOtpPartitionOwnerSwCfg,
&otp_owner_sw_cfg_measurement));
TRY(measure_otp_partition(kOtpPartitionRotCreatorAuthCodesign,
&otp_rot_creator_auth_codesign_measurement));
TRY(measure_otp_partition(kOtpPartitionRotCreatorAuthState,
&otp_rot_creator_auth_state_measurement));

/*****************************************************************************
* DICE certificates.
****************************************************************************/
Expand All @@ -367,8 +425,11 @@ static status_t personalize_gen_dice_certificates(ujson_t *uj) {
*kDiceKeyUds.keymgr_diversifier));

// Build the certificate in a temp buffer, use all_certs for that.
TRY(dice_uds_tbs_cert_build(&uds_key_ids, &curr_pubkey, all_certs,
&curr_cert_size));
TRY(dice_uds_tbs_cert_build(
&otp_creator_sw_cfg_measurement, &otp_owner_sw_cfg_measurement,
&otp_rot_creator_auth_codesign_measurement,
&otp_rot_creator_auth_state_measurement, &uds_key_ids, &curr_pubkey,
all_certs, &curr_cert_size));
TRY(perso_tlv_prepare_cert_for_shipping("UDS", true, all_certs,
curr_cert_size, &perso_blob_to_host));

Expand Down Expand Up @@ -595,6 +656,42 @@ static status_t send_final_hash(ujson_t *uj, serdes_sha256_hash_t *hash) {
return RESP_OK(ujson_serialize_serdes_sha256_hash_t, uj, hash);
}

/**
* Compare the OTP measurement used during certificate generation with the value
* stored in the OTP. Ensure that the UDS certificate was generated using the
* correct OTP values.
*/
static status_t check_otp_measurement(hmac_digest_t *measurement,
uint32_t offset) {
uint64_t expected_digest = otp_read64(offset);
uint32_t digest_hi = expected_digest >> 32;
uint32_t digest_lo = expected_digest & UINT32_MAX;
HARDENED_CHECK_EQ(digest_hi, measurement->digest[1]);
HARDENED_CHECK_EQ(digest_lo, measurement->digest[0]);
return OK_STATUS();
}

static status_t finalize_otp_partitions(void) {
// TODO(#21554): Complete the provisioning of the root keys and key policies.

// Complete the provisioning of OTP OwnerSwCfg partition.
if (!status_ok(manuf_individualize_device_owner_sw_cfg_check(&otp_ctrl))) {
TRY(manuf_individualize_device_rom_bootstrap_dis_cfg(&otp_ctrl));
TRY(manuf_individualize_device_owner_sw_cfg_lock(&otp_ctrl));
}
TRY(check_otp_measurement(&otp_owner_sw_cfg_measurement,
OTP_CTRL_PARAM_OWNER_SW_CFG_DIGEST_OFFSET));

// Complete the provisioning of OTP CreatorSwCfg partition.
if (!status_ok(manuf_individualize_device_creator_sw_cfg_check(&otp_ctrl))) {
TRY(manuf_individualize_device_creator_sw_cfg_lock(&otp_ctrl));
}
TRY(check_otp_measurement(&otp_creator_sw_cfg_measurement,
OTP_CTRL_PARAM_CREATOR_SW_CFG_DIGEST_OFFSET));

return OK_STATUS();
}

bool test_main(void) {
CHECK_STATUS_OK(peripheral_handles_init());
ujson_t uj = ujson_ottf_console();
Expand Down Expand Up @@ -629,6 +726,7 @@ bool test_main(void) {
hash.data[7], hash.data[6], hash.data[5], hash.data[4], hash.data[3],
hash.data[2], hash.data[1], hash.data[0]);

CHECK_STATUS_OK(finalize_otp_partitions());
// DO NOT CHANGE THE BELOW STRING without modifying the host code in
// sw/host/provisioning/ft_lib/src/lib.rs
LOG_INFO("Personalization done.");
Expand Down
Loading