Software APIs
individualize.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.h"
6 
8 #include "sw/device/lib/base/multibits.h"
9 #include "sw/device/lib/base/status.h"
10 #include "sw/device/lib/crypto/drivers/entropy.h"
15 #include "sw/device/lib/testing/flash_ctrl_testutils.h"
16 #include "sw/device/lib/testing/json/provisioning_data.h"
17 #include "sw/device/lib/testing/lc_ctrl_testutils.h"
18 #include "sw/device/lib/testing/otp_ctrl_testutils.h"
19 #include "sw/device/lib/testing/test_framework/check.h"
20 #include "sw/device/silicon_creator/manuf/lib/flash_info_fields.h"
21 #include "sw/device/silicon_creator/manuf/lib/otp_fields.h"
22 #include "sw/device/silicon_creator/manuf/lib/util.h"
23 
24 #include "otp_ctrl_regs.h"
25 
26 typedef struct hw_cfg1_settings {
27  /**
28  * Enable / disable execute from SRAM CSR switch.
29  */
30  multi_bit_bool_t en_sram_ifetch;
31  /**
32  * This input efuse is used to enable access to the NIST internal state per
33  * instance.
34  */
35  multi_bit_bool_t en_csrng_sw_app_read;
36  /**
37  * This efuse is to disable the RV_DM late debug enable behavior
38  */
39  multi_bit_bool_t dis_rv_dm_late_debug;
41 
42 // Changing any of the following values may result in unexpected device
43 // behavior.
44 //
45 // - en_sram_ifetch: required to enable SRAM code execution during
46 // manufacturing.
47 // - en_csrng_sw_app_read: required to be able to extract output from CSRNG.
48 const hw_cfg1_settings_t kHwCfg1Settings = {
49  .en_sram_ifetch = kMultiBitBool8True,
50  .en_csrng_sw_app_read = kMultiBitBool8True,
51  .dis_rv_dm_late_debug = kMultiBitBool8True,
52 };
53 
54 /**
55  * Configures digital logic settings in the HW_CFG1 partition.
56  *
57  * @param otp OTP controller instance.
58  * @return The result of the operation.
59  */
61 static status_t hw_cfg1_enable_knobs_set(const dif_otp_ctrl_t *otp_ctrl) {
62  uint32_t val =
63  bitfield_field32_write(0, kSramFetch, kHwCfg1Settings.en_sram_ifetch);
64  val = bitfield_field32_write(val, kCsrngAppRead,
65  kHwCfg1Settings.en_csrng_sw_app_read);
66  val = bitfield_field32_write(val, kDisRvDmLateDebug,
67  kHwCfg1Settings.dis_rv_dm_late_debug);
68 
69  TRY(otp_ctrl_testutils_dai_write32(otp_ctrl, kDifOtpCtrlPartitionHwCfg1,
70  kHwCfgEnSramIfetchOffset, &val,
71  /*len=*/1));
72  return OK_STATUS();
73 }
74 
75 status_t manuf_individualize_device_hw_cfg(
76  dif_flash_ctrl_state_t *flash_state, const dif_otp_ctrl_t *otp_ctrl,
77  dif_flash_ctrl_region_properties_t flash_info_page_0_permissions,
78  uint32_t *device_id) {
79  bool is_locked;
80 
81  // Provision HW_CFG0 if it is not locked.
83  &is_locked));
84  if (!is_locked) {
85  // Configure flash info page permissions in case we started from a cold
86  // boot. Note: device_id and manuf_state are on the same flash info page.
87  TRY(flash_ctrl_testutils_info_region_setup_properties(
88  flash_state, kFlashInfoFieldDeviceId.page, kFlashInfoFieldDeviceId.bank,
89  kFlashInfoFieldDeviceId.partition, flash_info_page_0_permissions,
90  /*offset=*/NULL));
91 
92  // Configure DeviceID
93  uint32_t device_id_from_flash[kHwCfgDeviceIdSizeIn32BitWords];
94  uint32_t empty_device_id[kHwCfgDeviceIdSizeIn32BitWords] = {0};
95  TRY(manuf_flash_info_field_read(flash_state, kFlashInfoFieldDeviceId,
96  device_id_from_flash,
97  kHwCfgDeviceIdSizeIn32BitWords));
98  bool flash_device_id_empty = true;
99  for (size_t i = 0;
100  flash_device_id_empty && i < kHwCfgDeviceIdSizeIn32BitWords; ++i) {
101  flash_device_id_empty &= device_id_from_flash[i] == 0;
102  }
103 
104  // If the device ID read from flash is non-empty, then it must match the
105  // device ID provided. If the device ID read from flash is empty, we check
106  // to ensure the device ID provided is also not empty. An empty (all zero)
107  // device ID will prevent the keymgr from advancing.
108  if (!flash_device_id_empty) {
109  TRY_CHECK_ARRAYS_EQ(device_id_from_flash, device_id,
110  kHwCfgDeviceIdSizeIn32BitWords);
111  } else {
112  TRY_CHECK_ARRAYS_NE(device_id, empty_device_id,
113  kHwCfgDeviceIdSizeIn32BitWords);
114  }
115  TRY(otp_ctrl_testutils_dai_write32(otp_ctrl, kDifOtpCtrlPartitionHwCfg0,
116  kHwCfgDeviceIdOffset, device_id,
117  kHwCfgDeviceIdSizeIn32BitWords));
118 
119  // Configure ManufState
120  uint32_t manuf_state[kHwCfgManufStateSizeIn32BitWords];
121  TRY(manuf_flash_info_field_read(flash_state, kFlashInfoFieldManufState,
122  manuf_state,
123  kHwCfgManufStateSizeIn32BitWords));
124  TRY(otp_ctrl_testutils_dai_write32(otp_ctrl, kDifOtpCtrlPartitionHwCfg0,
125  kHwCfgManufStateOffset, manuf_state,
126  kHwCfgManufStateSizeIn32BitWords));
127  TRY(otp_ctrl_testutils_lock_partition(otp_ctrl, kDifOtpCtrlPartitionHwCfg0,
128  /*digest=*/0));
129  }
130 
131  // Provision HW_CFG1 if it is not locked.
133  &is_locked));
134  if (!is_locked) {
135  // Configure byte-sized hardware enable knobs.
136  TRY(hw_cfg1_enable_knobs_set(otp_ctrl));
137 
138  TRY(otp_ctrl_testutils_lock_partition(otp_ctrl, kDifOtpCtrlPartitionHwCfg1,
139  /*digest=*/0));
140  }
141  return OK_STATUS();
142 }
143 
144 status_t manuf_individualize_device_hw_cfg_check(
145  const dif_otp_ctrl_t *otp_ctrl) {
146  // TODO: Add DeviceId by comparing OTP flash value against the value reported
147  // by lc_ctrl. Consider erasing the data from the flash info pages.
148  bool is_locked0, is_locked1;
150  &is_locked0));
152  &is_locked1));
153  uint64_t digest0, digest1;
154  TRY(dif_otp_ctrl_get_digest(otp_ctrl, kDifOtpCtrlPartitionHwCfg0, &digest0));
155  TRY(dif_otp_ctrl_get_digest(otp_ctrl, kDifOtpCtrlPartitionHwCfg1, &digest1));
156 
157  return is_locked0 && is_locked1 ? OK_STATUS() : INTERNAL();
158 }
159 
160 status_t manuf_individualize_device_secret0(
161  const dif_lc_ctrl_t *lc_ctrl, const dif_otp_ctrl_t *otp_ctrl,
162  const manuf_cp_provisioning_data_t *provisioning_data) {
163  bool is_locked;
165  &is_locked));
166  if (is_locked) {
167  return OK_STATUS();
168  }
169 
170  TRY(otp_ctrl_testutils_dai_write64(otp_ctrl, kDifOtpCtrlPartitionSecret0,
171  kSecret0TestUnlockTokenOffset,
172  provisioning_data->test_unlock_token_hash,
173  kSecret0TestUnlockTokenSizeIn64BitWords));
174  TRY(otp_ctrl_testutils_dai_write64(otp_ctrl, kDifOtpCtrlPartitionSecret0,
175  kSecret0TestExitTokenOffset,
176  provisioning_data->test_exit_token_hash,
177  kSecret0TestExitTokenSizeIn64BitWords));
178 
179  TRY(otp_ctrl_testutils_lock_partition(otp_ctrl, kDifOtpCtrlPartitionSecret0,
180  /*digest=*/0));
181 
182  return OK_STATUS();
183 }
184 
185 status_t manuf_individualize_device_secret0_check(
186  const dif_otp_ctrl_t *otp_ctrl) {
187  bool is_locked;
189  &is_locked));
190  return is_locked ? OK_STATUS() : INTERNAL();
191 }