Skip to content

[ownership] Handle primary_bl0_slot in ownership activate #27681

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: earlgrey_1.0.0
Choose a base branch
from
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
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ typedef struct boot_svc_ownership_activate_req {
uint32_t din[2];
/**
* Erase previous owner's flash (hardened_bool_t).
* Currently, this is not implemented.
*/
uint32_t erase_previous;
/**
Expand Down
12 changes: 6 additions & 6 deletions sw/device/silicon_creator/lib/ownership/ownership_activate.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,12 @@ static rom_error_t activate_handler(boot_svc_msg_t *msg,
HARDENED_RETURN_IF_ERROR(
ownership_activate(bootdata, /*write_both_pages=*/kHardenedBoolTrue));

// The requested primary_bl0_slot is user input. Validate and clamp it to
// legal values.
if (msg->ownership_activate_req.primary_bl0_slot == kBootSlotB) {
bootdata->primary_bl0_slot = kBootSlotB;
} else {
bootdata->primary_bl0_slot = kBootSlotA;
// The requested primary_bl0_slot is user input.
// Legal values change the primary boot slot. All other values result in no
// change.
if (msg->ownership_activate_req.primary_bl0_slot == kBootSlotA ||
msg->ownership_activate_req.primary_bl0_slot == kBootSlotB) {
bootdata->primary_bl0_slot = msg->ownership_activate_req.primary_bl0_slot;
}

if (bootdata->ownership_state == kOwnershipStateUnlockedSelf) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ class OwnershipActivateValidStateTest
: public OwnershipActivateTest,
public testing::WithParamInterface<ownership_state_t> {};

class OwnershipActivateNextBl0Slot
: public OwnershipActivateTest,
public testing::WithParamInterface<boot_slot_t> {};

// Tests that requesting Activate in all Locked non-Update states fails.
TEST_P(OwnershipActivateInvalidStateTest, InvalidState) {
bootdata_.ownership_state = static_cast<uint32_t>(GetParam());
Expand Down Expand Up @@ -298,7 +302,7 @@ TEST_P(OwnershipActivateValidStateTest, OwnerPageValid) {
//
// TODO(cfrantz): Refactor this test as it is nearly a complete copy of the
// previous test except for the manipulation of the min_sec_ver.
TEST_P(OwnershipActivateValidStateTest, UpdateBootdataBl0) {
TEST_P(OwnershipActivateValidStateTest, UpdateBootdataBl0MinSecVer) {
ownership_state_t state = GetParam();
bootdata_.ownership_state = static_cast<uint32_t>(state);

Expand Down Expand Up @@ -367,4 +371,80 @@ INSTANTIATE_TEST_SUITE_P(AllCases, OwnershipActivateValidStateTest,
kOwnershipStateUnlockedAny,
kOwnershipStateUnlockedEndorsed));

// TODO(cfrantz): Refactor this test as it is nearly a complete copy of the
// previous test except for the manipulation of the primary_bl0_slot.
TEST_P(OwnershipActivateNextBl0Slot, UpdateBootdataPrimaryBl0Slot) {
bootdata_.ownership_state = kOwnershipStateUnlockedAny;
boot_slot_t next_slot = GetParam();
message_.ownership_activate_req.primary_bl0_slot = next_slot;

// We initialize the primary slot with an invalid value so we can
// check later if the value is changed or unchanged according the
// requested next_slot value.
bootdata_.primary_bl0_slot = static_cast<boot_slot_t>(0);

owner_page[0].owner_key = {{1}};
memset(bootdata_.next_owner, 0, sizeof(bootdata_.next_owner));
MakePage1Valid(true);

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

// Once the new owner page is determined to be valid, the page will be sealed.
EXPECT_CALL(ownership_key_, seal_page(1));

// The sealed page will be written into flash owner slot 1 first.
EXPECT_CALL(flash_ctrl_,
InfoErase(&kFlashCtrlInfoPageOwnerSlot1, kFlashCtrlEraseTypePage))
.WillOnce(Return(kErrorOk));
EXPECT_CALL(flash_ctrl_, InfoWrite(&kFlashCtrlInfoPageOwnerSlot1, 0,
sizeof(owner_page[1]) / sizeof(uint32_t),
&owner_page[1]))
.WillOnce(Return(kErrorOk));
// The sealed page will be written into flash owner slot 0 second.
EXPECT_CALL(flash_ctrl_,
InfoErase(&kFlashCtrlInfoPageOwnerSlot0, kFlashCtrlEraseTypePage))
.WillOnce(Return(kErrorOk));
EXPECT_CALL(flash_ctrl_, InfoWrite(&kFlashCtrlInfoPageOwnerSlot0, 0,
sizeof(owner_page[1]) / sizeof(uint32_t),
&owner_page[1]))
.WillOnce(Return(kErrorOk));

// The transfer will regenerate the owner secret.
EXPECT_CALL(ownership_key_, secret_new(_, _)).WillOnce(Return(kErrorOk));

// The nonce will be regenerated.
EXPECT_CALL(rnd_, Uint32()).WillRepeatedly(Return(99));
// The boot_svc response will be finalized.
EXPECT_CALL(hdr_, Finalize(_, _, _));

rom_error_t error = ownership_activate_handler(&message_, &bootdata_);
EXPECT_EQ(error, kErrorWriteBootdataThenReboot);
// After succeeding, the page should be sealed, the nonce changed and the
// ownership state set to LockedOwner.
EXPECT_FALSE(nonce_equal(&bootdata_.nonce, &kDefaultNonce));
EXPECT_EQ(bootdata_.ownership_state, kOwnershipStateLockedOwner);

switch (next_slot) {
case kBootSlotA:
case kBootSlotB:
// Bootdata primary_bl0_slot should be updated.
EXPECT_EQ(bootdata_.primary_bl0_slot, next_slot);
break;
default:
// Bootdata primary_bl0_slot should be unchanged from the original value.
EXPECT_EQ(bootdata_.primary_bl0_slot, static_cast<boot_slot_t>(0));
}
}

INSTANTIATE_TEST_SUITE_P(AllCases, OwnershipActivateNextBl0Slot,
testing::Values(kBootSlotA, kBootSlotB,
// Both `Unspecified` and all garbage
// values should result in no change.
kBootSlotUnspecified,
static_cast<boot_slot_t>(12345)));

} // namespace
Loading