Skip to content

Commit

Permalink
[manuf] Calculate OTP measurements in ft_personalize
Browse files Browse the repository at this point in the history
This calculates the measurement of the OTP partitions in
`ft_personalize` and pass them to `dice_uds_tbs_cert_build()`.
This change is necessary because the CreatorSwCfg and OwnerSwCfg might
not be fully provisioned to the OTP when building the UDS certification.
By calculating the final measurements in `ft_personalize`, we can get
the values of unprovisioned field from the OTP image to ensure the
correct values are used in the certificate generation process.

Signed-off-by: Anthony Chen <[email protected]>
  • Loading branch information
anthonychen1251 committed Oct 14, 2024
1 parent ca3a53a commit dbd0a4a
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 81 deletions.
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
73 changes: 71 additions & 2 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,32 @@ 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));

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]);
}
return OK_STATUS();
}

/**
* Provision OTP SECRET{1,2} partitions, keymgr flash info pages, enable flash
* scrambling, and reboot.
Expand Down Expand Up @@ -353,6 +406,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 +433,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

0 comments on commit dbd0a4a

Please sign in to comment.