Skip to content

Commit

Permalink
[ownership] Perform flash lockdown of owner flash regions
Browse files Browse the repository at this point in the history
1. Add the capability to perform lockdown of the MP region configuration
   via the REGION_CFG_REGWEN registers.
2. In `owner_block_flash_apply`, apply the PROTECT_WHEN_PRIMARY and LOCK
   properties only when lockdown is requested.
3. In the `{un,}locked_init` functions, do not perform lockdown:
   - We do not want regions locked for the `LockedOwner` state should
     the user request rescue mode.
   - We do not want regions locked in the ownership unlocked states.
4. Prior to execution handoff to owner code, engage the owner-configured
   locks.

Signed-off-by: Chris Frantz <[email protected]>
(cherry picked from commit de7df51)
  • Loading branch information
cfrantz authored and moidx committed Oct 30, 2024
1 parent e6feb6a commit bb51827
Show file tree
Hide file tree
Showing 11 changed files with 116 additions and 50 deletions.
14 changes: 11 additions & 3 deletions sw/device/silicon_creator/lib/drivers/flash_ctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,8 @@ static void flash_ctrl_mp_region_cfg_reset(flash_ctrl_region_index_t region) {
static void flash_ctrl_mp_region_cfg_write(flash_ctrl_region_index_t region,
flash_ctrl_cfg_t cfg,
flash_ctrl_perms_t perms,
multi_bit_bool_t en) {
multi_bit_bool_t en,
hardened_bool_t lock) {
#define FLASH_CTRL_MP_REGION_CFG_WRITE_(region_macro_arg) \
case ((region_macro_arg)): { \
HARDENED_CHECK_EQ(region, (region_macro_arg)); \
Expand Down Expand Up @@ -624,6 +625,12 @@ static void flash_ctrl_mp_region_cfg_write(flash_ctrl_region_index_t region,
sec_mmio_write32( \
kBase + FLASH_CTRL_MP_REGION_CFG_##region_macro_arg##_REG_OFFSET, \
mp_region_cfg); \
if (lock != kHardenedBoolFalse) { \
sec_mmio_write32( \
kBase + \
FLASH_CTRL_REGION_CFG_REGWEN_##region_macro_arg##_REG_OFFSET, \
0); \
} \
return; \
}

Expand All @@ -639,7 +646,8 @@ static void flash_ctrl_mp_region_cfg_write(flash_ctrl_region_index_t region,
void flash_ctrl_data_region_protect(flash_ctrl_region_index_t region,
uint32_t page_offset, uint32_t num_pages,
flash_ctrl_perms_t perms,
flash_ctrl_cfg_t cfg) {
flash_ctrl_cfg_t cfg,
hardened_bool_t lock) {
// Reset the region's configuration via the MP_REGION_CFG_${region} register.
// This temporarily disables memory protection for the region.
flash_ctrl_mp_region_cfg_reset(region);
Expand All @@ -649,7 +657,7 @@ void flash_ctrl_data_region_protect(flash_ctrl_region_index_t region,

// Write the new value of MP_REGION_CFG_${region}.
flash_ctrl_mp_region_cfg_write(region, cfg, perms,
/*en=*/kMultiBitBool4True);
/*en=*/kMultiBitBool4True, lock);
}

void flash_ctrl_info_cfg_set(const flash_ctrl_info_page_t *info_page,
Expand Down
3 changes: 2 additions & 1 deletion sw/device/silicon_creator/lib/drivers/flash_ctrl.h
Original file line number Diff line number Diff line change
Expand Up @@ -529,11 +529,12 @@ typedef uint32_t flash_ctrl_region_index_t;
* @param perms The read/write/erase permissions for this region.
* @param cfg Flash config values that are used to fill in some fields of the
* `MP_REGION_CFG_${region}` register.
* @param lock Lock the configuration for this region.
*/
void flash_ctrl_data_region_protect(flash_ctrl_region_index_t region,
uint32_t page_offset, uint32_t num_pages,
flash_ctrl_perms_t perms,
flash_ctrl_cfg_t cfg);
flash_ctrl_cfg_t cfg, hardened_bool_t lock);

/**
* Sets configuration settings for an info page.
Expand Down
3 changes: 2 additions & 1 deletion sw/device/silicon_creator/lib/drivers/flash_ctrl_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -968,7 +968,8 @@ TEST_P(DataRegionProtectTestSuite, ProtectRegionReadWriteEraseEnabled) {
.scrambling = BoolToMultiBitBool4(kFlashScrambling),
.ecc = BoolToMultiBitBool4(kFlashEcc),
.he = BoolToMultiBitBool4(kFlashHe),
});
},
kHardenedBoolFalse);
}

} // namespace
Expand Down
5 changes: 3 additions & 2 deletions sw/device/silicon_creator/lib/drivers/mock_flash_ctrl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,10 @@ void flash_ctrl_info_cfg_set(const flash_ctrl_info_page_t *info_page,
void flash_ctrl_data_region_protect(flash_ctrl_region_index_t region,
uint32_t page_offset, uint32_t num_pages,
flash_ctrl_perms_t perms,
flash_ctrl_cfg_t cfg) {
flash_ctrl_cfg_t cfg,
hardened_bool_t lock) {
MockFlashCtrl::Instance().DataRegionProtect(region, page_offset, num_pages,
perms, cfg);
perms, cfg, lock);
}

void flash_ctrl_bank_erase_perms_set(hardened_bool_t enable) {
Expand Down
2 changes: 1 addition & 1 deletion sw/device/silicon_creator/lib/drivers/mock_flash_ctrl.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class MockFlashCtrl : public global_mock::GlobalMock<MockFlashCtrl> {
MOCK_METHOD(void, DataRegionProtect,
(flash_ctrl_region_index_t region, uint32_t page_offset,
uint32_t num_pages, flash_ctrl_perms_t perms,
flash_ctrl_cfg_t cfg));
flash_ctrl_cfg_t cfg, hardened_bool_t));
MOCK_METHOD(void, InfoCfgSet,
(const flash_ctrl_info_page_t *, flash_ctrl_cfg_t));
MOCK_METHOD(void, BankErasePermsSet, (hardened_bool_t));
Expand Down
27 changes: 19 additions & 8 deletions sw/device/silicon_creator/lib/ownership/owner_block.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,11 @@ rom_error_t owner_block_parse(const owner_block_t *block,
}

rom_error_t owner_block_flash_apply(const owner_flash_config_t *flash,
uint32_t config_side,
uint32_t primary_side) {
uint32_t config_side, uint32_t lockdown) {
if ((hardened_bool_t)flash == kHardenedBoolFalse)
return kErrorOk;
// TODO: Hardening: lockdown should be one of kBootSlotA, kBootSlotB or
// kHardenedBoolFalse.
uint32_t start = config_side == kBootSlotA ? 0
: config_side == kBootSlotB ? kFlashBankSize
: 0xFFFFFFFF;
Expand Down Expand Up @@ -118,13 +119,23 @@ rom_error_t owner_block_flash_apply(const owner_flash_config_t *flash,
.erase = bitfield_field32_read(val, FLASH_CONFIG_ERASE),
};

if (config_side == primary_side &&
bitfield_field32_read(val, FLASH_CONFIG_PROTECT_WHEN_PRIMARY) !=
kMultiBitBool4False) {
perm.write = kMultiBitBool4False;
perm.erase = kMultiBitBool4False;
if (lockdown == config_side) {
if (bitfield_field32_read(val, FLASH_CONFIG_PROTECT_WHEN_PRIMARY) !=
kMultiBitBool4False) {
perm.write = kMultiBitBool4False;
perm.erase = kMultiBitBool4False;
}
}

hardened_bool_t lock = kHardenedBoolFalse;
if (lockdown != kHardenedBoolFalse) {
if (bitfield_field32_read(val, FLASH_CONFIG_LOCK) !=
kMultiBitBool4False) {
lock = kHardenedBoolTrue;
}
}
flash_ctrl_data_region_protect(i, config->start, config->size, perm, cfg);
flash_ctrl_data_region_protect(i, config->start, config->size, perm, cfg,
lock);
}
}
return kErrorOk;
Expand Down
7 changes: 4 additions & 3 deletions sw/device/silicon_creator/lib/ownership/owner_block.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,13 @@ rom_error_t owner_block_parse(const owner_block_t *block,
*
* @param flash A pointer to a flash configuration struct.
* @param config_side Which side of the flash to configure.
* @param primary_side Which side of the flash is primary.
* @param lockdown Apply any special lockdown configuration to the specified
* side of the flash. May use kHardenedBoolFalse to skip
* lockdown.
* @return error code.
*/
rom_error_t owner_block_flash_apply(const owner_flash_config_t *flash,
uint32_t config_side,
uint32_t primary_side);
uint32_t config_side, uint32_t lockdown);

/**
* Apply the flash info configuration parameters from the owner block.
Expand Down
51 changes: 30 additions & 21 deletions sw/device/silicon_creator/lib/ownership/owner_block_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -239,21 +239,24 @@ TEST_F(OwnerBlockTest, FlashConfigApplySideA) {
FlashPerms(kMultiBitBool4True, kMultiBitBool4True,
kMultiBitBool4True),
FlashCfg(kMultiBitBool4False, kMultiBitBool4False,
kMultiBitBool4False)));
kMultiBitBool4False),
kHardenedBoolFalse));
EXPECT_CALL(
flash_ctrl_,
DataRegionProtect(1, 32, 192,
FlashPerms(kMultiBitBool4True, kMultiBitBool4True,
kMultiBitBool4True),
FlashCfg(kMultiBitBool4True, kMultiBitBool4True,
kMultiBitBool4False)));
DataRegionProtect(
1, 32, 192,
FlashPerms(kMultiBitBool4True, kMultiBitBool4True,
kMultiBitBool4True),
FlashCfg(kMultiBitBool4True, kMultiBitBool4True, kMultiBitBool4False),
kHardenedBoolFalse));
EXPECT_CALL(
flash_ctrl_,
DataRegionProtect(2, 224, 32,
FlashPerms(kMultiBitBool4True, kMultiBitBool4True,
kMultiBitBool4True),
FlashCfg(kMultiBitBool4False, kMultiBitBool4False,
kMultiBitBool4True)));
kMultiBitBool4True),
kHardenedBoolFalse));

rom_error_t error =
owner_block_flash_apply(&simple_flash_config, kBootSlotA, 0);
Expand All @@ -270,21 +273,24 @@ TEST_F(OwnerBlockTest, FlashConfigApplySideAPrimary) {
FlashPerms(kMultiBitBool4True, kMultiBitBool4False,
kMultiBitBool4False),
FlashCfg(kMultiBitBool4False, kMultiBitBool4False,
kMultiBitBool4False)));
kMultiBitBool4False),
kHardenedBoolFalse));
EXPECT_CALL(
flash_ctrl_,
DataRegionProtect(1, 32, 192,
FlashPerms(kMultiBitBool4True, kMultiBitBool4False,
kMultiBitBool4False),
FlashCfg(kMultiBitBool4True, kMultiBitBool4True,
kMultiBitBool4False)));
DataRegionProtect(
1, 32, 192,
FlashPerms(kMultiBitBool4True, kMultiBitBool4False,
kMultiBitBool4False),
FlashCfg(kMultiBitBool4True, kMultiBitBool4True, kMultiBitBool4False),
kHardenedBoolFalse));
EXPECT_CALL(
flash_ctrl_,
DataRegionProtect(2, 224, 32,
FlashPerms(kMultiBitBool4True, kMultiBitBool4True,
kMultiBitBool4True),
FlashCfg(kMultiBitBool4False, kMultiBitBool4False,
kMultiBitBool4True)));
kMultiBitBool4True),
kHardenedBoolFalse));

rom_error_t error =
owner_block_flash_apply(&simple_flash_config, kBootSlotA, kBootSlotA);
Expand All @@ -299,21 +305,24 @@ TEST_F(OwnerBlockTest, FlashConfigApplySideB) {
FlashPerms(kMultiBitBool4True, kMultiBitBool4True,
kMultiBitBool4True),
FlashCfg(kMultiBitBool4False, kMultiBitBool4False,
kMultiBitBool4False)));
kMultiBitBool4False),
kHardenedBoolFalse));
EXPECT_CALL(
flash_ctrl_,
DataRegionProtect(4, 256 + 32, 192,
FlashPerms(kMultiBitBool4True, kMultiBitBool4True,
kMultiBitBool4True),
FlashCfg(kMultiBitBool4True, kMultiBitBool4True,
kMultiBitBool4False)));
DataRegionProtect(
4, 256 + 32, 192,
FlashPerms(kMultiBitBool4True, kMultiBitBool4True,
kMultiBitBool4True),
FlashCfg(kMultiBitBool4True, kMultiBitBool4True, kMultiBitBool4False),
kHardenedBoolFalse));
EXPECT_CALL(
flash_ctrl_,
DataRegionProtect(5, 256 + 224, 32,
FlashPerms(kMultiBitBool4True, kMultiBitBool4True,
kMultiBitBool4True),
FlashCfg(kMultiBitBool4False, kMultiBitBool4False,
kMultiBitBool4True)));
kMultiBitBool4True),
kHardenedBoolFalse));

rom_error_t error =
owner_block_flash_apply(&simple_flash_config, kBootSlotB, 0);
Expand Down
35 changes: 27 additions & 8 deletions sw/device/silicon_creator/lib/ownership/ownership.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,12 @@ static rom_error_t locked_owner_init(boot_data_t *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_flash_apply(config->flash, kBootSlotA,
/*lockdown=*/kHardenedBoolFalse));
HARDENED_RETURN_IF_ERROR(
owner_block_flash_apply(config->flash, kBootSlotB,
/*lockdown=*/kHardenedBoolFalse));
HARDENED_RETURN_IF_ERROR(owner_block_info_apply(config->info));
return kErrorOk;
}
Expand Down Expand Up @@ -150,8 +152,9 @@ static rom_error_t unlocked_init(boot_data_t *bootdata, owner_config_t *config,
// 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));
HARDENED_RETURN_IF_ERROR(
owner_block_flash_apply(config->flash, bootdata->primary_bl0_slot,
/*lockdown=*/kHardenedBoolFalse));
}

if (ownership_page1_valid_for_transfer(bootdata) == kHardenedBoolTrue) {
Expand All @@ -160,8 +163,9 @@ static rom_error_t unlocked_init(boot_data_t *bootdata, owner_config_t *config,
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_flash_apply(config->flash, secondary,
/*lockdown=*/kHardenedBoolFalse));
HARDENED_RETURN_IF_ERROR(owner_block_info_apply(config->info));
return kErrorOk;
}
Expand Down Expand Up @@ -244,6 +248,21 @@ rom_error_t ownership_init(boot_data_t *bootdata, owner_config_t *config,
return error;
}

rom_error_t ownership_flash_lockdown(boot_data_t *bootdata,
const owner_config_t *config) {
if (bootdata->ownership_state == kOwnershipStateLockedOwner) {
HARDENED_RETURN_IF_ERROR(
owner_block_flash_apply(config->flash, kBootSlotA,
/*lockdown=*/bootdata->primary_bl0_slot));
HARDENED_RETURN_IF_ERROR(
owner_block_flash_apply(config->flash, kBootSlotB,
/*lockdown=*/bootdata->primary_bl0_slot));
} else {
HARDENED_CHECK_NE(bootdata->ownership_state, kOwnershipStateLockedOwner);
}
return kErrorOk;
}

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;
Expand Down
11 changes: 11 additions & 0 deletions sw/device/silicon_creator/lib/ownership/ownership.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,17 @@ rom_error_t ownership_init(boot_data_t *bootdata, owner_config_t *config,
*/
hardened_bool_t ownership_page1_valid_for_transfer(boot_data_t *bootdata);

/**
* Lockdown the flash configuration.
*
*
* @param bootdata The current bootdata.
* @param config The current owner configuration.
* @return error state.
*/
rom_error_t ownership_flash_lockdown(boot_data_t *bootdata,
const owner_config_t *config);

/**
* Seal an owner page.
*
Expand Down
8 changes: 6 additions & 2 deletions sw/device/silicon_creator/rom_ext/rom_ext.c
Original file line number Diff line number Diff line change
Expand Up @@ -495,7 +495,8 @@ static rom_error_t rom_ext_attestation_owner(const manifest_t *owner_manifest) {
}

OT_WARN_UNUSED_RESULT
static rom_error_t rom_ext_boot(const manifest_t *manifest) {
static rom_error_t rom_ext_boot(boot_data_t *boot_data,
const manifest_t *manifest) {
// Generate CDI_1 attestation keys and certificate.
HARDENED_RETURN_IF_ERROR(rom_ext_attestation_owner(manifest));

Expand Down Expand Up @@ -637,6 +638,9 @@ static rom_error_t rom_ext_boot(const manifest_t *manifest) {
ibex_addr_remap_lockdown(0);
ibex_addr_remap_lockdown(1);

// Lock the flash according to the ownership configuration.
HARDENED_RETURN_IF_ERROR(ownership_flash_lockdown(boot_data, &owner_config));

dbg_print_epmp();

// Verify expectations before jumping to owner code.
Expand Down Expand Up @@ -819,7 +823,7 @@ static rom_error_t rom_ext_try_next_stage(boot_data_t *boot_data,
boot_log_digest_update(boot_log);

// Boot fails if a verified ROM_EXT cannot be booted.
RETURN_IF_ERROR(rom_ext_boot(manifests.ordered[i]));
RETURN_IF_ERROR(rom_ext_boot(boot_data, manifests.ordered[i]));
// `rom_ext_boot()` should never return `kErrorOk`, but if it does
// we must shut down the chip instead of trying the next ROM_EXT.
return kErrorRomExtBootFailed;
Expand Down

0 comments on commit bb51827

Please sign in to comment.