Software APIs
personalize.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/personalize.h"
6 
7 #include "sw/device/lib/base/multibits.h"
8 #include "sw/device/lib/base/status.h"
9 #include "sw/device/lib/crypto/drivers/entropy.h"
13 #include "sw/device/lib/testing/flash_ctrl_testutils.h"
14 #include "sw/device/lib/testing/json/provisioning_data.h"
15 #include "sw/device/lib/testing/lc_ctrl_testutils.h"
16 #include "sw/device/lib/testing/otp_ctrl_testutils.h"
17 #include "sw/device/lib/testing/test_framework/check.h"
18 #include "sw/device/silicon_creator/lib/attestation.h"
19 #include "sw/device/silicon_creator/manuf/lib/flash_info_fields.h"
20 #include "sw/device/silicon_creator/manuf/lib/otp_fields.h"
21 #include "sw/device/silicon_creator/manuf/lib/util.h"
22 
23 #include "otp_ctrl_regs.h" // Generated.
24 
25 static_assert(OTP_CTRL_PARAM_CREATOR_ROOT_KEY_SHARE0_SIZE ==
26  OTP_CTRL_PARAM_CREATOR_ROOT_KEY_SHARE1_SIZE,
27  "Detected Root key share size mismatch");
28 static_assert(OTP_CTRL_PARAM_RMA_TOKEN_SIZE == 16,
29  "RMA token is not 128 bits (i.e., one AES block), re-evaluate "
30  "padding / AES mode. Additionally, update ujson struct "
31  "definition for the wrapped RMA unlock token.");
32 
33 /**
34  * Performs sanity check of buffers holding a masked secret.
35  *
36  * @param share0 Share 0 buffer.
37  * @param share1 Share 1 buffer.
38  * @param len Number of 64bit words to sanity check.
39  * @return OK_STATUS if share0 ^ share1 is not zero and if both shares don't
40  * contain non-zero and non-all-FFs 64bit words.
41  */
43 static status_t shares_check(uint64_t *share0, uint64_t *share1, size_t len) {
44  bool found_error = false;
45  for (size_t i = 0; i < len; ++i) {
46  found_error |= share0[i] == share1[i];
47  found_error |= share0[i] == UINT64_MAX || share0[i] == 0;
48  found_error |= share1[i] == UINT64_MAX || share1[0] == 0;
49  }
50  return found_error ? INTERNAL() : OK_STATUS();
51 }
52 
54 status_t manuf_personalize_flash_asymm_key_seed(
55  dif_flash_ctrl_state_t *flash_state, flash_info_field_t field, size_t len) {
56  TRY(entropy_csrng_instantiate(/*disable_trng_input=*/kHardenedBoolFalse,
57  /*seed_material=*/NULL));
58 
59  uint32_t seed[kAttestationSeedWords];
60  TRY(entropy_csrng_generate(/*seed_material=*/NULL, seed, len,
61  /*fips_check=*/kHardenedBoolTrue));
62  TRY(entropy_csrng_uninstantiate());
63 
64  // Since all seeds are on stored consecutively on the same flash info page,
65  // we only need to set up the permissions on the page, and erase it once.
66  uint32_t byte_address = 0;
67  if (field.byte_offset == 0) {
68  TRY(flash_ctrl_testutils_info_region_scrambled_setup(
69  flash_state, field.page, field.bank, field.partition, &byte_address));
70  TRY(flash_ctrl_testutils_erase_and_write_page(
71  flash_state, byte_address, field.partition, seed,
72  kDifFlashCtrlPartitionTypeInfo, kAttestationSeedWords));
73  } else {
75  byte_address =
76  (field.page * device_info.bytes_per_page) + field.byte_offset;
77  TRY(flash_ctrl_testutils_write(flash_state, byte_address, field.partition,
78  seed, kDifFlashCtrlPartitionTypeInfo,
79  kAttestationSeedWords));
80  }
81 
82  uint32_t seed_result[kAttestationSeedWords];
83  TRY(flash_ctrl_testutils_read(flash_state, byte_address, field.partition,
84  seed_result, kDifFlashCtrlPartitionTypeInfo,
85  len,
86  /*delay=*/0));
87  bool found_error = false;
88  for (size_t i = 0; i < len; ++i) {
89  found_error |=
90  seed[i] == 0 || seed[i] == UINT32_MAX || seed[i] != seed_result[i];
91  }
92  return found_error ? INTERNAL() : OK_STATUS();
93 }
94 
95 /**
96  * Writes a device-generated keymgr seed to the corresponding flash info page.
97  *
98  * Entropy is extracted from the CSRNG instance and programmed into the target
99  * flash info page.
100  *
101  * @param flash_state Flash controller instance.
102  * @param field Info flash field location information.
103  * @param len The number of uint32_t words to program starting at the beginning
104  * of the target flash info field.
105  * @return OK_STATUS on success.
106  */
108 static status_t flash_keymgr_secret_seed_write(
109  dif_flash_ctrl_state_t *flash_state, flash_info_field_t field, size_t len) {
110  TRY(entropy_csrng_instantiate(/*disable_trng_input=*/kHardenedBoolFalse,
111  /*seed_material=*/NULL));
112 
113  uint32_t seed[kFlashInfoKeySeedSizeIn32BitWords];
114  TRY(entropy_csrng_generate(/*seed_material=*/NULL, seed, len,
115  /*fips_check*/ kHardenedBoolTrue));
116  TRY(entropy_csrng_uninstantiate());
117 
118  uint32_t address = 0;
119  TRY(flash_ctrl_testutils_info_region_scrambled_setup(
120  flash_state, field.page, field.bank, field.partition, &address));
121 
122  TRY(flash_ctrl_testutils_erase_and_write_page(
123  flash_state, address, field.partition, seed,
124  kDifFlashCtrlPartitionTypeInfo, len));
125 
126  uint32_t seed_result[kFlashInfoKeySeedSizeIn32BitWords];
127  TRY(flash_ctrl_testutils_read(flash_state, address, field.partition,
128  seed_result, kDifFlashCtrlPartitionTypeInfo,
129  len,
130  /*delay=*/0));
131  bool found_error = false;
132  for (size_t i = 0; i < len; ++i) {
133  found_error |=
134  seed[i] == 0 || seed[i] == UINT32_MAX || seed[i] != seed_result[i];
135  }
136  return found_error ? INTERNAL() : OK_STATUS();
137 }
138 
139 /**
140  * Configures the RMA unlock token and Silicon Creator seed secret shares in the
141  * SECRET2 OTP partition.
142  *
143  * Entropy is extracted from the CSRNG instance and programmed into the SECRET2
144  * OTP partition. The data needs to be programmed before the OTP SECRET2
145  * partition is locked and when the device is in DEV, PROD, or PROD_END
146  * lifecyle state.
147  *
148  * @param otp_ctrl OTP controller instance.
149  * @param rma_unlock_token_hash Hash of the RMA unlock token to store on chip.
150  * @return OK_STATUS on success.
151  */
153 static status_t otp_partition_secret2_configure(
154  const dif_otp_ctrl_t *otp_ctrl,
155  const lc_token_hash_t *rma_unlock_token_hash) {
156  TRY(entropy_csrng_instantiate(/*disable_trng_input=*/kHardenedBoolFalse,
157  /*seed_material=*/NULL));
158 
159  // Generate RootKey shares.
160  uint64_t share0[kRootKeyShareSizeIn64BitWords];
161  TRY(entropy_csrng_generate(/*seed_material=*/NULL, (uint32_t *)share0,
162  kRootKeyShareSizeIn32BitWords,
163  /*fips_check*/ kHardenedBoolTrue));
164  TRY(entropy_csrng_reseed(/*disable_trng_input=*/kHardenedBoolFalse,
165  /*seed_material=*/NULL));
166 
167  uint64_t share1[kRootKeyShareSizeIn64BitWords];
168  TRY(entropy_csrng_generate(/*seed_material=*/NULL, (uint32_t *)share1,
169  kRootKeyShareSizeIn32BitWords,
170  /*fips_check*/ kHardenedBoolTrue));
171  TRY(entropy_csrng_uninstantiate());
172 
173  TRY(shares_check(share0, share1, kRootKeyShareSizeIn64BitWords));
174 
175  // Provision RMA unlock token and RootKey shares into OTP.
176  TRY(otp_ctrl_testutils_dai_write64(
177  otp_ctrl, kDifOtpCtrlPartitionSecret2, kRmaUnlockTokenOffset,
178  rma_unlock_token_hash->hash, kRmaUnlockTokenSizeIn64BitWords));
179  TRY(otp_ctrl_testutils_dai_write64(otp_ctrl, kDifOtpCtrlPartitionSecret2,
180  kRootKeyOffsetShare0, share0,
181  kRootKeyShareSizeIn64BitWords));
182  TRY(otp_ctrl_testutils_dai_write64(otp_ctrl, kDifOtpCtrlPartitionSecret2,
183  kRootKeyOffsetShare1, share1,
184  kRootKeyShareSizeIn64BitWords));
185 
186  TRY(otp_ctrl_testutils_lock_partition(otp_ctrl, kDifOtpCtrlPartitionSecret2,
187  /*digest=*/0));
188 
189  return OK_STATUS();
190 }
191 
192 status_t manuf_personalize_device_secrets(
193  dif_flash_ctrl_state_t *flash_state, const dif_lc_ctrl_t *lc_ctrl,
194  const dif_otp_ctrl_t *otp_ctrl,
195  const lc_token_hash_t *rma_unlock_token_hash) {
196  // Check life cycle in either PROD, PROD_END, or DEV.
197  TRY(lc_ctrl_testutils_operational_state_check(lc_ctrl));
198 
199  // Skip provisioning of SECRET1 OTP partition if already done.
200  bool is_locked;
202  &is_locked));
203  if (is_locked) {
204  return OK_STATUS();
205  }
206 
207  // Check the SECRET1 partition is locked. Flash scrambling seeds must be
208  // provisioned before the keymgr seeds can be written to flash info pages, as
209  // these pages must be scrambled.
210  //
211  // Note: for SECRET1 partition to be provisioned, the HW_CFG1 partition
212  // must have been provisioned, and the CSRNG SW interface should have been
213  // enabled, so no need to check again here.
215  &is_locked));
216  if (!is_locked) {
217  return INTERNAL();
218  }
219 
220  // Re-initialize the entropy complex in continous mode. This also configures
221  // the entropy_src health checks in FIPS mode.
222  TRY(entropy_complex_init());
223 
224  // Provision secret Creator / Owner key seeds in flash.
225  // Provision CreatorSeed into target flash info page.
226  TRY(flash_keymgr_secret_seed_write(flash_state, kFlashInfoFieldCreatorSeed,
227  kFlashInfoKeySeedSizeIn32BitWords));
228  // Provision preliminary OwnerSeed into target flash info page (with
229  // expectation that SiliconOwner will rotate this value during ownership
230  // transfer).
231  TRY(flash_keymgr_secret_seed_write(flash_state, kFlashInfoFieldOwnerSeed,
232  kFlashInfoKeySeedSizeIn32BitWords));
233 
234  // Provision the OTP SECRET2 partition.
235  TRY(otp_partition_secret2_configure(otp_ctrl, rma_unlock_token_hash));
236 
237  return OK_STATUS();
238 }
239 
241 static status_t otp_secret_write(const dif_otp_ctrl_t *otp_ctrl,
242  uint32_t offset, size_t len) {
243  enum {
244  kBufferSize = 4,
245  };
246  if (len > kBufferSize) {
247  return INTERNAL();
248  }
249 
250  TRY(entropy_csrng_reseed(/*disable_trng_inpu=*/kHardenedBoolFalse,
251  /*seed_material=*/NULL));
252 
253  size_t len_in_32bit_words = len * 2;
254  uint64_t data[kBufferSize];
255  TRY(entropy_csrng_generate(/*seed_material=*/NULL, (uint32_t *)data,
256  len_in_32bit_words,
257  /*fips_check=*/kHardenedBoolTrue));
258 
259  bool found_error = false;
260  uint64_t prev_val = 0;
261  for (size_t i = 0; i < len; ++i) {
262  found_error |= data[i] == 0 || data[i] == UINT64_MAX || data[i] == prev_val;
263  prev_val = data[i];
264  }
265  if (found_error) {
266  return INTERNAL();
267  }
268 
269  TRY(otp_ctrl_testutils_dai_write64(otp_ctrl, kDifOtpCtrlPartitionSecret1,
270  offset, data, len));
271  return OK_STATUS();
272 }
273 
274 status_t manuf_personalize_device_secrets_check(
275  const dif_otp_ctrl_t *otp_ctrl) {
276  bool is_locked;
278  &is_locked));
279  return is_locked ? OK_STATUS() : INTERNAL();
280 }
281 
282 status_t manuf_personalize_device_secret1(const dif_lc_ctrl_t *lc_ctrl,
283  const dif_otp_ctrl_t *otp_ctrl) {
284  // Skip provisioning of SECRET1 OTP partition if already done.
285  bool is_locked;
287  &is_locked));
288  if (is_locked) {
289  return OK_STATUS();
290  }
291 
292  // Check that the HW_CFG0 OTP partition has been locked (and is activated).
294  &is_locked));
295  if (!is_locked) {
296  return INTERNAL();
297  }
298 
299  // Check that the HW_CFG1 OTP partition has been locked (and is activated).
301  &is_locked));
302  if (!is_locked) {
303  return INTERNAL();
304  }
305 
306  // Check that the CSRNG SW application interface is enabled in the HW_CFG1
307  // partition, as we cannot provision SECRET1 without access to the CSRNG.
308  uint32_t otp_hw_cfg1_settings;
309  TRY(otp_ctrl_testutils_dai_read32(otp_ctrl, kDifOtpCtrlPartitionHwCfg1,
310  kHwCfgEnSramIfetchOffset,
311  &otp_hw_cfg1_settings));
312  uint32_t csrng_sw_app_read =
313  bitfield_field32_read(otp_hw_cfg1_settings, kCsrngAppRead);
314  if (csrng_sw_app_read != kMultiBitBool8True) {
315  return INTERNAL();
316  }
317 
318  uint32_t dis_rv_dm_late_debug =
319  bitfield_field32_read(otp_hw_cfg1_settings, kDisRvDmLateDebug);
320  if (dis_rv_dm_late_debug != kMultiBitBool8True) {
321  return INTERNAL();
322  }
323 
324  TRY(entropy_complex_init());
325  TRY(entropy_csrng_instantiate(/*disable_trng_input=*/kHardenedBoolFalse,
326  /*seed_material=*/NULL));
327 
328  TRY(otp_secret_write(otp_ctrl, kSecret1FlashAddrKeySeedOffset,
329  kSecret1FlashAddrKeySeed64BitWords));
330  TRY(otp_secret_write(otp_ctrl, kSecret1FlashDataKeySeedOffset,
331  kSecret1FlashDataKeySeed64BitWords));
332  TRY(otp_secret_write(otp_ctrl, kSecret1SramDataKeySeedOffset,
333  kSecret1SramDataKeySeed64Bitwords));
334 
335  TRY(entropy_csrng_uninstantiate());
336  TRY(otp_ctrl_testutils_lock_partition(otp_ctrl, kDifOtpCtrlPartitionSecret1,
337  /*digest=*/0));
338 
339  return OK_STATUS();
340 }
341 
342 status_t manuf_personalize_device_secret1_check(
343  const dif_otp_ctrl_t *otp_ctrl) {
344  bool is_locked;
346  &is_locked));
347  return is_locked ? OK_STATUS() : INTERNAL();
348 }