diff --git a/sw/device/silicon_creator/lib/ownership/BUILD b/sw/device/silicon_creator/lib/ownership/BUILD index 94c7f6df1e932..d2a5e8244b243 100644 --- a/sw/device/silicon_creator/lib/ownership/BUILD +++ b/sw/device/silicon_creator/lib/ownership/BUILD @@ -83,6 +83,7 @@ dual_cc_library( "//sw/device/silicon_creator/lib/drivers:keymgr", "//sw/device/silicon_creator/lib/drivers:kmac", "//sw/device/silicon_creator/lib/drivers:flash_ctrl", + "//sw/device/silicon_creator/lib/sigverify:flash_exec", ], host = [ "//sw/device/lib/base:global_mock", @@ -114,6 +115,7 @@ cc_library( "//sw/device/silicon_creator/lib/drivers:flash_ctrl", "//sw/device/silicon_creator/lib/drivers:lifecycle", "//sw/device/silicon_creator/lib/drivers:rnd", + "//sw/device/silicon_creator/lib/sigverify:flash_exec", ], ) @@ -166,6 +168,7 @@ cc_library( "//sw/device/silicon_creator/lib/drivers:flash_ctrl", "//sw/device/silicon_creator/lib/drivers:hmac", "//sw/device/silicon_creator/lib/drivers:lifecycle", + "//sw/device/silicon_creator/lib/sigverify:flash_exec", ], ) @@ -183,6 +186,7 @@ cc_test( "//sw/device/silicon_creator/lib/boot_svc:boot_svc_header", "//sw/device/silicon_creator/lib/drivers:lifecycle", "//sw/device/silicon_creator/lib/drivers:rnd", + "//sw/device/silicon_creator/lib/sigverify:flash_exec", "//sw/device/silicon_creator/testing:rom_test", "@googletest//:gtest_main", ], @@ -202,6 +206,7 @@ cc_library( "//sw/device/silicon_creator/lib/boot_svc:boot_svc_msg", "//sw/device/silicon_creator/lib/drivers:flash_ctrl", "//sw/device/silicon_creator/lib/drivers:lifecycle", + "//sw/device/silicon_creator/lib/sigverify:flash_exec", ], ) @@ -217,6 +222,7 @@ cc_test( "//sw/device/lib/base:hardened", "//sw/device/silicon_creator/lib:boot_data", "//sw/device/silicon_creator/lib/boot_svc:boot_svc_header", + "//sw/device/silicon_creator/lib/sigverify:flash_exec", "//sw/device/silicon_creator/testing:rom_test", "@googletest//:gtest_main", ], diff --git a/sw/device/silicon_creator/lib/ownership/mock_ownership_key.cc b/sw/device/silicon_creator/lib/ownership/mock_ownership_key.cc index 81e56a1c1bcea..ca017d6e7c306 100644 --- a/sw/device/silicon_creator/lib/ownership/mock_ownership_key.cc +++ b/sw/device/silicon_creator/lib/ownership/mock_ownership_key.cc @@ -9,9 +9,10 @@ extern "C" { hardened_bool_t ownership_key_validate(size_t page, ownership_key_t key, const owner_signature_t *signature, - const void *message, size_t len) { + const void *message, size_t len, + uint32_t *flash_exec) { return MockOwnershipKey::Instance().validate(page, key, signature, message, - len); + len, flash_exec); } rom_error_t ownership_seal_init() { diff --git a/sw/device/silicon_creator/lib/ownership/mock_ownership_key.h b/sw/device/silicon_creator/lib/ownership/mock_ownership_key.h index 6ffcf2ecc94d3..5fbb3317868c8 100644 --- a/sw/device/silicon_creator/lib/ownership/mock_ownership_key.h +++ b/sw/device/silicon_creator/lib/ownership/mock_ownership_key.h @@ -19,7 +19,7 @@ class MockOwnershipKey : public global_mock::GlobalMock { public: MOCK_METHOD(hardened_bool_t, validate, (size_t, ownership_key_t, const owner_signature_t *, const void *, - size_t)); + size_t, uint32_t *)); MOCK_METHOD(rom_error_t, seal_init, ()); MOCK_METHOD(rom_error_t, seal_page, (size_t)); MOCK_METHOD(rom_error_t, seal_check, (size_t)); diff --git a/sw/device/silicon_creator/lib/ownership/ownership.c b/sw/device/silicon_creator/lib/ownership/ownership.c index b855eca1ec7e0..7ead4a50c7c9f 100644 --- a/sw/device/silicon_creator/lib/ownership/ownership.c +++ b/sw/device/silicon_creator/lib/ownership/ownership.c @@ -47,9 +47,9 @@ static owner_page_status_t owner_page_validity_check(size_t page) { return kOwnerPageStatusSealed; } - hardened_bool_t result = ownership_key_validate(page, kOwnershipKeyOwner, - &owner_page[page].signature, - &owner_page[page], sig_len); + hardened_bool_t result = ownership_key_validate( + page, kOwnershipKeyOwner, &owner_page[page].signature, &owner_page[page], + sig_len, NULL); if (result == kHardenedBoolFalse) { // If the page is bad, destroy the RAM copy. memset(&owner_page[page], 0x5a, sizeof(owner_page[0])); diff --git a/sw/device/silicon_creator/lib/ownership/ownership_activate.c b/sw/device/silicon_creator/lib/ownership/ownership_activate.c index 5b0b25f7aa6ba..ec615543677bc 100644 --- a/sw/device/silicon_creator/lib/ownership/ownership_activate.c +++ b/sw/device/silicon_creator/lib/ownership/ownership_activate.c @@ -13,6 +13,7 @@ #include "sw/device/silicon_creator/lib/error.h" #include "sw/device/silicon_creator/lib/ownership/owner_block.h" #include "sw/device/silicon_creator/lib/ownership/ownership_key.h" +#include "sw/device/silicon_creator/lib/sigverify/flash_exec.h" rom_error_t ownership_activate(boot_data_t *bootdata, hardened_bool_t write_both_pages) { @@ -62,15 +63,21 @@ static rom_error_t activate_handler(boot_svc_msg_t *msg, return kErrorOwnershipInvalidInfoPage; } + // Set the variable checking whether the correct signatures have been + // verified. + uint32_t flash_exec = 0; + // Check the activation key and the nonce. size_t len = (uintptr_t)&msg->ownership_activate_req.signature - (uintptr_t)&msg->ownership_activate_req.primary_bl0_slot; if (ownership_key_validate(/*page=*/1, kOwnershipKeyActivate, &msg->ownership_activate_req.signature, - &msg->ownership_activate_req.primary_bl0_slot, - len) == kHardenedBoolFalse) { + &msg->ownership_activate_req.primary_bl0_slot, len, + &flash_exec) == kHardenedBoolFalse) { return kErrorOwnershipInvalidSignature; } + // Verify that we passed signature verification for the message. + HARDENED_CHECK_EQ(flash_exec, kSigverifyFlashExec); if (!nonce_equal(&msg->ownership_activate_req.nonce, &bootdata->nonce)) { return kErrorOwnershipInvalidNonce; } 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 867f7d58ee420..0443e3afe727f 100644 --- a/sw/device/silicon_creator/lib/ownership/ownership_activate_unittest.cc +++ b/sw/device/silicon_creator/lib/ownership/ownership_activate_unittest.cc @@ -21,10 +21,12 @@ #include "sw/device/silicon_creator/lib/ownership/datatypes.h" #include "sw/device/silicon_creator/lib/ownership/mock_ownership_key.h" #include "sw/device/silicon_creator/lib/ownership/owner_block.h" +#include "sw/device/silicon_creator/lib/sigverify/flash_exec.h" #include "sw/device/silicon_creator/testing/rom_test.h" namespace { using ::testing::_; +using ::testing::DoAll; using ::testing::Return; using ::testing::SetArgPointee; @@ -131,8 +133,9 @@ TEST_P(OwnershipActivateValidStateTest, InvalidVersion) { MakePage1Valid(true); owner_page[1].header.version.major = 5; - EXPECT_CALL(ownership_key_, validate(1, kOwnershipKeyActivate, _, _, _)) - .WillOnce(Return(kHardenedBoolTrue)); + EXPECT_CALL(ownership_key_, validate(1, kOwnershipKeyActivate, _, _, _, _)) + .WillOnce(DoAll(SetArgPointee<5>(kSigverifyFlashExec), + Return(kHardenedBoolTrue))); EXPECT_CALL(lifecycle_, DeviceId(_)) .WillOnce(SetArgPointee<0>((lifecycle_device_id_t){0})); EXPECT_CALL(hdr_, Finalize(_, _, _)); @@ -147,8 +150,8 @@ TEST_P(OwnershipActivateValidStateTest, InvalidSignature) { // We want to pass the page 1 validity test to check the signature on the // message. MakePage1Valid(true); - EXPECT_CALL(ownership_key_, validate(1, kOwnershipKeyActivate, _, _, _)) - .WillOnce(Return(kHardenedBoolFalse)); + EXPECT_CALL(ownership_key_, validate(1, kOwnershipKeyActivate, _, _, _, _)) + .WillOnce(DoAll(SetArgPointee<5>(0), Return(kHardenedBoolFalse))); EXPECT_CALL(hdr_, Finalize(_, _, _)); rom_error_t error = ownership_activate_handler(&message_, &bootdata_); @@ -162,8 +165,9 @@ TEST_P(OwnershipActivateValidStateTest, InvalidNonce) { // We want to pass the page 1 validity test to check the nonce of the // message. MakePage1Valid(true); - EXPECT_CALL(ownership_key_, validate(1, kOwnershipKeyActivate, _, _, _)) - .WillOnce(Return(kHardenedBoolTrue)); + EXPECT_CALL(ownership_key_, validate(1, kOwnershipKeyActivate, _, _, _, _)) + .WillOnce(DoAll(SetArgPointee<5>(kSigverifyFlashExec), + Return(kHardenedBoolTrue))); EXPECT_CALL(hdr_, Finalize(_, _, _)); rom_error_t error = ownership_activate_handler(&message_, &bootdata_); @@ -176,8 +180,9 @@ TEST_P(OwnershipActivateValidStateTest, InvalidActivateDin) { // We want to pass the page 1 validity test to check the nonce of the // message. MakePage1Valid(true); - EXPECT_CALL(ownership_key_, validate(1, kOwnershipKeyActivate, _, _, _)) - .WillOnce(Return(kHardenedBoolTrue)); + EXPECT_CALL(ownership_key_, validate(1, kOwnershipKeyActivate, _, _, _, _)) + .WillOnce(DoAll(SetArgPointee<5>(kSigverifyFlashExec), + Return(kHardenedBoolTrue))); EXPECT_CALL(lifecycle_, DeviceId(_)) .WillOnce(SetArgPointee<0>((lifecycle_device_id_t){0, 1, 1})); EXPECT_CALL(hdr_, Finalize(_, _, _)); @@ -228,8 +233,9 @@ TEST_P(OwnershipActivateValidStateTest, OwnerPageValid) { bootdata_.next_owner[0] = 12345; MakePage1Valid(true); - EXPECT_CALL(ownership_key_, validate(1, kOwnershipKeyActivate, _, _, _)) - .WillOnce(Return(kHardenedBoolTrue)); + EXPECT_CALL(ownership_key_, validate(1, kOwnershipKeyActivate, _, _, _, _)) + .WillOnce(DoAll(SetArgPointee<5>(kSigverifyFlashExec), + Return(kHardenedBoolTrue))); EXPECT_CALL(lifecycle_, DeviceId(_)) .WillOnce(SetArgPointee<0>((lifecycle_device_id_t){0})); @@ -297,8 +303,9 @@ TEST_P(OwnershipActivateValidStateTest, UpdateBootdataBl0) { MakePage1Valid(true); owner_page[1].min_security_version_bl0 = 5; - EXPECT_CALL(ownership_key_, validate(1, kOwnershipKeyActivate, _, _, _)) - .WillOnce(Return(kHardenedBoolTrue)); + EXPECT_CALL(ownership_key_, validate(1, kOwnershipKeyActivate, _, _, _, _)) + .WillOnce(DoAll(SetArgPointee<5>(kSigverifyFlashExec), + Return(kHardenedBoolTrue))); EXPECT_CALL(lifecycle_, DeviceId(_)) .WillOnce(SetArgPointee<0>((lifecycle_device_id_t){0})); diff --git a/sw/device/silicon_creator/lib/ownership/ownership_key.c b/sw/device/silicon_creator/lib/ownership/ownership_key.c index 0da48a5b4b597..1792b2e2449ff 100644 --- a/sw/device/silicon_creator/lib/ownership/ownership_key.c +++ b/sw/device/silicon_creator/lib/ownership/ownership_key.c @@ -10,6 +10,7 @@ #include "sw/device/silicon_creator/lib/drivers/keymgr.h" #include "sw/device/silicon_creator/lib/drivers/kmac.h" #include "sw/device/silicon_creator/lib/ownership/ecdsa.h" +#include "sw/device/silicon_creator/lib/sigverify/flash_exec.h" // RAM copy of the owner INFO pages from flash. extern owner_block_t owner_page[2]; @@ -18,7 +19,10 @@ OT_WEAK const owner_key_t *const kNoOwnerRecoveryKey; hardened_bool_t ownership_key_validate(size_t page, ownership_key_t key, const owner_signature_t *signature, - const void *message, size_t len) { + const void *message, size_t len, + uint32_t *flash_exec) { + // TODO: Pipe this through to a secure ecdsa. + *flash_exec = kSigverifyFlashExec; if ((key & kOwnershipKeyUnlock) == kOwnershipKeyUnlock) { if (ecdsa_verify_message(&owner_page[page].unlock_key.ecdsa, &signature->ecdsa, message, diff --git a/sw/device/silicon_creator/lib/ownership/ownership_key.h b/sw/device/silicon_creator/lib/ownership/ownership_key.h index 0f27edab87c12..f7c637682ec19 100644 --- a/sw/device/silicon_creator/lib/ownership/ownership_key.h +++ b/sw/device/silicon_creator/lib/ownership/ownership_key.h @@ -49,11 +49,14 @@ typedef struct owner_secret_page { * @param signature The signature over the message. * @param message Pointer to the message. * @param len Size of the message. + * @param flash_exec The magic value signifying whether the signature was + * verified. * @return kHardenedBoolTrue if the message is valid. */ hardened_bool_t ownership_key_validate(size_t page, ownership_key_t key, const owner_signature_t *signature, - const void *message, size_t len); + const void *message, size_t len, + uint32_t *flash_exec); /** * Initialize sealing. diff --git a/sw/device/silicon_creator/lib/ownership/ownership_unlock.c b/sw/device/silicon_creator/lib/ownership/ownership_unlock.c index 0484d36251759..99e6ba2738e9d 100644 --- a/sw/device/silicon_creator/lib/ownership/ownership_unlock.c +++ b/sw/device/silicon_creator/lib/ownership/ownership_unlock.c @@ -13,6 +13,7 @@ #include "sw/device/silicon_creator/lib/error.h" #include "sw/device/silicon_creator/lib/ownership/owner_block.h" #include "sw/device/silicon_creator/lib/ownership/ownership_key.h" +#include "sw/device/silicon_creator/lib/sigverify/flash_exec.h" static hardened_bool_t is_locked_none(uint32_t ownership_state) { if (ownership_state == kOwnershipStateLockedOwner || @@ -24,12 +25,16 @@ static hardened_bool_t is_locked_none(uint32_t ownership_state) { return kHardenedBoolTrue; } -static rom_error_t do_unlock(boot_svc_msg_t *msg, boot_data_t *bootdata) { +static rom_error_t do_unlock(boot_svc_msg_t *msg, boot_data_t *bootdata, + uint32_t *flash_exec) { // Verify that the nonce is correct. if (!nonce_equal(&msg->ownership_unlock_req.nonce, &bootdata->nonce)) { return kErrorOwnershipInvalidNonce; } + // Verify that we passed signature verification for the message. + HARDENED_CHECK_EQ(*flash_exec, kSigverifyFlashExec); + // Verify the device identification number is correct. lifecycle_device_id_t device_id; lifecycle_device_id_get(&device_id); @@ -59,6 +64,9 @@ static rom_error_t unlock(boot_svc_msg_t *msg, boot_data_t *bootdata) { size_t len = (uintptr_t)&msg->ownership_unlock_req.signature - (uintptr_t)&msg->ownership_unlock_req.unlock_mode; if (bootdata->ownership_state == kOwnershipStateLockedOwner) { + // Set the variable checking whether the correct signatures have been + // verified + uint32_t flash_exec = 0; switch (owner_page[0].update_mode) { case kOwnershipUpdateModeOpen: // The Open mode allows unlock to any unlock state. @@ -79,21 +87,24 @@ static rom_error_t unlock(boot_svc_msg_t *msg, boot_data_t *bootdata) { if (ownership_key_validate( /*page=*/0, kOwnershipKeyUnlock | kOwnershipKeyRecovery, &msg->ownership_unlock_req.signature, - &msg->ownership_unlock_req.unlock_mode, - len) == kHardenedBoolFalse) { + &msg->ownership_unlock_req.unlock_mode, len, + &flash_exec) == kHardenedBoolFalse) { return kErrorOwnershipInvalidSignature; } - return do_unlock(msg, bootdata); + return do_unlock(msg, bootdata, &flash_exec); } else if (is_locked_none(bootdata->ownership_state) == kHardenedBoolTrue) { // In the No-Owner state, we check against the silicon_creator's // no_owner_recovery_key. + // Set the variable checking whether the correct signatures have been + // verified + uint32_t flash_exec = 0; if (ownership_key_validate(/*page=*/0, kOwnershipKeyRecovery, &msg->ownership_unlock_req.signature, - &msg->ownership_unlock_req.unlock_mode, - len) == kHardenedBoolFalse) { + &msg->ownership_unlock_req.unlock_mode, len, + &flash_exec) == kHardenedBoolFalse) { return kErrorOwnershipInvalidSignature; } - return do_unlock(msg, bootdata); + return do_unlock(msg, bootdata, &flash_exec); } else { return kErrorOwnershipInvalidState; } @@ -102,6 +113,9 @@ static rom_error_t unlock(boot_svc_msg_t *msg, boot_data_t *bootdata) { static rom_error_t unlock_update(boot_svc_msg_t *msg, boot_data_t *bootdata) { size_t len = (uintptr_t)&msg->ownership_unlock_req.signature - (uintptr_t)&msg->ownership_unlock_req.unlock_mode; + // Set the variable checking whether the correct signatures have been + // verified. + uint32_t flash_exec = 0; if (bootdata->ownership_state == kOwnershipStateLockedOwner) { switch (owner_page[0].update_mode) { case kOwnershipUpdateModeNewVersion: @@ -118,11 +132,11 @@ static rom_error_t unlock_update(boot_svc_msg_t *msg, boot_data_t *bootdata) { // Check the signature against the unlock key. if (ownership_key_validate(/*page=*/0, kOwnershipKeyUnlock, &msg->ownership_unlock_req.signature, - &msg->ownership_unlock_req.unlock_mode, - len) == kHardenedBoolFalse) { + &msg->ownership_unlock_req.unlock_mode, len, + &flash_exec) == kHardenedBoolFalse) { return kErrorOwnershipInvalidSignature; } - return do_unlock(msg, bootdata); + return do_unlock(msg, bootdata, &flash_exec); } return kErrorOwnershipInvalidState; } @@ -133,13 +147,18 @@ static rom_error_t unlock_abort(boot_svc_msg_t *msg, boot_data_t *bootdata) { if (bootdata->ownership_state == kOwnershipStateUnlockedEndorsed || bootdata->ownership_state == kOwnershipStateUnlockedAny || bootdata->ownership_state == kOwnershipStateUnlockedSelf) { + // Set the variable checking whether the correct signatures have been + // verified. + uint32_t flash_exec = 0; // Check the signature against the unlock key. if (ownership_key_validate(/*page=*/0, kOwnershipKeyUnlock, &msg->ownership_unlock_req.signature, - &msg->ownership_unlock_req.unlock_mode, - len) == kHardenedBoolFalse) { + &msg->ownership_unlock_req.unlock_mode, len, + &flash_exec) == kHardenedBoolFalse) { return kErrorOwnershipInvalidSignature; } + // Verify that we passed signature verification for the message. + HARDENED_CHECK_EQ(flash_exec, kSigverifyFlashExec); if (!nonce_equal(&msg->ownership_unlock_req.nonce, &bootdata->nonce)) { return kErrorOwnershipInvalidNonce; } diff --git a/sw/device/silicon_creator/lib/ownership/ownership_unlock_unittest.cc b/sw/device/silicon_creator/lib/ownership/ownership_unlock_unittest.cc index b6086ab1f4b9a..4571b4b4b3b61 100644 --- a/sw/device/silicon_creator/lib/ownership/ownership_unlock_unittest.cc +++ b/sw/device/silicon_creator/lib/ownership/ownership_unlock_unittest.cc @@ -19,10 +19,12 @@ #include "sw/device/silicon_creator/lib/ownership/datatypes.h" #include "sw/device/silicon_creator/lib/ownership/mock_ownership_key.h" #include "sw/device/silicon_creator/lib/ownership/owner_block.h" +#include "sw/device/silicon_creator/lib/sigverify/flash_exec.h" #include "sw/device/silicon_creator/testing/rom_test.h" namespace { using ::testing::_; +using ::testing::DoAll; using ::testing::Return; using ::testing::SetArgPointee; @@ -102,8 +104,9 @@ TEST_F(OwnershipUnlockTest, UnlockAny) { validate(0, static_cast(kOwnershipKeyUnlock | kOwnershipKeyRecovery), - _, _, _)) - .WillOnce(Return(kHardenedBoolTrue)); + _, _, _, _)) + .WillOnce(DoAll(SetArgPointee<5>(kSigverifyFlashExec), + Return(kHardenedBoolTrue))); EXPECT_CALL(lifecycle_, DeviceId(_)) .WillOnce(SetArgPointee<0>((lifecycle_device_id_t){0})); EXPECT_CALL(rnd_, Uint32()).WillRepeatedly(Return(5)); @@ -124,8 +127,8 @@ TEST_F(OwnershipUnlockTest, UnlockAnyBadSignature) { validate(0, static_cast(kOwnershipKeyUnlock | kOwnershipKeyRecovery), - _, _, _)) - .WillOnce(Return(kHardenedBoolFalse)); + _, _, _, _)) + .WillOnce(DoAll(SetArgPointee<5>(0), Return(kHardenedBoolFalse))); EXPECT_CALL(hdr_, Finalize(_, _, _)); rom_error_t error = ownership_unlock_handler(&message_, &bootdata_); @@ -141,8 +144,9 @@ TEST_F(OwnershipUnlockTest, UnlockAnyBadDin) { validate(0, static_cast(kOwnershipKeyUnlock | kOwnershipKeyRecovery), - _, _, _)) - .WillOnce(Return(kHardenedBoolTrue)); + _, _, _, _)) + .WillOnce(DoAll(SetArgPointee<5>(kSigverifyFlashExec), + Return(kHardenedBoolTrue))); EXPECT_CALL(lifecycle_, DeviceId(_)) .WillOnce(SetArgPointee<0>((lifecycle_device_id_t){0, 1, 1})); EXPECT_CALL(hdr_, Finalize(_, _, _)); @@ -161,8 +165,9 @@ TEST_F(OwnershipUnlockTest, UnlockAnyBadNonce) { validate(0, static_cast(kOwnershipKeyUnlock | kOwnershipKeyRecovery), - _, _, _)) - .WillOnce(Return(kHardenedBoolTrue)); + _, _, _, _)) + .WillOnce(DoAll(SetArgPointee<5>(kSigverifyFlashExec), + Return(kHardenedBoolTrue))); EXPECT_CALL(hdr_, Finalize(_, _, _)); rom_error_t error = ownership_unlock_handler(&message_, &bootdata_); @@ -192,8 +197,9 @@ TEST_F(OwnershipUnlockTest, UnlockEndorsed) { validate(0, static_cast(kOwnershipKeyUnlock | kOwnershipKeyRecovery), - _, _, _)) - .WillOnce(Return(kHardenedBoolTrue)); + _, _, _, _)) + .WillOnce(DoAll(SetArgPointee<5>(kSigverifyFlashExec), + Return(kHardenedBoolTrue))); EXPECT_CALL(lifecycle_, DeviceId(_)) .WillOnce(SetArgPointee<0>((lifecycle_device_id_t){0})); EXPECT_CALL(hmac_, sha256(_, _, _)) @@ -223,8 +229,8 @@ TEST_F(OwnershipUnlockTest, UnlockEndorsedBadSignature) { validate(0, static_cast(kOwnershipKeyUnlock | kOwnershipKeyRecovery), - _, _, _)) - .WillOnce(Return(kHardenedBoolFalse)); + _, _, _, _)) + .WillOnce(DoAll(SetArgPointee<5>(0), Return(kHardenedBoolFalse))); EXPECT_CALL(hdr_, Finalize(_, _, _)); rom_error_t error = ownership_unlock_handler(&message_, &bootdata_); @@ -241,8 +247,9 @@ TEST_F(OwnershipUnlockTest, UnlockEndorsedBadNonce) { validate(0, static_cast(kOwnershipKeyUnlock | kOwnershipKeyRecovery), - _, _, _)) - .WillOnce(Return(kHardenedBoolTrue)); + _, _, _, _)) + .WillOnce(DoAll(SetArgPointee<5>(kSigverifyFlashExec), + Return(kHardenedBoolTrue))); EXPECT_CALL(hdr_, Finalize(_, _, _)); rom_error_t error = ownership_unlock_handler(&message_, &bootdata_); @@ -268,10 +275,11 @@ INSTANTIATE_TEST_SUITE_P(AllCases, OwnershipUnlockEndorsedStateTest, // Test that requesting LockedOwner->UnlockedSelf works. TEST_F(OwnershipUnlockTest, UnlockUpdate) { message_.ownership_unlock_req.unlock_mode = kBootSvcUnlockUpdate; - EXPECT_CALL( - ownership_key_, - validate(0, static_cast(kOwnershipKeyUnlock), _, _, _)) - .WillOnce(Return(kHardenedBoolTrue)); + EXPECT_CALL(ownership_key_, + validate(0, static_cast(kOwnershipKeyUnlock), _, + _, _, _)) + .WillOnce(DoAll(SetArgPointee<5>(kSigverifyFlashExec), + Return(kHardenedBoolTrue))); EXPECT_CALL(lifecycle_, DeviceId(_)) .WillOnce(SetArgPointee<0>((lifecycle_device_id_t){0})); EXPECT_CALL(rnd_, Uint32()).WillRepeatedly(Return(5)); @@ -288,10 +296,10 @@ TEST_F(OwnershipUnlockTest, UnlockUpdate) { // bad. TEST_F(OwnershipUnlockTest, UnlockedUpdateBadSignature) { message_.ownership_unlock_req.unlock_mode = kBootSvcUnlockUpdate; - EXPECT_CALL( - ownership_key_, - validate(0, static_cast(kOwnershipKeyUnlock), _, _, _)) - .WillOnce(Return(kHardenedBoolFalse)); + EXPECT_CALL(ownership_key_, + validate(0, static_cast(kOwnershipKeyUnlock), _, + _, _, _)) + .WillOnce(DoAll(SetArgPointee<5>(0), Return(kHardenedBoolFalse))); EXPECT_CALL(hdr_, Finalize(_, _, _)); rom_error_t error = ownership_unlock_handler(&message_, &bootdata_); @@ -305,10 +313,11 @@ TEST_F(OwnershipUnlockTest, UnlockedUpdateBadNonce) { message_.ownership_unlock_req.unlock_mode = kBootSvcUnlockUpdate; message_.ownership_unlock_req.nonce = {3, 4}; - EXPECT_CALL( - ownership_key_, - validate(0, static_cast(kOwnershipKeyUnlock), _, _, _)) - .WillOnce(Return(kHardenedBoolTrue)); + EXPECT_CALL(ownership_key_, + validate(0, static_cast(kOwnershipKeyUnlock), _, + _, _, _)) + .WillOnce(DoAll(SetArgPointee<5>(kSigverifyFlashExec), + Return(kHardenedBoolTrue))); EXPECT_CALL(hdr_, Finalize(_, _, _)); rom_error_t error = ownership_unlock_handler(&message_, &bootdata_); @@ -335,10 +344,11 @@ INSTANTIATE_TEST_SUITE_P(AllCases, OwnershipUnlockedUpdateStateTest, TEST_P(OwnershipUnlockAbortValidStateTest, UnlockAbort) { message_.ownership_unlock_req.unlock_mode = kBootSvcUnlockAbort; bootdata_.ownership_state = static_cast(GetParam()); - EXPECT_CALL( - ownership_key_, - validate(0, static_cast(kOwnershipKeyUnlock), _, _, _)) - .WillOnce(Return(kHardenedBoolTrue)); + EXPECT_CALL(ownership_key_, + validate(0, static_cast(kOwnershipKeyUnlock), _, + _, _, _)) + .WillOnce(DoAll(SetArgPointee<5>(kSigverifyFlashExec), + Return(kHardenedBoolTrue))); EXPECT_CALL(lifecycle_, DeviceId(_)) .WillOnce(SetArgPointee<0>((lifecycle_device_id_t){0})); EXPECT_CALL(rnd_, Uint32()).WillRepeatedly(Return(5)); @@ -383,8 +393,9 @@ TEST_P(OwnershipUnlockUpdateModesTest, UnlockAny) { validate(0, static_cast(kOwnershipKeyUnlock | kOwnershipKeyRecovery), - _, _, _)) - .WillOnce(Return(kHardenedBoolTrue)); + _, _, _, _)) + .WillOnce(DoAll(SetArgPointee<5>(kSigverifyFlashExec), + Return(kHardenedBoolTrue))); EXPECT_CALL(lifecycle_, DeviceId(_)) .WillOnce(SetArgPointee<0>((lifecycle_device_id_t){0})); EXPECT_CALL(rnd_, Uint32()).WillRepeatedly(Return(5)); @@ -417,8 +428,9 @@ TEST_P(OwnershipUnlockUpdateModesTest, UnlockUpdate) { case kOwnershipUpdateModeSelfVersion: EXPECT_CALL(ownership_key_, validate(0, static_cast(kOwnershipKeyUnlock), - _, _, _)) - .WillOnce(Return(kHardenedBoolTrue)); + _, _, _, _)) + .WillOnce(DoAll(SetArgPointee<5>(kSigverifyFlashExec), + Return(kHardenedBoolTrue))); EXPECT_CALL(lifecycle_, DeviceId(_)) .WillOnce(SetArgPointee<0>((lifecycle_device_id_t){0})); EXPECT_CALL(rnd_, Uint32()).WillRepeatedly(Return(5)); diff --git a/sw/device/silicon_creator/lib/sigverify/BUILD b/sw/device/silicon_creator/lib/sigverify/BUILD index 6bbf7214cb619..b45a11f39d848 100644 --- a/sw/device/silicon_creator/lib/sigverify/BUILD +++ b/sw/device/silicon_creator/lib/sigverify/BUILD @@ -246,10 +246,6 @@ cc_library( cc_library( name = "flash_exec", hdrs = ["flash_exec.h"], - deps = [ - ":rsa_verify", - ":spx_verify", - ], ) cc_test( @@ -257,6 +253,8 @@ cc_test( srcs = ["flash_exec_unittest.cc"], deps = [ ":flash_exec", + ":rsa_verify", + ":spx_verify", "//hw/top:flash_ctrl_c_regs", "//sw/device/silicon_creator/testing:rom_test", "@googletest//:gtest_main", @@ -268,6 +266,7 @@ cc_library( hdrs = ["sigverify.h"], deps = [ ":ecdsa_p256_verify", + ":flash_exec", ":rsa_verify", ":spx_verify", ":usage_constraints", diff --git a/sw/device/silicon_creator/rom_ext/rom_ext.c b/sw/device/silicon_creator/rom_ext/rom_ext.c index 1e44ae84b8031..4b5c464acb0c1 100644 --- a/sw/device/silicon_creator/rom_ext/rom_ext.c +++ b/sw/device/silicon_creator/rom_ext/rom_ext.c @@ -42,6 +42,7 @@ #include "sw/device/silicon_creator/lib/ownership/ownership_unlock.h" #include "sw/device/silicon_creator/lib/shutdown.h" #include "sw/device/silicon_creator/lib/sigverify/ecdsa_p256_key.h" +#include "sw/device/silicon_creator/lib/sigverify/flash_exec.h" #include "sw/device/silicon_creator/lib/sigverify/rsa_verify.h" #include "sw/device/silicon_creator/lib/sigverify/sigverify.h" #include "sw/device/silicon_creator/lib/sigverify/sphincsplus/verify.h" @@ -208,7 +209,7 @@ static rom_error_t rom_ext_spx_verify( const sigverify_spx_signature_t *signature, const sigverify_spx_key_t *key, uint32_t key_alg, const void *msg_prefix_1, size_t msg_prefix_1_len, const void *msg_prefix_2, size_t msg_prefix_2_len, const void *msg, - size_t msg_len, hmac_digest_t digest) { + size_t msg_len, hmac_digest_t digest, uint32_t *flash_exec) { /* * Shares for producing kErrorOk if SPHINCS+ verification succeeds. The first * three shares are generated using the `sparse-fsm-encode` script while the @@ -266,6 +267,7 @@ static rom_error_t rom_ext_spx_verify( } uint32_t result = 0; uint32_t diff = 0; + *flash_exec = kErrorOk ^ kSigverifySpxSuccess; for (--i; launder32(i) < kSigverifySpxRootNumWords; --i) { uint32_t val = expected_root.data[i] ^ actual_root.data[i]; diff |= val ^ shares[i]; @@ -273,6 +275,9 @@ static rom_error_t rom_ext_spx_verify( diff |= ~(diff >> 31) + 1; // Set all 1s if MSB is set, no change o/w. result ^= val; result |= diff; + + *flash_exec ^= val; + *flash_exec |= diff; } HARDENED_CHECK_EQ(i, SIZE_MAX); if (result != kErrorOk) { @@ -283,7 +288,8 @@ static rom_error_t rom_ext_spx_verify( OT_WARN_UNUSED_RESULT static rom_error_t rom_ext_verify(const manifest_t *manifest, - const boot_data_t *boot_data) { + const boot_data_t *boot_data, + uint32_t *flash_exec) { RETURN_IF_ERROR(rom_ext_boot_policy_manifest_check(manifest, boot_data)); uint32_t key_id = @@ -336,7 +342,6 @@ static rom_error_t rom_ext_verify(const manifest_t *manifest, "Unexpected BL0 digest size."); memcpy(&boot_measurements.bl0, &act_digest, sizeof(boot_measurements.bl0)); - uint32_t flash_exec = 0; if (key_alg == kOwnershipKeyAlgEcdsaP256) { return sigverify_ecdsa_p256_verify(&manifest->ecdsa_signature, &keyring.key[verify_key]->data.ecdsa, @@ -348,12 +353,12 @@ static rom_error_t rom_ext_verify(const manifest_t *manifest, // OTBN and compute the SPX+ verify in parallel on Ibex. HARDENED_RETURN_IF_ERROR(sigverify_ecdsa_p256_verify( &manifest->ecdsa_signature, &keyring.key[verify_key]->data.hybrid.ecdsa, - &act_digest, &flash_exec)); + &act_digest, flash_exec)); return rom_ext_spx_verify( &ext_spx_signature->signature, &keyring.key[verify_key]->data.hybrid.spx, key_alg, &usage_constraints_from_hw, sizeof(usage_constraints_from_hw), NULL, 0, - digest_region.start, digest_region.length, act_digest); + digest_region.start, digest_region.length, act_digest, flash_exec); } else { // TODO: consider whether an SPX+-only verify is sufficent. return kErrorOwnershipInvalidAlgorithm; @@ -383,7 +388,8 @@ static uintptr_t owner_vma_get(const manifest_t *manifest, uintptr_t lma_addr) { OT_WARN_UNUSED_RESULT static rom_error_t rom_ext_boot(boot_data_t *boot_data, boot_log_t *boot_log, - const manifest_t *manifest) { + const manifest_t *manifest, + uint32_t *flash_exec) { // Determine which owner block the key came from and measure that block. hmac_digest_t owner_measurement; const owner_application_key_t *key = keyring.key[verify_key]; @@ -501,6 +507,8 @@ static rom_error_t rom_ext_boot(boot_data_t *boot_data, boot_log_t *boot_log, // to know if it's allowed to used the CSRNG and OTP is locked down. sec_mmio_check_values_except_otp(/*rnd_uint32()*/ 0, TOP_EARLGREY_OTP_CTRL_CORE_BASE_ADDR); + + HARDENED_CHECK_EQ(*flash_exec, kSigverifyFlashExec); // Jump to OWNER entry point. dbg_printf("entry: 0x%x\r\n", (unsigned int)entry_point); ((owner_stage_entry_point *)entry_point)(); @@ -581,12 +589,12 @@ static rom_error_t boot_svc_min_sec_ver_handler(boot_svc_msg_t *boot_svc_msg, // value of the new minimum_security_version. This prevents a malicious // MinBl0SecVer request from making the chip un-bootable. const manifest_t *manifest = rom_ext_boot_policy_manifest_a_get(); - rom_error_t error = rom_ext_verify(manifest, boot_data); + rom_error_t error = rom_ext_verify(manifest, boot_data, NULL); if (error == kErrorOk && manifest->security_version > max_sec_ver) { max_sec_ver = manifest->security_version; } manifest = rom_ext_boot_policy_manifest_b_get(); - error = rom_ext_verify(manifest, boot_data); + error = rom_ext_verify(manifest, boot_data, NULL); if (error == kErrorOk && manifest->security_version > max_sec_ver) { max_sec_ver = manifest->security_version; } @@ -664,11 +672,13 @@ static rom_error_t rom_ext_try_next_stage(boot_data_t *boot_data, rom_error_t error = kErrorRomExtBootFailed; rom_error_t slot[2] = {0, 0}; for (size_t i = 0; i < ARRAYSIZE(manifests.ordered); ++i) { - error = rom_ext_verify(manifests.ordered[i], boot_data); + uint32_t flash_exec = 0; + error = rom_ext_verify(manifests.ordered[i], boot_data, &flash_exec); slot[i] = error; if (error != kErrorOk) { continue; } + HARDENED_CHECK_EQ(flash_exec, kSigverifyFlashExec); if (manifests.ordered[i] == rom_ext_boot_policy_manifest_a_get()) { boot_log->bl0_slot = kBootSlotA; @@ -680,7 +690,8 @@ 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(boot_data, boot_log, manifests.ordered[i])); + RETURN_IF_ERROR( + rom_ext_boot(boot_data, boot_log, manifests.ordered[i], &flash_exec)); // `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;