Software APIs
personalize_functest.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/lib/base/status.h"
10 #include "sw/device/lib/testing/json/provisioning_data.h"
11 #include "sw/device/lib/testing/rstmgr_testutils.h"
12 #include "sw/device/lib/testing/test_framework/check.h"
14 #include "sw/device/lib/testing/test_framework/ujson_ottf.h"
15 #include "sw/device/lib/ujson/ujson.h"
16 #include "sw/device/silicon_creator/lib/attestation.h"
17 #include "sw/device/silicon_creator/lib/drivers/retention_sram.h"
18 #include "sw/device/silicon_creator/manuf/lib/flash_info_fields.h"
19 #include "sw/device/silicon_creator/manuf/lib/personalize.h"
20 
22 
23 OTTF_DEFINE_TEST_CONFIG(.enable_uart_flow_control = true);
24 
25 /**
26  * DIF Handles.
27  *
28  * Keep this list sorted in alphabetical order.
29  */
30 static dif_flash_ctrl_state_t flash_state;
31 static dif_lc_ctrl_t lc_ctrl;
32 static dif_otp_ctrl_t otp_ctrl;
33 static dif_rstmgr_t rstmgr;
34 
35 /**
36  * Initializes all DIF handles used in this module.
37  */
38 static status_t peripheral_handles_init(void) {
40  &flash_state,
42  TRY(dif_lc_ctrl_init(
44  TRY(dif_otp_ctrl_init(
47  &rstmgr));
48  return OK_STATUS();
49 }
50 
51 /**
52  * Perform software reset.
53  */
54 static void sw_reset(void) {
55  rstmgr_testutils_reason_clear();
56  CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr));
58 }
59 
60 static status_t check_array_non_zero(uint32_t *array, size_t num_words) {
61  for (size_t i = 0; i < num_words; ++i) {
62  if (array[i] == 0) {
63  return INTERNAL();
64  }
65  }
66  return OK_STATUS();
67 }
68 
69 bool test_main(void) {
70  ujson_t uj = ujson_ottf_console();
71  CHECK_STATUS_OK(peripheral_handles_init());
72 
73  // If we are in the RMA state, this means that the personalization is complete
74  // and that the host has issued an LC transition to the RMA state. To allow
75  // the host to connect over JTAG and check that we have indeed reached this
76  // state, just spin to prevent a reboot.
78  CHECK_DIF_OK(dif_lc_ctrl_get_state(&lc_ctrl, &lc_state));
79  if (lc_state == kDifLcCtrlStateRma) {
80  LOG_INFO("Now in RMA state, spinning for host to connect over JTAG.");
81  // Wait in a loop so that OpenOCD can connect to the TAP without the ROM
82  // resetting the chip.
83  // Abort simply forever loops on a wait_for_interrupt.
84  abort();
85  }
86 
87  dif_rstmgr_reset_info_bitfield_t info = rstmgr_testutils_reason_get();
88  if (info & kDifRstmgrResetInfoPor) {
89  // Provision the OTP SECRET1 partition.
90  if (!status_ok(manuf_personalize_device_secret1_check(&otp_ctrl))) {
91  LOG_INFO("Provisioning OTP SECRET1 ...");
92  CHECK_STATUS_OK(manuf_personalize_device_secret1(&lc_ctrl, &otp_ctrl));
93  // Wait in a loop so that the test harness can trigger a second bootstrap
94  // operation. This is required because the flash scrambling setting may
95  // have changed in OTP.
96  // The following log message is polled in the host side of this test.
97  LOG_INFO("Provisioning OTP SECRET1 Done ...");
98  abort();
99  }
100 
101  // Provision the OTP SECRET2 partition and flash info pages.
102  if (!status_ok(manuf_personalize_device_secrets_check(&otp_ctrl))) {
103  lc_token_hash_t token_hash;
104  // Wait for host the host generated RMA unlock token hash to arrive over
105  // the console.
106  LOG_INFO("Waiting For RMA Unlock Token Hash ...");
107 
108  CHECK_STATUS_OK(
109  UJSON_WITH_CRC(ujson_deserialize_lc_token_hash_t, &uj, &token_hash));
110 
111  // Perform OTP and flash info writes.
112  CHECK_STATUS_OK(manuf_personalize_device_secrets(&flash_state, &lc_ctrl,
113  &otp_ctrl, &token_hash));
114  LOG_INFO("Provisioning flash info asymmetric keygen seeds ...");
115  CHECK_STATUS_OK(manuf_personalize_flash_asymm_key_seed(
116  &flash_state, kFlashInfoFieldUdsAttestationKeySeed,
117  kAttestationSeedWords));
118  CHECK_STATUS_OK(manuf_personalize_flash_asymm_key_seed(
119  &flash_state, kFlashInfoFieldCdi0AttestationKeySeed,
120  kAttestationSeedWords));
121  CHECK_STATUS_OK(manuf_personalize_flash_asymm_key_seed(
122  &flash_state, kFlashInfoFieldCdi1AttestationKeySeed,
123  kAttestationSeedWords));
124 
125  // Read the attestation key seed fields to ensure they are non-zero.
126  uint32_t uds_attestation_key_seed[kAttestationSeedWords];
127  uint32_t cdi_0_attestation_key_seed[kAttestationSeedWords];
128  uint32_t cdi_1_attestation_key_seed[kAttestationSeedWords];
129  CHECK_STATUS_OK(manuf_flash_info_field_read(
130  &flash_state, kFlashInfoFieldUdsAttestationKeySeed,
131  uds_attestation_key_seed, kAttestationSeedWords));
132  CHECK_STATUS_OK(check_array_non_zero(uds_attestation_key_seed,
133  kAttestationSeedWords));
134  CHECK_STATUS_OK(manuf_flash_info_field_read(
135  &flash_state, kFlashInfoFieldCdi0AttestationKeySeed,
136  cdi_0_attestation_key_seed, kAttestationSeedWords));
137  CHECK_STATUS_OK(check_array_non_zero(cdi_0_attestation_key_seed,
138  kAttestationSeedWords));
139  CHECK_STATUS_OK(manuf_flash_info_field_read(
140  &flash_state, kFlashInfoFieldCdi1AttestationKeySeed,
141  cdi_1_attestation_key_seed, kAttestationSeedWords));
142  CHECK_STATUS_OK(check_array_non_zero(cdi_1_attestation_key_seed,
143  kAttestationSeedWords));
144  LOG_INFO(
145  "Finished provisioning OTP SECRET2 and keymgr flash info pages ...");
146 
147  // Reset the chip to activate the OTP partitions and flash pages.
148  sw_reset();
149  }
150  } else if (info == kDifRstmgrResetInfoSw) {
151  // Wait in a loop so that OpenOCD can connect to the TAP without the ROM
152  // resetting the chip.
153  LOG_INFO("Spinning for host to connect over JTAG.");
154  abort();
155  } else {
156  LOG_FATAL("Unexpected reset reason: %08x", info);
157  }
158 
159  return true;
160 }