Skip to content

Commit

Permalink
[manuf] move SECRET1 provisioning to the personlize lib
Browse files Browse the repository at this point in the history
SECRET1 provisioning must be done in the personalize stage, as it must
happen after the HW_CFG partition as been provisioned (and locked) as
provisioning this partition require SW access to the CSRNG, which is
enabled during HW_CFG partition provisioning.

Signed-off-by: Tim Trippel <[email protected]>
  • Loading branch information
timothytrippel committed Oct 23, 2023
1 parent 011901a commit cb61338
Show file tree
Hide file tree
Showing 8 changed files with 125 additions and 126 deletions.
5 changes: 2 additions & 3 deletions hw/ip/otp_ctrl/data/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -492,14 +492,13 @@ otp_image(
],
)

# Represents a device in DEV state with the SECRET0 and SECRET1 partitions in
# locked state. SECRET2 partition is unlocked.
# Represents a device in DEV state with the SECRET0 partition in the locked
# state. SECRET1 and SECRET2 partitions are in the unlocked state.
otp_image(
name = "img_dev_individualized",
src = ":otp_json_dev",
overlays = [
":otp_json_secret0",
":otp_json_secret1",
] + STD_OTP_OVERLAYS_WITHOUT_SECRET_PARTITIONS,
)

Expand Down
69 changes: 0 additions & 69 deletions sw/device/silicon_creator/manuf/lib/individualize.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,40 +186,6 @@ status_t manuf_individualize_device_hw_cfg_check(
return is_locked ? OK_STATUS() : INTERNAL();
}

OT_WARN_UNUSED_RESULT
static status_t otp_secret_write(const dif_otp_ctrl_t *otp_ctrl,
uint32_t offset, size_t len) {
enum {
kBufferSize = 4,
};
if (len > kBufferSize) {
return INTERNAL();
}

TRY(entropy_csrng_reseed(/*disable_trng_inpu=*/kHardenedBoolFalse,
/*seed_material=*/NULL));

size_t len_in_32bit_words = len * 2;
uint64_t data[kBufferSize];
TRY(entropy_csrng_generate(/*seed_material=*/NULL, (uint32_t *)data,
len_in_32bit_words,
/*fips_check=*/kHardenedBoolTrue));

bool found_error = false;
uint64_t prev_val = 0;
for (size_t i = 0; i < len; ++i) {
found_error |= data[i] == 0 || data[i] == UINT64_MAX || data[i] == prev_val;
prev_val = data[i];
}
if (found_error) {
return INTERNAL();
}

TRY(otp_ctrl_testutils_dai_write64(otp_ctrl, kDifOtpCtrlPartitionSecret1,
offset, data, len));
return OK_STATUS();
}

status_t manuf_individualize_device_secret0(
const dif_lc_ctrl_t *lc_ctrl, const dif_otp_ctrl_t *otp_ctrl,
const manuf_cp_provisioning_data_t *provisioning_data) {
Expand Down Expand Up @@ -262,38 +228,3 @@ status_t manuf_individualize_device_secret0_check(
&is_locked));
return is_locked ? OK_STATUS() : INTERNAL();
}

status_t manuf_individualize_device_secret1(const dif_lc_ctrl_t *lc_ctrl,
const dif_otp_ctrl_t *otp_ctrl) {
bool is_locked;
TRY(dif_otp_ctrl_is_digest_computed(otp_ctrl, kDifOtpCtrlPartitionSecret1,
&is_locked));
if (is_locked) {
return OK_STATUS();
}

TRY(entropy_complex_init());
TRY(entropy_csrng_instantiate(/*disable_trng_input=*/kHardenedBoolFalse,
/*seed_material=*/NULL));

TRY(otp_secret_write(otp_ctrl, kSecret1FlashAddrKeySeedOffset,
kSecret1FlashAddrKeySeed64BitWords));
TRY(otp_secret_write(otp_ctrl, kSecret1FlashDataKeySeedOffset,
kSecret1FlashDataKeySeed64BitWords));
TRY(otp_secret_write(otp_ctrl, kSecret1SramDataKeySeedOffset,
kSecret1SramDataKeySeed64Bitwords));

TRY(entropy_csrng_uninstantiate());
TRY(otp_ctrl_testutils_lock_partition(otp_ctrl, kDifOtpCtrlPartitionSecret1,
/*digest=*/0));

return OK_STATUS();
}

status_t manuf_individualize_device_secret1_check(
const dif_otp_ctrl_t *otp_ctrl) {
bool is_locked;
TRY(dif_otp_ctrl_is_digest_computed(otp_ctrl, kDifOtpCtrlPartitionSecret1,
&is_locked));
return is_locked ? OK_STATUS() : INTERNAL();
}
29 changes: 0 additions & 29 deletions sw/device/silicon_creator/manuf/lib/individualize.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,33 +78,4 @@ status_t manuf_individualize_device_secret0(
status_t manuf_individualize_device_secret0_check(
const dif_otp_ctrl_t *otp_ctrl);

/**
* Configures the SECRET1 OTP partition.
*
* The SECRET1 partition contains the Flash and SRAM scrambling seeds for the
* device.
*
* Note: The test will skip all programming steps and succeed if the SECRET1
* parition is already locked. This is to facilitate test re-runs.
*
* The caller should reset the device after calling this function and call
* `manuf_individualize_device_secret1_check()` afterwards to confirm that the
* OTP partition was successfully locked.
*
* @param lc_ctrl Lifecycle controller instance.
* @param otp_ctrl OTP controller instance.
* @return OK_STATUS on success.
*/
status_t manuf_individualize_device_secret1(const dif_lc_ctrl_t *lc_ctrl,
const dif_otp_ctrl_t *otp_ctrl);

/**
* Checks the SECRET1 OTP partition end state.
*
* @param otp_ctrl OTP controller interface.
* @return OK_STATUS if the SECRET1 partition is locked.
*/
status_t manuf_individualize_device_secret1_check(
const dif_otp_ctrl_t *otp_ctrl);

#endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_MANUF_LIB_INDIVIDUALIZE_H_
5 changes: 0 additions & 5 deletions sw/device/silicon_creator/manuf/lib/individualize_functest.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,5 @@ bool test_main(void) {
sw_reset();
}

if (!status_ok(manuf_individualize_device_secret1_check(&otp_ctrl))) {
CHECK_STATUS_OK(manuf_individualize_device_secret1(&lc_ctrl, &otp_ctrl));
sw_reset();
}

return true;
}
69 changes: 69 additions & 0 deletions sw/device/silicon_creator/manuf/lib/personalize.c
Original file line number Diff line number Diff line change
Expand Up @@ -339,8 +339,77 @@ status_t manuf_personalize_device(dif_flash_ctrl_state_t *flash_state,
return OK_STATUS();
}

OT_WARN_UNUSED_RESULT
static status_t otp_secret_write(const dif_otp_ctrl_t *otp_ctrl,
uint32_t offset, size_t len) {
enum {
kBufferSize = 4,
};
if (len > kBufferSize) {
return INTERNAL();
}

TRY(entropy_csrng_reseed(/*disable_trng_inpu=*/kHardenedBoolFalse,
/*seed_material=*/NULL));

size_t len_in_32bit_words = len * 2;
uint64_t data[kBufferSize];
TRY(entropy_csrng_generate(/*seed_material=*/NULL, (uint32_t *)data,
len_in_32bit_words,
/*fips_check=*/kHardenedBoolTrue));

bool found_error = false;
uint64_t prev_val = 0;
for (size_t i = 0; i < len; ++i) {
found_error |= data[i] == 0 || data[i] == UINT64_MAX || data[i] == prev_val;
prev_val = data[i];
}
if (found_error) {
return INTERNAL();
}

TRY(otp_ctrl_testutils_dai_write64(otp_ctrl, kDifOtpCtrlPartitionSecret1,
offset, data, len));
return OK_STATUS();
}

status_t manuf_personalize_device_check(const dif_otp_ctrl_t *otp_ctrl) {
bool is_locked;
TRY(otp_partition_secret2_is_locked(otp_ctrl, &is_locked));
return is_locked ? OK_STATUS() : INTERNAL();
}

status_t manuf_personalize_device_secret1(const dif_lc_ctrl_t *lc_ctrl,
const dif_otp_ctrl_t *otp_ctrl) {
bool is_locked;
TRY(dif_otp_ctrl_is_digest_computed(otp_ctrl, kDifOtpCtrlPartitionSecret1,
&is_locked));
if (is_locked) {
return OK_STATUS();
}

TRY(entropy_complex_init());
TRY(entropy_csrng_instantiate(/*disable_trng_input=*/kHardenedBoolFalse,
/*seed_material=*/NULL));

TRY(otp_secret_write(otp_ctrl, kSecret1FlashAddrKeySeedOffset,
kSecret1FlashAddrKeySeed64BitWords));
TRY(otp_secret_write(otp_ctrl, kSecret1FlashDataKeySeedOffset,
kSecret1FlashDataKeySeed64BitWords));
TRY(otp_secret_write(otp_ctrl, kSecret1SramDataKeySeedOffset,
kSecret1SramDataKeySeed64Bitwords));

TRY(entropy_csrng_uninstantiate());
TRY(otp_ctrl_testutils_lock_partition(otp_ctrl, kDifOtpCtrlPartitionSecret1,
/*digest=*/0));

return OK_STATUS();
}

status_t manuf_personalize_device_secret1_check(
const dif_otp_ctrl_t *otp_ctrl) {
bool is_locked;
TRY(dif_otp_ctrl_is_digest_computed(otp_ctrl, kDifOtpCtrlPartitionSecret1,
&is_locked));
return is_locked ? OK_STATUS() : INTERNAL();
}
28 changes: 28 additions & 0 deletions sw/device/silicon_creator/manuf/lib/personalize.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,34 @@

#include "otp_ctrl_regs.h" // Generated.

/**
* Configures the SECRET1 OTP partition.
*
* The SECRET1 partition contains the Flash and SRAM scrambling seeds for the
* device.
*
* Note: The test will skip all programming steps and succeed if the SECRET1
* parition is already locked. This is to facilitate test re-runs.
*
* The caller should reset the device after calling this function and call
* `manuf_personalize_device_secret1_check()` afterwards to confirm that the
* OTP partition was successfully locked.
*
* @param lc_ctrl Lifecycle controller instance.
* @param otp_ctrl OTP controller instance.
* @return OK_STATUS on success.
*/
status_t manuf_personalize_device_secret1(const dif_lc_ctrl_t *lc_ctrl,
const dif_otp_ctrl_t *otp_ctrl);

/**
* Checks the SECRET1 OTP partition end state.
*
* @param otp_ctrl OTP controller interface.
* @return OK_STATUS if the SECRET1 partition is locked.
*/
status_t manuf_personalize_device_secret1_check(const dif_otp_ctrl_t *otp_ctrl);

/**
* Personalize device with unique secrets.
*
Expand Down
40 changes: 25 additions & 15 deletions sw/device/silicon_creator/manuf/lib/personalize_functest.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,13 @@ static status_t peripheral_handles_init(void) {
return OK_STATUS();
}

status_t personalize_test(manuf_perso_data_out_t *export_data) {
LOG_INFO("Personalizing device.");
TRY(manuf_personalize_device(&flash_state, &lc_ctrl, &otp_ctrl, export_data));
return OK_STATUS();
/**
* Perform software reset.
*/
static void sw_reset(void) {
rstmgr_testutils_reason_clear();
CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr));
wait_for_interrupt();
}

status_t export_data_over_console(ujson_t *uj,
Expand Down Expand Up @@ -89,25 +92,32 @@ bool test_main(void) {

dif_rstmgr_reset_info_bitfield_t info = rstmgr_testutils_reason_get();
if (info & kDifRstmgrResetInfoPor) {
// Provision secrets into the device.
CHECK_STATUS_OK(personalize_test(export_data));

// Issue and wait for reset.
rstmgr_testutils_reason_clear();
CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr));
wait_for_interrupt();
// Provision the OTP SECRET1 partition.
if (!status_ok(manuf_personalize_device_secret1_check(&otp_ctrl))) {
LOG_INFO("Provisioning OTP SECRET1 ...");
CHECK_STATUS_OK(manuf_personalize_device_secret1(&lc_ctrl, &otp_ctrl));
}
// We move the SW reset outside the above if-clause so the next block of the
// outter conditional (the block executed under a soft reset condition) is
// always executed. This facilitates test-reruns.
sw_reset();
} else if (info == kDifRstmgrResetInfoSw) {
// Check personalization completed successfully.
LOG_INFO("Personalization complete. Checking status ...");
CHECK_STATUS_OK(manuf_personalize_device_check(&otp_ctrl));
// Provision the OTP SECRET2 partition.
if (!status_ok(manuf_personalize_device_check(&otp_ctrl))) {
LOG_INFO("Provisioning OTP SECRET2 ...");
CHECK_STATUS_OK(manuf_personalize_device(&flash_state, &lc_ctrl,
&otp_ctrl, export_data));
sw_reset();
}

// Send the RMA unlock token data (stored in the retention SRAM) over the
// console using ujson framework.
LOG_INFO("Exporting RMA unlock token ...");
CHECK_STATUS_OK(export_data_over_console(&uj, export_data));

// Wait in a loop so that OpenOCD can connect to the TAP without the ROM
// resetting the chip.
LOG_INFO("Spinning for host to connect over JTAG.");
// Abort simply forever loops on a wait_for_interrupt.
abort();
} else {
LOG_FATAL("Unexpected reset reason: %08x", info);
Expand Down
6 changes: 1 addition & 5 deletions sw/host/tests/manuf/personalize/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,7 @@ fn rma_unlock_token_export(opts: &Opts, transport: &TransportWrapper) -> Result<
// Get UART, set flow control, and wait for for test to start running.
let uart = transport.uart("console")?;
uart.set_flow_control(true)?;
let _ = UartConsole::wait_for(
&*uart,
r"Personalization complete. Checking status ...",
opts.timeout,
)?;
let _ = UartConsole::wait_for(&*uart, r"Exporting RMA unlock token ...", opts.timeout)?;

// Wait for exported data to be transimitted over the console.
let export_data = ManufPersoDataOut::recv(&*uart, opts.timeout, false)?;
Expand Down

0 comments on commit cb61338

Please sign in to comment.