From ddea231c278fc3d7dbc3625c43ad6b995730bfc9 Mon Sep 17 00:00:00 2001 From: Miguel Osorio Date: Fri, 15 Oct 2021 14:42:15 -0700 Subject: [PATCH] [sw/rom] Add rom_ext sec_mmio initialization sec_mmio initialization for the ROM_EXT clears the current check count expectation and resets all entries in the expectation table that were not used by the ROM. This is to ensure that an attacker is not able to recreate the state of the expectation table after injecting a reset fault. Signed-off-by: Miguel Osorio --- sw/device/silicon_creator/lib/base/sec_mmio.c | 11 +++++ sw/device/silicon_creator/lib/base/sec_mmio.h | 15 +++++++ .../lib/base/sec_mmio_unittest.cc | 41 +++++++++++++++++++ 3 files changed, 67 insertions(+) diff --git a/sw/device/silicon_creator/lib/base/sec_mmio.c b/sw/device/silicon_creator/lib/base/sec_mmio.c index 514029fec4c00..d798e782696cf 100644 --- a/sw/device/silicon_creator/lib/base/sec_mmio.c +++ b/sw/device/silicon_creator/lib/base/sec_mmio.c @@ -63,6 +63,17 @@ void sec_mmio_init(sec_mmio_shutdown_handler cb) { sec_mmio_ctx.expected_write_count = 0; for (size_t i = 0; i < ARRAYSIZE(sec_mmio_ctx.addrs); ++i) { sec_mmio_ctx.addrs[i] = UINT32_MAX; + sec_mmio_ctx.values[i] = UINT32_MAX; + } +} + +void sec_mmio_next_stage_init(sec_mmio_shutdown_handler cb) { + sec_mmio_shutdown_cb = cb; + sec_mmio_ctx.check_count = 0; + for (size_t i = sec_mmio_ctx.last_index; i < ARRAYSIZE(sec_mmio_ctx.addrs); + ++i) { + sec_mmio_ctx.addrs[i] = UINT32_MAX; + sec_mmio_ctx.values[i] = UINT32_MAX; } } diff --git a/sw/device/silicon_creator/lib/base/sec_mmio.h b/sw/device/silicon_creator/lib/base/sec_mmio.h index e63f03954276d..666b29a877218 100644 --- a/sw/device/silicon_creator/lib/base/sec_mmio.h +++ b/sw/device/silicon_creator/lib/base/sec_mmio.h @@ -131,6 +131,21 @@ typedef void (*sec_mmio_shutdown_handler)(rom_error_t); */ void sec_mmio_init(sec_mmio_shutdown_handler cb); +/** + * Executes sec_mmio next boot stage initialization. + * + * Registers the `cb` callback handler, and performs the following operations to + * the internal `sec_mmio_ctx_t` context: + * + * - Clear the check count. This allows the caller to reset the + * `sec_mmio_check_counters()` expected count argument. + * - Reset all expected address and values in the expectations table starting at + * the last_index. + * + * @param cb Shutdown module callback handler. + */ +void sec_mmio_next_stage_init(sec_mmio_shutdown_handler cb); + /** * Reads an aligned uint32_t from the MMIO region `addr`. * diff --git a/sw/device/silicon_creator/lib/base/sec_mmio_unittest.cc b/sw/device/silicon_creator/lib/base/sec_mmio_unittest.cc index 031709d5345d5..0655faafd960a 100644 --- a/sw/device/silicon_creator/lib/base/sec_mmio_unittest.cc +++ b/sw/device/silicon_creator/lib/base/sec_mmio_unittest.cc @@ -20,6 +20,7 @@ extern sec_mmio_ctx_t sec_mmio_ctx; namespace sec_mmio_unittest { namespace { using ::testing::Each; +using ::testing::ElementsAreArray; using ::testing::Eq; using ::testing::Test; @@ -46,6 +47,46 @@ TEST_F(SecMmioTest, Initialize) { EXPECT_EQ(ctx_->last_index, 0); EXPECT_EQ(ctx_->write_count, 0); EXPECT_THAT(ctx_->addrs, Each(Eq(UINT32_MAX))); + EXPECT_THAT(ctx_->values, Each(Eq(UINT32_MAX))); +} + +TEST_F(SecMmioTest, NextStageInitialize) { + // Ensure the register file size is greater than zero to ensure checks are + // performed on non-zero sized arrays. + static_assert(kSecMmioRegFileSize > 2); + std::array expected_addrs; + std::array expected_values; + + // Prefill data to simulate a pre-initialization conditions. Use different + // values for `addr` and `values` to ensure the test checks are specific for + // each array. + for (size_t i = 0; i < kSecMmioRegFileSize; ++i) { + ctx_->addrs[i] = i ^ 0xa; + ctx_->values[i] = i ^ 0x5; + expected_addrs[i] = ctx_->addrs[i]; + expected_values[i] = ctx_->values[i]; + } + + ctx_->check_count = 5; + ctx_->expected_write_count = 6; + ctx_->write_count = 6; + + const uint32_t kExpectedWriteCount = kSecMmioRegFileSize / 2; + ctx_->last_index = kExpectedWriteCount; + + for (size_t i = kExpectedWriteCount; i < kSecMmioRegFileSize; ++i) { + expected_addrs[i] = UINT32_MAX; + expected_values[i] = UINT32_MAX; + } + + sec_mmio_next_stage_init(+[](rom_error_t) { std::abort(); }); + + EXPECT_EQ(ctx_->write_count, 6); + EXPECT_EQ(ctx_->expected_write_count, 6); + EXPECT_EQ(ctx_->last_index, kExpectedWriteCount); + EXPECT_EQ(ctx_->check_count, 0); + EXPECT_THAT(ctx_->addrs, ElementsAreArray(expected_addrs)); + EXPECT_THAT(ctx_->values, ElementsAreArray(expected_values)); } TEST_F(SecMmioTest, Read32OrDie) {