From 0f59c02f49adbe8c9cfddbd0f8c1b28fb96dcc49 Mon Sep 17 00:00:00 2001 From: Anthony Chen Date: Mon, 14 Oct 2024 19:57:51 +0800 Subject: [PATCH 1/2] [manuf] Calculate OTP measurements in ft_personalize 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 (cherry picked from commit dbd0a4a1a8cadb88d6800552b4908e27409030e3) --- sw/device/silicon_creator/lib/cert/BUILD | 2 - sw/device/silicon_creator/lib/cert/dice.c | 82 +++---------------- sw/device/silicon_creator/lib/cert/dice.h | 17 +++- sw/device/silicon_creator/lib/cert/dice_cwt.c | 10 ++- .../manuf/base/ft_personalize.c | 73 ++++++++++++++++- 5 files changed, 103 insertions(+), 81 deletions(-) diff --git a/sw/device/silicon_creator/lib/cert/BUILD b/sw/device/silicon_creator/lib/cert/BUILD index 7296ea6ad66f2..d7403dc25ff38 100644 --- a/sw/device/silicon_creator/lib/cert/BUILD +++ b/sw/device/silicon_creator/lib/cert/BUILD @@ -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", @@ -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", ], diff --git a/sw/device/silicon_creator/lib/cert/dice.c b/sw/device/silicon_creator/lib/cert/dice.c index 6eedd3a0b4e2a..3c0d8bf3b2ee2 100644 --- a/sw/device/silicon_creator/lib/cert/dice.c +++ b/sw/device/silicon_creator/lib/cert/dice.c @@ -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 = { @@ -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."); @@ -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, diff --git a/sw/device/silicon_creator/lib/cert/dice.h b/sw/device/silicon_creator/lib/cert/dice.h index f59ca73fbda45..a84b1f320337e 100644 --- a/sw/device/silicon_creator/lib/cert/dice.h +++ b/sw/device/silicon_creator/lib/cert/dice.h @@ -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. @@ -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. diff --git a/sw/device/silicon_creator/lib/cert/dice_cwt.c b/sw/device/silicon_creator/lib/cert/dice_cwt.c index 45377b806a5d1..64f4174e6b313 100644 --- a/sw/device/silicon_creator/lib/cert/dice_cwt.c +++ b/sw/device/silicon_creator/lib/cert/dice_cwt.c @@ -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; diff --git a/sw/device/silicon_creator/manuf/base/ft_personalize.c b/sw/device/silicon_creator/manuf/base/ft_personalize.c index bbc0a1ea6e347..20f9880d21d5d 100644 --- a/sw/device/silicon_creator/manuf/base/ft_personalize.c +++ b/sw/device/silicon_creator/manuf/base/ft_personalize.c @@ -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" @@ -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. */ @@ -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; @@ -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. @@ -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. ****************************************************************************/ @@ -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)); From 862923f09e05169e3841afbf006510b2b0f174ad Mon Sep 17 00:00:00 2001 From: Anthony Chen Date: Mon, 14 Oct 2024 22:20:35 +0800 Subject: [PATCH 2/2] [manuf] Finalize {Creator,Owner}SwCfg at end of perso flow This modifies the perso flow to complete the provisioning of the CreatorSwCfg and OwnerSwCfg OTP partitions at the end of the process. This ensures that the perso firmware can be reentrant in case of unexpected resets during personalization. Previously, these partitions were provisioned earlier in the flow. However, since we are going to bind the perso firmware with `CREATOR_SW_CFG_MANUF_STATE`, we need to ensure that this field is provisioned as late as possible. Since CreatorSwCfg and OwnerSwCfg partitions are now not fully provisioned in the OTP during the UDS certificate generation process, overwrite the fields that are not provisioned until the end of personalization process with the values from the OTP image. At the end of perso flow, compare the OTP measurement used during certificate generation with the digest stored in the OTP. Ensure that the UDS certificate was generated using the correct OTP values. Signed-off-by: Anthony Chen (cherry picked from commit 1404534e9ca1949acc6bd443c824af22f40377f2) --- .../manuf/base/ft_personalize.c | 69 +++++++++++++------ .../manuf/lib/individualize_sw_cfg.c | 60 +++++++++++++++- .../manuf/lib/individualize_sw_cfg.h | 23 +++++++ 3 files changed, 130 insertions(+), 22 deletions(-) diff --git a/sw/device/silicon_creator/manuf/base/ft_personalize.c b/sw/device/silicon_creator/manuf/base/ft_personalize.c index 20f9880d21d5d..e27056d654764 100644 --- a/sw/device/silicon_creator/manuf/base/ft_personalize.c +++ b/sw/device/silicon_creator/manuf/base/ft_personalize.c @@ -199,19 +199,18 @@ static status_t measure_otp_partition(otp_partition_t partition, 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); - // 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(); } @@ -225,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))) { @@ -664,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(); @@ -698,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."); diff --git a/sw/device/silicon_creator/manuf/lib/individualize_sw_cfg.c b/sw/device/silicon_creator/manuf/lib/individualize_sw_cfg.c index 009dba5e72e46..a58a642211336 100644 --- a/sw/device/silicon_creator/manuf/lib/individualize_sw_cfg.c +++ b/sw/device/silicon_creator/manuf/lib/individualize_sw_cfg.c @@ -36,7 +36,7 @@ enum { * @param kv OTP Array of OTP key values. See `otp_kv_t` documentation for more * details. * @param len Length of the `kv` array. - * @return OT_WARN_UNUSED_RESULT + * @return OK_STATUS if the OTP values were written into the target partition. */ OT_WARN_UNUSED_RESULT static status_t otp_img_write(const dif_otp_ctrl_t *otp, @@ -86,6 +86,32 @@ static status_t otp_img_write(const dif_otp_ctrl_t *otp, return OK_STATUS(); } +/** + * Overwrites the target field with its expected final value in a buffer + * representing the provided partition. + * + * @param partition Target OTP partition. + * @param field_offset An offest of the target OTP field. + * @param buffer A buffer containing the entire target OTP partition. + * @return OK_STATUS if the expected OTP values are successfully written to the + * `buffer`. + */ +static status_t otp_img_expected_value_read(dif_otp_ctrl_partition_t partition, + uint32_t field_offset, + uint8_t *buffer) { + uint32_t relative_addr; + TRY(dif_otp_ctrl_relative_address(partition, field_offset, &relative_addr)); + switch (field_offset) { + case OTP_CTRL_PARAM_OWNER_SW_CFG_ROM_BOOTSTRAP_DIS_OFFSET: + memcpy(buffer + relative_addr, &kOwnerSwCfgRomBootstrapDisValue, + sizeof(uint32_t)); + break; + default: + return INTERNAL(); + } + return OK_STATUS(); +} + /** * Computes a SHA256 digest of an OTP partition and uses the least significant * 64-bits of the digest to additionally lock the partition. @@ -95,7 +121,7 @@ static status_t otp_img_write(const dif_otp_ctrl_t *otp, * * @param otp OTP Controller instance. * @param partition Target OTP partition. - * @return OT_WARN_UNUSED_RESULT + * @return OK_STATUS if the target partition was locked. */ OT_WARN_UNUSED_RESULT static status_t lock_otp_partition(const dif_otp_ctrl_t *otp_ctrl, @@ -181,6 +207,19 @@ status_t manuf_individualize_device_flash_data_default_cfg( return OK_STATUS(); } +status_t manuf_individualize_device_flash_data_default_cfg_check( + const dif_otp_ctrl_t *otp_ctrl) { + uint32_t offset; + TRY(dif_otp_ctrl_relative_address( + kDifOtpCtrlPartitionCreatorSwCfg, + OTP_CTRL_PARAM_CREATOR_SW_CFG_FLASH_DATA_DEFAULT_CFG_OFFSET, &offset)); + uint32_t val = 0; + TRY(otp_ctrl_testutils_dai_read32(otp_ctrl, kDifOtpCtrlPartitionCreatorSwCfg, + offset, &val)); + bool is_provisioned = (val == kCreatorSwCfgFlashDataDefaultCfgValue); + return is_provisioned ? OK_STATUS() : INTERNAL(); +} + status_t manuf_individualize_device_creator_sw_cfg_lock( const dif_otp_ctrl_t *otp_ctrl) { TRY(lock_otp_partition(otp_ctrl, kDifOtpCtrlPartitionCreatorSwCfg)); @@ -214,6 +253,23 @@ status_t manuf_individualize_device_rom_bootstrap_dis_cfg( return OK_STATUS(); } +status_t manuf_individualize_device_partition_expected_read( + dif_otp_ctrl_partition_t partition, uint8_t *buffer) { + switch (partition) { + case kDifOtpCtrlPartitionOwnerSwCfg: + TRY(otp_img_expected_value_read( + partition, OTP_CTRL_PARAM_OWNER_SW_CFG_ROM_BOOTSTRAP_DIS_OFFSET, + buffer)); + break; + case kDifOtpCtrlPartitionCreatorSwCfg: + break; + default: + return INTERNAL(); + } + + return OK_STATUS(); +} + status_t manuf_individualize_device_owner_sw_cfg_lock( const dif_otp_ctrl_t *otp_ctrl) { TRY(lock_otp_partition(otp_ctrl, kDifOtpCtrlPartitionOwnerSwCfg)); diff --git a/sw/device/silicon_creator/manuf/lib/individualize_sw_cfg.h b/sw/device/silicon_creator/manuf/lib/individualize_sw_cfg.h index 6fe8fcd0d2006..4b6e6eca7d3ae 100644 --- a/sw/device/silicon_creator/manuf/lib/individualize_sw_cfg.h +++ b/sw/device/silicon_creator/manuf/lib/individualize_sw_cfg.h @@ -68,6 +68,17 @@ OT_WARN_UNUSED_RESULT status_t manuf_individualize_device_flash_data_default_cfg( const dif_otp_ctrl_t *otp_ctrl); +/** + * Checks the FLASH_DATA_DEFAULT_CFG field in the CREATOR_SW_CFG OTP + * partition. + * + * @param otp_ctrl OTP controller instance. + * @return OK_STATUS if the FLASH_DATA_DEFAULT_CFG field is provisioned. + */ +OT_WARN_UNUSED_RESULT +status_t manuf_individualize_device_flash_data_default_cfg_check( + const dif_otp_ctrl_t *otp_ctrl); + /** * Locks the CREATOR_SW_CFG OTP partition. * @@ -147,4 +158,16 @@ status_t manuf_individualize_device_owner_sw_cfg_lock( status_t manuf_individualize_device_owner_sw_cfg_check( const dif_otp_ctrl_t *otp_ctrl); +/** + * Overwrites unprovisioned fields with their expected final values in a buffer + * representing the provided partition. + * + * @param partition Target OTP partition. + * @param[out] buffer A buffer containing the entire target OTP partition. + * @return OK_STATUS if the expected partition values are successfully written + * to the `buffer`. + */ +status_t manuf_individualize_device_partition_expected_read( + dif_otp_ctrl_partition_t partition, uint8_t *buffer); + #endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_MANUF_LIB_INDIVIDUALIZE_SW_CFG_H_