Software APIs
owner_block.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 
5 #include "sw/device/silicon_creator/lib/ownership/owner_block.h"
6 
13 #include "sw/device/silicon_creator/lib/boot_data.h"
14 #include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h"
15 #include "sw/device/silicon_creator/lib/error.h"
16 
17 #include "flash_ctrl_regs.h"
18 
19 // RAM copy of the owner INFO pages from flash.
20 owner_block_t owner_page[2];
21 owner_page_status_t owner_page_valid[2];
22 
23 enum {
24  kFlashBankSize = FLASH_CTRL_PARAM_REG_PAGES_PER_BANK,
25  kFlashPageSize = FLASH_CTRL_PARAM_BYTES_PER_PAGE,
26 };
27 
28 hardened_bool_t owner_block_newversion_mode(void) {
29  if (owner_page_valid[0] == kOwnerPageStatusSealed &&
30  (owner_page[0].update_mode == kOwnershipUpdateModeNewVersion ||
31  owner_page[0].update_mode == kOwnershipUpdateModeSelfVersion)) {
32  return kHardenedBoolTrue;
33  }
34  return kHardenedBoolFalse;
35 }
36 
37 hardened_bool_t owner_block_page1_valid_for_transfer(boot_data_t *bootdata) {
38  if (bootdata->ownership_state == kOwnershipStateLockedOwner &&
39  owner_page_valid[1] == kOwnerPageStatusSealed) {
40  return kHardenedBoolTrue;
41  }
42  if (owner_page_valid[1] == kOwnerPageStatusSigned) {
43  hmac_digest_t digest;
44  switch (bootdata->ownership_state) {
45  case kOwnershipStateUnlockedAny:
46  // In UnlockedAny, any valid (signed) Owner Page 1 is acceptable.
47  return kHardenedBoolTrue;
48  case kOwnershipStateUnlockedSelf:
49  // In UnlockedSelf, the owner key must be the same. If not,
50  // skip parsing of Owner Page 1.
51  if (hardened_memeq(
52  owner_page[0].owner_key.raw, owner_page[1].owner_key.raw,
53  ARRAYSIZE(owner_page[0].owner_key.raw)) == kHardenedBoolTrue) {
54  return kHardenedBoolTrue;
55  }
56  break;
57  case kOwnershipStateUnlockedEndorsed:
58  // In UnlockedEndorsed, the owner key must match the key endorsed by the
59  // next_owner field in bootdata. If not, skip parsing owner page 1.
60  hmac_sha256(owner_page[1].owner_key.raw,
61  sizeof(owner_page[1].owner_key.raw), &digest);
62  if (hardened_memeq(bootdata->next_owner, digest.digest,
63  ARRAYSIZE(digest.digest)) == kHardenedBoolTrue) {
64  return kHardenedBoolTrue;
65  }
66  break;
67  default:
68  /* nothing */;
69  }
70  }
71  return kHardenedBoolFalse;
72 }
73 
74 void owner_config_default(owner_config_t *config) {
75  // Use a bogus pointer value to avoid the all-zeros pattern of NULL.
79  config->sram_exec = kOwnerSramExecModeDisabledLocked;
80 }
81 
82 rom_error_t owner_block_parse(const owner_block_t *block,
83  owner_config_t *config,
84  owner_application_keyring_t *keyring) {
85  owner_config_default(config);
86  if (block->header.tag != kTlvTagOwner)
87  return kErrorOwnershipInvalidTag;
88  if (block->header.length != sizeof(owner_block_t))
89  return kErrorOwnershipInvalidTagLength;
90  if (block->header.version.major != 0)
91  return kErrorOwnershipOWNRVersion;
92 
93  config->sram_exec = block->sram_exec_mode;
94 
95  uint32_t remain = sizeof(block->data);
96  uint32_t offset = 0;
97  while (remain) {
98  const tlv_header_t *item = (const tlv_header_t *)(block->data + offset);
99  if (item->tag == kTlvTagNotPresent) {
100  break;
101  }
102  if (item->length < 8 || item->length > remain || item->length % 4 != 0) {
103  return kErrorOwnershipInvalidTagLength;
104  }
105  remain -= item->length;
106  offset += item->length;
107  uint32_t tag = item->tag;
108  switch (launder32(item->tag)) {
109  case kTlvTagApplicationKey:
110  HARDENED_CHECK_EQ(tag, kTlvTagApplicationKey);
111  if (item->version.major != 0)
112  return kErrorOwnershipAPPKVersion;
113 
114  if (keyring->length < ARRAYSIZE(keyring->key)) {
115  keyring->key[keyring->length++] =
116  (const owner_application_key_t *)item;
117  }
118  break;
119  case kTlvTagFlashConfig:
120  HARDENED_CHECK_EQ(tag, kTlvTagFlashConfig);
121  if (item->version.major != 0)
122  return kErrorOwnershipFLSHVersion;
123  if ((hardened_bool_t)config->flash != kHardenedBoolFalse)
124  return kErrorOwnershipDuplicateItem;
125  HARDENED_RETURN_IF_ERROR(
126  owner_block_flash_check((const owner_flash_config_t *)item));
127  config->flash = (const owner_flash_config_t *)item;
128  break;
129  case kTlvTagInfoConfig:
130  HARDENED_CHECK_EQ(tag, kTlvTagInfoConfig);
131  if (item->version.major != 0)
132  return kErrorOwnershipINFOVersion;
133  if ((hardened_bool_t)config->info != kHardenedBoolFalse)
134  return kErrorOwnershipDuplicateItem;
135  config->info = (const owner_flash_info_config_t *)item;
136  break;
137  case kTlvTagRescueConfig:
138  HARDENED_CHECK_EQ(tag, kTlvTagRescueConfig);
139  if (item->version.major != 0)
140  return kErrorOwnershipRESQVersion;
141  if ((hardened_bool_t)config->rescue != kHardenedBoolFalse)
142  return kErrorOwnershipDuplicateItem;
143  config->rescue = (const owner_rescue_config_t *)item;
144  break;
145  default:
146  return kErrorOwnershipInvalidTag;
147  }
148  }
149  return kErrorOk;
150 }
151 
152 rom_error_t owner_block_flash_check(const owner_flash_config_t *flash) {
153  size_t len = (flash->header.length - sizeof(owner_flash_config_t)) /
154  sizeof(owner_flash_region_t);
155  if (len >= 8) {
156  return kErrorOwnershipFlashConfigLenth;
157  }
158 
159  const uint32_t kRomExtAStart = 0 / kFlashPageSize;
160  const uint32_t kRomExtAEnd = CHIP_ROM_EXT_SIZE_MAX / kFlashPageSize;
161  const uint32_t kRomExtBStart = kFlashBankSize + kRomExtAStart;
162  const uint32_t kRomExtBEnd = kFlashBankSize + kRomExtAEnd;
163 
164  const owner_flash_region_t *config = flash->config;
165  uint32_t crypt = 0;
166  for (size_t i = 0; i < len; ++i, ++config, crypt += 0x11111111) {
167  uint32_t start = config->start;
168  uint32_t end = start + config->size;
169  if ((kRomExtAStart >= start && kRomExtAStart < end) ||
170  (kRomExtAEnd > start && kRomExtAEnd <= end) ||
171  (kRomExtBStart >= start && kRomExtBStart < end) ||
172  (kRomExtBEnd > start && kRomExtBEnd <= end)) {
173  uint32_t val = config->properties ^ crypt;
174  flash_ctrl_cfg_t cfg = {
175  .scrambling = bitfield_field32_read(val, FLASH_CONFIG_SCRAMBLE),
176  .ecc = bitfield_field32_read(val, FLASH_CONFIG_ECC),
177  .he = bitfield_field32_read(val, FLASH_CONFIG_HIGH_ENDURANCE),
178  };
179  flash_ctrl_cfg_t dfl = flash_ctrl_data_default_cfg_get();
180  // Any non-true value should be forced to false.
181  if (dfl.ecc != kMultiBitBool4True)
182  dfl.ecc = kMultiBitBool4False;
183  if (dfl.scrambling != kMultiBitBool4True)
184  dfl.scrambling = kMultiBitBool4False;
185 
186  if (cfg.ecc != dfl.ecc || cfg.scrambling != dfl.scrambling) {
187  // The config region convering the ROM_EXT needs to match the
188  // default config's ECC and scrambling settings.
189  return kErrorOwnershipFlashConfigRomExt;
190  }
191  }
192  }
193  return kErrorOk;
194 }
195 
196 rom_error_t owner_block_flash_apply(const owner_flash_config_t *flash,
197  uint32_t config_side, uint32_t lockdown) {
198  if ((hardened_bool_t)flash == kHardenedBoolFalse)
199  return kErrorOk;
200  // TODO: Hardening: lockdown should be one of kBootSlotA, kBootSlotB or
201  // kHardenedBoolFalse.
202  uint32_t start = config_side == kBootSlotA ? 0
203  : config_side == kBootSlotB ? kFlashBankSize
204  : 0xFFFFFFFF;
205  uint32_t end = config_side == kBootSlotA ? kFlashBankSize
206  : config_side == kBootSlotB ? 2 * kFlashBankSize
207  : 0;
208  size_t len = (flash->header.length - sizeof(owner_flash_config_t)) /
209  sizeof(owner_flash_region_t);
210  if (len >= 8) {
211  return kErrorOwnershipFlashConfigLenth;
212  }
213 
214  const owner_flash_region_t *config = flash->config;
215  uint32_t crypt = 0;
216  for (size_t i = 0; i < len; ++i, ++config, crypt += 0x11111111) {
217  if (config->start >= start && config->start + config->size <= end) {
218  uint32_t val = config->properties ^ crypt;
219  flash_ctrl_cfg_t cfg = {
220  .scrambling = bitfield_field32_read(val, FLASH_CONFIG_SCRAMBLE),
221  .ecc = bitfield_field32_read(val, FLASH_CONFIG_ECC),
222  .he = bitfield_field32_read(val, FLASH_CONFIG_HIGH_ENDURANCE),
223  };
224  val = config->access ^ crypt;
225  flash_ctrl_perms_t perm = {
226  .read = bitfield_field32_read(val, FLASH_CONFIG_READ),
227  .write = bitfield_field32_read(val, FLASH_CONFIG_PROGRAM),
228  .erase = bitfield_field32_read(val, FLASH_CONFIG_ERASE),
229  };
230 
231  if (lockdown == config_side) {
232  if (bitfield_field32_read(val, FLASH_CONFIG_PROTECT_WHEN_PRIMARY) !=
233  kMultiBitBool4False) {
234  perm.write = kMultiBitBool4False;
235  perm.erase = kMultiBitBool4False;
236  }
237  }
238 
240  if (lockdown != kHardenedBoolFalse) {
241  if (bitfield_field32_read(val, FLASH_CONFIG_LOCK) !=
242  kMultiBitBool4False) {
243  lock = kHardenedBoolTrue;
244  }
245  }
246  flash_ctrl_data_region_protect(i, config->start, config->size, perm, cfg,
247  lock);
248  }
249  }
250  return kErrorOk;
251 }
252 
253 static inline hardened_bool_t is_owner_page(const owner_info_page_t *config) {
254  if (config->bank == 0) {
255  if (config->page >= 6 && config->page <= 9) {
256  // Currently, bank0, pages 6-9 (inclusive) are the pages reserved
257  // for the owner's use.
258  return kHardenedBoolTrue;
259  }
260  }
261  return kHardenedBoolFalse;
262 }
263 
264 rom_error_t owner_block_info_apply(const owner_flash_info_config_t *info) {
265  if ((hardened_bool_t)info == kHardenedBoolFalse)
266  return kErrorOk;
267  size_t len = (info->header.length - sizeof(owner_flash_info_config_t)) /
268  sizeof(owner_info_page_t);
269  const owner_info_page_t *config = info->config;
270  uint32_t crypt = 0;
271  for (size_t i = 0; i < len; ++i, ++config, crypt += 0x11111111) {
272  if (is_owner_page(config) == kHardenedBoolTrue) {
273  flash_ctrl_info_page_t page = {
274  .base_addr = config->bank * FLASH_CTRL_PARAM_BYTES_PER_BANK +
275  config->page * FLASH_CTRL_PARAM_BYTES_PER_PAGE,
276  .cfg_wen_offset =
277  config->page * sizeof(uint32_t) +
278  (config->bank == 0 ? FLASH_CTRL_BANK0_INFO0_REGWEN_0_REG_OFFSET
279  : FLASH_CTRL_BANK1_INFO0_REGWEN_0_REG_OFFSET),
280  .cfg_offset = config->page * sizeof(uint32_t) +
281  (config->bank == 0
282  ? FLASH_CTRL_BANK0_INFO0_PAGE_CFG_0_REG_OFFSET
283  : FLASH_CTRL_BANK1_INFO0_PAGE_CFG_0_REG_OFFSET),
284  };
285 
286  uint32_t val = config->properties ^ crypt;
287  flash_ctrl_cfg_t cfg = {
288  .scrambling = bitfield_field32_read(val, FLASH_CONFIG_SCRAMBLE),
289  .ecc = bitfield_field32_read(val, FLASH_CONFIG_ECC),
290  .he = bitfield_field32_read(val, FLASH_CONFIG_HIGH_ENDURANCE),
291  };
292  flash_ctrl_info_cfg_set(&page, cfg);
293 
294  val = config->access ^ crypt;
295  flash_ctrl_perms_t perm = {
296  .read = bitfield_field32_read(val, FLASH_CONFIG_READ),
297  .write = bitfield_field32_read(val, FLASH_CONFIG_PROGRAM),
298  .erase = bitfield_field32_read(val, FLASH_CONFIG_ERASE),
299  };
300  flash_ctrl_info_perms_set(&page, perm);
301  }
302  }
303  return kErrorOk;
304 }
305 
306 rom_error_t owner_keyring_find_key(const owner_application_keyring_t *keyring,
307  uint32_t key_alg, uint32_t key_id,
308  size_t *index) {
309  for (size_t i = 0; i < keyring->length; ++i) {
310  if (keyring->key[i]->key_alg == key_alg &&
311  keyring->key[i]->data.id == key_id) {
312  *index = i;
313  return kErrorOk;
314  }
315  }
316  return kErrorOwnershipKeyNotFound;
317 }
318 
319 size_t owner_block_key_page(const owner_application_key_t *key) {
320  // The key pointer must point to a memory address on one of the two owner
321  // pages.
322  HARDENED_CHECK_GT((uintptr_t)key, (uintptr_t)&owner_page[0]);
323  HARDENED_CHECK_LT((uintptr_t)key,
324  (uintptr_t)&owner_page[ARRAYSIZE(owner_page)]);
325  return (uintptr_t)key < (uintptr_t)&owner_page[1] ? 0 : 1;
326 }
327 
328 hardened_bool_t owner_rescue_command_allowed(
329  const owner_rescue_config_t *rescue, uint32_t command) {
330  // If no rescue configuration is supplied in the owner config, then all rescue
331  // commands are allowed.
332  if ((hardened_bool_t)rescue == kHardenedBoolFalse)
333  return kHardenedBoolTrue;
334 
336  size_t length = (rescue->header.length - sizeof(*rescue)) / sizeof(uint32_t);
337  for (size_t i = 0; i < length; ++i) {
338  if (command == rescue->command_allow[i]) {
339  allowed = kHardenedBoolTrue;
340  }
341  }
342  return allowed;
343 }
344 
345 void owner_block_measurement(size_t page, hmac_digest_t *measurement) {
346  HARDENED_CHECK_LT(page, ARRAYSIZE(owner_page));
347  // Digest of the contents of the owner page, not including the signature or
348  // the seal.
349  size_t len = offsetof(owner_block_t, signature);
350  hmac_sha256(&owner_page[page], len, measurement);
351 }