Software APIs
individualize_sw_cfg.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/manuf/lib/individualize_sw_cfg.h"
6 
13 #include "sw/device/lib/testing/flash_ctrl_testutils.h"
14 #include "sw/device/lib/testing/otp_ctrl_testutils.h"
15 #include "sw/device/silicon_creator/manuf/lib/flash_info_fields.h"
16 #include "sw/device/silicon_creator/manuf/lib/otp_img_types.h"
17 #include "sw/device/silicon_creator/manuf/lib/util.h"
18 
19 #include "flash_ctrl_regs.h" // Generated.
21 #include "otp_ctrl_regs.h" // Generated.
22 
23 enum {
24  kValidAstCfgOtpAddrLow = OTP_CTRL_PARAM_CREATOR_SW_CFG_AST_CFG_OFFSET,
25  kInvalidAstCfgOtpAddrHigh =
26  kValidAstCfgOtpAddrLow + OTP_CTRL_PARAM_CREATOR_SW_CFG_AST_CFG_SIZE,
27 
28 };
29 
30 static uint32_t
31  flash_info_page_buf[FLASH_CTRL_PARAM_BYTES_PER_PAGE / sizeof(uint32_t)];
32 
33 /**
34  * Writes OTP values to target OTP `partition`.
35  *
36  * The `kv` array is preferrably generated using the build infrastructure. See
37  * individualize_preop.c and its build target for an example.
38  *
39  * @param otp OTP Controller instance.
40  * @param partition Target OTP partition.
41  * @param kv OTP Array of OTP key values. See `otp_kv_t` documentation for more
42  * details.
43  * @param len Length of the `kv` array.
44  * @return OK_STATUS if the OTP values were written into the target partition.
45  */
47 static status_t otp_img_write(const dif_otp_ctrl_t *otp,
48  dif_otp_ctrl_partition_t partition,
49  const otp_kv_t *kv, size_t len) {
50  for (size_t i = 0; i < len; ++i) {
51  // We purposely skip the provisioning of the flash data region default
52  // configuration as it must be enabled only after the OTP SECRET1
53  // partition has been provisioned. Since OTP SECRET1 provisioning requires
54  // the HW_CFG0 partition to be provisioned to use the CSRNG SW interface,
55  // there is a delicate order of operations in which this field is
56  // provisioned. Therefore we require explicit provisioning of this field
57  // immediately before the transport image is loaded, after all other
58  // provisioning is complete.
59  //
60  // We skip the provisioning of the creator manufacturing status as it must
61  // be provisioned only at the end of the personalization flow. The
62  // personalization firmware is bound with the INITIAL (empty) manufacturing
63  // state, so once the manufacturing state is provisioned, the
64  // personalization firmware can't be re-entrant.
65  //
66  // We skip the provisioning of the immutable ROM_EXT enablement
67  // configuration as it must be provisioned only at the end of the
68  // personalization flow. The personalization firmware doesn't include an
69  // immutable ROM_EXT section. Enabling this feature with personalization
70  // firmware would result in ROM self-shutdown due to an invalid immutable
71  // ROM extension hash.
72  //
73  // We also skip the provisioning of the ROM bootstrap disablement
74  // configuration. This should only be disabled after all bootstrap
75  // operations in the personalization flow have been completed.
76  //
77  // Additionally, we skip the provisioning of the AST configuration data, as
78  // this should already be written to a flash info page. We will pull the
79  // data directly from there.
80  if (kv[i].offset ==
81  OTP_CTRL_PARAM_CREATOR_SW_CFG_FLASH_DATA_DEFAULT_CFG_OFFSET ||
82  kv[i].offset == OTP_CTRL_PARAM_CREATOR_SW_CFG_MANUF_STATE_OFFSET ||
83  kv[i].offset ==
84  OTP_CTRL_PARAM_CREATOR_SW_CFG_IMMUTABLE_ROM_EXT_EN_OFFSET ||
85  kv[i].offset == OTP_CTRL_PARAM_OWNER_SW_CFG_ROM_BOOTSTRAP_DIS_OFFSET ||
86  (kv[i].offset >= kValidAstCfgOtpAddrLow &&
87  kv[i].offset < kInvalidAstCfgOtpAddrHigh)) {
88  continue;
89  }
90  uint32_t offset;
91  TRY(dif_otp_ctrl_relative_address(partition, kv[i].offset, &offset));
92  switch (kv[i].type) {
93  case kOptValTypeUint32Buff:
94  TRY(otp_ctrl_testutils_dai_write32(otp, partition, offset,
95  kv[i].value32, kv[i].num_values));
96  break;
97  case kOptValTypeUint64Buff:
98  TRY(otp_ctrl_testutils_dai_write64(otp, partition, offset,
99  kv[i].value64, kv[i].num_values));
100  break;
101  case kOptValTypeUint64Rnd:
102  return UNIMPLEMENTED();
103  default:
104  return INTERNAL();
105  }
106  }
107  return OK_STATUS();
108 }
109 
110 /**
111  * Overwrites the target field with its expected final value in a buffer
112  * representing the provided partition.
113  *
114  * @param partition Target OTP partition.
115  * @param field_offset An offest of the target OTP field.
116  * @param buffer A buffer containing the entire target OTP partition.
117  * @return OK_STATUS if the expected OTP values are successfully written to the
118  * `buffer`.
119  */
120 static status_t otp_img_expected_value_read(dif_otp_ctrl_partition_t partition,
121  uint32_t field_offset,
122  uint8_t *buffer) {
123  uint32_t relative_addr;
124  TRY(dif_otp_ctrl_relative_address(partition, field_offset, &relative_addr));
125  switch (field_offset) {
126  case OTP_CTRL_PARAM_OWNER_SW_CFG_ROM_BOOTSTRAP_DIS_OFFSET:
127  memcpy(buffer + relative_addr, &kOwnerSwCfgRomBootstrapDisValue,
128  sizeof(uint32_t));
129  break;
130  case OTP_CTRL_PARAM_CREATOR_SW_CFG_MANUF_STATE_OFFSET:
131  memcpy(buffer + relative_addr, &kCreatorSwCfgManufStateValue,
132  sizeof(uint32_t));
133  break;
134  case OTP_CTRL_PARAM_CREATOR_SW_CFG_IMMUTABLE_ROM_EXT_EN_OFFSET:
135  memcpy(buffer + relative_addr, &kCreatorSwCfgImmutableRomExtEnValue,
136  sizeof(uint32_t));
137  break;
138  default:
139  return INTERNAL();
140  }
141  return OK_STATUS();
142 }
143 
144 /**
145  * Computes a SHA256 digest of an OTP partition and uses the least significant
146  * 64-bits of the digest to additionally lock the partition.
147  *
148  * Note: only {Creator,Owner}SwCfg partitions and the VendorTest partition may
149  * be locked in this manner. All other partitions are locked via hardware.
150  *
151  * @param otp OTP Controller instance.
152  * @param partition Target OTP partition.
153  * @return OK_STATUS if the target partition was locked.
154  */
156 static status_t lock_otp_partition(const dif_otp_ctrl_t *otp_ctrl,
157  dif_otp_ctrl_partition_t partition) {
158  // Compute SHA256 of the OTP partition.
159  uint32_t digest[kSha256DigestWords];
160  otcrypto_word32_buf_t otp_partition_digest = {
161  .len = ARRAYSIZE(digest),
162  .data = digest,
163  };
164  TRY(manuf_util_hash_otp_partition(otp_ctrl, partition, otp_partition_digest));
165 
166  // Get the least significant 64 bits of the digest. We will use this as the
167  // digest to lock the OTP partition. The complete digest will be used in the
168  // attestation key / certificate generation. Note: cryptolib generates the
169  // digest in big-endian format so we must rearrange the bytes.
170  uint64_t partition_digest_lowest_64bits = __builtin_bswap32(digest[6]);
171  partition_digest_lowest_64bits =
172  (partition_digest_lowest_64bits << 32) | __builtin_bswap32(digest[7]);
173 
174  TRY(otp_ctrl_testutils_lock_partition(
175  otp_ctrl, partition, /*digest=*/partition_digest_lowest_64bits));
176 
177  return OK_STATUS();
178 }
179 
180 static status_t manuf_individualize_device_ast_cfg(
181  const dif_otp_ctrl_t *otp_ctrl, dif_flash_ctrl_state_t *flash_state) {
182  // Clear flash info page buffer.
183  memset(flash_info_page_buf, UINT8_MAX, FLASH_CTRL_PARAM_BYTES_PER_PAGE);
184 
185  // Copy all of flash info page 0 into RAM. This contains the AST configuration
186  // data, which we will extract and then delete.
187  uint32_t page_byte_address = 0;
188  TRY(flash_ctrl_testutils_info_region_setup_properties(
189  flash_state, kFlashInfoFieldAstCalibrationData.page,
190  kFlashInfoFieldAstCalibrationData.bank,
191  kFlashInfoFieldAstCalibrationData.partition,
193  .ecc_en = kMultiBitBool4True,
194  .high_endurance_en = kMultiBitBool4False,
195  .erase_en = kMultiBitBool4True,
196  .prog_en = kMultiBitBool4True,
197  .rd_en = kMultiBitBool4True,
198  .scramble_en = kMultiBitBool4False},
199  &page_byte_address));
200  TRY(flash_ctrl_testutils_read(
201  flash_state, page_byte_address,
202  kFlashInfoFieldAstCalibrationData.partition, flash_info_page_buf,
203  kDifFlashCtrlPartitionTypeInfo,
204  FLASH_CTRL_PARAM_BYTES_PER_PAGE / sizeof(uint32_t),
205  /*delay=*/0));
206 
207  // Write AST configuration data to OTP.
208  size_t ast_cfg_offset =
209  kFlashInfoFieldAstCalibrationData.byte_offset / sizeof(uint32_t);
210  for (size_t i = 0; i < kFlashInfoAstCalibrationDataSizeIn32BitWords; ++i) {
211  uint32_t addr =
212  OTP_CTRL_PARAM_CREATOR_SW_CFG_AST_CFG_OFFSET + i * sizeof(uint32_t);
213  uint32_t data = flash_info_page_buf[ast_cfg_offset + i];
214  uint32_t relative_addr;
215  // Check the range is valid.
216  if (addr < kValidAstCfgOtpAddrLow || addr >= kInvalidAstCfgOtpAddrHigh) {
217  return OUT_OF_RANGE();
218  }
220  &relative_addr));
221  TRY(otp_ctrl_testutils_dai_write32(otp_ctrl,
223  relative_addr, &data, /*len=*/1));
224  flash_info_page_buf[ast_cfg_offset + i] =
225  UINT32_MAX; // Erase AST config data after use.
226  }
227 
228  // Erase AST data from flash by erasing the entire page and rewriting the
229  // modified buffered contents back to the page.
230  TRY(flash_ctrl_testutils_erase_page(
231  flash_state, page_byte_address,
232  kFlashInfoFieldAstCalibrationData.partition,
233  kDifFlashCtrlPartitionTypeInfo));
234  TRY(flash_ctrl_testutils_write(
235  flash_state, page_byte_address,
236  kFlashInfoFieldAstCalibrationData.partition, flash_info_page_buf,
237  kDifFlashCtrlPartitionTypeInfo,
238  FLASH_CTRL_PARAM_BYTES_PER_PAGE / sizeof(uint32_t)));
239 
240  return OK_STATUS();
241 }
242 
243 status_t manuf_individualize_device_creator_sw_cfg(
244  const dif_otp_ctrl_t *otp_ctrl, dif_flash_ctrl_state_t *flash_state) {
245  TRY(otp_img_write(otp_ctrl, kDifOtpCtrlPartitionCreatorSwCfg,
246  kOtpKvCreatorSwCfg, kOtpKvCreatorSwCfgSize));
247  TRY(manuf_individualize_device_ast_cfg(otp_ctrl, flash_state));
248  return OK_STATUS();
249 }
250 
251 status_t manuf_individualize_device_field_cfg(const dif_otp_ctrl_t *otp_ctrl,
252  uint32_t field_offset) {
253  uint32_t relative_addr;
254  const uint32_t *field_value_addr;
255  dif_otp_ctrl_partition_t partition;
256  switch (field_offset) {
257  case OTP_CTRL_PARAM_OWNER_SW_CFG_ROM_BOOTSTRAP_DIS_OFFSET:
258  field_value_addr = &kOwnerSwCfgRomBootstrapDisValue;
259  partition = kDifOtpCtrlPartitionOwnerSwCfg;
260  break;
261  case OTP_CTRL_PARAM_CREATOR_SW_CFG_FLASH_DATA_DEFAULT_CFG_OFFSET:
262  field_value_addr = &kCreatorSwCfgFlashDataDefaultCfgValue;
264  break;
265  case OTP_CTRL_PARAM_CREATOR_SW_CFG_IMMUTABLE_ROM_EXT_EN_OFFSET:
266  field_value_addr = &kCreatorSwCfgImmutableRomExtEnValue;
268  break;
269  case OTP_CTRL_PARAM_CREATOR_SW_CFG_MANUF_STATE_OFFSET:
270  field_value_addr = &kCreatorSwCfgManufStateValue;
272  break;
273  default:
274  return INTERNAL();
275  }
276 
277  TRY(dif_otp_ctrl_relative_address(partition, field_offset, &relative_addr));
278  TRY(otp_ctrl_testutils_dai_write32(otp_ctrl, partition, relative_addr,
279  field_value_addr, /*len=*/1));
280 
281  return OK_STATUS();
282 }
283 
284 status_t manuf_individualize_device_flash_data_default_cfg_check(
285  const dif_otp_ctrl_t *otp_ctrl) {
286  uint32_t offset;
289  OTP_CTRL_PARAM_CREATOR_SW_CFG_FLASH_DATA_DEFAULT_CFG_OFFSET, &offset));
290  uint32_t val = 0;
291  TRY(otp_ctrl_testutils_dai_read32(otp_ctrl, kDifOtpCtrlPartitionCreatorSwCfg,
292  offset, &val));
293  bool is_provisioned = (val == kCreatorSwCfgFlashDataDefaultCfgValue);
294  return is_provisioned ? OK_STATUS() : INTERNAL();
295 }
296 
297 status_t manuf_individualize_device_creator_sw_cfg_lock(
298  const dif_otp_ctrl_t *otp_ctrl) {
299  TRY(lock_otp_partition(otp_ctrl, kDifOtpCtrlPartitionCreatorSwCfg));
300  return OK_STATUS();
301 }
302 
303 status_t manuf_individualize_device_creator_sw_cfg_check(
304  const dif_otp_ctrl_t *otp_ctrl) {
305  bool is_locked;
307  otp_ctrl, kDifOtpCtrlPartitionCreatorSwCfg, &is_locked));
308  return is_locked ? OK_STATUS() : INTERNAL();
309 }
310 
311 status_t manuf_individualize_device_owner_sw_cfg(
312  const dif_otp_ctrl_t *otp_ctrl) {
313  TRY(otp_img_write(otp_ctrl, kDifOtpCtrlPartitionOwnerSwCfg, kOtpKvOwnerSwCfg,
314  kOtpKvOwnerSwCfgSize));
315  return OK_STATUS();
316 }
317 
318 status_t manuf_individualize_device_partition_expected_read(
319  dif_otp_ctrl_partition_t partition, uint8_t *buffer) {
320  switch (partition) {
322  TRY(otp_img_expected_value_read(
323  partition, OTP_CTRL_PARAM_OWNER_SW_CFG_ROM_BOOTSTRAP_DIS_OFFSET,
324  buffer));
325  break;
327  TRY(otp_img_expected_value_read(
328  partition, OTP_CTRL_PARAM_CREATOR_SW_CFG_MANUF_STATE_OFFSET, buffer));
329  TRY(otp_img_expected_value_read(
330  partition, OTP_CTRL_PARAM_CREATOR_SW_CFG_IMMUTABLE_ROM_EXT_EN_OFFSET,
331  buffer));
332  break;
333  default:
334  return INTERNAL();
335  }
336 
337  return OK_STATUS();
338 }
339 
340 status_t manuf_individualize_device_owner_sw_cfg_lock(
341  const dif_otp_ctrl_t *otp_ctrl) {
342  TRY(lock_otp_partition(otp_ctrl, kDifOtpCtrlPartitionOwnerSwCfg));
343  return OK_STATUS();
344 }
345 
346 status_t manuf_individualize_device_owner_sw_cfg_check(
347  const dif_otp_ctrl_t *otp_ctrl) {
348  bool is_locked;
350  &is_locked));
351  return is_locked ? OK_STATUS() : INTERNAL();
352 }
353 
354 status_t manuf_individualize_device_rot_creator_auth_codesign(
355  const dif_otp_ctrl_t *otp_ctrl) {
356  TRY(otp_img_write(otp_ctrl, kDifOtpCtrlPartitionRotCreatorAuthCodesign,
357  kOtpKvRotCreatorAuthCodesign,
358  kOtpKvRotCreatorAuthCodesignSize));
359  TRY(lock_otp_partition(otp_ctrl, kDifOtpCtrlPartitionRotCreatorAuthCodesign));
360  return OK_STATUS();
361 }
362 
363 status_t manuf_individualize_device_rot_creator_auth_state(
364  const dif_otp_ctrl_t *otp_ctrl) {
365  TRY(otp_img_write(otp_ctrl, kDifOtpCtrlPartitionRotCreatorAuthState,
366  kOtpKvRotCreatorAuthState, kOtpKvRotCreatorAuthStateSize));
367  TRY(lock_otp_partition(otp_ctrl, kDifOtpCtrlPartitionRotCreatorAuthState));
368  return OK_STATUS();
369 }
370 
371 status_t manuf_individualize_device_rot_creator_auth_codesign_check(
372  const dif_otp_ctrl_t *otp_ctrl) {
373  bool is_locked;
375  otp_ctrl, kDifOtpCtrlPartitionRotCreatorAuthCodesign, &is_locked));
376  return is_locked ? OK_STATUS() : INTERNAL();
377 }
378 
379 status_t manuf_individualize_device_rot_creator_auth_state_check(
380  const dif_otp_ctrl_t *otp_ctrl) {
381  bool is_locked;
383  otp_ctrl, kDifOtpCtrlPartitionRotCreatorAuthState, &is_locked));
384  return is_locked ? OK_STATUS() : INTERNAL();
385 }