diff --git a/sw/device/silicon_creator/lib/ownership/BUILD b/sw/device/silicon_creator/lib/ownership/BUILD index c283589ad60eb..efae23fb2100a 100644 --- a/sw/device/silicon_creator/lib/ownership/BUILD +++ b/sw/device/silicon_creator/lib/ownership/BUILD @@ -100,7 +100,11 @@ cc_library( deps = [ ":datatypes", ":ecdsa", + ":owner_block", ":ownership_key", + "//sw/device/lib/base:hardened_memory", + "//sw/device/silicon_creator/lib:boot_data", + "//sw/device/silicon_creator/lib:dbg_print", "//sw/device/silicon_creator/lib/drivers:flash_ctrl", ], ) @@ -169,6 +173,39 @@ cc_test( ], ) +cc_library( + name = "ownership_activate", + srcs = ["ownership_activate.c"], + hdrs = ["ownership_activate.h"], + deps = [ + ":datatypes", + ":ownership", + ":ownership_key", + "//sw/device/lib/base:memory", + "//sw/device/silicon_creator/lib:boot_data", + "//sw/device/silicon_creator/lib:error", + "//sw/device/silicon_creator/lib/boot_svc:boot_svc_msg", + "//sw/device/silicon_creator/lib/drivers:flash_ctrl", + ], +) + +cc_test( + name = "ownership_activate_unittest", + srcs = [ + "ownership_activate_unittest.cc", + ], + deps = [ + ":datatypes", + ":ownership_activate", + ":ownership_key", + "//sw/device/lib/base:hardened", + "//sw/device/silicon_creator/lib:boot_data", + "//sw/device/silicon_creator/lib/boot_svc:boot_svc_header", + "//sw/device/silicon_creator/testing:rom_test", + "@googletest//:gtest_main", + ], +) + cc_library( name = "test_owner", testonly = True, @@ -178,6 +215,7 @@ cc_library( ":owner_block", ":ownership", "//sw/device/silicon_creator/lib:boot_data", + "//sw/device/silicon_creator/lib/drivers:flash_ctrl", "//sw/device/silicon_creator/lib/ownership/keys/fake:includes", ], alwayslink = True, diff --git a/sw/device/silicon_creator/lib/ownership/datatypes.h b/sw/device/silicon_creator/lib/ownership/datatypes.h index f30e49352262b..e661c5635e741 100644 --- a/sw/device/silicon_creator/lib/ownership/datatypes.h +++ b/sw/device/silicon_creator/lib/ownership/datatypes.h @@ -42,7 +42,7 @@ typedef enum ownership_state { /* Unlocked Endorsed: `UEND`. */ kOwnershipStateUnlockedEndorsed = 0x444e4555, /* Locked None: any bit pattern not listed above. */ - kOwnershipStateLockedNone = 0, + kOwnershipStateRecovery = 0, } ownership_state_t; typedef enum ownership_key_alg { diff --git a/sw/device/silicon_creator/lib/ownership/owner_block.c b/sw/device/silicon_creator/lib/ownership/owner_block.c index b11a653f5b6a5..a24597eb01baa 100644 --- a/sw/device/silicon_creator/lib/ownership/owner_block.c +++ b/sw/device/silicon_creator/lib/ownership/owner_block.c @@ -19,6 +19,14 @@ enum { kFlashBankSize = FLASH_CTRL_PARAM_REG_PAGES_PER_BANK, }; +void owner_config_default(owner_config_t *config) { + // Use a bogus pointer value to avoid the all-zeros pattern of NULL. + config->flash = (const owner_flash_config_t *)kHardenedBoolFalse; + config->info = (const owner_flash_info_config_t *)kHardenedBoolFalse; + config->rescue = (const owner_rescue_config_t *)kHardenedBoolFalse; + config->sram_exec = kOwnerSramExecModeDisabledLocked; +} + rom_error_t owner_block_parse(const owner_block_t *block, owner_config_t *config, owner_application_keyring_t *keyring) { @@ -27,13 +35,9 @@ rom_error_t owner_block_parse(const owner_block_t *block, if (block->header.length != sizeof(owner_block_t)) return kErrorOwnershipInvalidTagLength; + owner_config_default(config); config->sram_exec = block->sram_exec_mode; - // Use a bogus pointer value to avoid the all-zeros pattern of NULL. - config->flash = (const owner_flash_config_t *)kHardenedBoolFalse; - config->info = (const owner_flash_info_config_t *)kHardenedBoolFalse; - config->rescue = (const owner_rescue_config_t *)kHardenedBoolFalse; - uint32_t remain = sizeof(block->data); uint32_t offset = 0; while (remain) { diff --git a/sw/device/silicon_creator/lib/ownership/owner_block.h b/sw/device/silicon_creator/lib/ownership/owner_block.h index de2fcc1d54798..d849f9fc833a8 100644 --- a/sw/device/silicon_creator/lib/ownership/owner_block.h +++ b/sw/device/silicon_creator/lib/ownership/owner_block.h @@ -38,6 +38,16 @@ typedef struct owner_application_keyring { const owner_application_key_t *key[16]; } owner_application_keyring_t; +/** + * Initialize the owner config with default values. + * + * The sram_exec mode is set to DisabledLocked and the three configuration + * pointers are set to kHardenedBoolFalse. + * + * @param config A pointer to a config struct holding pointers to config items. + */ +void owner_config_default(owner_config_t *config); + /** * Parse an owner block, extracting pointers to keys and configuration items. * diff --git a/sw/device/silicon_creator/lib/ownership/ownership.c b/sw/device/silicon_creator/lib/ownership/ownership.c index 0f3d832baae50..183814f60a416 100644 --- a/sw/device/silicon_creator/lib/ownership/ownership.c +++ b/sw/device/silicon_creator/lib/ownership/ownership.c @@ -1,21 +1,177 @@ // Copyright lowRISC contributors (OpenTitan project). // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 - #include "sw/device/silicon_creator/lib/ownership/ownership.h" #include "sw/device/lib/base/hardened.h" +#include "sw/device/lib/base/hardened_memory.h" #include "sw/device/lib/base/macros.h" #include "sw/device/lib/base/memory.h" +#include "sw/device/silicon_creator/lib/boot_data.h" +#include "sw/device/silicon_creator/lib/dbg_print.h" #include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h" +#include "sw/device/silicon_creator/lib/drivers/hmac.h" #include "sw/device/silicon_creator/lib/error.h" #include "sw/device/silicon_creator/lib/ownership/ecdsa.h" +#include "sw/device/silicon_creator/lib/ownership/owner_block.h" +#include "sw/device/silicon_creator/lib/ownership/ownership.h" #include "sw/device/silicon_creator/lib/ownership/ownership_key.h" // RAM copy of the owner INFO pages from flash. owner_block_t owner_page[2]; +owner_page_status_t owner_page_valid[2]; + +static owner_page_status_t owner_page_validity_check(size_t page) { + size_t seal_len = (uintptr_t)&owner_page[0].seal - (uintptr_t)&owner_page[0]; + size_t sig_len = + (uintptr_t)&owner_page[0].signature - (uintptr_t)&owner_page[0]; + + // TODO(cfrantz): validate owner pages. + // For now, we consider the seal to be just the sha256 over the page. + // This really needs to be the KMAC over the page with a keymgr-created + // sealing secret. + hmac_digest_t digest; + hmac_sha256(&owner_page[page], seal_len, &digest); + if (hardened_memeq(owner_page[page].seal, digest.digest, + ARRAYSIZE(digest.digest)) == kHardenedBoolTrue) { + return kOwnerPageStatusSealed; + } + hardened_bool_t result = ownership_key_validate(page, kOwnershipKeyOwner, + &owner_page[page].signature, + &owner_page[page], sig_len); + if (result == kHardenedBoolFalse) { + // If the page is bad, destroy the RAM copy. + memset(&owner_page[page], 0x5a, sizeof(owner_page[0])); + return kOwnerPageStatusInvalid; + } + return kOwnerPageStatusSigned; +} -rom_error_t ownership_init(void) { +OT_WEAK rom_error_t test_owner_init(boot_data_t *bootdata, + owner_config_t *config, + owner_application_keyring_t *keyring) { + dbg_printf("error: no owner.\r\n"); + return kErrorOwnershipNoOwner; +} + +static rom_error_t locked_owner_init(boot_data_t *bootdata, + owner_config_t *config, + owner_application_keyring_t *keyring) { + if (owner_page_valid[0] == kOwnerPageStatusInvalid && + owner_page_valid[1] == kOwnerPageStatusSealed) { + // Page 0 bad, Page 1 good: copy page 1 to page 0. + memcpy(&owner_page[0], &owner_page[1], sizeof(owner_page[0])); + HARDENED_RETURN_IF_ERROR(flash_ctrl_info_erase( + &kFlashCtrlInfoPageOwnerSlot0, kFlashCtrlEraseTypePage)); + HARDENED_RETURN_IF_ERROR(flash_ctrl_info_write( + &kFlashCtrlInfoPageOwnerSlot0, 0, + sizeof(owner_page[0]) / sizeof(uint32_t), &owner_page[0])); + owner_page_valid[0] = owner_page_valid[1]; + } else if (owner_page_valid[1] == kOwnerPageStatusInvalid && + owner_page_valid[0] == kOwnerPageStatusSealed) { + // Page 1 bad, Page 0 good: copy page 0 to page 1. + memcpy(&owner_page[1], &owner_page[0], sizeof(owner_page[0])); + HARDENED_RETURN_IF_ERROR(flash_ctrl_info_erase( + &kFlashCtrlInfoPageOwnerSlot1, kFlashCtrlEraseTypePage)); + HARDENED_RETURN_IF_ERROR(flash_ctrl_info_write( + &kFlashCtrlInfoPageOwnerSlot1, 0, + sizeof(owner_page[1]) / sizeof(uint32_t), &owner_page[1])); + owner_page_valid[1] = owner_page_valid[0]; + } else if (owner_page_valid[0] != kOwnerPageStatusSealed && + owner_page_valid[1] != kOwnerPageStatusSealed) { + // Neither page is valid; go to the Recovery state. + dbg_printf("error: both owner pages invalid.\r\n"); + bootdata->ownership_state = kOwnershipStateRecovery; + nonce_new(&bootdata->nonce); + HARDENED_RETURN_IF_ERROR(boot_data_write(bootdata)); + return kErrorOwnershipBadInfoPage; + } + HARDENED_RETURN_IF_ERROR(owner_block_parse(&owner_page[0], config, keyring)); + HARDENED_RETURN_IF_ERROR(owner_block_flash_apply(config->flash, kBootSlotA, + bootdata->primary_bl0_slot)); + HARDENED_RETURN_IF_ERROR(owner_block_flash_apply(config->flash, kBootSlotB, + bootdata->primary_bl0_slot)); + HARDENED_RETURN_IF_ERROR(owner_block_info_apply(config->info)); + // TODO: apply SRAM exec config + // TODO: apply rescue config + return kErrorOk; +} + +hardened_bool_t ownership_page1_valid_for_transfer(boot_data_t *bootdata) { + if (bootdata->ownership_state == kOwnershipStateLockedOwner && + owner_page_valid[1] == kOwnerPageStatusSealed) { + return kHardenedBoolTrue; + } + if (owner_page_valid[1] == kOwnerPageStatusSigned) { + hmac_digest_t digest; + switch (bootdata->ownership_state) { + case kOwnershipStateUnlockedAny: + // In UnlockedAny, any valid (signed) Owner Page 1 is acceptable. + return kHardenedBoolTrue; + case kOwnershipStateLockedUpdate: + // In LockedUpdate, the owner key must be the same. If not, + // skip parsing of Owner Page 1. + if (hardened_memeq( + owner_page[0].owner_key.key, owner_page[1].owner_key.key, + ARRAYSIZE(owner_page[0].owner_key.key)) == kHardenedBoolTrue) { + return kHardenedBoolTrue; + } + break; + case kOwnershipStateUnlockedEndorsed: + // In UnlockedEndorsed, the owner key must match the key endorsed by the + // next_owner field in bootdata. If not, skip parsing owner page 1. + hmac_sha256(owner_page[1].owner_key.key, + sizeof(owner_page[1].owner_key.key), &digest); + if (hardened_memeq(bootdata->next_owner, digest.digest, + ARRAYSIZE(digest.digest)) == kHardenedBoolTrue) { + return kHardenedBoolTrue; + } + break; + default: + /* nothing */; + } + } + return kHardenedBoolFalse; +} + +static rom_error_t unlocked_init(boot_data_t *bootdata, owner_config_t *config, + owner_application_keyring_t *keyring) { + uint32_t secondary = + bootdata->primary_bl0_slot == kBootSlotA ? kBootSlotB : kBootSlotA; + if (bootdata->ownership_state == kOwnershipStateLockedUpdate && + owner_page_valid[0] != kOwnerPageStatusSealed) { + // Owner Page 0 must be sealed in the "LockedUpdate" state. If not, + // go to the Recovery state. + bootdata->ownership_state = kOwnershipStateRecovery; + nonce_new(&bootdata->nonce); + HARDENED_RETURN_IF_ERROR(boot_data_write(bootdata)); + return kErrorOwnershipBadInfoPage; + } + + if (owner_page_valid[0] == kOwnerPageStatusSealed) { + // Configure the primary half of the flash as Owner Page 0 requests. + HARDENED_RETURN_IF_ERROR( + owner_block_parse(&owner_page[0], config, keyring)); + HARDENED_RETURN_IF_ERROR(owner_block_flash_apply( + config->flash, bootdata->primary_bl0_slot, bootdata->primary_bl0_slot)); + } + + if (ownership_page1_valid_for_transfer(bootdata) == kHardenedBoolTrue) { + // If we passed the validity test for Owner Page 1, parse the configuration + // and add its keys to the keyring. + HARDENED_RETURN_IF_ERROR( + owner_block_parse(&owner_page[1], config, keyring)); + } + HARDENED_RETURN_IF_ERROR(owner_block_flash_apply(config->flash, secondary, + bootdata->primary_bl0_slot)); + HARDENED_RETURN_IF_ERROR(owner_block_info_apply(config->info)); + // TODO: apply SRAM exec config + // TODO: apply rescue config + return kErrorOk; +} + +rom_error_t ownership_init(boot_data_t *bootdata, owner_config_t *config, + owner_application_keyring_t *keyring) { flash_ctrl_perms_t perm = { .read = kMultiBitBool4True, .write = kMultiBitBool4True, @@ -31,33 +187,23 @@ rom_error_t ownership_init(void) { flash_ctrl_info_cfg_set(&kFlashCtrlInfoPageOwnerSlot1, cfg); // We don't want to abort ownership setup if we fail to // read the INFO pages, so we discard the error result. - OT_DISCARD(flash_ctrl_info_read(&kFlashCtrlInfoPageOwnerSlot0, 0, - sizeof(owner_page[0]) / sizeof(uint32_t), - &owner_page[0])); - OT_DISCARD(flash_ctrl_info_read(&kFlashCtrlInfoPageOwnerSlot1, 0, - sizeof(owner_page[1]) / sizeof(uint32_t), - &owner_page[1])); - - // TODO(cfrantz): validate owner pages. - // For now, just validate the signature on the page - size_t len = (uintptr_t)&owner_page[0].signature - (uintptr_t)&owner_page[0]; - hardened_bool_t result; - result = - ownership_key_validate(/*page=*/0, kOwnershipKeyOwner, - &owner_page[0].signature, &owner_page[0], len); - if (result == kHardenedBoolFalse) { - // If the page is bad, destroy the RAM copy. - memset(&owner_page[0], 0xFF, sizeof(owner_page[0])); + if (flash_ctrl_info_read(&kFlashCtrlInfoPageOwnerSlot0, 0, + sizeof(owner_page[0]) / sizeof(uint32_t), + &owner_page[0]) == kErrorOk) { + owner_page_valid[0] = owner_page_validity_check(0); + } else { + owner_page_valid[0] = kOwnerPageStatusInvalid; + memset(&owner_page[0], 0xff, sizeof(owner_page[0])); } - result = - ownership_key_validate(/*page=*/0, kOwnershipKeyOwner, - &owner_page[0].signature, &owner_page[0], len); - if (result == kHardenedBoolFalse) { - // If the page is bad, destroy the RAM copy;. - memset(&owner_page[1], 0xFF, sizeof(owner_page[1])); + if (flash_ctrl_info_read(&kFlashCtrlInfoPageOwnerSlot1, 0, + sizeof(owner_page[1]) / sizeof(uint32_t), + &owner_page[1]) == kErrorOk) { + owner_page_valid[1] = owner_page_validity_check(1); + } else { + owner_page_valid[1] = kOwnerPageStatusInvalid; + memset(&owner_page[1], 0xff, sizeof(owner_page[1])); } - // TOOD(cfrantz): // Depending on ownership state: // - kOwnershipStateLockedOwner: // - Make sure page0 and page1 are identical and fix if not. @@ -75,9 +221,35 @@ rom_error_t ownership_init(void) { // - Allow the pages to be different. // - Set up flash config: primary from page0, secondary from page 1. // - Enumerate application keys from both pages. - // - kOwnershipStateLockedNone: Allow the pages to be different. + // - kOwnershipStateRecovery: Allow the pages to be different. // - Disaster state. Do nothing and wait for remediation via // the recovery key. - return kErrorOk; + dbg_printf("ownership: %C\r\n", bootdata->ownership_state); + owner_config_default(config); + rom_error_t error = kErrorOwnershipNoOwner; + switch (bootdata->ownership_state) { + case kOwnershipStateLockedOwner: + error = locked_owner_init(bootdata, config, keyring); + break; + case kOwnershipStateLockedUpdate: + OT_FALLTHROUGH_INTENDED; + case kOwnershipStateUnlockedAny: + OT_FALLTHROUGH_INTENDED; + case kOwnershipStateUnlockedEndorsed: + error = unlocked_init(bootdata, config, keyring); + break; + default: + // The `test_owner_init` function is weak and the default implementation + // does nothing. + error = test_owner_init(bootdata, config, keyring); + } + return error; +} + +void ownership_page_seal(size_t page) { + size_t seal_len = (uintptr_t)&owner_page[0].seal - (uintptr_t)&owner_page[0]; + hmac_digest_t digest; + hmac_sha256(&owner_page[page], seal_len, &digest); + memcpy(&owner_page[page].seal, digest.digest, sizeof(digest.digest)); } diff --git a/sw/device/silicon_creator/lib/ownership/ownership.h b/sw/device/silicon_creator/lib/ownership/ownership.h index c8b587e83cdbf..53501c9164850 100644 --- a/sw/device/silicon_creator/lib/ownership/ownership.h +++ b/sw/device/silicon_creator/lib/ownership/ownership.h @@ -6,17 +6,49 @@ #define OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_OWNERSHIP_OWNERSHIP_H_ #include "sw/device/lib/base/hardened.h" +#include "sw/device/silicon_creator/lib/boot_data.h" #include "sw/device/silicon_creator/lib/error.h" #include "sw/device/silicon_creator/lib/ownership/datatypes.h" +#include "sw/device/silicon_creator/lib/ownership/owner_block.h" + +/** + * The signature or sealing status of an owner page. + */ +typedef enum owner_page_status { + /** Invalid: `INV_`. */ + kOwnerPageStatusInvalid = 0x5f564e49, + /** Sealed: `SEAL`. */ + kOwnerPageStatusSealed = 0x4c414553, + /** Signed: `SIGN`. */ + kOwnerPageStatusSigned = 0x4e474953, +} owner_page_status_t; /** * RAM copies of the owner pages read out of flash INFO pages. */ extern owner_block_t owner_page[2]; +extern owner_page_status_t owner_page_valid[2]; /** * Initialize the owner pages from flash */ -rom_error_t ownership_init(void); +rom_error_t ownership_init(boot_data_t *bootdata, owner_config_t *config, + owner_application_keyring_t *keyring); + +/** + * Check if owner page 1 is valid for ownership transfer. + * + * @param bootdata The current bootdata. + * @return kHardenedBoolTrue if page 1 is valid. + */ +hardened_bool_t ownership_page1_valid_for_transfer(boot_data_t *bootdata); +/** + * Seal an owner page. + * + * Calculates and applies the seal to an owner page in RAM. + * + * @param page Which owner page to seal. + */ +void ownership_page_seal(size_t page); #endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_OWNERSHIP_OWNERSHIP_H_ diff --git a/sw/device/silicon_creator/lib/ownership/ownership_activate.c b/sw/device/silicon_creator/lib/ownership/ownership_activate.c new file mode 100644 index 0000000000000..96b9f2bc73ae1 --- /dev/null +++ b/sw/device/silicon_creator/lib/ownership/ownership_activate.c @@ -0,0 +1,88 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#include "sw/device/silicon_creator/lib/ownership/ownership_activate.h" + +#include "sw/device/lib/base/macros.h" +#include "sw/device/lib/base/memory.h" +#include "sw/device/silicon_creator/lib/boot_data.h" +#include "sw/device/silicon_creator/lib/boot_svc/boot_svc_msg.h" +#include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h" +#include "sw/device/silicon_creator/lib/error.h" +#include "sw/device/silicon_creator/lib/ownership/ecdsa.h" +#include "sw/device/silicon_creator/lib/ownership/ownership.h" +#include "sw/device/silicon_creator/lib/ownership/ownership_key.h" + +static rom_error_t activate(boot_svc_msg_t *msg, boot_data_t *bootdata) { + size_t len = (uintptr_t)&msg->ownership_activate_req.signature - + (uintptr_t)&msg->ownership_activate_req.primary_bl0_slot; + // First check if page1 is even in a valid state for a transfer. + if (ownership_page1_valid_for_transfer(bootdata) != kHardenedBoolTrue) { + return kErrorOwnershipInvalidInfoPage; + } + + // Check the activation key and the nonce. + if (ownership_key_validate(/*page=*/1, kOwnershipKeyActivate, + &msg->ownership_activate_req.signature, + &msg->ownership_activate_req.primary_bl0_slot, + len) == kHardenedBoolFalse) { + return kErrorOwnershipInvalidSignature; + } + if (!nonce_equal(&msg->ownership_activate_req.nonce, &bootdata->nonce)) { + return kErrorOwnershipInvalidNonce; + } + + // Seal page one to this chip. + ownership_page_seal(/*page=*/1); + + // TODO(cfrantz): Consider reading back the flash pages to check that the + // flash writes succeeded. + // + // Program the sealed page into slot 1. + HARDENED_RETURN_IF_ERROR(flash_ctrl_info_erase(&kFlashCtrlInfoPageOwnerSlot1, + kFlashCtrlEraseTypePage)); + HARDENED_RETURN_IF_ERROR(flash_ctrl_info_write( + &kFlashCtrlInfoPageOwnerSlot1, 0, + sizeof(owner_page[1]) / sizeof(uint32_t), &owner_page[1])); + + // Program the same data into slot 0. + HARDENED_RETURN_IF_ERROR(flash_ctrl_info_erase(&kFlashCtrlInfoPageOwnerSlot0, + kFlashCtrlEraseTypePage)); + HARDENED_RETURN_IF_ERROR(flash_ctrl_info_write( + &kFlashCtrlInfoPageOwnerSlot0, 0, + sizeof(owner_page[1]) / sizeof(uint32_t), &owner_page[1])); + + // The requested primary_bl0_slot is user input. Validate and clamp it to + // legal values. + if (msg->ownership_activate_req.primary_bl0_slot == kBootSlotB) { + bootdata->primary_bl0_slot = kBootSlotB; + } else { + bootdata->primary_bl0_slot = kBootSlotA; + } + + // Set the ownership state to LockedOwner. + nonce_new(&bootdata->nonce); + bootdata->ownership_state = kOwnershipStateLockedOwner; + bootdata->ownership_transfers += 1; + memset(bootdata->next_owner, 0, sizeof(bootdata->next_owner)); + return kErrorWriteBootdataThenReboot; +} + +rom_error_t ownership_activate_handler(boot_svc_msg_t *msg, + boot_data_t *bootdata) { + rom_error_t error = kErrorOwnershipInvalidState; + switch (bootdata->ownership_state) { + case kOwnershipStateLockedUpdate: + case kOwnershipStateUnlockedAny: + case kOwnershipStateUnlockedEndorsed: + error = activate(msg, bootdata); + break; + default: + /* nothing */; + } + boot_svc_ownership_activate_res_init( + error == kErrorWriteBootdataThenReboot ? kErrorOk : error, + &msg->ownership_activate_res); + return error; +} diff --git a/sw/device/silicon_creator/lib/ownership/ownership_activate.h b/sw/device/silicon_creator/lib/ownership/ownership_activate.h new file mode 100644 index 0000000000000..89230f9300935 --- /dev/null +++ b/sw/device/silicon_creator/lib/ownership/ownership_activate.h @@ -0,0 +1,29 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#ifndef OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_OWNERSHIP_OWNERSHIP_ACTIVATE_H_ +#define OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_OWNERSHIP_OWNERSHIP_ACTIVATE_H_ + +#include "sw/device/silicon_creator/lib/boot_data.h" +#include "sw/device/silicon_creator/lib/boot_svc/boot_svc_msg.h" +#include "sw/device/silicon_creator/lib/error.h" + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * Process a boot_svc OwnershipActivate message. + * + * @param msg The boot_svc OwnershipActivate message to process. + * @param bootdata A pointer to the current boot_data in RAM. + * @return rom_error_t + */ +rom_error_t ownership_activate_handler(boot_svc_msg_t *msg, + boot_data_t *bootdata); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus +#endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_OWNERSHIP_OWNERSHIP_ACTIVATE_H_ diff --git a/sw/device/silicon_creator/lib/ownership/ownership_activate_unittest.cc b/sw/device/silicon_creator/lib/ownership/ownership_activate_unittest.cc new file mode 100644 index 0000000000000..639b76fadd5d8 --- /dev/null +++ b/sw/device/silicon_creator/lib/ownership/ownership_activate_unittest.cc @@ -0,0 +1,236 @@ +// Copyright lowRISC contributors (OpenTitan project). +// Licensed under the Apache License, Version 2.0, see LICENSE for details. +// SPDX-License-Identifier: Apache-2.0 + +#include "sw/device/silicon_creator/lib/ownership/ownership_activate.h" + +#include + +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include "sw/device/lib/base/global_mock.h" +#include "sw/device/lib/base/hardened.h" +#include "sw/device/silicon_creator/lib/boot_data.h" +#include "sw/device/silicon_creator/lib/boot_svc/mock_boot_svc_header.h" +#include "sw/device/silicon_creator/lib/drivers/mock_flash_ctrl.h" +#include "sw/device/silicon_creator/lib/drivers/mock_hmac.h" +#include "sw/device/silicon_creator/lib/drivers/mock_rnd.h" +#include "sw/device/silicon_creator/lib/error.h" +#include "sw/device/silicon_creator/lib/nonce.h" +#include "sw/device/silicon_creator/lib/ownership/datatypes.h" +#include "sw/device/silicon_creator/lib/ownership/mock_ownership_key.h" +#include "sw/device/silicon_creator/lib/ownership/ownership.h" +#include "sw/device/silicon_creator/testing/rom_test.h" + +namespace { +using ::testing::_; +using ::testing::Return; +using ::testing::SetArgPointee; + +constexpr nonce_t kDefaultNonce = {1, 2}; + +class OwnershipActivateTest : public rom_test::RomTest { + protected: + void MakePage1Valid(bool valid) { + ownership_state_t state = + static_cast(bootdata_.ownership_state); + owner_page_valid[1] = kOwnerPageStatusSigned; + uint32_t modifier = valid ? 0 : 1; + switch (state) { + case kOwnershipStateUnlockedEndorsed: + // In UnlockedEndorsed, the hash of the owner key in page1 must be equal + // to the value stored in boot_data. + EXPECT_CALL(hmac_, sha256(_, _, _)) + .WillOnce(SetArgPointee<2>((hmac_digest_t){{ + bootdata_.next_owner[0] + modifier, + bootdata_.next_owner[1], + bootdata_.next_owner[2], + bootdata_.next_owner[3], + bootdata_.next_owner[4], + bootdata_.next_owner[5], + bootdata_.next_owner[6], + bootdata_.next_owner[7], + }})); + case kOwnershipStateLockedUpdate: + owner_page[1].owner_key = owner_page[0].owner_key; + owner_page[1].owner_key.key[0] += modifier; + break; + case kOwnershipStateUnlockedAny: + // In UnlockedAny, there are no conditions that page1 must meet. + break; + case kOwnershipStateLockedOwner: + owner_page_valid[1] = kOwnerPageStatusSealed; + break; + case kOwnershipStateLockedNone: + owner_page_valid[1] = kOwnerPageStatusInvalid; + break; + } + } + + boot_data_t bootdata_ = { + .nonce = kDefaultNonce, + .ownership_state = kOwnershipStateLockedOwner, + }; + boot_svc_msg_t message_ = { + .ownership_activate_req = + { + .header = + { + .type = kBootSvcOwnershipActivateReqType, + }, + .nonce = kDefaultNonce, + }, + }; + + rom_test::MockHmac hmac_; + rom_test::MockRnd rnd_; + rom_test::MockFlashCtrl flash_ctrl_; + rom_test::MockBootSvcHeader hdr_; + rom_test::MockOwnershipKey ownership_key_; +}; + +class OwnershipActivateInvalidStateTest + : public OwnershipActivateTest, + public testing::WithParamInterface {}; + +class OwnershipActivateValidStateTest + : public OwnershipActivateTest, + public testing::WithParamInterface {}; + +// Tests that requesting Activate in all Locked non-Update states fails. +TEST_P(OwnershipActivateInvalidStateTest, InvalidState) { + bootdata_.ownership_state = static_cast(GetParam()); + EXPECT_CALL(hdr_, Finalize(_, _, _)); + + rom_error_t error = ownership_activate_handler(&message_, &bootdata_); + EXPECT_EQ(error, kErrorOwnershipInvalidState); +} + +INSTANTIATE_TEST_SUITE_P(AllCases, OwnershipActivateInvalidStateTest, + testing::Values(kOwnershipStateLockedOwner, + kOwnershipStateLockedNone)); + +// Tests that an owner block with an invalid signature fails. +TEST_P(OwnershipActivateValidStateTest, InvalidSignature) { + bootdata_.ownership_state = static_cast(GetParam()); + // We want to pass the page 1 validity test to check the signature on the + // message. + MakePage1Valid(true); + EXPECT_CALL(ownership_key_, validate(1, kOwnershipKeyActivate, _, _, _)) + .WillOnce(Return(kHardenedBoolFalse)); + EXPECT_CALL(hdr_, Finalize(_, _, _)); + + rom_error_t error = ownership_activate_handler(&message_, &bootdata_); + EXPECT_EQ(error, kErrorOwnershipInvalidSignature); +} + +// Tests that an owner block with an invalid nonce fails. +TEST_P(OwnershipActivateValidStateTest, InvalidNonce) { + bootdata_.ownership_state = static_cast(GetParam()); + bootdata_.nonce = {3, 4}; + // We want to pass the page 1 validity test to check the nonce of the + // message. + MakePage1Valid(true); + EXPECT_CALL(ownership_key_, validate(1, kOwnershipKeyActivate, _, _, _)) + .WillOnce(Return(kHardenedBoolTrue)); + EXPECT_CALL(hdr_, Finalize(_, _, _)); + + rom_error_t error = ownership_activate_handler(&message_, &bootdata_); + EXPECT_EQ(error, kErrorOwnershipInvalidNonce); +} + +// Tests that an owner block with an invalid owner page with respect to the +// current update state fails. +TEST_P(OwnershipActivateValidStateTest, OwnerPageInvalid) { + ownership_state_t state = GetParam(); + if (state == kOwnershipStateUnlockedAny) { + SUCCEED() << "There are no invalid conditions for UnlockedAny"; + return; + } + bootdata_.ownership_state = static_cast(state); + + rom_error_t expected_result = kErrorOk; + owner_page[0].owner_key = {{1, 2, 3, 4, 5}}; + bootdata_.next_owner[0] = 12345; + MakePage1Valid(false); + + switch (state) { + case kOwnershipStateLockedUpdate: + case kOwnershipStateUnlockedEndorsed: + // Test should fail with "Invalid Info Page". + expected_result = kErrorOwnershipInvalidInfoPage; + break; + default: + FAIL() << "Invalid state for this test: " << state; + } + + EXPECT_CALL(hdr_, Finalize(_, _, _)); + + rom_error_t error = ownership_activate_handler(&message_, &bootdata_); + EXPECT_EQ(error, expected_result); +} + +// Tests that an owner block with a valid owner page with respect to the current +// update state succeeds. +TEST_P(OwnershipActivateValidStateTest, OwnerPageValid) { + ownership_state_t state = GetParam(); + bootdata_.ownership_state = static_cast(state); + + owner_page[0].owner_key = {{1}}; + memset(bootdata_.next_owner, 0, sizeof(bootdata_.next_owner)); + bootdata_.next_owner[0] = 12345; + MakePage1Valid(true); + + EXPECT_CALL(ownership_key_, validate(1, kOwnershipKeyActivate, _, _, _)) + .WillOnce(Return(kHardenedBoolTrue)); + + switch (state) { + case kOwnershipStateLockedUpdate: + case kOwnershipStateUnlockedAny: + case kOwnershipStateUnlockedEndorsed: + // Test should pass. + break; + default: + FAIL() << "Invalid state for this test: " << state; + } + // Once the new owner page is determined to be valid, the page will be sealed. + EXPECT_CALL(hmac_, sha256(_, _, _)) + .WillOnce(SetArgPointee<2>((hmac_digest_t){{0x5a5a5a5a}})); + + // The sealed page will be written into flash owner slot 1 first. + EXPECT_CALL(flash_ctrl_, + InfoErase(&kFlashCtrlInfoPageOwnerSlot1, kFlashCtrlEraseTypePage)) + .WillOnce(Return(kErrorOk)); + EXPECT_CALL(flash_ctrl_, InfoWrite(&kFlashCtrlInfoPageOwnerSlot1, 0, + sizeof(owner_page[1]) / sizeof(uint32_t), + &owner_page[1])) + .WillOnce(Return(kErrorOk)); + // The sealed page will be written into flash owner slot 0 second. + EXPECT_CALL(flash_ctrl_, + InfoErase(&kFlashCtrlInfoPageOwnerSlot0, kFlashCtrlEraseTypePage)) + .WillOnce(Return(kErrorOk)); + EXPECT_CALL(flash_ctrl_, InfoWrite(&kFlashCtrlInfoPageOwnerSlot0, 0, + sizeof(owner_page[1]) / sizeof(uint32_t), + &owner_page[1])) + .WillOnce(Return(kErrorOk)); + + // The nonce will be regenerated. + EXPECT_CALL(rnd_, Uint32()).WillRepeatedly(Return(99)); + // The boot_svc response will be finalized. + EXPECT_CALL(hdr_, Finalize(_, _, _)); + + rom_error_t error = ownership_activate_handler(&message_, &bootdata_); + EXPECT_EQ(error, kErrorWriteBootdataThenReboot); + // After succeeding, the page should be sealed, the nonce changed and the + // ownership state set to LocedOwner. + EXPECT_EQ(owner_page[1].seal[0], 0x5a5a5a5a); + EXPECT_FALSE(nonce_equal(&bootdata_.nonce, &kDefaultNonce)); + EXPECT_EQ(bootdata_.ownership_state, kOwnershipStateLockedOwner); +} + +INSTANTIATE_TEST_SUITE_P(AllCases, OwnershipActivateValidStateTest, + testing::Values(kOwnershipStateLockedUpdate, + kOwnershipStateUnlockedAny, + kOwnershipStateUnlockedEndorsed)); + +} // namespace diff --git a/sw/device/silicon_creator/lib/ownership/ownership_key.h b/sw/device/silicon_creator/lib/ownership/ownership_key.h index 16adc9b12e1ff..fe013f2e2b49b 100644 --- a/sw/device/silicon_creator/lib/ownership/ownership_key.h +++ b/sw/device/silicon_creator/lib/ownership/ownership_key.h @@ -11,7 +11,7 @@ /** * The OwnershipNoOwnerRecoveryKey is a silicon_creator key that allows - * recovery of a device should it get into the LockedNone state (ie: + * recovery of a device should it get into the Recovery state (ie: * a state where there is no valid owner). */ extern const owner_key_t *const kNoOwnerRecoveryKey; diff --git a/sw/device/silicon_creator/lib/ownership/test_owner.c b/sw/device/silicon_creator/lib/ownership/test_owner.c index 248f255ce6de3..f059d7a3e32ad 100644 --- a/sw/device/silicon_creator/lib/ownership/test_owner.c +++ b/sw/device/silicon_creator/lib/ownership/test_owner.c @@ -2,8 +2,10 @@ // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 +#include "sw/device/lib/base/macros.h" #include "sw/device/lib/base/memory.h" #include "sw/device/silicon_creator/lib/dbg_print.h" +#include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h" #include "sw/device/silicon_creator/lib/error.h" #include "sw/device/silicon_creator/lib/ownership/keys/fake/activate_ecdsa_p256.h" #include "sw/device/silicon_creator/lib/ownership/keys/fake/app_dev_key_rsa_3072_exp_f4.h" @@ -22,6 +24,9 @@ rom_error_t test_owner_init(boot_data_t *bootdata, owner_config_t *config, owner_application_keyring_t *keyring) { + bool flash_invalid = owner_page[0].header.tag == 0xFFFFFFFF && + owner_page[1].header.tag == 0xFFFFFFFF; + owner_page[0].header.tag = kTlvTagOwner; owner_page[0].header.length = 2048; owner_page[0].version = 0; @@ -92,12 +97,20 @@ rom_error_t test_owner_init(boot_data_t *bootdata, owner_config_t *config, RETURN_IF_ERROR(owner_block_flash_apply(config->flash, kBootSlotB, bootdata->primary_bl0_slot)); RETURN_IF_ERROR(owner_block_info_apply(config->info)); - // TODO: apply SRAM exec config - // TODO: apply rescue config // Since this module should only get linked in to FPGA builds, we can simply // thunk the ownership state to LockedOwner. bootdata->ownership_state = kOwnershipStateLockedOwner; - dbg_printf("Test owner initialized\r\n"); + if (flash_invalid) { + OT_DISCARD(flash_ctrl_info_erase(&kFlashCtrlInfoPageOwnerSlot0, + kFlashCtrlEraseTypePage)); + OT_DISCARD(flash_ctrl_info_write(&kFlashCtrlInfoPageOwnerSlot0, 0, + sizeof(owner_page[0]) / sizeof(uint32_t), + &owner_page[0])); + OT_DISCARD(boot_data_write(bootdata)); + dbg_printf("Test owner flash initialized\r\n"); + } else { + dbg_printf("Test owner ram initialized\r\n"); + } return kErrorOk; } diff --git a/sw/device/silicon_creator/rom_ext/BUILD b/sw/device/silicon_creator/rom_ext/BUILD index 8fdad703cc269..2617af6ec9da0 100644 --- a/sw/device/silicon_creator/rom_ext/BUILD +++ b/sw/device/silicon_creator/rom_ext/BUILD @@ -35,6 +35,7 @@ cc_library( deps = [ "//hw/top_earlgrey/ip_autogen/flash_ctrl:flash_ctrl_c_regs", "//sw/device/lib/base:memory", + "//sw/device/silicon_creator/lib:boot_data", "//sw/device/silicon_creator/lib:dbg_print", "//sw/device/silicon_creator/lib:error", "//sw/device/silicon_creator/lib:xmodem", @@ -257,6 +258,7 @@ cc_library( "//sw/device/silicon_creator/lib/drivers:rnd", "//sw/device/silicon_creator/lib/drivers:uart", "//sw/device/silicon_creator/lib/ownership", + "//sw/device/silicon_creator/lib/ownership:ownership_activate", "//sw/device/silicon_creator/lib/ownership:ownership_unlock", "//sw/device/silicon_creator/lib/sigverify", "//sw/otbn/crypto:boot", @@ -274,6 +276,7 @@ manifest(d = { opentitan_binary( name = "rom_ext_slot_a", + testonly = True, # TODO(#22780): Integrate real keys for A1 flows. ecdsa_key = {"//sw/device/silicon_creator/rom/keys/fake/ecdsa:prod_key_0_ecdsa_p256": "prod_key_0"}, exec_env = [ @@ -290,13 +293,14 @@ opentitan_binary( ":rom_ext", "//sw/device/lib/crt", "//sw/device/silicon_creator/lib:manifest_def", + "//sw/device/silicon_creator/lib/ownership:test_owner", "//sw/device/silicon_creator/lib/ownership/keys/fake", - "//sw/device/silicon_creator/rom_ext/keys/fake", ], ) opentitan_binary( name = "rom_ext_slot_b", + testonly = True, # TODO(#22780): Integrate real keys for A1 flows. ecdsa_key = {"//sw/device/silicon_creator/rom/keys/fake/ecdsa:prod_key_0_ecdsa_p256": "prod_key_0"}, exec_env = [ @@ -313,13 +317,14 @@ opentitan_binary( ":rom_ext", "//sw/device/lib/crt", "//sw/device/silicon_creator/lib:manifest_def", + "//sw/device/silicon_creator/lib/ownership:test_owner", "//sw/device/silicon_creator/lib/ownership/keys/fake", - "//sw/device/silicon_creator/rom_ext/keys/fake", ], ) opentitan_binary( name = "rom_ext_slot_virtual", + testonly = True, # TODO(#22780): Integrate real keys for A1 flows. ecdsa_key = {"//sw/device/silicon_creator/rom/keys/fake/ecdsa:prod_key_0_ecdsa_p256": "prod_key_0"}, exec_env = [ @@ -335,8 +340,8 @@ opentitan_binary( ":rom_ext", "//sw/device/lib/crt", "//sw/device/silicon_creator/lib:manifest_def", + "//sw/device/silicon_creator/lib/ownership:test_owner", "//sw/device/silicon_creator/lib/ownership/keys/fake", - "//sw/device/silicon_creator/rom_ext/keys/fake", ], ) diff --git a/sw/device/silicon_creator/rom_ext/e2e/boot_svc/BUILD b/sw/device/silicon_creator/rom_ext/e2e/boot_svc/BUILD index e9d9513c4b2c2..f4e2889643f29 100644 --- a/sw/device/silicon_creator/rom_ext/e2e/boot_svc/BUILD +++ b/sw/device/silicon_creator/rom_ext/e2e/boot_svc/BUILD @@ -186,7 +186,7 @@ opentitan_test( --exec="fpga clear-bitstream" --exec="fpga load-bitstream {bitstream}" --exec="bootstrap --clear-uart=true {firmware}" - --exec="console --non-interactive --exit-success='ownership_state = .x00.x00.x00.x00\r\n' --exit-failure='{exit_failure}'" + --exec="console --non-interactive --exit-success='ownership_state: \\x00\\x00\\x00\\x00\r\n' --exit-failure='{exit_failure}'" --exec="rescue boot-svc ownership-unlock \ --mode Any \ --nonce 0 \ diff --git a/sw/device/silicon_creator/rom_ext/rom_ext.c b/sw/device/silicon_creator/rom_ext/rom_ext.c index 09be2ba3f35c4..bf95f9b9a214b 100644 --- a/sw/device/silicon_creator/rom_ext/rom_ext.c +++ b/sw/device/silicon_creator/rom_ext/rom_ext.c @@ -43,6 +43,7 @@ #include "sw/device/silicon_creator/lib/manifest_def.h" #include "sw/device/silicon_creator/lib/otbn_boot_services.h" #include "sw/device/silicon_creator/lib/ownership/ownership.h" +#include "sw/device/silicon_creator/lib/ownership/ownership_activate.h" #include "sw/device/silicon_creator/lib/ownership/ownership_unlock.h" #include "sw/device/silicon_creator/lib/shutdown.h" #include "sw/device/silicon_creator/lib/sigverify/ecdsa_p256_key.h" @@ -70,6 +71,12 @@ extern const char _rom_chip_info_start[]; // Life cycle state of the chip. lifecycle_state_t lc_state = kLcStateProd; +// Owner configuration details parsed from the onwer info pages. +owner_config_t owner_config; + +// Owner application keys. +owner_application_keyring_t keyring; + // ePMP regions for important address spaces. const epmp_region_t kRamRegion = { .start = TOP_EARLGREY_RAM_MAIN_BASE_ADDR, @@ -236,9 +243,13 @@ OT_WARN_UNUSED_RESULT static rom_error_t rom_ext_verify(const manifest_t *manifest, const boot_data_t *boot_data) { RETURN_IF_ERROR(rom_ext_boot_policy_manifest_check(manifest, boot_data)); - const sigverify_rsa_key_t *key; - RETURN_IF_ERROR(sigverify_rsa_key_get( - sigverify_rsa_key_id_get(&manifest->rsa_modulus), &key)); + size_t kindex = 0; + RETURN_IF_ERROR(owner_keyring_find_key( + &keyring, kOwnershipKeyAlgRsa, + sigverify_rsa_key_id_get(&manifest->rsa_modulus), &kindex)); + + dbg_printf("application key %u: alg=%C domain=%C\r\n", kindex, + keyring.key[kindex]->key_alg, keyring.key[kindex]->key_domain); memset(boot_measurements.bl0.data, (int)rnd_uint32(), sizeof(boot_measurements.bl0.data)); @@ -264,7 +275,8 @@ static rom_error_t rom_ext_verify(const manifest_t *manifest, memcpy(&boot_measurements.bl0, &act_digest, sizeof(boot_measurements.bl0)); uint32_t flash_exec = 0; - return sigverify_rsa_verify(&manifest->rsa_signature, key, &act_digest, + return sigverify_rsa_verify(&manifest->rsa_signature, + &keyring.key[kindex]->data.rsa, &act_digest, lc_state, &flash_exec); } @@ -760,10 +772,14 @@ static rom_error_t handle_boot_svc(boot_data_t *boot_data) { case kBootSvcOwnershipUnlockReqType: HARDENED_CHECK_EQ(msg_type, kBootSvcOwnershipUnlockReqType); return ownership_unlock_handler(boot_svc_msg, boot_data); + case kBootSvcOwnershipActivateReqType: + HARDENED_CHECK_EQ(msg_type, kBootSvcOwnershipActivateReqType); + return ownership_activate_handler(boot_svc_msg, boot_data); case kBootSvcEmptyResType: case kBootSvcNextBl0SlotResType: case kBootSvcMinBl0SecVerResType: case kBootSvcOwnershipUnlockResType: + case kBootSvcOwnershipActivateResType: // For response messages left in ret-ram we do nothing. break; default: @@ -775,7 +791,8 @@ static rom_error_t handle_boot_svc(boot_data_t *boot_data) { } OT_WARN_UNUSED_RESULT -static rom_error_t rom_ext_try_next_stage(boot_data_t *boot_data) { +static rom_error_t rom_ext_try_next_stage(boot_data_t *boot_data, + boot_log_t *boot_log) { rom_ext_boot_policy_manifests_t manifests = rom_ext_boot_policy_manifests_get(boot_data); rom_error_t error = kErrorRomExtBootFailed; @@ -787,7 +804,6 @@ static rom_error_t rom_ext_try_next_stage(boot_data_t *boot_data) { continue; } - boot_log_t *boot_log = &retention_sram_get()->creator.boot_log; if (manifests.ordered[i] == rom_ext_boot_policy_manifest_a_get()) { boot_log->bl0_slot = kBootSlotA; } else if (manifests.ordered[i] == rom_ext_boot_policy_manifest_b_get()) { @@ -845,10 +861,13 @@ static rom_error_t rom_ext_start(boot_data_t *boot_data, boot_log_t *boot_log) { boot_log->primary_bl0_slot = boot_data->primary_bl0_slot; // Initialize the chip ownership state. - HARDENED_RETURN_IF_ERROR(ownership_init()); + rom_error_t error; + error = ownership_init(boot_data, &owner_config, &keyring); + if (error == kErrorWriteBootdataThenReboot) { + return error; + } // Handle any pending boot_svc commands. - rom_error_t error; uint32_t reset_reasons = retention_sram_get()->creator.reset_reasons; uint32_t skip_boot_svc = reset_reasons & (1 << kRstmgrReasonLowPowerExit); if (skip_boot_svc == 0) { @@ -870,9 +889,11 @@ static rom_error_t rom_ext_start(boot_data_t *boot_data, boot_log_t *boot_log) { if (uart_break_detect(kRescueDetectTime) == kHardenedBoolTrue) { dbg_printf("rescue: remember to clear break\r\n"); uart_enable_receiver(); + // TODO: update rescue protocol to accept boot data and rescue + // config from the owner_config. error = rescue_protocol(); } else { - error = rom_ext_try_next_stage(boot_data); + error = rom_ext_try_next_stage(boot_data, boot_log); } return error; } diff --git a/sw/host/opentitanlib/src/chip/boot_log.rs b/sw/host/opentitanlib/src/chip/boot_log.rs index b6211f7041171..f79346a189d59 100644 --- a/sw/host/opentitanlib/src/chip/boot_log.rs +++ b/sw/host/opentitanlib/src/chip/boot_log.rs @@ -14,8 +14,8 @@ use super::ChipDataError; use crate::with_unknown; with_unknown! { - pub enum OwnershipState: u32 [default = Self::None] { - None = 0, + pub enum OwnershipState: u32 [default = Self::Recovery] { + Recovery = 0, LockedOwner = 0x444e574f, LockedUpdate = 0x4450554c, UnlockedAny = 0x594e4155, diff --git a/sw/host/opentitanlib/src/chip/boot_svc.rs b/sw/host/opentitanlib/src/chip/boot_svc.rs index a5e163274823f..e65e598792b9c 100644 --- a/sw/host/opentitanlib/src/chip/boot_svc.rs +++ b/sw/host/opentitanlib/src/chip/boot_svc.rs @@ -45,7 +45,7 @@ with_unknown! { NextBl0SlotRequest = u32::from_le_bytes(*b"NEXT"), NextBl0SlotResponse = u32::from_le_bytes(*b"TXEN"), OwnershipUnlockRequest = u32::from_le_bytes(*b"UNLK"), - OwnershipUnlockResponse = u32::from_le_bytes(*b"LKNU"), + OwnershipUnlockResponse = u32::from_le_bytes(*b"KLNU"), OwnershipActivateRequest = u32::from_le_bytes(*b"ACTV"), OwnershipActivateResponse = u32::from_le_bytes(*b"VTCA"), }