diff --git a/sw/device/silicon_creator/lib/ownership/datatypes.h b/sw/device/silicon_creator/lib/ownership/datatypes.h index f433288c76bff..166f80f0089ef 100644 --- a/sw/device/silicon_creator/lib/ownership/datatypes.h +++ b/sw/device/silicon_creator/lib/ownership/datatypes.h @@ -106,8 +106,12 @@ typedef struct owner_block { uint32_t sram_exec_mode; /** Ownership key algorithm (currently, only ECDSA is supported). */ uint32_t ownership_key_alg; + /** Configuraion version (monotonically increasing per owner) */ + uint32_t config_version; + /** Set the minimum security version to this value (UINT32_MAX: no change) */ + uint32_t min_security_version_bl0; /** Reserved space for future use. */ - uint32_t reserved[27]; + uint32_t reserved[25]; /** Owner public key. */ owner_key_t owner_key; /** Owner's Activate public key. */ @@ -126,7 +130,9 @@ OT_ASSERT_MEMBER_OFFSET(owner_block_t, header, 0); OT_ASSERT_MEMBER_OFFSET(owner_block_t, struct_version, 8); OT_ASSERT_MEMBER_OFFSET(owner_block_t, sram_exec_mode, 12); OT_ASSERT_MEMBER_OFFSET(owner_block_t, ownership_key_alg, 16); -OT_ASSERT_MEMBER_OFFSET(owner_block_t, reserved, 20); +OT_ASSERT_MEMBER_OFFSET(owner_block_t, config_version, 20); +OT_ASSERT_MEMBER_OFFSET(owner_block_t, min_security_version_bl0, 24); +OT_ASSERT_MEMBER_OFFSET(owner_block_t, reserved, 28); OT_ASSERT_MEMBER_OFFSET(owner_block_t, owner_key, 128); OT_ASSERT_MEMBER_OFFSET(owner_block_t, activate_key, 224); OT_ASSERT_MEMBER_OFFSET(owner_block_t, unlock_key, 320); diff --git a/sw/device/silicon_creator/lib/ownership/ownership.c b/sw/device/silicon_creator/lib/ownership/ownership.c index 05453035e0a12..eac7b55c7eda6 100644 --- a/sw/device/silicon_creator/lib/ownership/ownership.c +++ b/sw/device/silicon_creator/lib/ownership/ownership.c @@ -43,11 +43,10 @@ static owner_page_status_t owner_page_validity_check(size_t page) { return kOwnerPageStatusSigned; } -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; +OT_WEAK rom_error_t +sku_creator_owner_init(boot_data_t *bootdata, owner_config_t *config, + owner_application_keyring_t *keyring) { + return kErrorOk; } static rom_error_t locked_owner_init(boot_data_t *bootdata, @@ -186,6 +185,19 @@ rom_error_t ownership_init(boot_data_t *bootdata, owner_config_t *config, dbg_printf("ownership: %C\r\n", bootdata->ownership_state); owner_config_default(config); + + // We give the weak `sku_creator_owner_init` function the opportunity to + // initialize ownership if it is uninitialized or needs updating. + // + // This is a temporary measure to get ownership configs installed on + // pre-existing silicon and to update the owner configuration automatically + // should we decide to update it during development. + // + // When we settle on a default ownership configuration, we'll remove this + // function and possibly relegate it to the `default` case below, only to + // be used should the chip enter the "no owner recovery" state. + HARDENED_RETURN_IF_ERROR(sku_creator_owner_init(bootdata, config, keyring)); + rom_error_t error = kErrorOwnershipNoOwner; // TODO(#22386): Harden this switch/case statement. switch (bootdata->ownership_state) { @@ -200,9 +212,7 @@ rom_error_t ownership_init(boot_data_t *bootdata, owner_config_t *config, 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); + /* Do nothing. */; } return error; } diff --git a/sw/device/silicon_creator/lib/ownership/ownership_activate.c b/sw/device/silicon_creator/lib/ownership/ownership_activate.c index bd6d04be96f25..b507a58f9c5bc 100644 --- a/sw/device/silicon_creator/lib/ownership/ownership_activate.c +++ b/sw/device/silicon_creator/lib/ownership/ownership_activate.c @@ -69,6 +69,11 @@ static rom_error_t activate(boot_svc_msg_t *msg, boot_data_t *bootdata) { bootdata->primary_bl0_slot = kBootSlotA; } + // If requested, reset the mim security version of the application firmware. + if (owner_page[1].min_security_version_bl0 != UINT32_MAX) { + bootdata->min_security_version_bl0 = owner_page[1].min_security_version_bl0; + } + // Set the ownership state to LockedOwner. nonce_new(&bootdata->nonce); bootdata->ownership_state = kOwnershipStateLockedOwner; diff --git a/sw/device/silicon_creator/lib/ownership/ownership_activate_unittest.cc b/sw/device/silicon_creator/lib/ownership/ownership_activate_unittest.cc index b491808514d76..d9c2899121548 100644 --- a/sw/device/silicon_creator/lib/ownership/ownership_activate_unittest.cc +++ b/sw/device/silicon_creator/lib/ownership/ownership_activate_unittest.cc @@ -35,6 +35,8 @@ class OwnershipActivateTest : public rom_test::RomTest { owner_page[1].header.tag = kTlvTagOwner; owner_page[1].header.length = sizeof(owner_page[1]); owner_page[1].struct_version = 0; + owner_page[1].config_version = 0; + owner_page[1].min_security_version_bl0 = UINT32_MAX; memset(owner_page[1].data, 0x5a, sizeof(owner_page[1].data)); } @@ -192,7 +194,7 @@ TEST_P(OwnershipActivateValidStateTest, OwnerPageInvalid) { } // Tests that an owner block with a valid owner page with respect to the current -// update state succeeds. +// unlock state succeeds. TEST_P(OwnershipActivateValidStateTest, OwnerPageValid) { ownership_state_t state = GetParam(); bootdata_.ownership_state = static_cast(state); @@ -243,10 +245,77 @@ TEST_P(OwnershipActivateValidStateTest, OwnerPageValid) { 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. + // ownership state set to LockedOwner. EXPECT_EQ(owner_page[1].seal[0], 0x5a5a5a5a); EXPECT_FALSE(nonce_equal(&bootdata_.nonce, &kDefaultNonce)); EXPECT_EQ(bootdata_.ownership_state, kOwnershipStateLockedOwner); + // The default value of `owner_page.min_security_version_bl0` should perform + // no update to the bootdata's minimum version. + EXPECT_EQ(bootdata_.min_security_version_bl0, 0); +} + +// Tests that an owner update with a non-default value of +// `min_security_version_bl0` updates bootdata's copy. +// +// TODO(cfrantz): Refactor this test as it is nearly a complete copy of the +// previous test except for the manipulation of the min_sec_ver. +TEST_P(OwnershipActivateValidStateTest, UpdateBootdataBl0) { + 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); + owner_page[1].min_security_version_bl0 = 5; + + EXPECT_CALL(ownership_key_, validate(1, kOwnershipKeyActivate, _, _, _)) + .WillOnce(Return(kHardenedBoolTrue)); + + switch (state) { + case kOwnershipStateUnlockedSelf: + 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 LockedOwner. + EXPECT_EQ(owner_page[1].seal[0], 0x5a5a5a5a); + EXPECT_FALSE(nonce_equal(&bootdata_.nonce, &kDefaultNonce)); + EXPECT_EQ(bootdata_.ownership_state, kOwnershipStateLockedOwner); + // Bootdata should receive the owner_block's minimum version upon activation. + EXPECT_EQ(bootdata_.min_security_version_bl0, 5); } INSTANTIATE_TEST_SUITE_P(AllCases, OwnershipActivateValidStateTest, diff --git a/sw/device/silicon_creator/lib/ownership/test_owner.c b/sw/device/silicon_creator/lib/ownership/test_owner.c index 69977846d4ae1..689db2202659c 100644 --- a/sw/device/silicon_creator/lib/ownership/test_owner.c +++ b/sw/device/silicon_creator/lib/ownership/test_owner.c @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0, see LICENSE for details. // SPDX-License-Identifier: Apache-2.0 +#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/dbg_print.h" @@ -20,25 +21,50 @@ #include "sw/device/silicon_creator/lib/ownership/ownership.h" /* - * This module overrides the weak `test_owner_init` symbol in ownership.c, thus - * allowing FPGA builds to boot in the `LockedOwner` state with a valid set of - * keys. + * This module overrides the weak `sku_creator_owner_init` symbol in + * ownership.c, thus allowing FPGA builds to boot in the `LockedOwner` state + * with a valid set of keys. */ -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; +// NOTE: if you update this version number, you must also update the version +// number in the test library `sw/host/tests/ownership/transfer_lib.rs`. +#define TEST_OWNER_CONFIG_VERSION 1 + +rom_error_t sku_creator_owner_init(boot_data_t *bootdata, + owner_config_t *config, + owner_application_keyring_t *keyring) { + owner_key_t owner = (owner_key_t){ + // Although this is an ECDSA key, we initialize the `raw` member of the + // union to zero-initialize the unused space. + .raw = OWNER_ECDSA_P256}; + ownership_state_t state = bootdata->ownership_state; + + if (state == kOwnershipStateUnlockedSelf || + state == kOwnershipStateUnlockedAny || + state == kOwnershipStateUnlockedEndorsed) { + // Nothing to do when in an unlocked state. + return kErrorOk; + } else if (state == kOwnershipStateLockedOwner) { + if (hardened_memeq(owner.raw, owner_page[0].owner_key.raw, + ARRAYSIZE(owner.raw)) != kHardenedBoolTrue || + TEST_OWNER_CONFIG_VERSION <= owner_page[0].config_version) { + // Different owner or already newest config version; nothing to do. + return kErrorOk; + } + } else { + // State is an unknown value, which is the same as kOwnershipStateRecovery. + // We'll not return, thus allowing the owner config below to be programmed + // into flash. + } owner_page[0].header.tag = kTlvTagOwner; owner_page[0].header.length = 2048; owner_page[0].struct_version = 0; owner_page[0].sram_exec_mode = kOwnerSramExecModeDisabledLocked; owner_page[0].ownership_key_alg = kOwnershipKeyAlgEcdsaP256; - owner_page[0].owner_key = (owner_key_t){ - // Although this is an ECDSA key, we initialize the `raw` member of the - // union to zero-initialize the unused space. - .raw = OWNER_ECDSA_P256}; + owner_page[0].config_version = TEST_OWNER_CONFIG_VERSION; + owner_page[0].min_security_version_bl0 = UINT32_MAX; + owner_page[0].owner_key = owner; owner_page[0].activate_key = (owner_key_t){ // Although this is an ECDSA key, we initialize the `raw` member of the // union to zero-initialize the unused space. @@ -141,6 +167,7 @@ rom_error_t test_owner_init(boot_data_t *bootdata, owner_config_t *config, memset(app, 0x5a, len); owner_block_page_seal(/*page=*/0); + memcpy(&owner_page[1], &owner_page[0], sizeof(owner_page[0])); RETURN_IF_ERROR(owner_block_parse(&owner_page[0], config, keyring)); RETURN_IF_ERROR(owner_block_flash_apply(config->flash, kBootSlotA, @@ -152,16 +179,23 @@ rom_error_t test_owner_init(boot_data_t *bootdata, owner_config_t *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; - 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_init: flash\r\n"); - } else { - dbg_printf("test_owner_init: ram\r\n"); - } + + // Write the configuration to both owner pages. + 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])); + owner_page_valid[0] = kOwnerPageStatusSealed; + + OT_DISCARD(flash_ctrl_info_erase(&kFlashCtrlInfoPageOwnerSlot1, + kFlashCtrlEraseTypePage)); + OT_DISCARD(flash_ctrl_info_write(&kFlashCtrlInfoPageOwnerSlot1, 0, + sizeof(owner_page[0]) / sizeof(uint32_t), + &owner_page[0])); + owner_page_valid[1] = kOwnerPageStatusSealed; + + OT_DISCARD(boot_data_write(bootdata)); + dbg_printf("sku_creator_owner_init: saved to flash\r\n"); return kErrorOk; } diff --git a/sw/device/silicon_creator/rom_ext/e2e/ownership/BUILD b/sw/device/silicon_creator/rom_ext/e2e/ownership/BUILD index eb7bf269ccd53..e84e4d761f0ae 100644 --- a/sw/device/silicon_creator/rom_ext/e2e/ownership/BUILD +++ b/sw/device/silicon_creator/rom_ext/e2e/ownership/BUILD @@ -368,3 +368,30 @@ ownership_transfer_test( "//sw/device/lib/testing/test_framework:ottf_main", ], ) + +# Test that the `sku_creator_owner_init` function responsible for installing the test owner on +# FPGA builds will automatically update from an older owner block. +ownership_transfer_test( + name = "fpga_owner_upgrade_test", + fpga = fpga_params( + changes_otp = True, + test_cmd = """ + --clear-bitstream + --bootstrap={firmware} + --unlock-mode=Update + --unlock-key=$(location //sw/device/silicon_creator/lib/ownership/keys/fake:unlock_key) + --next-owner-key=$(location //sw/device/silicon_creator/lib/ownership/keys/fake:owner_key) + --next-unlock-key=$(location //sw/device/silicon_creator/lib/ownership/keys/fake:unlock_key) + --next-activate-key=$(location //sw/device/silicon_creator/lib/ownership/keys/fake:activate_key) + # `sku_creator_owner_init` has a newer version number than this and should self-update. + --config-version=0 + # NOTE: Should sku_creator_owner_init fail to upgrade to its built-in owner block, then the + # dummy key will prevent the test program from executing and we'll get a failure from the test. + --next-application-key=$(location //sw/device/silicon_creator/lib/ownership/keys/dummy:app_prod_pub) + """, + test_harness = "//sw/host/tests/ownership:transfer_test", + ), + rsa_key = { + "//sw/device/silicon_creator/lib/ownership/keys/fake:app_prod": "app_prod", + }, +) diff --git a/sw/device/silicon_creator/rom_ext/rom_ext.c b/sw/device/silicon_creator/rom_ext/rom_ext.c index 711f812b2d6f3..f341d7f51095e 100644 --- a/sw/device/silicon_creator/rom_ext/rom_ext.c +++ b/sw/device/silicon_creator/rom_ext/rom_ext.c @@ -848,7 +848,7 @@ static rom_error_t rom_ext_start(boot_data_t *boot_data, boot_log_t *boot_log) { } // TODO(cfrantz): evaluate permissible ownership init failure conditions // and change this to HARDENED_RETURN_IF_ERROR. - if (error == kErrorOk) { + if (error != kErrorOk) { dbg_printf("ownership_init: %x\r\n", error); } diff --git a/sw/host/opentitanlib/src/ownership/owner.rs b/sw/host/opentitanlib/src/ownership/owner.rs index c7e09f3fa07b2..76299be173271 100644 --- a/sw/host/opentitanlib/src/ownership/owner.rs +++ b/sw/host/opentitanlib/src/ownership/owner.rs @@ -20,6 +20,10 @@ with_unknown! { Disabled = u32::from_le_bytes(*b"NOEX"), Enabled = u32::from_le_bytes(*b"EXEC"), } + + pub enum MinSecurityVersion: u32 [default = Self::NoChange] { + NoChange = 0xFFFFFFFFu32, + } } /// Describes the owner configuration and key material. @@ -36,9 +40,15 @@ pub struct OwnerBlock { pub sram_exec: SramExecMode, /// The key algorithm of the ownership keys. pub ownership_key_alg: OwnershipKeyAlg, + /// Configuraion version (monotonically increasing per owner). + #[serde(default)] + pub config_version: u32, + /// Set the minimum security version to this value. + #[serde(default)] + pub min_security_version_bl0: MinSecurityVersion, #[serde(default)] #[annotate(format=hex)] - pub reserved: [u32; 27], + pub reserved: [u32; 25], /// The owner identity key. pub owner_key: KeyMaterial, /// The owner activation key. @@ -65,7 +75,9 @@ impl Default for OwnerBlock { struct_version: 0, sram_exec: SramExecMode::default(), ownership_key_alg: OwnershipKeyAlg::default(), - reserved: [0u32; 27], + config_version: 0, + min_security_version_bl0: MinSecurityVersion::default(), + reserved: [0u32; 25], owner_key: KeyMaterial::default(), activate_key: KeyMaterial::default(), unlock_key: KeyMaterial::default(), @@ -101,6 +113,8 @@ impl OwnerBlock { dest.write_u32::(self.struct_version)?; dest.write_u32::(u32::from(self.sram_exec))?; dest.write_u32::(u32::from(self.ownership_key_alg))?; + dest.write_u32::(self.config_version)?; + dest.write_u32::(u32::from(self.min_security_version_bl0))?; for x in &self.reserved { dest.write_u32::(*x)?; } @@ -122,7 +136,9 @@ impl OwnerBlock { let struct_version = src.read_u32::()?; let sram_exec = SramExecMode(src.read_u32::()?); let ownership_key_alg = OwnershipKeyAlg(src.read_u32::()?); - let mut reserved = [0u32; 27]; + let config_version = src.read_u32::()?; + let min_security_version_bl0 = MinSecurityVersion(src.read_u32::()?); + let mut reserved = [0u32; 25]; src.read_u32_into::(&mut reserved)?; let owner_key = KeyMaterial::read_length(src, ownership_key_alg, 96)?; let activate_key = KeyMaterial::read_length(src, ownership_key_alg, 96)?; @@ -145,6 +161,8 @@ impl OwnerBlock { struct_version, sram_exec, ownership_key_alg, + config_version, + min_security_version_bl0, reserved, owner_key, activate_key, @@ -227,7 +245,7 @@ mod test { #[rustfmt::skip] const OWNER_BIN: &str = r#"00000000: 4f 57 4e 52 00 08 00 00 00 00 00 00 4c 4e 45 58 OWNR........LNEX -00000010: 50 32 35 36 00 00 00 00 00 00 00 00 00 00 00 00 P256............ +00000010: 50 32 35 36 00 00 00 00 ff ff ff ff 00 00 00 00 P256............ 00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 00000040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ @@ -364,6 +382,8 @@ r#"00000000: 4f 57 4e 52 00 08 00 00 00 00 00 00 4c 4e 45 58 OWNR........LNEX struct_version: 0, sram_exec: "DisabledLocked", ownership_key_alg: "EcdsaP256", + config_version: 0, + min_security_version_bl0: "NoChange", reserved: [ 0x0, 0x0, @@ -389,8 +409,6 @@ r#"00000000: 4f 57 4e 52 00 08 00 00 00 00 00 00 4c 4e 45 58 OWNR........LNEX 0x0, 0x0, 0x0, - 0x0, - 0x0, 0x0 ], owner_key: { diff --git a/sw/host/tests/ownership/flash_permission_test.rs b/sw/host/tests/ownership/flash_permission_test.rs index be67d5d6c9be7..a00a59a7ad3e5 100644 --- a/sw/host/tests/ownership/flash_permission_test.rs +++ b/sw/host/tests/ownership/flash_permission_test.rs @@ -132,6 +132,7 @@ fn flash_permission_test(opts: &Opts, transport: &TransportWrapper) -> Result<() &opts.next_unlock_key, &opts.next_application_key, opts.config_kind, + /*customize=*/ |_| {}, )?; if opts.dual_owner_boot_check { diff --git a/sw/host/tests/ownership/rescue_limit_test.rs b/sw/host/tests/ownership/rescue_limit_test.rs index 728e6d569f375..05e52c9075cec 100644 --- a/sw/host/tests/ownership/rescue_limit_test.rs +++ b/sw/host/tests/ownership/rescue_limit_test.rs @@ -89,6 +89,7 @@ fn flash_limit_test(opts: &Opts, transport: &TransportWrapper) -> Result<()> { &opts.next_unlock_key, &opts.next_application_key, opts.config_kind, + /*customize=*/ |_| {}, )?; log::info!("###### Get Boot Log (2/2) ######"); diff --git a/sw/host/tests/ownership/rescue_permission_test.rs b/sw/host/tests/ownership/rescue_permission_test.rs index 3f6f3234fafd4..93d6ae72f87f6 100644 --- a/sw/host/tests/ownership/rescue_permission_test.rs +++ b/sw/host/tests/ownership/rescue_permission_test.rs @@ -81,6 +81,7 @@ fn rescue_permission_test(opts: &Opts, transport: &TransportWrapper) -> Result<( &opts.next_unlock_key, &opts.next_application_key, opts.config_kind, + /*customize=*/ |_| {}, )?; log::info!("###### Get Boot Log (2/2) ######"); diff --git a/sw/host/tests/ownership/transfer_lib.rs b/sw/host/tests/ownership/transfer_lib.rs index 58b1b9c5baa61..daceb7640af80 100644 --- a/sw/host/tests/ownership/transfer_lib.rs +++ b/sw/host/tests/ownership/transfer_lib.rs @@ -19,6 +19,8 @@ use opentitanlib::rescue::serial::RescueSerial; use std::path::Path; +pub const TEST_OWNER_CONFIG_VERSION: u32 = 1; + /// Gets the BootLog. pub fn get_boot_log(transport: &TransportWrapper, rescue: &RescueSerial) -> Result { rescue.enter(transport, /*reset=*/ true)?; @@ -161,7 +163,8 @@ fn filesystem(lock: bool) -> FlashFlags { } /// Prepares an OwnerBlock and sends it to the chip. -pub fn create_owner( +#[allow(clippy::too_many_arguments)] +pub fn create_owner( transport: &TransportWrapper, rescue: &RescueSerial, owner_key: &Path, @@ -169,7 +172,11 @@ pub fn create_owner( unlock_key: &Path, app_key: &Path, config: OwnerConfigKind, -) -> Result<()> { + customize: F, +) -> Result<()> +where + F: Fn(&mut OwnerBlock), +{ let config = config as u32; let owner_key = EcdsaPrivateKey::load(owner_key)?; let activate_key = EcdsaPrivateKey::load(activate_key)?; @@ -217,6 +224,7 @@ pub fn create_owner( } owner.data.push(OwnerConfigItem::RescueConfig(rescue)); } + customize(&mut owner); owner.sign(&owner_key)?; if config & CFG_CORRUPT != 0 { owner.signature.r[0] += 1; diff --git a/sw/host/tests/ownership/transfer_test.rs b/sw/host/tests/ownership/transfer_test.rs index 6ed051e8d0773..d167caca56e4d 100644 --- a/sw/host/tests/ownership/transfer_test.rs +++ b/sw/host/tests/ownership/transfer_test.rs @@ -39,6 +39,12 @@ struct Opts { next_unlock_key: PathBuf, #[arg(long, help = "Next Owner's application public key (RSA3K)")] next_application_key: PathBuf, + #[arg( + long, + default_value_t = transfer_lib::TEST_OWNER_CONFIG_VERSION, + help = "Configuration version to put in the owner config" + )] + config_version: u32, #[arg( long, @@ -92,6 +98,10 @@ fn transfer_test(opts: &Opts, transport: &TransportWrapper) -> Result<()> { &opts.next_unlock_key, &opts.next_application_key, opts.config_kind, + /*customize=*/ + |owner| { + owner.config_version = opts.config_version; + }, )?; let mut transfers0 = 0;