Skip to content

Commit

Permalink
[ownership] Require the device ID for ownership unlock/activate
Browse files Browse the repository at this point in the history
1. Include the Device Identification Number (DIN) subfield of the full
   256-bit device ID into the ownership unlock and activate commands.
2. Update the Rust versions of the unlock/activate requests to include
   the DIN.
3. Update unittests.
4. Update the rescue mode-change function to wait for the requested
   `mode` event to confirm entry into the requested mode.
5. Update ownership transfer tests.

Signed-off-by: Chris Frantz <cfrantz@google.com>
(cherry picked from commit 0a8689f)
(cherry picked from commit 6a2fce8)
  • Loading branch information
cfrantz authored and github-actions[bot] committed Jan 23, 2025
1 parent 633038a commit fbf18ce
Show file tree
Hide file tree
Showing 23 changed files with 218 additions and 71 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,18 @@ typedef struct boot_svc_ownership_activate_req {
* Which side of the flash is primary after activation.
*/
uint32_t primary_bl0_slot;
/**
* The 64-bit DIN subfield of the full 256-bit device ID.
*/
uint32_t din[2];
/**
* Erase previous owner's flash (hardened_bool_t).
*/
uint32_t erase_previous;
/**
* Reserved for future use.
*/
uint32_t reserved[33];
uint32_t reserved[31];
/**
* The current ownership nonce.
*/
Expand All @@ -59,10 +63,12 @@ typedef struct boot_svc_ownership_activate_req {
OT_ASSERT_MEMBER_OFFSET(boot_svc_ownership_activate_req_t, header, 0);
OT_ASSERT_MEMBER_OFFSET(boot_svc_ownership_activate_req_t, primary_bl0_slot,
CHIP_BOOT_SVC_MSG_HEADER_SIZE);
OT_ASSERT_MEMBER_OFFSET(boot_svc_ownership_activate_req_t, erase_previous,
OT_ASSERT_MEMBER_OFFSET(boot_svc_ownership_activate_req_t, din,
CHIP_BOOT_SVC_MSG_HEADER_SIZE + 4);
OT_ASSERT_MEMBER_OFFSET(boot_svc_ownership_activate_req_t, erase_previous,
CHIP_BOOT_SVC_MSG_HEADER_SIZE + 12);
OT_ASSERT_MEMBER_OFFSET(boot_svc_ownership_activate_req_t, reserved,
CHIP_BOOT_SVC_MSG_HEADER_SIZE + 8);
CHIP_BOOT_SVC_MSG_HEADER_SIZE + 16);
OT_ASSERT_MEMBER_OFFSET(boot_svc_ownership_activate_req_t, nonce,
CHIP_BOOT_SVC_MSG_HEADER_SIZE + 140);
OT_ASSERT_MEMBER_OFFSET(boot_svc_ownership_activate_req_t, signature,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,14 @@ typedef struct boot_svc_ownership_unlock_req {
* Unlock mode: Any, Endorsed, Update or Abort.
*/
uint32_t unlock_mode;
/**
* The 64-bit ID subfield of the full 256-bit device ID.
*/
uint32_t din[2];
/**
* Reserved for future use.
*/
uint32_t reserved[10];
uint32_t reserved[8];
/**
* The current ownership nonce.
*/
Expand All @@ -68,8 +72,10 @@ typedef struct boot_svc_ownership_unlock_req {
OT_ASSERT_MEMBER_OFFSET(boot_svc_ownership_unlock_req_t, header, 0);
OT_ASSERT_MEMBER_OFFSET(boot_svc_ownership_unlock_req_t, unlock_mode,
CHIP_BOOT_SVC_MSG_HEADER_SIZE);
OT_ASSERT_MEMBER_OFFSET(boot_svc_ownership_unlock_req_t, reserved,
OT_ASSERT_MEMBER_OFFSET(boot_svc_ownership_unlock_req_t, din,
CHIP_BOOT_SVC_MSG_HEADER_SIZE + 4);
OT_ASSERT_MEMBER_OFFSET(boot_svc_ownership_unlock_req_t, reserved,
CHIP_BOOT_SVC_MSG_HEADER_SIZE + 12);
OT_ASSERT_MEMBER_OFFSET(boot_svc_ownership_unlock_req_t, nonce,
CHIP_BOOT_SVC_MSG_HEADER_SIZE + 44);
OT_ASSERT_MEMBER_OFFSET(boot_svc_ownership_unlock_req_t, next_owner_key,
Expand Down
6 changes: 6 additions & 0 deletions sw/device/silicon_creator/lib/drivers/lifecycle.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,9 @@ void lifecycle_hw_rev_get(lifecycle_hw_rev_t *hw_rev) {
reg1, LC_CTRL_HW_REVISION1_REVISION_ID_FIELD),
};
}

hardened_bool_t lifecycle_din_eq(lifecycle_device_id_t *id, uint32_t *din) {
if (id->device_id[1] == din[0] && id->device_id[2] == din[1])
return kHardenedBoolTrue;
return kHardenedBoolFalse;
}
9 changes: 9 additions & 0 deletions sw/device/silicon_creator/lib/drivers/lifecycle.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <stdint.h>

#include "sw/device/lib/base/hardened.h"
#include "sw/device/lib/base/macros.h"

#ifdef __cplusplus
Expand Down Expand Up @@ -117,6 +118,14 @@ void lifecycle_device_id_get(lifecycle_device_id_t *device_id);
*/
void lifecycle_hw_rev_get(lifecycle_hw_rev_t *hw_rev);

/**
* Determine if the device identification number subfield of the Device Id is
* equal to the supplied DIN.
*
* @returns kHardenedBoolTrue if equal, kHardenedBoolFalse if not equal.
*/
hardened_bool_t lifecycle_din_eq(lifecycle_device_id_t *id, uint32_t *din);

#ifdef __cplusplus
}
#endif
Expand Down
6 changes: 6 additions & 0 deletions sw/device/silicon_creator/lib/drivers/mock_lifecycle.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,11 @@ void lifecycle_device_id_get(lifecycle_device_id_t *device_id) {
void lifecycle_hw_rev_get(lifecycle_hw_rev_t *hw_rev) {
MockLifecycle::Instance().HwRev(hw_rev);
}

hardened_bool_t lifecycle_din_eq(lifecycle_device_id_t *id, uint32_t *din) {
if (id->device_id[1] == din[0] && id->device_id[2] == din[1])
return kHardenedBoolTrue;
return kHardenedBoolFalse;
}
} // extern "C"
} // namespace rom_test
1 change: 1 addition & 0 deletions sw/device/silicon_creator/lib/error.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ enum module_ {
X(kErrorOwnershipNoOwner, ERROR_(11, kModuleOwnership, kInternal)), \
X(kErrorOwnershipKeyNotFound, ERROR_(12, kModuleOwnership, kNotFound)), \
X(kErrorOwnershipInvalidVersion, ERROR_(13, kModuleOwnership, kInvalidArgument)), \
X(kErrorOwnershipInvalidDin, ERROR_(14, kModuleOwnership, kInvalidArgument)), \
\
X(kErrorPersoTlvInternal, ERROR_(0, kModulePersoTlv, kInternal)), \
X(kErrorPersoTlvCertObjNotFound, ERROR_(1, kModulePersoTlv, kNotFound)), \
Expand Down
3 changes: 3 additions & 0 deletions sw/device/silicon_creator/lib/ownership/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,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:hmac",
"//sw/device/silicon_creator/lib/drivers:lifecycle",
],
)

Expand All @@ -168,6 +169,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/drivers:lifecycle",
"//sw/device/silicon_creator/testing:rom_test",
"@googletest//:gtest_main",
],
Expand All @@ -186,6 +188,7 @@ cc_library(
"//sw/device/silicon_creator/lib:error",
"//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",
],
)

Expand Down
9 changes: 9 additions & 0 deletions sw/device/silicon_creator/lib/ownership/ownership_activate.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "sw/device/silicon_creator/lib/boot_data.h"
#include "sw/device/silicon_creator/lib/boot_svc/boot_svc_msg.h"
#include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h"
#include "sw/device/silicon_creator/lib/drivers/lifecycle.h"
#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"
Expand Down Expand Up @@ -41,6 +42,14 @@ static rom_error_t activate(boot_svc_msg_t *msg, boot_data_t *bootdata) {
return kErrorOwnershipInvalidNonce;
}

// Verify the device identification number is correct.
lifecycle_device_id_t device_id;
lifecycle_device_id_get(&device_id);
if (lifecycle_din_eq(&device_id, msg->ownership_activate_req.din) !=
kHardenedBoolTrue) {
return kErrorOwnershipInvalidDin;
}

// Seal page one to this chip.
ownership_seal_page(/*page=*/1);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "sw/device/silicon_creator/lib/boot_svc/mock_boot_svc_header.h"
#include "sw/device/silicon_creator/lib/drivers/mock_flash_ctrl.h"
#include "sw/device/silicon_creator/lib/drivers/mock_hmac.h"
#include "sw/device/silicon_creator/lib/drivers/mock_lifecycle.h"
#include "sw/device/silicon_creator/lib/drivers/mock_rnd.h"
#include "sw/device/silicon_creator/lib/error.h"
#include "sw/device/silicon_creator/lib/nonce.h"
Expand Down Expand Up @@ -97,6 +98,7 @@ class OwnershipActivateTest : public rom_test::RomTest {
rom_test::MockRnd rnd_;
rom_test::MockFlashCtrl flash_ctrl_;
rom_test::MockBootSvcHeader hdr_;
rom_test::MockLifecycle lifecycle_;
rom_test::MockOwnershipKey ownership_key_;
};

Expand Down Expand Up @@ -162,6 +164,22 @@ TEST_P(OwnershipActivateValidStateTest, InvalidNonce) {
EXPECT_EQ(error, kErrorOwnershipInvalidNonce);
}

// Tests that an owner block with an invalid DIN fails.
TEST_P(OwnershipActivateValidStateTest, InvalidDin) {
bootdata_.ownership_state = static_cast<uint32_t>(GetParam());
// 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(lifecycle_, DeviceId(_))
.WillOnce(SetArgPointee<0>((lifecycle_device_id_t){0, 1, 1}));
EXPECT_CALL(hdr_, Finalize(_, _, _));

rom_error_t error = ownership_activate_handler(&message_, &bootdata_);
EXPECT_EQ(error, kErrorOwnershipInvalidDin);
}

// Tests that an owner block with an invalid owner page with respect to the
// current update state fails.
TEST_P(OwnershipActivateValidStateTest, OwnerPageInvalid) {
Expand Down Expand Up @@ -206,6 +224,8 @@ TEST_P(OwnershipActivateValidStateTest, OwnerPageValid) {

EXPECT_CALL(ownership_key_, validate(1, kOwnershipKeyActivate, _, _, _))
.WillOnce(Return(kHardenedBoolTrue));
EXPECT_CALL(lifecycle_, DeviceId(_))
.WillOnce(SetArgPointee<0>((lifecycle_device_id_t){0}));

switch (state) {
case kOwnershipStateUnlockedSelf:
Expand Down Expand Up @@ -269,6 +289,8 @@ TEST_P(OwnershipActivateValidStateTest, UpdateBootdataBl0) {

EXPECT_CALL(ownership_key_, validate(1, kOwnershipKeyActivate, _, _, _))
.WillOnce(Return(kHardenedBoolTrue));
EXPECT_CALL(lifecycle_, DeviceId(_))
.WillOnce(SetArgPointee<0>((lifecycle_device_id_t){0}));

switch (state) {
case kOwnershipStateUnlockedSelf:
Expand Down
18 changes: 18 additions & 0 deletions sw/device/silicon_creator/lib/ownership/ownership_unlock.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "sw/device/silicon_creator/lib/boot_data.h"
#include "sw/device/silicon_creator/lib/boot_svc/boot_svc_msg.h"
#include "sw/device/silicon_creator/lib/drivers/hmac.h"
#include "sw/device/silicon_creator/lib/drivers/lifecycle.h"
#include "sw/device/silicon_creator/lib/error.h"
#include "sw/device/silicon_creator/lib/ownership/ownership_key.h"

Expand All @@ -27,6 +28,15 @@ static rom_error_t do_unlock(boot_svc_msg_t *msg, boot_data_t *bootdata) {
if (!nonce_equal(&msg->ownership_unlock_req.nonce, &bootdata->nonce)) {
return kErrorOwnershipInvalidNonce;
}

// Verify the device identification number is correct.
lifecycle_device_id_t device_id;
lifecycle_device_id_get(&device_id);
if (lifecycle_din_eq(&device_id, msg->ownership_unlock_req.din) !=
kHardenedBoolTrue) {
return kErrorOwnershipInvalidDin;
}

if (msg->ownership_unlock_req.unlock_mode == kBootSvcUnlockEndorsed) {
hmac_digest_t digest;
hmac_sha256(&msg->ownership_unlock_req.next_owner_key,
Expand Down Expand Up @@ -106,6 +116,14 @@ static rom_error_t unlock_abort(boot_svc_msg_t *msg, boot_data_t *bootdata) {
if (!nonce_equal(&msg->ownership_unlock_req.nonce, &bootdata->nonce)) {
return kErrorOwnershipInvalidNonce;
}

// Verify the device identification number is correct.
lifecycle_device_id_t device_id;
lifecycle_device_id_get(&device_id);
if (lifecycle_din_eq(&device_id, msg->ownership_unlock_req.din) !=
kHardenedBoolTrue) {
return kErrorOwnershipInvalidDin;
}
// Go back to locked owner.
bootdata->ownership_state = kOwnershipStateLockedOwner;
nonce_new(&bootdata->nonce);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "sw/device/silicon_creator/lib/boot_data.h"
#include "sw/device/silicon_creator/lib/boot_svc/mock_boot_svc_header.h"
#include "sw/device/silicon_creator/lib/drivers/mock_hmac.h"
#include "sw/device/silicon_creator/lib/drivers/mock_lifecycle.h"
#include "sw/device/silicon_creator/lib/drivers/mock_rnd.h"
#include "sw/device/silicon_creator/lib/error.h"
#include "sw/device/silicon_creator/lib/ownership/datatypes.h"
Expand All @@ -22,6 +23,7 @@
namespace {
using ::testing::_;
using ::testing::Return;
using ::testing::SetArgPointee;

/*
* The OwnershipUnlockTest fixture provides a pre-initialized bootdata and
Expand All @@ -42,13 +44,15 @@ class OwnershipUnlockTest : public rom_test::RomTest {
{
.type = kBootSvcOwnershipUnlockReqType,
},
.din = {0, 0},
.nonce = {1, 2},
},
};

rom_test::MockHmac hmac_;
rom_test::MockRnd rnd_;
rom_test::MockBootSvcHeader hdr_;
rom_test::MockLifecycle lifecycle_;
rom_test::MockOwnershipKey ownership_key_;
};

Expand Down Expand Up @@ -89,6 +93,8 @@ TEST_F(OwnershipUnlockTest, UnlockAny) {
kOwnershipKeyRecovery),
_, _, _))
.WillOnce(Return(kHardenedBoolTrue));
EXPECT_CALL(lifecycle_, DeviceId(_))
.WillOnce(SetArgPointee<0>((lifecycle_device_id_t){0}));
EXPECT_CALL(rnd_, Uint32()).WillRepeatedly(Return(5));
EXPECT_CALL(hdr_, Finalize(_, _, _));

Expand Down Expand Up @@ -116,6 +122,25 @@ TEST_F(OwnershipUnlockTest, UnlockAnyBadSignature) {
EXPECT_EQ(bootdata_.ownership_state, kOwnershipStateLockedOwner);
}

// Test that requesting LockedOwner->UnlockedAny fails when the DIN doesn't
// match.
TEST_F(OwnershipUnlockTest, UnlockAnyBadDin) {
message_.ownership_unlock_req.unlock_mode = kBootSvcUnlockAny;
EXPECT_CALL(ownership_key_,
validate(0,
static_cast<ownership_key_t>(kOwnershipKeyUnlock |
kOwnershipKeyRecovery),
_, _, _))
.WillOnce(Return(kHardenedBoolTrue));
EXPECT_CALL(lifecycle_, DeviceId(_))
.WillOnce(SetArgPointee<0>((lifecycle_device_id_t){0, 1, 1}));
EXPECT_CALL(hdr_, Finalize(_, _, _));

rom_error_t error = ownership_unlock_handler(&message_, &bootdata_);
EXPECT_EQ(error, kErrorOwnershipInvalidDin);
EXPECT_EQ(bootdata_.ownership_state, kOwnershipStateLockedOwner);
}

// Test that requesting LockedOwner->UnlockedAny fails when the nonce doesn't
// match.
TEST_F(OwnershipUnlockTest, UnlockAnyBadNonce) {
Expand Down Expand Up @@ -158,6 +183,8 @@ TEST_F(OwnershipUnlockTest, UnlockEndorsed) {
kOwnershipKeyRecovery),
_, _, _))
.WillOnce(Return(kHardenedBoolTrue));
EXPECT_CALL(lifecycle_, DeviceId(_))
.WillOnce(SetArgPointee<0>((lifecycle_device_id_t){0}));
EXPECT_CALL(hmac_, sha256(_, _, _))
.WillOnce([&](const void *, size_t, hmac_digest_t *digest) {
for (size_t i = 0; i < ARRAYSIZE(digest->digest); ++i) {
Expand Down Expand Up @@ -234,6 +261,8 @@ TEST_F(OwnershipUnlockTest, UnlockUpdate) {
ownership_key_,
validate(0, static_cast<ownership_key_t>(kOwnershipKeyUnlock), _, _, _))
.WillOnce(Return(kHardenedBoolTrue));
EXPECT_CALL(lifecycle_, DeviceId(_))
.WillOnce(SetArgPointee<0>((lifecycle_device_id_t){0}));
EXPECT_CALL(rnd_, Uint32()).WillRepeatedly(Return(5));
EXPECT_CALL(hdr_, Finalize(_, _, _));

Expand Down Expand Up @@ -299,6 +328,8 @@ TEST_P(OwnershipUnlockAbortValidStateTest, UnlockAbort) {
ownership_key_,
validate(0, static_cast<ownership_key_t>(kOwnershipKeyUnlock), _, _, _))
.WillOnce(Return(kHardenedBoolTrue));
EXPECT_CALL(lifecycle_, DeviceId(_))
.WillOnce(SetArgPointee<0>((lifecycle_device_id_t){0}));
EXPECT_CALL(rnd_, Uint32()).WillRepeatedly(Return(5));
EXPECT_CALL(hdr_, Finalize(_, _, _));

Expand Down
Loading

0 comments on commit fbf18ce

Please sign in to comment.