Software APIs
edn_boot_mode.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 
10 #include "sw/device/lib/dif/dif_rv_core_ibex.h"
13 #include "sw/device/lib/testing/edn_testutils.h"
14 #include "sw/device/lib/testing/entropy_testutils.h"
16 #include "sw/device/lib/testing/rv_core_ibex_testutils.h"
17 #include "sw/device/lib/testing/test_framework/check.h"
19 #include "sw/device/tests/otbn_randomness_impl.h"
20 
21 #include "edn_regs.h" // Generated
23 
24 enum {
25  kEdnBootModeTimeout = (10 * 1000 * 1000),
26  kEdnBootModeOtbnRandomnessIterations = 1,
27 };
28 
29 static dif_entropy_src_t entropy_src;
30 static dif_csrng_t csrng;
31 static dif_edn_t edn0;
32 static dif_edn_t edn1;
33 static dif_otbn_t otbn;
34 static dif_rv_core_ibex_t rv_core_ibex;
35 
37  .fips_enable = false,
38  .fips_flag = false,
39  .rng_fips = false,
40  .route_to_firmware = false,
41  .bypass_conditioner = false,
42  .single_bit_mode = kDifEntropySrcSingleBitModeDisabled,
43  .health_test_window_size = 0x0200,
44  .alert_threshold = 2,
45 };
46 
47 OTTF_DEFINE_TEST_CONFIG();
48 
49 // Initializes the peripherals used in this test.
50 static void init_peripherals(void) {
51  CHECK_DIF_OK(dif_entropy_src_init(
53  CHECK_DIF_OK(dif_csrng_init(
55  CHECK_DIF_OK(
57  CHECK_DIF_OK(
59  CHECK_DIF_OK(
60  dif_otbn_init(mmio_region_from_addr(TOP_EARLGREY_OTBN_BASE_ADDR), &otbn));
61  CHECK_DIF_OK(dif_rv_core_ibex_init(
63  &rv_core_ibex));
64 }
65 
66 static void configure_otbn(void) {
67  otbn_randomness_test_prepare(&otbn, kEdnBootModeOtbnRandomnessIterations);
68 }
69 
70 // configure the entropy complex
71 static status_t entropy_config(unsigned int round) {
72  // EDN params with high values for glen so we don't have to reseed.
73  dif_edn_auto_params_t edn_params0 = edn_testutils_auto_params_build(
74  true, /*res_itval=*/32, /*glen_val=*/4095);
75  dif_edn_auto_params_t edn_params1 = edn_testutils_auto_params_build(
76  true, /*res_itval=*/32, /*glen_val=*/4095);
77  // Disable the entropy complex.
78  TRY(entropy_testutils_stop_all());
79  // Enable ENTROPY_SRC in Non-FIPS/FIPS mode based on the value of round.
80  entropy_src_config.fips_enable = (round != 1);
81  CHECK_DIF_OK(dif_entropy_src_configure(&entropy_src, entropy_src_config,
83  // Enable CSRNG.
84  CHECK_DIF_OK(dif_csrng_configure(&csrng));
85 
86  if (round == 1) {
87  // Enable EDN1 (the one connected to OTBN RND) in boot-time request mode.
88  CHECK_DIF_OK(dif_edn_set_boot_mode(&edn1));
89  CHECK_DIF_OK(dif_edn_configure(&edn1));
90  EDN_TESTUTILS_WAIT_FOR_STATUS(&edn1, kDifEdnSmStateBootGenAckWait, true,
91  kEdnBootModeTimeout);
92  // Re-enable ENTROPY_SRC in FIPS mode.
93  CHECK_DIF_OK(dif_entropy_src_stop(&entropy_src));
97  CHECK_DIF_OK(dif_entropy_src_configure(&entropy_src, entropy_src_config,
99  // Enable EDN0 in auto request mode.
100  CHECK_DIF_OK(dif_edn_set_auto_mode(&edn0, edn_params0));
101  }
102 
103  if (round == 2) {
104  // Enable EDN1 (the one connected to OTBN RND) in auto request mode.
105  CHECK_DIF_OK(dif_edn_set_auto_mode(&edn1, edn_params1));
106  EDN_TESTUTILS_WAIT_FOR_STATUS(&edn1, kDifEdnSmStateAutoAckWait, true,
107  kEdnBootModeTimeout);
108  // Re-enable ENTROPY_SRC in Non-FIPS mode.
109  CHECK_DIF_OK(dif_entropy_src_stop(&entropy_src));
113  CHECK_DIF_OK(dif_entropy_src_configure(&entropy_src, entropy_src_config,
115  // Enable EDN0 in boot-time request mode.
116  CHECK_DIF_OK(dif_edn_set_boot_mode(&edn0));
117  CHECK_DIF_OK(dif_edn_configure(&edn0));
118  EDN_TESTUTILS_WAIT_FOR_STATUS(&edn0, kDifEdnSmStateBootGenAckWait, true,
119  kEdnBootModeTimeout);
120  // Set rng_fips and fips_flag to true for the next round.
123  }
124 
125  if (round == 3) {
126  // Enable both EDNs in auto request mode.
127  CHECK_DIF_OK(dif_edn_set_auto_mode(&edn0, edn_params0));
128  CHECK_DIF_OK(dif_edn_set_auto_mode(&edn1, edn_params1));
129  }
130 
131  return OK_STATUS();
132 }
133 
134 static void consume_entropy(unsigned int round,
135  dif_otbn_err_bits_t otbn_err_val,
136  dif_rv_core_ibex_rnd_status_t ibex_rnd_fips) {
137  uint32_t ibex_rnd_data;
138  dif_rv_core_ibex_rnd_status_t ibex_rnd_status;
139  dif_otbn_irq_state_snapshot_t intr_state;
140  CHECK_STATUS_OK(entropy_config(round));
141  // Launch an OTBN program consuming entropy via both
142  // the RND and the URND interface.
143  CHECK_STATUS_OK(otbn_testutils_execute(&otbn));
144  // Verify that the OTBN finishes with the expected error values
145  // and interrupt flags.
146  CHECK_STATUS_OK(otbn_testutils_wait_for_done(&otbn, otbn_err_val));
147  CHECK_DIF_OK(dif_otbn_irq_get_state(&otbn, &intr_state));
148  CHECK(intr_state & 0x1);
149  CHECK_DIF_OK(dif_otbn_irq_acknowledge_all(&otbn));
150  // Read rnd data through the IBEX and verify if the FIPS compliance
151  // status is as expected.
152  // The first read gets rid of leftover entropy from previous configurations
153  // of the entropy complex.
154  CHECK_DIF_OK(dif_rv_core_ibex_read_rnd_data(&rv_core_ibex, &ibex_rnd_data));
155  IBEX_SPIN_FOR(rv_core_ibex_testutils_is_rnd_data_valid(&rv_core_ibex),
156  kEdnBootModeTimeout);
157  CHECK_DIF_OK(
158  dif_rv_core_ibex_get_rnd_status(&rv_core_ibex, &ibex_rnd_status));
159  // The second read now contains the entropy from the current configuration.
160  CHECK_DIF_OK(dif_rv_core_ibex_read_rnd_data(&rv_core_ibex, &ibex_rnd_data));
161  CHECK((ibex_rnd_status & kDifRvCoreIbexRndStatusFipsCompliant) ==
162  ibex_rnd_fips);
163 }
164 
165 bool test_main(void) {
166  init_peripherals();
167  // Prepare the OTBN for execution.
168  configure_otbn();
169  // Run the Procedure and check if EDN1 produces FIPS non-compliant entropy.
170  consume_entropy(/*round=*/1, kDifOtbnErrBitsRndFipsChkFail,
171  kDifRvCoreIbexRndStatusFipsCompliant);
172  // Run the Procedure and check if EDN0 produces FIPS non-compliant entropy.
173  consume_entropy(/*round=*/2, kDifOtbnErrBitsNoError, 0);
174  // Run the Procedure and check if both EDNs produce FIPS compliant entropy.
175  consume_entropy(/*round=*/3, kDifOtbnErrBitsNoError,
176  kDifRvCoreIbexRndStatusFipsCompliant);
177 
178  return true;
179 }