-
Notifications
You must be signed in to change notification settings - Fork 782
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[rom_ext] Implement Integrator Specific FW Binding (ISFB) logic.
Implements Integrator Specific FW Binding (ISFB) functionality to provide anti-rollback and product binding functionality to application firmware. The following changes are included: 1. Add flash_ctrl helper function to generate the info flash page configuration based on the ownership ISFB config. 2. Implement isfb logic as a separate module to simplify ROM_EXT integration. 3. Add unittest cases to verify anti-rollback and product association functionality. 4. Add minimum level of hardening against FI. The ROM_EXT integration and e2e test cases will be implemented in a follow up commit. Signed-off-by: Miguel Osorio <[email protected]>
- Loading branch information
Showing
11 changed files
with
492 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
// 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/drivers/flash_ctrl.h" | ||
#include "sw/device/silicon_creator/lib/error.h" | ||
#include "sw/device/silicon_creator/lib/manifest.h" | ||
#include "sw/device/silicon_creator/lib/ownership/owner_block.h" | ||
|
||
enum { | ||
kFlashWordSize = 64, | ||
|
||
// The number of bits in the strike mask is fixed to 128. Each bit in the | ||
// strike mask corresponds to a flash word. | ||
kExpectedStrikeBitCount = 128, | ||
|
||
// The expected size of the strike region in bytes and words. | ||
kExpectedStrikeRegionBytesCount = | ||
(kExpectedStrikeBitCount * kFlashWordSize) / CHAR_BIT, | ||
kExpectedStrikeRegionWordsCount = | ||
kExpectedStrikeRegionBytesCount / sizeof(uint32_t), | ||
}; | ||
|
||
rom_error_t isfb_boot_request_process(const manifest_ext_isfb_t *ext, | ||
const owner_config_t *owner_config, | ||
uint32_t *checks_performed_count) { | ||
*checks_performed_count = UINT32_MAX; | ||
if (ext->header.name != kManifestExtIdIsfb || | ||
(hardened_bool_t)owner_config->isfb == kHardenedBoolFalse) { | ||
return kErrorOwnershipISFBNotPresent; | ||
} | ||
const owner_isfb_config_t *isfb = owner_config->isfb; | ||
if (ext->product_expr_count * 2 > isfb->product_words) { | ||
return kErrorOwnershipISFBProductExpCnt; | ||
} | ||
|
||
flash_ctrl_perms_t perm = { | ||
.read = kMultiBitBool4True, | ||
.write = kMultiBitBool4False, | ||
.erase = kMultiBitBool4False, | ||
}; | ||
flash_ctrl_cfg_t cfg = { | ||
.scrambling = kMultiBitBool4True, | ||
.ecc = kMultiBitBool4True, | ||
.he = kMultiBitBool4True, | ||
}; | ||
|
||
flash_ctrl_info_page_t isfb_info_page; | ||
HARDENED_RETURN_IF_ERROR(flash_ctrl_info_type0_params_build( | ||
isfb->bank, isfb->page, &isfb_info_page)); | ||
flash_ctrl_info_perms_set(&isfb_info_page, perm); | ||
flash_ctrl_info_cfg_set(&isfb_info_page, cfg); | ||
|
||
// There are in total 128 bits in the strike mask. Each bit corresponds to a | ||
// flash word. Each flash word is 64 bits. | ||
uint32_t data[kExpectedStrikeRegionWordsCount]; | ||
static_assert(sizeof(ext->strike_mask) * CHAR_BIT == kExpectedStrikeBitCount, | ||
"Strike mask size mismatch"); | ||
static_assert(sizeof(data) == kExpectedStrikeRegionBytesCount, | ||
"Data size mismatch"); | ||
|
||
HARDENED_RETURN_IF_ERROR(flash_ctrl_info_read(&isfb_info_page, /*offset=*/0, | ||
ARRAYSIZE(data), data)); | ||
|
||
uint32_t strike_cnt_ok = 0; | ||
uint32_t strike_cnt_bad = 0; | ||
uint64_t *strike_word = (uint64_t *)data; | ||
size_t i; | ||
for (i = 0; i < ARRAYSIZE(data) / 2; ++i, ++strike_word) { | ||
uint32_t strike_bit = ext->strike_mask[i >> 5] & (1 << (i & 31)); | ||
if (launder32(strike_bit) && *strike_word == 0) { | ||
strike_cnt_bad++; | ||
} else if (!launder32(strike_bit) || *strike_word != 0) { | ||
strike_cnt_ok++; | ||
} else { | ||
// This condition is equivalent to a potential fault in either the strike | ||
// mask or the ISFB info buffer. | ||
strike_cnt_bad++; | ||
} | ||
} | ||
// Check loop completion and count consistency. | ||
HARDENED_CHECK_EQ(strike_cnt_ok + strike_cnt_bad + i, | ||
kExpectedStrikeBitCount * 2); | ||
|
||
if (launder32(strike_cnt_bad) > 0) { | ||
return kErrorOwnershipISFBStrikeMask; | ||
} | ||
|
||
// Read the product expressions from the ISFB info page. | ||
HARDENED_RETURN_IF_ERROR(flash_ctrl_info_read( | ||
&isfb_info_page, /*offset=*/1024, ARRAYSIZE(data), data)); | ||
|
||
uint32_t pexpr_cnt_ok = 0; | ||
uint32_t pexpr_cnt_bad = 0; | ||
for (i = 0; i < ext->product_expr_count; ++i) { | ||
if ((data[i] & ext->product_expr[i].mask) == ext->product_expr[i].value) { | ||
pexpr_cnt_ok++; | ||
} else { | ||
pexpr_cnt_bad++; | ||
} | ||
} | ||
HARDENED_CHECK_EQ(pexpr_cnt_ok + pexpr_cnt_bad, ext->product_expr_count); | ||
HARDENED_CHECK_EQ(i, ext->product_expr_count); | ||
|
||
if (launder32(pexpr_cnt_bad) > 0) { | ||
return kErrorOwnershipISFBProductExp; | ||
} | ||
|
||
// Redundant checks to ensure there were no faults in any previous checks. | ||
if (launder32(strike_cnt_ok) == kExpectedStrikeBitCount && | ||
launder32(strike_cnt_bad) == 0 && | ||
launder32(pexpr_cnt_ok) == ext->product_expr_count && | ||
launder32(pexpr_cnt_bad) == 0) { | ||
*checks_performed_count = kExpectedStrikeBitCount + ext->product_expr_count; | ||
return kErrorOk; | ||
} | ||
|
||
*checks_performed_count = UINT32_MAX; | ||
return kErrorOwnershipISFBFailed; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// 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_ECDSA_H_ | ||
#define OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_OWNERSHIP_ECDSA_H_ | ||
|
||
#include <stdint.h> | ||
|
||
#include "sw/device/silicon_creator/lib/error.h" | ||
#include "sw/device/silicon_creator/lib/manifest.h" | ||
#include "sw/device/silicon_creator/lib/ownership/owner_block.h" | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
/** | ||
* Processes the Integrator Specific FW Binding (ISFB) boot request. | ||
* | ||
* This function processes the ISFB boot request and performs the necessary | ||
* checks to ensure that the firmware is bound to the correct | ||
* integrator-specific firmware binding configuration. | ||
* | ||
* The checks performed are: | ||
* - The ISFB extension is valid. | ||
* - The ISFB configuration is present in the owner configuration. | ||
* - The product expression count set in the manifest is within the bounds of | ||
* the owner configuration. | ||
* - The strike mask yields the expected number of strikes in the ISFB info | ||
* page. | ||
* - The product expressions in the ISFB info page match the expected values. | ||
* | ||
* @param ext The ISFB extension from the manifest. | ||
* @param owner_config The owner configuration. | ||
* @param[out] checks_performed_count The number of checks performed. This | ||
* should be equivalent to the number of strike bits and the number of product | ||
* expressions. Use this value in the consuming code as a way to harden the call | ||
* against fault injection. | ||
* | ||
* @return The result of the operation. | ||
*/ | ||
rom_error_t isfb_boot_request_process(const manifest_ext_isfb_t *ext, | ||
const owner_config_t *owner_config, | ||
uint32_t *checks_performed_count); | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif | ||
|
||
#endif // OPENTITAN_SW_DEVICE_SILICON_CREATOR_LIB_OWNERSHIP_ECDSA_H_ |
Oops, something went wrong.