Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions rules/const.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ CONST = struct(
ROM = struct(
IMM_SECTION = 0x034d5203,
),
ISFB = struct(
STRIKE_MASK = 0x624f5707,
PRODUCT_EXP = 0x634f5707,
),
UNKNOWN = 0xffffffff,
OK = 0x739,
),
Expand Down
34 changes: 34 additions & 0 deletions sw/device/lib/testing/flash_ctrl_testutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -318,3 +318,37 @@ status_t flash_ctrl_testutils_show_faults(

return OK_STATUS();
}

static const char *mubi_prop(multi_bit_bool_t val, const char *name) {
switch (val) {
case kMultiBitBool4True:
return name;
case kMultiBitBool4False:
return "xx";
default:
return "uu";
}
}

void flash_ctrl_testutils_data_region_print(
size_t index, dif_flash_ctrl_data_region_properties_t *p, bool locked) {
LOG_INFO("data region n=%u st=%u sz=%u %s-%s-%s-%s-%s-%s %s", index, p->base,
p->size, mubi_prop(p->properties.rd_en, "RD"),
mubi_prop(p->properties.prog_en, "WR"),
mubi_prop(p->properties.erase_en, "ER"),
mubi_prop(p->properties.scramble_en, "SC"),
mubi_prop(p->properties.ecc_en, "EC"),
mubi_prop(p->properties.high_endurance_en, "HE"),
locked ? "LK" : "UN");
}

void flash_ctrl_testutils_info_region_print(
dif_flash_ctrl_info_region_t region, dif_flash_ctrl_region_properties_t *p,
bool locked) {
LOG_INFO("info region bank=%u part=%u page=%u %s-%s-%s-%s-%s-%s %s",
region.bank, region.partition_id, region.page,
mubi_prop(p->rd_en, "RD"), mubi_prop(p->prog_en, "WR"),
mubi_prop(p->erase_en, "ER"), mubi_prop(p->scramble_en, "SC"),
mubi_prop(p->ecc_en, "EC"), mubi_prop(p->high_endurance_en, "HE"),
locked ? "LK" : "UN");
}
39 changes: 39 additions & 0 deletions sw/device/lib/testing/flash_ctrl_testutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,4 +245,43 @@ enum {
OT_WARN_UNUSED_RESULT
status_t flash_ctrl_testutils_show_faults(
const dif_flash_ctrl_state_t *flash_state);

/**
* Print the properties of a flash data region configuration.
*
* This prints:
*
* data region n=<index> st=<start> sz=<size> RD-WR-ER-SC-EC-HE LK
*
* The various properties are printed depending on their mubi bool value:
* - The property (e.g. `RD`, `WR`, etc) is printed if enabled by Mubi4True.
* - The string `xx` is printed if disabled by Mubi4False.
* - The string `uu` is printed if disabled by any other non-True value.
*
* @param index The index of the region.
* @param p The properties of the region.
* @param locked Whether or not the region is locked.
*/
void flash_ctrl_testutils_data_region_print(
size_t index, dif_flash_ctrl_data_region_properties_t *p, bool locked);

/**
* Print the properties of a flash data region configuration.
*
* This prints:
*
* info region bank=<bank> part=<partition> page=<page> RD-WR-ER-SC-EC-HE LK
*
* The various properties are printed depending on their mubi bool value:
* - The property (e.g. `RD`, `WR`, etc) is printed if enabled by Mubi4True.
* - The string `xx` is printed if disabled by Mubi4False.
* - The string `uu` is printed if disabled by any other non-True value.
*
* @param region The info region descriptor.
* @param p The properties of the region.
* @param locked Whether or not the region is locked.
*/
void flash_ctrl_testutils_info_region_print(
dif_flash_ctrl_info_region_t region, dif_flash_ctrl_region_properties_t *p,
bool locked);
#endif // OPENTITAN_SW_DEVICE_LIB_TESTING_FLASH_CTRL_TESTUTILS_H_
4 changes: 4 additions & 0 deletions sw/device/silicon_creator/lib/manifest.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,7 @@ extern rom_error_t manifest_ext_get_spx_key(
extern rom_error_t manifest_ext_get_spx_signature(
const manifest_t *manifest,
const manifest_ext_spx_signature_t **spx_signature);
extern rom_error_t manifest_ext_get_isfb(const manifest_t *manifest,
const manifest_ext_isfb_t **isfb);
extern rom_error_t manifest_ext_get_isfb_erase(
const manifest_t *manifest, const manifest_ext_isfb_erase_t **isfb_erase);
4 changes: 4 additions & 0 deletions sw/device/silicon_creator/lib/manifest.h
Original file line number Diff line number Diff line change
Expand Up @@ -718,6 +718,10 @@ rom_error_t manifest_ext_get_spx_key(const manifest_t *manifest,
rom_error_t manifest_ext_get_spx_signature(
const manifest_t *manifest,
const manifest_ext_spx_signature_t **spx_signature);
rom_error_t manifest_ext_get_isfb(const manifest_t *manifest,
const manifest_ext_isfb_t **isfb);
rom_error_t manifest_ext_get_isfb_erase(
const manifest_t *manifest, const manifest_ext_isfb_erase_t **isfb_erase);

#endif // defined(OT_PLATFORM_RV32) || defined(MANIFEST_UNIT_TEST_)

Expand Down
83 changes: 72 additions & 11 deletions sw/device/silicon_creator/lib/ownership/isfb.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// 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/isfb.h"

#include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h"
#include "sw/device/silicon_creator/lib/error.h"
Expand All @@ -17,12 +18,9 @@ enum {
// The maximum size of the product expressions in bytes.
KProductExprMaxCountBytes = kProductExprMaxCount * sizeof(uint32_t),

// The number of bits in the strike mask is fixed to 128. Each bit in the
// strike mask corresponds to a `uint32_t` word.
kExpectedStrikeBitCount = 128,

// The expected size of the strike region in bytes and words.
kExpectedStrikeRegionBytesCount = kExpectedStrikeBitCount * sizeof(uint32_t),
kExpectedStrikeRegionBytesCount =
kIsfbExpectedStrikeBitCount * sizeof(uint32_t),
kExpectedStrikeRegionWordsCount =
kExpectedStrikeRegionBytesCount / sizeof(uint32_t),
};
Expand All @@ -36,7 +34,7 @@ rom_error_t isfb_boot_request_process(const manifest_ext_isfb_t *ext,
return kErrorOwnershipISFBNotPresent;
}
const owner_isfb_config_t *isfb = owner_config->isfb;
if (ext->product_expr_count * 2 > isfb->product_words ||
if (ext->product_expr_count > isfb->product_words ||
ext->product_expr_count > kProductExprMaxCount) {
return kErrorOwnershipISFBProductExpCnt;
}
Expand All @@ -50,8 +48,9 @@ rom_error_t isfb_boot_request_process(const manifest_ext_isfb_t *ext,
// There are in total 128 bits in the strike mask. Each bit corresponds to a
// `uint32_t` word.
uint32_t strikes[kExpectedStrikeRegionWordsCount];
static_assert(sizeof(ext->strike_mask) * CHAR_BIT == kExpectedStrikeBitCount,
"Strike mask size mismatch");
static_assert(
sizeof(ext->strike_mask) * CHAR_BIT == kIsfbExpectedStrikeBitCount,
"Strike mask size mismatch");
static_assert(sizeof(strikes) == kExpectedStrikeRegionBytesCount,
"Data size mismatch");

Expand All @@ -76,7 +75,7 @@ rom_error_t isfb_boot_request_process(const manifest_ext_isfb_t *ext,
}
// Check loop completion and count consistency.
HARDENED_CHECK_EQ(strike_cnt_ok + strike_cnt_bad + i,
kExpectedStrikeBitCount * 2);
kIsfbExpectedStrikeBitCount * 2);

if (launder32(strike_cnt_bad) > 0) {
return kErrorOwnershipISFBStrikeMask;
Expand Down Expand Up @@ -110,14 +109,76 @@ rom_error_t isfb_boot_request_process(const manifest_ext_isfb_t *ext,
}

// Redundant checks to ensure there were no faults in any previous checks.
if (launder32(strike_cnt_ok) == kExpectedStrikeBitCount &&
if (launder32(strike_cnt_ok) == kIsfbExpectedStrikeBitCount &&
launder32(strike_cnt_bad) == 0 &&
launder32(pe_cnt_ok) == ext->product_expr_count &&
launder32(p_cnt_bad) == 0) {
*checks_performed_count = kExpectedStrikeBitCount + ext->product_expr_count;
*checks_performed_count =
kIsfbExpectedStrikeBitCount + ext->product_expr_count;
return kErrorOk;
}

*checks_performed_count = UINT32_MAX;
return kErrorOwnershipISFBFailed;
}

rom_error_t isfb_info_flash_erase_policy_get(
owner_config_t *owner_config, uint32_t key_domain,
hardened_bool_t manifest_is_node_locked,
const manifest_ext_isfb_erase_t *ext_isfb_erase,
hardened_bool_t *erase_en) {
if ((hardened_bool_t)owner_config->isfb == kHardenedBoolFalse) {
return kErrorOwnershipISFBNotPresent;
}

uint32_t check_cnt_exp = 0;
uint32_t conditions = owner_config->isfb->erase_conditions;
hardened_bool_t policies[3] = {0};
static_assert(ARRAYSIZE(policies) <= sizeof(conditions) * 2,
"Erase conditions count mismatch");

// Only disable the expected check iff strictly set to `kMultiBitBool4False`
// in the owner config. Any other value will require the check to be
// performed.
for (uint32_t i = 0; i < ARRAYSIZE(policies); ++i, conditions >>= 4) {
if (launder32(conditions & 0xF) == kMultiBitBool4False) {
policies[i] = kHardenedBoolTrue;
} else {
check_cnt_exp = launder32(check_cnt_exp) + 1;
}
}

// Hardended counter used to detect any faults in the checks.
uint32_t check_cnt_got = 0;

// B0: Firmware must be signed with key specified by `key_domain` field.
if (policies[0] != kHardenedBoolTrue && key_domain &&
key_domain == owner_config->isfb->key_domain) {
policies[0] = kHardenedBoolTrue;
check_cnt_got = launder32(check_cnt_got) + 1;
}

// B1: Firmware must be node locked.
if (policies[1] != kHardenedBoolTrue &&
manifest_is_node_locked == kHardenedBoolTrue) {
policies[1] = kHardenedBoolTrue;
check_cnt_got = launder32(check_cnt_got) + 1;
}

// B3: `manifest_ext_isfb_erase_t` must be present and set to harden true in
// the firmware manifest.
if (policies[2] != kHardenedBoolTrue && ext_isfb_erase != NULL) {
policies[2] = (hardened_bool_t)ext_isfb_erase->erase_allowed;
check_cnt_got = launder32(check_cnt_got) + 1;
}

if (policies[0] == kHardenedBoolTrue && policies[1] == kHardenedBoolTrue &&
policies[2] == kHardenedBoolTrue) {
HARDENED_CHECK_EQ(check_cnt_got, check_cnt_exp);
// The erase policy is satisfied. Update the info flash page configuration
// with the new erase policy.
*erase_en = kHardenedBoolTrue;
}

return kErrorOk;
}
31 changes: 31 additions & 0 deletions sw/device/silicon_creator/lib/ownership/isfb.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,16 @@
extern "C" {
#endif

enum {
// The number of bits in the strike mask is fixed to 128. Each bit in the
// strike mask corresponds to a `uint32_t` word.
kIsfbExpectedStrikeBitCount = 128,
};

inline uint32_t isfb_expected_count_get(const manifest_ext_isfb_t *ext) {
return ext->product_expr_count + kIsfbExpectedStrikeBitCount;
}

/**
* Processes the Integrator Specific FW Binding (ISFB) boot request.
*
Expand Down Expand Up @@ -44,6 +54,27 @@ rom_error_t isfb_boot_request_process(const manifest_ext_isfb_t *ext,
const owner_config_t *owner_config,
uint32_t *checks_performed_count);

/**
* Gets the flash erase policy for the ISFB info page.
*
* This function checks the erase policy for the ISFB info page based on the
* provided owner configuration, key domain, and manifest node lock status.
*
* @param owner_config The owner configuration.
* @param key_domain The key domain associated with the active secure boot key.
* @param manifest_is_node_locked Indicates whether the manifest is node locked.
* @param ext_isfb_erase The ISFB erase policy extension from the manifest. May
* be NULL.
* @param[out] erase_en The erase enable flag. Set to kHardenedBoolTrue if
* erasing the ISFB info page is allowed, otherwise
* kHardenedBoolFalse.
* @return The result of the operation.
*/
rom_error_t isfb_info_flash_erase_policy_get(
owner_config_t *owner_config, uint32_t key_domain,
hardened_bool_t manifest_is_node_locked,
const manifest_ext_isfb_erase_t *ext_isfb_erase, hardened_bool_t *erase_en);

#ifdef __cplusplus
}
#endif
Expand Down
2 changes: 1 addition & 1 deletion sw/device/silicon_creator/lib/ownership/isfb_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ TEST_F(IsfbTest, InvalidManifestProductExpressionCount) {
},
// The product expression count is larger than what is allowed in the
// ownership configuration.
.product_expr_count = 4,
.product_expr_count = 5,
};
uint32_t checks_performed_count;
rom_error_t error =
Expand Down
37 changes: 37 additions & 0 deletions sw/device/silicon_creator/lib/ownership/owner_block.c
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,43 @@ rom_error_t owner_block_info_lockdown(const owner_flash_info_config_t *info) {
return kErrorOk;
}

rom_error_t owner_block_info_isfb_erase_enable(
boot_data_t *bootdata, const owner_config_t *owner_config) {
if (bootdata->ownership_state != kOwnershipStateLockedOwner)
return kErrorOk;
// Check whether the ISFB configuration exists.
if ((hardened_bool_t)owner_config->isfb == kHardenedBoolFalse)
return kErrorOk;
// Check whether the FLASH INFO configuration exists.
if ((hardened_bool_t)owner_config->info == kHardenedBoolFalse)
return kErrorOk;

const owner_flash_info_config_t *info = owner_config->info;
size_t len = (info->header.length - sizeof(owner_flash_info_config_t)) /
sizeof(owner_info_page_t);

const owner_info_page_t *config = info->config;
uint32_t crypt = 0;
for (size_t i = 0; i < len; ++i, ++config, crypt += 0x11111111) {
if (is_owner_page(config->bank, config->page) == kHardenedBoolTrue &&
config->bank == owner_config->isfb->bank &&
config->page == owner_config->isfb->page) {
flash_ctrl_info_page_t page;
HARDENED_RETURN_IF_ERROR(flash_ctrl_info_type0_params_build(
config->bank, config->page, &page));

uint32_t val = config->access ^ crypt;
flash_ctrl_perms_t perm = {
.read = bitfield_field32_read(val, FLASH_CONFIG_READ),
.write = bitfield_field32_read(val, FLASH_CONFIG_PROGRAM),
.erase = kMultiBitBool4True,
};
flash_ctrl_info_perms_set(&page, perm);
}
}
return kErrorOk;
}

rom_error_t owner_block_rescue_apply(const owner_rescue_config_t *rescue) {
rescue_detect_t detect = bitfield_field32_read(rescue->detect, RESCUE_DETECT);
uint32_t index = bitfield_field32_read(rescue->detect, RESCUE_DETECT_INDEX);
Expand Down
18 changes: 18 additions & 0 deletions sw/device/silicon_creator/lib/ownership/owner_block.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,24 @@ rom_error_t owner_block_info_apply(const owner_flash_info_config_t *info);
*/
rom_error_t owner_block_info_lockdown(const owner_flash_info_config_t *info);

/**
* Enable erase on the ISFB info page.
*
* Unconditionally enables erase on the ISFB info page. This function is used
* to enable the erase policy for the ISFB info page.
*
* The function does not enable erase on the ISFB info page if the owner config
* does not contain the ISFB or info page owner blocks. The settings are also
* ignored if the device is not in the `kOwnershipStateLockedOwner` state.
*
* @param bootdata The current boot data.
* @param owner_config The owner configuration.
*
* @return The result of the operation.
*/
rom_error_t owner_block_info_isfb_erase_enable(
boot_data_t *bootdata, const owner_config_t *owner_config);

rom_error_t owner_keyring_find_key(const owner_application_keyring_t *keyring,
uint32_t key_id, size_t *index);

Expand Down
Loading
Loading