Skip to content

Commit b2822c7

Browse files
committed
[ownership] Handle primary_bl0_slot in ownership activate
Correctly handle the `rimary_bl0_slot` field in the ownership activate command: use the value if it is one of the legal values and ignore otherwise. Signed-off-by: Chris Frantz <cfrantz@google.com>
1 parent 573efe9 commit b2822c7

File tree

3 files changed

+88
-7
lines changed

3 files changed

+88
-7
lines changed

sw/device/silicon_creator/lib/boot_svc/boot_svc_ownership_activate.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ typedef struct boot_svc_ownership_activate_req {
4343
uint32_t din[2];
4444
/**
4545
* Erase previous owner's flash (hardened_bool_t).
46+
* Currently, this is not implemented.
4647
*/
4748
uint32_t erase_previous;
4849
/**

sw/device/silicon_creator/lib/ownership/ownership_activate.c

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,12 @@ static rom_error_t activate_handler(boot_svc_msg_t *msg,
8787
HARDENED_RETURN_IF_ERROR(
8888
ownership_activate(bootdata, /*write_both_pages=*/kHardenedBoolTrue));
8989

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

9898
if (bootdata->ownership_state == kOwnershipStateUnlockedSelf) {

sw/device/silicon_creator/lib/ownership/ownership_activate_unittest.cc

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ class OwnershipActivateValidStateTest
118118
: public OwnershipActivateTest,
119119
public testing::WithParamInterface<ownership_state_t> {};
120120

121+
class OwnershipActivateNextBl0Slot
122+
: public OwnershipActivateTest,
123+
public testing::WithParamInterface<boot_slot_t> {};
124+
121125
// Tests that requesting Activate in all Locked non-Update states fails.
122126
TEST_P(OwnershipActivateInvalidStateTest, InvalidState) {
123127
bootdata_.ownership_state = static_cast<uint32_t>(GetParam());
@@ -298,7 +302,7 @@ TEST_P(OwnershipActivateValidStateTest, OwnerPageValid) {
298302
//
299303
// TODO(cfrantz): Refactor this test as it is nearly a complete copy of the
300304
// previous test except for the manipulation of the min_sec_ver.
301-
TEST_P(OwnershipActivateValidStateTest, UpdateBootdataBl0) {
305+
TEST_P(OwnershipActivateValidStateTest, UpdateBootdataBl0MinSecVer) {
302306
ownership_state_t state = GetParam();
303307
bootdata_.ownership_state = static_cast<uint32_t>(state);
304308

@@ -367,4 +371,80 @@ INSTANTIATE_TEST_SUITE_P(AllCases, OwnershipActivateValidStateTest,
367371
kOwnershipStateUnlockedAny,
368372
kOwnershipStateUnlockedEndorsed));
369373

374+
// TODO(cfrantz): Refactor this test as it is nearly a complete copy of the
375+
// previous test except for the manipulation of the primary_bl0_slot.
376+
TEST_P(OwnershipActivateNextBl0Slot, UpdateBootdataPrimaryBl0Slot) {
377+
bootdata_.ownership_state = kOwnershipStateUnlockedAny;
378+
boot_slot_t next_slot = GetParam();
379+
message_.ownership_activate_req.primary_bl0_slot = next_slot;
380+
381+
// We initialize the primary slot with an invalid value so we can
382+
// check later if the value is changed or unchanged according the
383+
// requested next_slot value.
384+
bootdata_.primary_bl0_slot = static_cast<boot_slot_t>(0);
385+
386+
owner_page[0].owner_key = {{1}};
387+
memset(bootdata_.next_owner, 0, sizeof(bootdata_.next_owner));
388+
MakePage1Valid(true);
389+
390+
EXPECT_CALL(ownership_key_,
391+
validate(1, kOwnershipKeyActivate, kActivate, _, _, _, _))
392+
.WillOnce(Return(kErrorOk));
393+
EXPECT_CALL(lifecycle_, DeviceId(_))
394+
.WillOnce(SetArgPointee<0>((lifecycle_device_id_t){0}));
395+
396+
// Once the new owner page is determined to be valid, the page will be sealed.
397+
EXPECT_CALL(ownership_key_, seal_page(1));
398+
399+
// The sealed page will be written into flash owner slot 1 first.
400+
EXPECT_CALL(flash_ctrl_,
401+
InfoErase(&kFlashCtrlInfoPageOwnerSlot1, kFlashCtrlEraseTypePage))
402+
.WillOnce(Return(kErrorOk));
403+
EXPECT_CALL(flash_ctrl_, InfoWrite(&kFlashCtrlInfoPageOwnerSlot1, 0,
404+
sizeof(owner_page[1]) / sizeof(uint32_t),
405+
&owner_page[1]))
406+
.WillOnce(Return(kErrorOk));
407+
// The sealed page will be written into flash owner slot 0 second.
408+
EXPECT_CALL(flash_ctrl_,
409+
InfoErase(&kFlashCtrlInfoPageOwnerSlot0, kFlashCtrlEraseTypePage))
410+
.WillOnce(Return(kErrorOk));
411+
EXPECT_CALL(flash_ctrl_, InfoWrite(&kFlashCtrlInfoPageOwnerSlot0, 0,
412+
sizeof(owner_page[1]) / sizeof(uint32_t),
413+
&owner_page[1]))
414+
.WillOnce(Return(kErrorOk));
415+
416+
// The transfer will regenerate the owner secret.
417+
EXPECT_CALL(ownership_key_, secret_new(_, _)).WillOnce(Return(kErrorOk));
418+
419+
// The nonce will be regenerated.
420+
EXPECT_CALL(rnd_, Uint32()).WillRepeatedly(Return(99));
421+
// The boot_svc response will be finalized.
422+
EXPECT_CALL(hdr_, Finalize(_, _, _));
423+
424+
rom_error_t error = ownership_activate_handler(&message_, &bootdata_);
425+
EXPECT_EQ(error, kErrorWriteBootdataThenReboot);
426+
// After succeeding, the page should be sealed, the nonce changed and the
427+
// ownership state set to LockedOwner.
428+
EXPECT_FALSE(nonce_equal(&bootdata_.nonce, &kDefaultNonce));
429+
EXPECT_EQ(bootdata_.ownership_state, kOwnershipStateLockedOwner);
430+
431+
switch (next_slot) {
432+
case kBootSlotA:
433+
case kBootSlotB:
434+
// Bootdata primary_bl0_slot should be updated.
435+
EXPECT_EQ(bootdata_.primary_bl0_slot, next_slot);
436+
break;
437+
default:
438+
// Bootdata primary_bl0_slot should be unchanged from the original value.
439+
EXPECT_EQ(bootdata_.primary_bl0_slot, static_cast<boot_slot_t>(0));
440+
}
441+
}
442+
443+
INSTANTIATE_TEST_SUITE_P(AllCases, OwnershipActivateNextBl0Slot,
444+
testing::Values(kBootSlotA, kBootSlotB,
445+
// Both `Unspecified` and all garbage
446+
// values should result in no change.
447+
kBootSlotUnspecified,
448+
static_cast<boot_slot_t>(12345)));
449+
370450
} // namespace

0 commit comments

Comments
 (0)