Software APIs
ownership.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 #include "sw/device/silicon_creator/lib/ownership/ownership.h"
5 
11 #include "sw/device/silicon_creator/lib/boot_data.h"
12 #include "sw/device/silicon_creator/lib/dbg_print.h"
13 #include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h"
14 #include "sw/device/silicon_creator/lib/drivers/hmac.h"
15 #include "sw/device/silicon_creator/lib/drivers/lifecycle.h"
16 #include "sw/device/silicon_creator/lib/error.h"
17 #include "sw/device/silicon_creator/lib/ownership/ecdsa.h"
18 #include "sw/device/silicon_creator/lib/ownership/owner_block.h"
19 #include "sw/device/silicon_creator/lib/ownership/ownership.h"
20 #include "sw/device/silicon_creator/lib/ownership/ownership_activate.h"
21 #include "sw/device/silicon_creator/lib/ownership/ownership_key.h"
22 
23 static owner_page_status_t owner_page_validity_check(size_t page) {
24  size_t sig_len =
25  (uintptr_t)&owner_page[0].signature - (uintptr_t)&owner_page[0];
26 
27  // Any non-constrained words of the owner block device_id field are required
28  // to be `kLockConstraintNone`. We wipe the field and then fill in the
29  // relevant words from the lifecycle constroller.
30  //
31  // For node-locked owner configurations, this makes the device_id from the
32  // lifecycle controller relevant to the cryptographic verification.
33  memset(owner_page[page].device_id, 0, sizeof(owner_page[page].device_id));
35  lifecycle_device_id_get(&id);
36  for (uint32_t i = 0; i < ARRAYSIZE(owner_page[0].device_id); ++i) {
37  if (owner_page[page].lock_constraint & (1u << i)) {
38  owner_page[page].device_id[i] = id.device_id[i];
39  } else {
40  owner_page[page].device_id[i] = kLockConstraintNone;
41  }
42  }
43 
44  rom_error_t sealed = ownership_seal_check(page);
45  if (sealed == kErrorOk) {
46  HARDENED_CHECK_EQ(sealed, kErrorOk);
47  return kOwnerPageStatusSealed;
48  }
49 
50  hardened_bool_t result = ownership_key_validate(page, kOwnershipKeyOwner,
51  &owner_page[page].signature,
52  &owner_page[page], sig_len);
53  if (result == kHardenedBoolFalse) {
54  // If the page is bad, destroy the RAM copy.
55  memset(&owner_page[page], 0x5a, sizeof(owner_page[0]));
56  return kOwnerPageStatusInvalid;
57  }
58  return kOwnerPageStatusSigned;
59 }
60 
61 OT_WEAK rom_error_t
62 sku_creator_owner_init(boot_data_t *bootdata, owner_config_t *config,
63  owner_application_keyring_t *keyring) {
64  return kErrorOk;
65 }
66 
67 static rom_error_t locked_owner_init(boot_data_t *bootdata,
68  owner_config_t *config,
69  owner_application_keyring_t *keyring) {
70  if (owner_page_valid[0] == kOwnerPageStatusSealed &&
71  owner_page_valid[1] == kOwnerPageStatusSigned &&
72  owner_block_newversion_mode() == kHardenedBoolTrue &&
73  owner_page[1].config_version > owner_page[0].config_version &&
74  hardened_memeq(owner_page[0].owner_key.raw, owner_page[1].owner_key.raw,
75  ARRAYSIZE(owner_page[0].owner_key.raw)) ==
77  rom_error_t error =
78  ownership_activate(bootdata, /*write_both_pages=*/kHardenedBoolFalse);
79  if (error == kErrorOk) {
80  HARDENED_CHECK_EQ(error, kErrorOk);
81  // Thunk the status of page 0 to Invalid so the next set of validity
82  // checks will copy the new page 1 content over to page 0 and establish a
83  // redundant backup of the new configuration.
84  owner_page_valid[0] = kOwnerPageStatusInvalid;
85  owner_page_valid[1] = kOwnerPageStatusSealed;
86  } else {
87  // If the new page wasn't good, we'll do nothing here and let the next set
88  // of validity checks copy page 0 over to page 1 and re-establish a
89  // redundant backup of the current configuration.
90  }
91  }
92 
93  if (owner_page_valid[0] == kOwnerPageStatusSealed &&
94  owner_page_valid[1] == kOwnerPageStatusSealed) {
95  // Both pages sealed, nothing to do.
96  } else if (owner_page_valid[0] != kOwnerPageStatusSealed &&
97  owner_page_valid[1] == kOwnerPageStatusSealed) {
98  // Page 0 bad, Page 1 good: copy page 1 to page 0.
99  memcpy(&owner_page[0], &owner_page[1], sizeof(owner_page[0]));
100  HARDENED_RETURN_IF_ERROR(flash_ctrl_info_erase(
101  &kFlashCtrlInfoPageOwnerSlot0, kFlashCtrlEraseTypePage));
102  HARDENED_RETURN_IF_ERROR(flash_ctrl_info_write(
103  &kFlashCtrlInfoPageOwnerSlot0, 0,
104  sizeof(owner_page[0]) / sizeof(uint32_t), &owner_page[0]));
105  owner_page_valid[0] = owner_page_valid[1];
106 
107  } else if (owner_page_valid[1] != kOwnerPageStatusSealed &&
108  owner_page_valid[0] == kOwnerPageStatusSealed) {
109  // Page 1 bad, Page 0 good: copy page 0 to page 1.
110  memcpy(&owner_page[1], &owner_page[0], sizeof(owner_page[0]));
111  HARDENED_RETURN_IF_ERROR(flash_ctrl_info_erase(
112  &kFlashCtrlInfoPageOwnerSlot1, kFlashCtrlEraseTypePage));
113  HARDENED_RETURN_IF_ERROR(flash_ctrl_info_write(
114  &kFlashCtrlInfoPageOwnerSlot1, 0,
115  sizeof(owner_page[1]) / sizeof(uint32_t), &owner_page[1]));
116  owner_page_valid[1] = owner_page_valid[0];
117  } else {
118  // Neither page is valid; go to the Recovery state.
119  dbg_printf("error: both owner pages invalid.\r\n");
120  bootdata->ownership_state = kOwnershipStateRecovery;
121  nonce_new(&bootdata->nonce);
122  HARDENED_RETURN_IF_ERROR(boot_data_write(bootdata));
123  return kErrorOwnershipBadInfoPage;
124  }
125  HARDENED_RETURN_IF_ERROR(owner_block_parse(&owner_page[0], config, keyring));
126  HARDENED_RETURN_IF_ERROR(
127  owner_block_flash_apply(config->flash, kBootSlotA,
128  /*lockdown=*/kHardenedBoolFalse));
129  HARDENED_RETURN_IF_ERROR(
130  owner_block_flash_apply(config->flash, kBootSlotB,
131  /*lockdown=*/kHardenedBoolFalse));
132  HARDENED_RETURN_IF_ERROR(owner_block_info_apply(config->info));
133  return kErrorOk;
134 }
135 
136 static rom_error_t unlocked_init(boot_data_t *bootdata, owner_config_t *config,
137  owner_application_keyring_t *keyring) {
138  uint32_t secondary =
139  bootdata->primary_bl0_slot == kBootSlotA ? kBootSlotB : kBootSlotA;
140  if (bootdata->ownership_state == kOwnershipStateUnlockedSelf &&
141  owner_page_valid[0] != kOwnerPageStatusSealed) {
142  // Owner Page 0 must be sealed in the "UnlockedSelf" state. If not,
143  // go to the Recovery state.
144  bootdata->ownership_state = kOwnershipStateRecovery;
145  nonce_new(&bootdata->nonce);
146  HARDENED_RETURN_IF_ERROR(boot_data_write(bootdata));
147  return kErrorOwnershipBadInfoPage;
148  }
149 
150  if (owner_page_valid[0] == kOwnerPageStatusSealed) {
151  // Configure the primary half of the flash as Owner Page 0 requests.
152  HARDENED_RETURN_IF_ERROR(
153  owner_block_parse(&owner_page[0], config, keyring));
154  HARDENED_RETURN_IF_ERROR(
155  owner_block_flash_apply(config->flash, bootdata->primary_bl0_slot,
156  /*lockdown=*/kHardenedBoolFalse));
157  }
158 
159  if (owner_block_page1_valid_for_transfer(bootdata) == kHardenedBoolTrue) {
160  // If we passed the validity test for Owner Page 1, test parse the config.
161  owner_config_t testcfg;
163  rom_error_t result = owner_block_parse(&owner_page[1], &testcfg, &testring);
164  if (result == kErrorOk) {
165  // Parse the configuration and add its keys to the keyring.
166  HARDENED_RETURN_IF_ERROR(
167  owner_block_parse(&owner_page[1], config, keyring));
168  } else {
169  dbg_printf("error: owner page 1 invalid.\r\n");
170  }
171  }
172  HARDENED_RETURN_IF_ERROR(
173  owner_block_flash_apply(config->flash, secondary,
174  /*lockdown=*/kHardenedBoolFalse));
175  HARDENED_RETURN_IF_ERROR(owner_block_info_apply(config->info));
176  return kErrorOk;
177 }
178 
179 rom_error_t ownership_init(boot_data_t *bootdata, owner_config_t *config,
180  owner_application_keyring_t *keyring) {
181  flash_ctrl_perms_t perm = {
182  .read = kMultiBitBool4True,
183  .write = kMultiBitBool4True,
184  .erase = kMultiBitBool4True,
185  };
186  flash_ctrl_cfg_t cfg = {
187  .scrambling = kMultiBitBool4True,
188  .ecc = kMultiBitBool4True,
189  .he = kMultiBitBool4False,
190  };
191  flash_ctrl_info_perms_set(&kFlashCtrlInfoPageOwnerSlot0, perm);
192  flash_ctrl_info_cfg_set(&kFlashCtrlInfoPageOwnerSlot0, cfg);
193  flash_ctrl_info_perms_set(&kFlashCtrlInfoPageOwnerSlot1, perm);
194  flash_ctrl_info_cfg_set(&kFlashCtrlInfoPageOwnerSlot1, cfg);
195  // Set up the OwnerSecret page for ECC & Scrambling. We won't
196  // turn on read/write/earse permissions until we need them.
197  flash_ctrl_info_cfg_set(&kFlashCtrlInfoPageOwnerSecret, cfg);
198 
199  // We don't want to abort ownership setup if we fail to
200  // read the INFO pages, so we discard the error result.
201  if (flash_ctrl_info_read(&kFlashCtrlInfoPageOwnerSlot0, 0,
202  sizeof(owner_page[0]) / sizeof(uint32_t),
203  &owner_page[0]) == kErrorOk) {
204  owner_page_valid[0] = owner_page_validity_check(0);
205  } else {
206  owner_page_valid[0] = kOwnerPageStatusInvalid;
207  memset(&owner_page[0], 0xff, sizeof(owner_page[0]));
208  }
209  if (flash_ctrl_info_read(&kFlashCtrlInfoPageOwnerSlot1, 0,
210  sizeof(owner_page[1]) / sizeof(uint32_t),
211  &owner_page[1]) == kErrorOk) {
212  owner_page_valid[1] = owner_page_validity_check(1);
213  } else {
214  owner_page_valid[1] = kOwnerPageStatusInvalid;
215  memset(&owner_page[1], 0xff, sizeof(owner_page[1]));
216  }
217 
218  // Depending on ownership state:
219  // - kOwnershipStateLockedOwner:
220  // - Make sure page0 and page1 are identical and fix if not.
221  // - Set up flash config.
222  // - Enumerate application keys.
223  // - kOwnershipStateUnlockedSelf:
224  // - Allow the pages to be different if the owner keys are the same.
225  // - Set up flash config: primary from page0, secondary from page 1.
226  // - Enumerate application keys from both pages.
227  // - kOwnershipStateUnlockedAny: Allow the pages to be different.
228  // - Allow the pages to be different.
229  // - Set up flash config: primary from page0, secondary from page 1.
230  // - Enumerate application keys from both pages.
231  // - kOwnershipStateUnlockedEndorsed: Allow the pages to be different.
232  // - Allow the pages to be different.
233  // - Set up flash config: primary from page0, secondary from page 1.
234  // - Enumerate application keys from both pages.
235  // - kOwnershipStateRecovery: Allow the pages to be different.
236  // - Disaster state. Do nothing and wait for remediation via
237  // the recovery key.
238 
239  dbg_printf("ownership: %C\r\n", bootdata->ownership_state);
240  owner_config_default(config);
241 
242  // We give the weak `sku_creator_owner_init` function the opportunity to
243  // initialize ownership if it is uninitialized or needs updating.
244  //
245  // This is a temporary measure to get ownership configs installed on
246  // pre-existing silicon and to update the owner configuration automatically
247  // should we decide to update it during development.
248  //
249  // When we settle on a default ownership configuration, we'll remove this
250  // function and possibly relegate it to the `default` case below, only to
251  // be used should the chip enter the "no owner recovery" state.
252  HARDENED_RETURN_IF_ERROR(sku_creator_owner_init(bootdata, config, keyring));
253 
254  rom_error_t error = kErrorOwnershipNoOwner;
255  // TODO(#22386): Harden this switch/case statement.
256  switch (bootdata->ownership_state) {
257  case kOwnershipStateLockedOwner:
258  error = locked_owner_init(bootdata, config, keyring);
259  break;
260  case kOwnershipStateUnlockedSelf:
262  case kOwnershipStateUnlockedAny:
264  case kOwnershipStateUnlockedEndorsed:
265  error = unlocked_init(bootdata, config, keyring);
266  break;
267  default:
268  /* Do nothing. */;
269  }
270  return error;
271 }
272 
273 rom_error_t ownership_flash_lockdown(boot_data_t *bootdata,
274  uint32_t active_slot,
275  const owner_config_t *config) {
276  if (bootdata->ownership_state == kOwnershipStateLockedOwner) {
277  HARDENED_RETURN_IF_ERROR(owner_block_flash_apply(config->flash, kBootSlotA,
278  /*lockdown=*/active_slot));
279  HARDENED_RETURN_IF_ERROR(owner_block_flash_apply(config->flash, kBootSlotB,
280  /*lockdown=*/active_slot));
281  } else {
282  HARDENED_CHECK_NE(bootdata->ownership_state, kOwnershipStateLockedOwner);
283  }
284  return kErrorOk;
285 }
286 
287 void ownership_pages_lockdown(boot_data_t *bootdata, hardened_bool_t rescue) {
288 #ifdef ROM_EXT_KLOBBER_ALLOWED
289  if (rescue == kHardenedBoolTrue) {
290  // If ROM_EXT_KLOBBER_ALLOWED and we're in rescue mode, we skip
291  // lockdown because the rescue protcol is permitted, on DEV chips
292  // only, to erase the ownership pages. This exists to simulate
293  // disaster scenarios and test the disaster recovery mechanisms.
294  //
295  // Under normal circumstances, the ROM_EXT is not built with this
296  // capability.
297  return;
298  }
299 #endif
300  flash_ctrl_perms_t perm = {
301  .read = kMultiBitBool4True,
302  .write = kMultiBitBool4False,
303  .erase = kMultiBitBool4False,
304  };
305  flash_ctrl_cfg_t cfg = {
306  .scrambling = kMultiBitBool4True,
307  .ecc = kMultiBitBool4True,
308  .he = kMultiBitBool4False,
309  };
310  // Always make page 0 read only.
311  flash_ctrl_info_perms_set(&kFlashCtrlInfoPageOwnerSlot0, perm);
312  flash_ctrl_info_cfg_set(&kFlashCtrlInfoPageOwnerSlot0, cfg);
313  flash_ctrl_info_lock(&kFlashCtrlInfoPageOwnerSlot0);
314  if (rescue == kHardenedBoolTrue) {
315  // Do not lock page 1 in rescue mode.
317  return;
318  }
319  if (bootdata->ownership_state == kOwnershipStateLockedOwner) {
320  if (owner_block_newversion_mode() == kHardenedBoolTrue) {
321  // Leave page 1 unlocked if we're in "NewVersion" update mode.
322  } else {
323  // Otherwise, make the page read-only.
324  flash_ctrl_info_perms_set(&kFlashCtrlInfoPageOwnerSlot1, perm);
325  flash_ctrl_info_cfg_set(&kFlashCtrlInfoPageOwnerSlot1, cfg);
326  }
327  } else {
328  // In any of the unlocked modes, leave page 1 unlocked.
329  }
330  flash_ctrl_info_lock(&kFlashCtrlInfoPageOwnerSlot1);
331  return;
332 }