Software APIs
entropy_src_edn_reqs_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 
16 #include "sw/device/lib/dif/dif_rv_core_ibex.h"
18 #include "sw/device/lib/testing/aes_testutils.h"
19 #include "sw/device/lib/testing/alert_handler_testutils.h"
20 #include "sw/device/lib/testing/entropy_src_testutils.h"
21 #include "sw/device/lib/testing/entropy_testutils.h"
22 #include "sw/device/lib/testing/keymgr_testutils.h"
23 #include "sw/device/lib/testing/otp_ctrl_testutils.h"
24 #include "sw/device/lib/testing/pwrmgr_testutils.h"
25 #include "sw/device/lib/testing/test_framework/check.h"
27 #include "sw/device/tests/otbn_randomness_impl.h"
28 
29 #include "alert_handler_regs.h" // Generated.
31 
32 static dif_aes_t aes;
33 static dif_csrng_t csrng;
34 static dif_edn_t edn0;
35 static dif_edn_t edn1;
36 static dif_entropy_src_t entropy_src;
37 static dif_kmac_t kmac;
38 static dif_keymgr_t kmgr;
39 static dif_otbn_t otbn;
40 static dif_otp_ctrl_t otp;
41 static dif_pwrmgr_t pwrmgr;
42 static dif_rv_core_ibex_t ibex;
43 static dif_alert_handler_t alert_handler;
44 static dif_rv_core_ibex_fpga_info_t fpga_info;
45 
46 enum {
47  kFpgaLoop = 5,
48 };
49 
50 OTTF_DEFINE_TEST_CONFIG();
51 
52 /**
53  * Trigger an reseed operation.
54  *
55  * @param aes Aes dif handle.
56  */
57 static void aes_test(const dif_aes_t *aes) {
58  LOG_INFO("%s", __func__);
59 
60  dif_aes_transaction_t transaction = {
61  .operation = kDifAesOperationEncrypt,
62  .mode = kDifAesModeEcb,
63  .key_len = kDifAesKey128,
64  .key_provider = kDifAesKeySideload,
65  .mask_reseeding = kDifAesReseedPerBlock,
66  .manual_operation = kDifAesManualOperationManual,
67  .reseed_on_key_change = false,
68  .ctrl_aux_lock = false,
69  };
70  CHECK_DIF_OK(dif_aes_start(aes, &transaction, /*key=*/NULL, /*iv=*/NULL));
71  CHECK_DIF_OK(dif_aes_trigger(aes, kDifAesTriggerPrngReseed));
72 }
73 
74 /**
75  * Configure the kmac to use entropy from edn to request entropy.
76  */
77 static void kmac_test(dif_kmac_t *kmac) {
78  LOG_INFO("%s", __func__);
79 
81  .entropy_mode = kDifKmacEntropyModeEdn,
82  .entropy_fast_process = kDifToggleDisabled,
83  };
84  CHECK_DIF_OK(dif_kmac_configure(kmac, config));
85 }
86 
87 /**
88  * Configure the otp to request entropy from the edn.
89  */
90 static void otp_ctrl_test(const dif_otp_ctrl_t *otp) {
91  LOG_INFO("%s", __func__);
92  // In the owner stage, the OTP direct access interface is blocked by the ePMP
93  // so we cannot run this test.
94  if (kBootStage == kBootStageOwner) {
95  return;
96  }
97 
98  // For security reasons, the LFSR is periodically reseeded with entropy coming
99  // from EDN. Setting the integrity period to a small value will make the
100  // otp_ctrl to fetch entropy from EDN.
101  dif_otp_ctrl_config_t config = {
102  .check_timeout = 100000,
103  .integrity_period_mask = 0x4,
104  .consistency_period_mask = 0x3ffffff,
105  };
106  CHECK_DIF_OK(dif_otp_ctrl_configure(otp, config));
107  CHECK_STATUS_OK(otp_ctrl_testutils_wait_for_dai(otp));
108 }
109 
110 /**
111  * Configure the reseed interval to a short period and
112  * advance to the `kDifKeymgrStateInitialized` to request entropy from the edn.
113  */
114 static void keymgr_test(const dif_keymgr_t *kmgr) {
115  /**
116  * Key manager can only be tested once per boot.
117  */
118  static bool tested = false;
119  dif_keymgr_state_t expected_stage_before = kBootStage == kBootStageOwner
122  dif_keymgr_state_t expected_stage_after = kBootStage == kBootStageOwner
125  if (!tested) {
126  LOG_INFO("%s", __func__);
127  dif_keymgr_config_t config = {.entropy_reseed_interval = 4};
128  CHECK_DIF_OK(dif_keymgr_configure(kmgr, config));
129  CHECK_STATUS_OK(keymgr_testutils_check_state(kmgr, expected_stage_before));
130  CHECK_DIF_OK(dif_keymgr_advance_state(kmgr, NULL));
131  CHECK_STATUS_OK(keymgr_testutils_wait_for_operation_done(kmgr));
132  CHECK_STATUS_OK(keymgr_testutils_check_state(kmgr, expected_stage_after));
133  tested = true;
134  }
135 }
136 
137 /**
138  * Read 4 words of rnd data to request entropy from the edn.
139  */
140 static void ibex_test(const dif_rv_core_ibex_t *ibex) {
141  LOG_INFO("%s", __func__);
142  for (size_t i = 0; i < 4; i++) {
143  uint32_t rnd;
144  CHECK_DIF_OK(dif_rv_core_ibex_read_rnd_data(ibex, &rnd));
145  }
146 }
147 
148 /**
149  * Configure the `alert_handler`to escalate up to phase 0.
150  */
151 static void alert_handler_configure(const dif_alert_handler_t *alert_handler) {
152  LOG_INFO("%s", __func__);
153 
154  dif_alert_handler_local_alert_t loc_alerts[] = {
155  kDifAlertHandlerLocalAlertAlertPingFail};
156  dif_alert_handler_class_t loc_alert_classes[] = {kDifAlertHandlerClassB};
157 
158  dif_alert_handler_escalation_phase_t esc_phases[] = {
160  .signal = 0,
161  .duration_cycles = 2000}};
162 
163  dif_alert_handler_class_config_t class_config = {
165  .accumulator_threshold = 0,
166  .irq_deadline_cycles = 10000,
167  .escalation_phases = esc_phases,
168  .escalation_phases_len = ARRAYSIZE(esc_phases),
169  .crashdump_escalation_phase = kDifAlertHandlerClassStatePhase1,
170  };
171 
172  dif_alert_handler_class_config_t class_configs[] = {class_config,
173  class_config};
174  dif_alert_handler_class_t classes[] = {kDifAlertHandlerClassA,
175  kDifAlertHandlerClassB};
176  dif_alert_handler_config_t config = {
177  .alerts = NULL,
178  .alert_classes = NULL,
179  .alerts_len = 0,
180  .local_alerts = loc_alerts,
181  .local_alert_classes = loc_alert_classes,
182  .local_alerts_len = ARRAYSIZE(loc_alerts),
183  .classes = classes,
184  .class_configs = class_configs,
185  .classes_len = ARRAYSIZE(class_configs),
186  .ping_timeout = 10,
187  };
188  CHECK_STATUS_OK(alert_handler_testutils_configure_all(alert_handler, config,
190 }
191 
192 /**
193  * Trigger fault in the pwrmgr in order to escalate the alert handler.
194  */
195 static void alert_handler_test(const dif_pwrmgr_t *pwrmgr) {
196  LOG_INFO("%s", __func__);
197 
198  dif_pwrmgr_alert_t alert = kDifPwrmgrAlertFatalFault;
199  CHECK_DIF_OK(dif_pwrmgr_alert_force(pwrmgr, alert));
200 }
201 
202 void test_initialize(void) {
203  CHECK_DIF_OK(dif_entropy_src_init(
205  CHECK_DIF_OK(dif_csrng_init(
207  CHECK_DIF_OK(
208  dif_edn_init(mmio_region_from_addr(TOP_EARLGREY_EDN0_BASE_ADDR), &edn0));
209  CHECK_DIF_OK(
210  dif_edn_init(mmio_region_from_addr(TOP_EARLGREY_EDN1_BASE_ADDR), &edn1));
211  CHECK_DIF_OK(dif_rv_core_ibex_init(
213  CHECK_DIF_OK(dif_pwrmgr_init(
215  CHECK_DIF_OK(dif_keymgr_init(
217  CHECK_DIF_OK(
218  dif_otbn_init(mmio_region_from_addr(TOP_EARLGREY_OTBN_BASE_ADDR), &otbn));
219  CHECK_DIF_OK(dif_otp_ctrl_init(
221  CHECK_DIF_OK(
223  CHECK_DIF_OK(
224  dif_kmac_init(mmio_region_from_addr(TOP_EARLGREY_KMAC_BASE_ADDR), &kmac));
225  CHECK_DIF_OK(dif_alert_handler_init(
227  &alert_handler));
228 }
229 
230 status_t execute_test(void) {
231  CHECK_DIF_OK(dif_rv_core_ibex_read_fpga_info(&ibex, &fpga_info));
232  uint32_t loop = (fpga_info != 0) ? kFpgaLoop : 1;
233 
234  for (size_t i = 0; i < loop; ++i) {
235  LOG_INFO("Entropy src test %d/%d", i, loop);
236  alert_handler_test(&pwrmgr);
237  aes_test(&aes);
238  otbn_randomness_test_start(&otbn, /*iters=*/0);
239  keymgr_test(&kmgr);
240  otp_ctrl_test(&otp);
241  kmac_test(&kmac);
242  ibex_test(&ibex);
243 
244  AES_TESTUTILS_WAIT_FOR_STATUS(&aes, kDifAesStatusIdle, /*value=*/true,
245  /*timeout_usec=*/100000);
246  CHECK(otbn_randomness_test_end(&otbn, /*skip_otbn_done_check=*/false));
247  CHECK_STATUS_OK(entropy_testutils_error_check(&csrng, &edn0, &edn1));
248  }
249 
250  return OK_STATUS();
251 }
252 
253 bool test_main(void) {
254  test_initialize();
255 
256  // The keymgr cannot be initialized after ROM_EXT because the flash controller
257  // is locked out with the ePMP.
258  if (kBootStage != kBootStageOwner) {
259  CHECK_STATUS_OK(keymgr_testutils_init_nvm_then_reset());
260  }
261 
262  alert_handler_configure(&alert_handler);
263  CHECK_STATUS_OK(entropy_testutils_auto_mode_init());
264 
265  // ensure health tests are actually running
266  CHECK_STATUS_OK(entropy_src_testutils_wait_for_state(
267  &entropy_src, kDifEntropySrcMainFsmStateContHTRunning));
268 
269  return status_ok(execute_test());
270 }