Software APIs
keymgr_testutils.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/testing/keymgr_testutils.h"
6 
15 #include "sw/device/lib/testing/entropy_testutils.h"
16 #include "sw/device/lib/testing/flash_ctrl_testutils.h"
17 #include "sw/device/lib/testing/kmac_testutils.h"
18 #include "sw/device/lib/testing/otp_ctrl_testutils.h"
19 #include "sw/device/lib/testing/rstmgr_testutils.h"
20 #include "sw/device/lib/testing/test_framework/check.h"
22 #include "sw/device/silicon_creator/lib/drivers/retention_sram.h"
23 
25 
26 #define MODULE_ID MAKE_MODULE_ID('k', 'm', 't')
27 
28 enum {
29  /** Flash Secret partition ID. */
30  kFlashInfoPartitionId = 0,
31 
32  /** Secret partition flash bank ID. */
33  kFlashInfoBankId = 0,
34 
35  /** Creator Secret flash info page ID. */
36  kFlashInfoPageIdCreatorSecret = 1,
37 
38  /** Owner Secret flash info page ID. */
39  kFlashInfoPageIdOwnerSecret = 2,
40 };
41 
42 const static char *kKeymgrStageNames[] = {
43  [kDifKeymgrStateReset] = "Reset",
44  [kDifKeymgrStateInitialized] = "Init",
45  [kDifKeymgrStateCreatorRootKey] = "CreatorRootKey",
46  [kDifKeymgrStateOwnerIntermediateKey] = "OwnerIntKey",
47  [kDifKeymgrStateOwnerRootKey] = "OwnerKey",
48  [kDifKeymgrStateDisabled] = "Disabled",
49  [kDifKeymgrStateInvalid] = "Invalid",
50 };
51 
52 static status_t write_info_page(dif_flash_ctrl_state_t *flash, uint32_t page_id,
53  const keymgr_testutils_secret_t *data,
54  bool scramble) {
55  uint32_t address = 0;
56  if (scramble) {
57  TRY(flash_ctrl_testutils_info_region_scrambled_setup(
58  flash, page_id, kFlashInfoBankId, kFlashInfoPartitionId, &address));
59  } else {
60  TRY(flash_ctrl_testutils_info_region_setup(
61  flash, page_id, kFlashInfoBankId, kFlashInfoPartitionId, &address));
62  }
63 
64  TRY(flash_ctrl_testutils_erase_and_write_page(
65  flash, address, kFlashInfoPartitionId, data->value,
66  kDifFlashCtrlPartitionTypeInfo, ARRAYSIZE(data->value)));
67 
68  keymgr_testutils_secret_t readback_data;
69  TRY(flash_ctrl_testutils_read(
70  flash, address, kFlashInfoPartitionId, readback_data.value,
71  kDifFlashCtrlPartitionTypeInfo, ARRAYSIZE(readback_data.value), 0));
72  TRY_CHECK(memcmp(data->value, readback_data.value, sizeof(data->value)) == 0);
73  return OK_STATUS();
74 }
75 
76 status_t keymgr_testutils_flash_init(
78  const keymgr_testutils_secret_t *creator_secret,
79  const keymgr_testutils_secret_t *owner_secret) {
80  // Initialize flash secrets.
81  write_info_page(flash, kFlashInfoPageIdCreatorSecret, creator_secret,
82  /*scramble=*/true);
83  write_info_page(flash, kFlashInfoPageIdOwnerSecret, owner_secret,
84  /*scramble=*/true);
85  return OK_STATUS();
86 }
87 
88 static status_t check_lock_otp_partition(void) {
89  dif_otp_ctrl_t otp;
90  TRY(dif_otp_ctrl_init(
92 
93  bool is_computed;
95  &is_computed));
96  if (is_computed) {
97  uint64_t digest;
99  LOG_INFO("OTP partition locked. Digest: %x-%x", ((uint32_t *)&digest)[0],
100  ((uint32_t *)&digest)[1]);
101  return OK_STATUS();
102  }
103 
104  TRY(otp_ctrl_testutils_lock_partition(&otp, kDifOtpCtrlPartitionSecret2, 0));
105  return OK_STATUS();
106 }
107 
108 static status_t dif_init(dif_keymgr_t *keymgr, dif_kmac_t *kmac) {
109  // Initialize KMAC in preparation for keymgr use.
110  TRY(dif_kmac_init(mmio_region_from_addr(TOP_EARLGREY_KMAC_BASE_ADDR), kmac));
111 
112  // We shouldn't use the KMAC block's default entropy setting for keymgr, so
113  // configure it to use software entropy (and a sideloaded key, although it
114  // shouldn't matter here and tests should reconfigure if needed).
115  TRY(kmac_testutils_config(kmac, /*sideload=*/true));
116 
117  // Initialize keymgr context.
119  keymgr));
120  return OK_STATUS();
121 }
122 
123 status_t keymgr_initialize_sim_dv(dif_keymgr_t *keymgr, dif_kmac_t *kmac) {
124  // Initialize keymgr and advance to CreatorRootKey state.
125  TRY(keymgr_testutils_startup(keymgr, kmac));
126  LOG_INFO("Keymgr entered CreatorRootKey State");
127  // Generate identity at CreatorRootKey (to follow same sequence and reuse
128  // chip_sw_keymgr_key_derivation_vseq.sv).
129  TRY(keymgr_testutils_generate_identity(
130  keymgr,
132  LOG_INFO("Keymgr generated identity at CreatorRootKey State");
133 
134  // Advance to OwnerIntermediateKey state and check that the state is correct.
135  // The sim_dv testbench expects this state.
136  TRY(keymgr_testutils_advance_state(keymgr, &kOwnerIntParams));
137  TRY(keymgr_testutils_check_state(keymgr,
139  LOG_INFO("Keymgr entered OwnerIntKey State");
140  return OK_STATUS();
141 }
142 
143 status_t keymgr_initialize_sival(dif_keymgr_t *keymgr, dif_kmac_t *kmac) {
144  dif_keymgr_state_t keymgr_state;
145  TRY(keymgr_testutils_try_startup(keymgr, kmac, &keymgr_state));
146 
147  if (keymgr_state == kDifKeymgrStateInitialized) {
148  TRY(keymgr_testutils_advance_state(keymgr, &kOwnerIntParams));
149  TRY(dif_keymgr_get_state(keymgr, &keymgr_state));
150  }
151 
152  if (keymgr_state == kDifKeymgrStateOwnerIntermediateKey) {
153  TRY(keymgr_testutils_advance_state(keymgr, &kOwnerRootKeyParams));
154  }
155 
156  return keymgr_testutils_check_state(keymgr, kDifKeymgrStateOwnerRootKey);
157 }
158 
159 status_t keymgr_testutils_initialize(dif_keymgr_t *keymgr, dif_kmac_t *kmac) {
160  if (kBootStage == kBootStageOwner) {
161  return keymgr_initialize_sival(keymgr, kmac);
162  }
163  // All other configurations use the sim_dv initialization.
164  return keymgr_initialize_sim_dv(keymgr, kmac);
165 }
166 
167 status_t keymgr_testutils_try_startup(dif_keymgr_t *keymgr, dif_kmac_t *kmac,
168  dif_keymgr_state_t *keymgr_state) {
169  TRY(dif_init(keymgr, kmac));
170 
171  // Check keymgr state. If initialized, there is no need to proceed with
172  // the initialization process.
173  TRY(dif_keymgr_get_state(keymgr, keymgr_state));
174 
175  if (*keymgr_state == kDifKeymgrStateInvalid ||
176  *keymgr_state == kDifKeymgrStateDisabled) {
177  LOG_INFO("Unexpected keymgr state: 0x%x", keymgr_state);
178  return INTERNAL();
179  }
180 
181  if (*keymgr_state == kDifKeymgrStateReset) {
182  TRY(keymgr_testutils_startup(keymgr, kmac));
183  TRY(dif_keymgr_get_state(keymgr, keymgr_state));
184  }
185 
186  return OK_STATUS();
187 }
188 
189 status_t keymgr_testutils_init_nvm_then_reset(void) {
191  dif_rstmgr_t rstmgr;
192 
194  &rstmgr));
195  const dif_rstmgr_reset_info_bitfield_t reset_info =
196  rstmgr_testutils_reason_get();
197 
198  // POR reset.
199  if (reset_info == kDifRstmgrResetInfoPor) {
200  LOG_INFO("Powered up for the first time, program flash");
201 
204 
205  TRY(keymgr_testutils_flash_init(&flash, &kCreatorSecret, &kOwnerSecret));
206 
207  TRY(check_lock_otp_partition());
208 
209  // Reboot device.
210  LOG_INFO("Requesting a reset to make OTP partitions accessible to keymgr");
211  rstmgr_testutils_reason_clear();
212  TRY(dif_rstmgr_software_device_reset(&rstmgr));
213 
214  // Wait here until device reset.
216 
217  // Should never reach this.
218  return INTERNAL();
219 
220  } else {
221  // Not POR reset: this function has done its job (or can't run because it's
222  // supposed to run after POR).
223  return OK_STATUS();
224  }
225 }
226 
227 status_t keymgr_testutils_startup(dif_keymgr_t *keymgr, dif_kmac_t *kmac) {
228  dif_rstmgr_t rstmgr;
229 
230  // Check the last word of the retention SRAM creator area to determine the
231  // type of the ROM.
232  bool is_using_test_rom =
233  retention_sram_get()
234  ->creator
235  .reserved[ARRAYSIZE((retention_sram_t){0}.creator.reserved) - 1] ==
237 
238  TRY(keymgr_testutils_init_nvm_then_reset());
239 
241  &rstmgr));
242  const dif_rstmgr_reset_info_bitfield_t info = rstmgr_testutils_reason_get();
243 
244  TRY_CHECK(info == kDifRstmgrResetInfoSw, "Unexpected reset reason: %08x",
245  info);
246 
247  LOG_INFO("Initializing entropy complex in Auto mode");
248 
249  TRY(entropy_testutils_auto_mode_init());
250 
251  LOG_INFO("Powered up for the second time, actuate keymgr and perform test.");
252 
253  TRY(dif_init(keymgr, kmac));
254 
255  // Advance to Initialized state.
256  TRY(keymgr_testutils_check_state(keymgr, kDifKeymgrStateReset));
257  TRY(keymgr_testutils_advance_state(keymgr, NULL));
258  TRY(keymgr_testutils_check_state(keymgr, kDifKeymgrStateInitialized));
259  LOG_INFO("Keymgr entered Init State");
260 
261  // Advance to CreatorRootKey state.
262  if (is_using_test_rom) {
263  LOG_INFO("Using test_rom, setting inputs and advancing state...");
264  TRY(keymgr_testutils_advance_state(keymgr, &kCreatorParams));
265  } else {
266  LOG_INFO("Using rom, only advancing state...");
267  TRY(dif_keymgr_advance_state_raw(keymgr));
268  TRY(keymgr_testutils_wait_for_operation_done(keymgr));
269  }
270  TRY(keymgr_testutils_check_state(keymgr, kDifKeymgrStateCreatorRootKey));
271  LOG_INFO("Keymgr entered CreatorRootKey State");
272 
273  // Identity generation is not really necessary for all tests, but it is
274  // added to make sure each test using this function is also compatible with
275  // the DV_WAIT sequences from keymgr_key_derivation vseq
276  TRY(keymgr_testutils_generate_identity(
277  keymgr,
279  LOG_INFO("Keymgr generated identity at CreatorRootKey State");
280 
281  return OK_STATUS();
282 }
283 
284 status_t keymgr_testutils_advance_state(
285  const dif_keymgr_t *keymgr, const dif_keymgr_state_params_t *params) {
286  TRY(dif_keymgr_advance_state(keymgr, params));
287  return keymgr_testutils_wait_for_operation_done(keymgr);
288 }
289 
290 status_t keymgr_testutils_check_state(const dif_keymgr_t *keymgr,
291  const dif_keymgr_state_t exp_state) {
292  dif_keymgr_state_t act_state;
293  TRY(dif_keymgr_get_state(keymgr, &act_state));
294  TRY_CHECK(act_state == exp_state,
295  "Keymgr in unexpected state: %x, expected to be %x", act_state,
296  exp_state);
297  return OK_STATUS();
298 }
299 
300 status_t keymgr_testutils_generate_identity(
301  const dif_keymgr_t *keymgr,
302  const dif_keymgr_identity_seed_params_t params) {
303  TRY(dif_keymgr_generate_identity_seed(keymgr, params));
304  return keymgr_testutils_wait_for_operation_done(keymgr);
305 }
306 
307 status_t keymgr_testutils_generate_versioned_key(
308  const dif_keymgr_t *keymgr,
309  const dif_keymgr_versioned_key_params_t params) {
310  TRY(dif_keymgr_generate_versioned_key(keymgr, params));
311  return keymgr_testutils_wait_for_operation_done(keymgr);
312 }
313 
314 status_t keymgr_testutils_disable(const dif_keymgr_t *keymgr) {
315  TRY(dif_keymgr_disable(keymgr));
316  return keymgr_testutils_wait_for_operation_done(keymgr);
317 }
318 
319 status_t keymgr_testutils_wait_for_operation_done(const dif_keymgr_t *keymgr) {
321  do {
322  TRY(dif_keymgr_get_status_codes(keymgr, &status));
323  } while (status == 0);
324  TRY_CHECK(status == kDifKeymgrStatusCodeIdle, "Unexpected status: %x",
325  status);
326  return OK_STATUS();
327 }
328 
329 status_t keymgr_testutils_max_key_version_get(const dif_keymgr_t *keymgr,
330  uint32_t *max_key_version) {
331  dif_keymgr_state_t keymgr_state;
332  TRY(dif_keymgr_get_state(keymgr, &keymgr_state));
333 
334  if (keymgr_state == kDifKeymgrStateInvalid ||
335  keymgr_state == kDifKeymgrStateDisabled ||
336  keymgr_state == kDifKeymgrStateReset) {
337  LOG_INFO("Unexpected keymgr state: 0x%x", keymgr_state);
338  return INTERNAL();
339  }
340 
342  TRY(dif_keymgr_read_max_key_version(keymgr, &versions));
343 
344  switch (keymgr_state) {
346  *max_key_version = versions.creator_max_key_version;
347  break;
349  *max_key_version = versions.owner_int_max_key_version;
350  break;
352  *max_key_version = versions.owner_max_key_version;
353  break;
354  default:
355  return INTERNAL();
356  }
357 
358  return OK_STATUS();
359 }
360 
361 status_t keymgr_testutils_state_string_get(const dif_keymgr_t *keymgr,
362  const char **stage_name) {
363  dif_keymgr_state_t state;
364  CHECK_DIF_OK(dif_keymgr_get_state(keymgr, &state));
365 
366  if (state >= ARRAYSIZE(kKeymgrStageNames)) {
367  *stage_name = NULL;
368  return INTERNAL();
369  }
370 
371  *stage_name = kKeymgrStageNames[state];
372  return OK_STATUS();
373 }