Software APIs
sival_owner.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 
8 #include "sw/device/silicon_creator/lib/dbg_print.h"
9 #include "sw/device/silicon_creator/lib/drivers/flash_ctrl.h"
10 #include "sw/device/silicon_creator/lib/error.h"
11 #include "sw/device/silicon_creator/lib/ownership/owner_block.h"
12 #include "sw/device/silicon_creator/lib/ownership/ownership.h"
13 #include "sw/device/silicon_creator/lib/ownership/ownership_key.h"
14 #include "sw/device/silicon_creator/rom_ext/sival/keys/appkey_dev_0.h"
15 #include "sw/device/silicon_creator/rom_ext/sival/keys/appkey_prod_0.h"
16 #include "sw/device/silicon_creator/rom_ext/sival/keys/appkey_test_0.h"
17 #include "sw/device/silicon_creator/rom_ext/sival/keys/ownership_activate_key.h"
18 #include "sw/device/silicon_creator/rom_ext/sival/keys/ownership_owner_key.h"
19 #include "sw/device/silicon_creator/rom_ext/sival/keys/ownership_unlock_key.h"
20 
21 /*
22  * This module overrides the weak `sku_creator_owner_init` symbol in
23  * ownership.c, thus allowing existing sival chips without an ownership
24  * configuration to receive their ownership config simply installing the latest
25  * ROM_EXT.
26  */
27 
28 #define SIVAL_OWNER_CONFIG_VERSION 1
29 
30 rom_error_t sku_creator_owner_init(boot_data_t *bootdata,
31  owner_config_t *config,
32  owner_application_keyring_t *keyring) {
33  owner_key_t owner = (owner_key_t){
34  // Although this is an ECDSA key, we initialize the `raw` member of the
35  // union to zero-initialize the unused space.
36  .raw = OWNERSHIP_OWNER_KEY};
37  ownership_state_t state = bootdata->ownership_state;
38 
39  if (state == kOwnershipStateUnlockedSelf ||
40  state == kOwnershipStateUnlockedAny ||
41  state == kOwnershipStateUnlockedEndorsed) {
42  // Nothing to do when in an unlocked state.
43  return kErrorOk;
44  } else if (state == kOwnershipStateLockedOwner) {
45  if (hardened_memeq(owner.raw, owner_page[0].owner_key.raw,
46  ARRAYSIZE(owner.raw)) != kHardenedBoolTrue ||
47  SIVAL_OWNER_CONFIG_VERSION <= owner_page[0].config_version) {
48  // Different owner or already newest config version; nothing to do.
49  return kErrorOk;
50  }
51  } else {
52  // State is an unknown value, which is the same as kOwnershipStateRecovery.
53  // We'll not return, thus allowing the owner config below to be programmed
54  // into flash.
55  }
56 
57  memset(&owner_page[0], 0, sizeof(owner_page[0]));
58  owner_page[0].header.tag = kTlvTagOwner;
59  owner_page[0].header.length = 2048;
60  owner_page[0].header.version = (struct_version_t){0, 0};
61  owner_page[0].config_version = SIVAL_OWNER_CONFIG_VERSION;
62  owner_page[0].sram_exec_mode = kOwnerSramExecModeDisabledLocked;
63  owner_page[0].ownership_key_alg = kOwnershipKeyAlgEcdsaP256;
64  owner_page[0].update_mode = kOwnershipUpdateModeOpen;
65  owner_page[0].min_security_version_bl0 = UINT32_MAX;
66  owner_page[0].lock_constraint = 0;
67  memset(owner_page[0].device_id, kLockConstraintNone,
68  sizeof(owner_page[0].device_id));
69  owner_page[0].owner_key = owner;
70  owner_page[0].activate_key = (owner_key_t){
71  // Although this is an ECDSA key, we initialize the `raw` member of the
72  // union to zero-initialize the unused space.
73  .raw = OWNERSHIP_ACTIVATE_KEY};
74  owner_page[0].unlock_key = (owner_key_t){
75  // Although this is an ECDSA key, we initialize the `raw` member of the
76  // union to zero-initialize the unused space.
77  .raw = OWNERSHIP_UNLOCK_KEY};
78 
79  owner_application_key_t *app = (owner_application_key_t *)owner_page[0].data;
80  *app = (owner_application_key_t){
81  .header =
82  {
83  .tag = kTlvTagApplicationKey,
84  .length = kTlvLenApplicationKeyEcdsa,
85  },
86  .key_alg = kOwnershipKeyAlgEcdsaP256,
87  .key_domain = kOwnerAppDomainTest,
88  .key_diversifier = {0},
89  .usage_constraint = 0,
90  .data =
91  {
92  .ecdsa = APPKEY_TEST_0,
93  },
94  };
95 
96  app = (owner_application_key_t *)((uintptr_t)app + app->header.length);
97  *app = (owner_application_key_t){
98  .header =
99  {
100  .tag = kTlvTagApplicationKey,
101  .length = kTlvLenApplicationKeyEcdsa,
102  },
103  .key_alg = kOwnershipKeyAlgEcdsaP256,
104  .key_domain = kOwnerAppDomainProd,
105  .key_diversifier = {0},
106  .usage_constraint = 0,
107  .data =
108  {
109  .ecdsa = APPKEY_PROD_0,
110  },
111  };
112 
113  app = (owner_application_key_t *)((uintptr_t)app + app->header.length);
114  *app = (owner_application_key_t){
115  .header =
116  {
117  .tag = kTlvTagApplicationKey,
118  .length = kTlvLenApplicationKeyEcdsa,
119  },
120  .key_alg = kOwnershipKeyAlgEcdsaP256,
121  .key_domain = kOwnerAppDomainDev,
122  .key_diversifier = {0},
123  .usage_constraint = 0,
124  .data =
125  {
126  .ecdsa = APPKEY_DEV_0,
127  },
128  };
129 
130  // Fill the remainder of the data segment with the end tag (0x5a5a5a5a).
131  app = (owner_application_key_t *)((uintptr_t)app + app->header.length);
132  size_t len = (uintptr_t)(owner_page[0].data + sizeof(owner_page[0].data)) -
133  (uintptr_t)app;
134  memset(app, 0x5a, len);
135 
136  ownership_seal_page(/*page=*/0);
137  memcpy(&owner_page[1], &owner_page[0], sizeof(owner_page[0]));
138 
139  // Since this code should only execute when the ownership state is unknown, we
140  // can thunk the ownership state to LockedOwner.
141  bootdata->ownership_state = kOwnershipStateLockedOwner;
142 
143  // Write the configuration to page 0.
144  OT_DISCARD(flash_ctrl_info_erase(&kFlashCtrlInfoPageOwnerSlot0,
145  kFlashCtrlEraseTypePage));
146  OT_DISCARD(flash_ctrl_info_write(&kFlashCtrlInfoPageOwnerSlot0, 0,
147  sizeof(owner_page[0]) / sizeof(uint32_t),
148  &owner_page[0]));
149  owner_page_valid[0] = kOwnerPageStatusSealed;
150 
151  OT_DISCARD(boot_data_write(bootdata));
152  dbg_printf("sku_creator_owner_init: saved to flash\r\n");
153  return kErrorOk;
154 }