Software APIs
flash_ctrl_lc_rw_en_test.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 
13 #include "sw/device/lib/testing/flash_ctrl_testutils.h"
14 #include "sw/device/lib/testing/test_framework/check.h"
16 
18 
19 static dif_flash_ctrl_state_t flash;
20 static dif_keymgr_t keymgr;
21 static dif_kmac_t kmac;
22 static dif_lc_ctrl_t lc;
23 static dif_otp_ctrl_t otp;
24 
25 OTTF_DEFINE_TEST_CONFIG();
26 
27 enum {
28  kFlashInfoPageIdCreatorSecret = 1,
29  kFlashInfoPageIdOwnerSecret = 2,
30  kFlashInfoPageIdIsoPart = 3,
31  kPartSize = 16,
32  kBankId = 0,
33  kPartitionId = 0,
34 };
35 
36 // Random data to read/write to flash partitions.
37 
38 const uint32_t kCreatorSecret[kPartSize] = {
39  0xb295d21b, 0xecdfbdcd, 0x67e7ab2d, 0x6f660b08, 0x273bf65c, 0xe80f1695,
40  0x586b80db, 0xc3dba27e, 0xdc124c5d, 0xb01ccd52, 0x815713e1, 0x31a141b2,
41  0x2124be3b, 0x299a6f2a, 0x1f2a4741, 0x1a073cc0,
42 };
43 
44 const uint32_t kOwnerSecret[kPartSize] = {
45  0x69e705a0, 0x65c2ec6b, 0x04b0b634, 0x59313526, 0x1858aee1, 0xd49f3ba9,
46  0x230bcd38, 0xc1eb6b3e, 0x68c15e3b, 0x024d02a9, 0x0b062ae4, 0x334dd155,
47  0x53fdbf8a, 0x3792f1e2, 0xee317161, 0x33b19bf3,
48 };
49 
50 const uint32_t kIsoPartData[kPartSize] = {
51  0x2b78dbf5, 0x3e6e5a00, 0xbf82c6d5, 0x68d8e33f, 0x9c524bbc, 0xac5beeef,
52  0x1287ca5a, 0x12b61419, 0x872e709f, 0xf91b7c0c, 0x18312a1f, 0x325cef9a,
53  0x19fefa95, 0x4ceb421b, 0xa57d74c4, 0xaf1d723d,
54 };
55 
56 typedef enum check_id {
57  // Unprovisioned state checks.
58  kCheckIdUnprovisionedCreatorSeed = 0,
59  kCheckIdUnprovisonedOwnerSeed,
60  kCheckIdLcDevIsoPartAccess,
61 
62  // Provisioned state checks.
63  kCheckIdProvisionedCreatorSeed,
64  kCheckIdProvisionedOwnerSeed,
65  kCheckIdLcProdIsoPartAccess,
66 } check_id_t;
67 
68 typedef struct partition_check_cfg {
69  // Test identifier.
70  check_id_t check_id;
71 
72  // Page ID of the partition to check.
73  uint32_t page_id;
74 
75  // Data to write to the partition.
76  const uint32_t *data;
77 
78  // Size of the data to write.
79  uint32_t size;
80 
81  // Whether to write to the partition.
82  bool do_write;
83 
84  // Whether to expect the read operation to succeed.
85  bool expect_read_ok;
86 
87  // Whether to read from the partition.
88  bool do_read;
89 
90  // Whether to expect the write operation to succeed.
91  bool expect_write_ok;
93 
94 static const partition_check_cfg_t kTest[] = {
95  [kCheckIdUnprovisionedCreatorSeed] =
96  {
97  .check_id = kCheckIdUnprovisionedCreatorSeed,
98  .page_id = kFlashInfoPageIdCreatorSecret,
99  .data = kCreatorSecret,
100  .size = kPartSize,
101  .do_write = true,
102  .expect_write_ok = true,
103  .do_read = true,
104  .expect_read_ok = true,
105  },
106  [kCheckIdUnprovisonedOwnerSeed] =
107  {
108  .check_id = kCheckIdUnprovisonedOwnerSeed,
109  .page_id = kFlashInfoPageIdOwnerSecret,
110  .data = kOwnerSecret,
111  .size = kPartSize,
112  .do_write = true,
113  .expect_write_ok = true,
114  .do_read = true,
115  .expect_read_ok = true,
116  },
117  [kCheckIdLcDevIsoPartAccess] =
118  {
119  .check_id = kCheckIdLcDevIsoPartAccess,
120  .page_id = kFlashInfoPageIdIsoPart,
121  .data = kIsoPartData,
122  .size = kPartSize,
123  .do_write = true,
124  .expect_write_ok = true,
125  .do_read = true,
126  .expect_read_ok = false,
127  },
128  [kCheckIdProvisionedCreatorSeed] =
129  {
130  .check_id = kCheckIdProvisionedCreatorSeed,
131  .page_id = kFlashInfoPageIdCreatorSecret,
132  .data = kCreatorSecret,
133  .size = kPartSize,
134  .do_write = true,
135  .expect_write_ok = false,
136  .do_read = false,
137  .expect_read_ok = false,
138  },
139  [kCheckIdProvisionedOwnerSeed] =
140  {
141  .check_id = kCheckIdProvisionedOwnerSeed,
142  .page_id = kFlashInfoPageIdOwnerSecret,
143  .data = kOwnerSecret,
144  .size = kPartSize,
145  .do_write = true,
146  .expect_write_ok = true,
147  .do_read = true,
148  .expect_read_ok = true,
149  },
150  [kCheckIdLcProdIsoPartAccess] =
151  {
152  .check_id = kCheckIdLcProdIsoPartAccess,
153  .page_id = kFlashInfoPageIdIsoPart,
154  .data = kIsoPartData,
155  .size = kPartSize,
156  .do_write = false,
157  .expect_write_ok = false,
158  .do_read = true,
159  .expect_read_ok = true,
160  },
161 };
162 
163 /**
164  * Initializes all DIF handles for each peripheral used in this test.
165  */
166 static void init_peripheral_handles(void) {
167  CHECK_DIF_OK(dif_keymgr_init(
169  CHECK_DIF_OK(dif_otp_ctrl_init(
171  CHECK_DIF_OK(
172  dif_kmac_init(mmio_region_from_addr(TOP_EARLGREY_KMAC_BASE_ADDR), &kmac));
173  CHECK_DIF_OK(dif_lc_ctrl_init(
175  CHECK_DIF_OK(dif_flash_ctrl_init_state(
177 }
178 
179 static void partition_check(const partition_check_cfg_t cfg) {
180  uint32_t address = 0;
181  CHECK_STATUS_OK(flash_ctrl_testutils_info_region_setup(
182  &flash, cfg.page_id, kBankId, kPartitionId, &address));
183 
184  if (cfg.do_write) {
185  status_t result = flash_ctrl_testutils_erase_and_write_page(
186  &flash, address, kPartitionId, cfg.data, kDifFlashCtrlPartitionTypeInfo,
187  cfg.size);
188 
189  if (cfg.expect_write_ok) {
190  CHECK_STATUS_OK(result);
191  } else {
192  CHECK_STATUS_NOT_OK(result);
193  }
194  }
195 
196  if (cfg.do_read) {
197  uint32_t readback_data[cfg.size];
198  status_t result =
199  flash_ctrl_testutils_read(&flash, address, kPartitionId, readback_data,
200  kDifFlashCtrlPartitionTypeInfo, cfg.size, 0);
201 
202  if (cfg.expect_read_ok) {
203  CHECK_STATUS_OK(result);
204  CHECK_ARRAYS_EQ(cfg.data, readback_data, cfg.size);
205  } else {
206  CHECK_STATUS_NOT_OK(result);
207  CHECK_ARRAYS_NE(cfg.data, readback_data, cfg.size);
208  }
209  }
210 }
211 
212 // Advance the keymgr state to the expected state.
213 static void keymgr_advance_state(dif_keymgr_t *keymgr,
215  dif_keymgr_state_t expected_state) {
216  CHECK_DIF_OK(dif_keymgr_advance_state(keymgr, params));
217  dif_keymgr_status_codes_t keymgr_status_codes;
218  do {
219  CHECK_DIF_OK(dif_keymgr_get_status_codes(keymgr, &keymgr_status_codes));
220  } while (!(keymgr_status_codes & kDifKeymgrStatusCodeIdle));
221 
222  dif_keymgr_state_t keymgr_state;
223  CHECK_DIF_OK(dif_keymgr_get_state(keymgr, &keymgr_state));
224  LOG_INFO("Keymgr state: 0x%x", keymgr_state);
225  CHECK(keymgr_state == expected_state,
226  "Expected keymgr state not reached. got: %d, expected: %d",
227  keymgr_state, expected_state);
228 }
229 
230 // Provision the creator secrets in the OTP. This signals the DUT that the
231 // creator secrets are provisioned and the DUT will not allow further writes to
232 // the creator secrets.
233 static void dut_provision_creator_secrets(void) {
235  dif_otp_ctrl_status_t otp_status;
236  do {
237  CHECK_DIF_OK(dif_otp_ctrl_get_status(&otp, &otp_status));
238  } while (
240 }
241 
242 bool test_main(void) {
243  init_peripheral_handles();
244 
245  CHECK_DIF_OK(
247  .entropy_reseed_interval = 0xFFFF,
248  }));
249 
250  CHECK_DIF_OK(
252  .sideload = true,
253  .entropy_mode = kDifKmacEntropyModeSoftware,
254  }));
255 
256  // chip_sw_flash_ctrl_lc_rw_en_vseq steps through DEV and PROD LC states.
257  // DEV LC state:
258  // - Initial state: Unprovisioned.
259  // - Final state: Provisioned.
260  // PROD LC state:
261  // - Initial state: Provisioned.
262  //
263  // Even though the DUT does not support transitions from DEV to PROD, the
264  // test does this to check the expected behavior of the Isolation Partition.
265  // In practice, the DUT will go from TEST_UNLOCKED to either DEV or PROD.
266  dif_lc_ctrl_state_t curr_state;
267  CHECK_DIF_OK(dif_lc_ctrl_get_state(&lc, &curr_state));
268  if (curr_state == kDifLcCtrlStateDev) {
269  partition_check(kTest[kCheckIdUnprovisionedCreatorSeed]);
270  partition_check(kTest[kCheckIdUnprovisonedOwnerSeed]);
271  partition_check(kTest[kCheckIdLcDevIsoPartAccess]);
272 
273  // The DUT has not been personalized, so we expect this to fail.
274  keymgr_advance_state(&keymgr, NULL, kDifKeymgrStateInvalid);
275  dut_provision_creator_secrets();
276  } else if (curr_state == kDifLcCtrlStateProd) {
277  partition_check(kTest[kCheckIdProvisionedCreatorSeed]);
278  partition_check(kTest[kCheckIdProvisionedOwnerSeed]);
279  partition_check(kTest[kCheckIdLcProdIsoPartAccess]);
280  keymgr_advance_state(&keymgr, NULL, kDifKeymgrStateInitialized);
281 
282  dif_keymgr_state_params_t params = {
283  .binding_value = {0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF},
284  .max_key_version = 0xFFFFFFFF};
285  keymgr_advance_state(&keymgr, &params, kDifKeymgrStateCreatorRootKey);
286  }
287 
288  test_status_set(kTestStatusInWfi);
290 
291  return true;
292 }