Software APIs
entropy_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 #include "sw/device/lib/testing/entropy_testutils.h"
5 
7 #include "sw/device/lib/dif/dif_csrng_shared.h"
9 #include "sw/device/lib/testing/test_framework/check.h"
10 
11 #ifdef HAS_ENTROPY_SRC
13 #endif
14 
15 #define MODULE_ID MAKE_MODULE_ID('e', 'n', 'y')
16 
17 status_t entropy_testutils_entropy_src_init(void) {
18 #ifdef HAS_ENTROPY_SRC
19  dif_entropy_src_t entropy_src;
20  CHECK_DIF_OK(dif_entropy_src_init_from_dt(kDtEntropySrc, &entropy_src));
21  dif_entropy_src_config_t config = {
22  .fips_enable = true,
23  .fips_flag = true,
24  .rng_fips = true,
25  .route_to_firmware = false,
26  .bypass_conditioner = false,
27  .single_bit_mode = kDifEntropySrcSingleBitModeDisabled,
28  .health_test_window_size = 0x0200,
29  .alert_threshold = 2,
30  };
31  CHECK_DIF_OK(
32  dif_entropy_src_configure(&entropy_src, config, kDifToggleEnabled));
33 #endif
34  return OK_STATUS();
35 }
36 
37 status_t entropy_testutils_auto_mode_init(void) {
38  dif_csrng_t csrng;
39  dif_edn_t edn0;
40  dif_edn_t edn1;
41  CHECK_DIF_OK(dif_csrng_init_from_dt(kDtCsrng, &csrng));
42  CHECK_DIF_OK(dif_edn_init_from_dt(kDtEdn0, &edn0));
43  CHECK_DIF_OK(dif_edn_init_from_dt(kDtEdn1, &edn1));
44 
45  TRY(entropy_testutils_stop_all());
46 
47  // re-enable entropy src and csrng
48  TRY(entropy_testutils_entropy_src_init());
49  TRY(dif_csrng_configure(&csrng));
50 
51  // Re-enable EDN0 in auto mode.
53  &edn0,
55  // EDN0 provides lower-quality entropy. Let one generate command
56  // return 8
57  // blocks, and reseed every 32 generates.
58  .instantiate_cmd =
59  {
60  .cmd = csrng_cmd_header_build(kCsrngAppCmdInstantiate,
62  /*cmd_len=*/0,
63  /*generate_len=*/0),
64  .seed_material =
65  {
66  .len = 0,
67  },
68  },
69  .reseed_cmd =
70  {
71  .cmd = csrng_cmd_header_build(
72  kCsrngAppCmdReseed, kDifCsrngEntropySrcToggleEnable,
73  /*cmd_len=*/0, /*generate_len=*/0),
74  .seed_material =
75  {
76  .len = 0,
77  },
78  },
79  .generate_cmd =
80  {
81  // Generate 8 128-bit blocks.
82  .cmd = csrng_cmd_header_build(kCsrngAppCmdGenerate,
84  /*cmd_len=*/0,
85  /*generate_len=*/8),
86  .seed_material =
87  {
88  .len = 0,
89  },
90  },
91  // Reseed every 32 generates.
92  .reseed_interval = 32,
93  }));
94 
95  // Re-enable EDN1 in auto mode.
97  &edn1,
99  // EDN1 provides highest-quality entropy. Let one generate command
100  // return 1 block, and reseed after every generate.
101  .instantiate_cmd =
102  {
103  .cmd = csrng_cmd_header_build(kCsrngAppCmdInstantiate,
105  /*cmd_len=*/0,
106  /*generate_len=*/0),
107  .seed_material =
108  {
109  .len = 0,
110  },
111  },
112  .reseed_cmd =
113  {
114  .cmd = csrng_cmd_header_build(
115  kCsrngAppCmdReseed, kDifCsrngEntropySrcToggleEnable,
116  /*cmd_len=*/0, /*generate_len=*/0),
117  .seed_material =
118  {
119  .len = 0,
120  },
121  },
122  .generate_cmd =
123  {
124  // Generate 1 128-bit block.
125  .cmd = csrng_cmd_header_build(kCsrngAppCmdGenerate,
127  /*cmd_len=*/0,
128  /*generate_len=*/1),
129  .seed_material =
130  {
131  .len = 0,
132  },
133  },
134  // Reseed after every 4 generates.
135  .reseed_interval = 4,
136  }));
137  return OK_STATUS();
138 }
139 
140 status_t entropy_testutils_boot_mode_init(void) {
141  dif_csrng_t csrng;
142  dif_edn_t edn0;
143  dif_edn_t edn1;
144  CHECK_DIF_OK(dif_csrng_init_from_dt(kDtCsrng, &csrng));
145  CHECK_DIF_OK(dif_edn_init_from_dt(kDtEdn0, &edn0));
146  CHECK_DIF_OK(dif_edn_init_from_dt(kDtEdn1, &edn1));
147 
148  TRY(entropy_testutils_stop_all());
149 
150  TRY(entropy_testutils_entropy_src_init());
151  TRY(dif_csrng_configure(&csrng));
152  TRY(dif_edn_set_boot_mode(&edn0));
153  TRY(dif_edn_set_boot_mode(&edn1));
154  TRY(dif_edn_configure(&edn0));
155  TRY(dif_edn_configure(&edn1));
156  return OK_STATUS();
157 }
158 
159 status_t entropy_testutils_stop_csrng_edn(void) {
160  dif_csrng_t csrng;
161  dif_edn_t edn0;
162  dif_edn_t edn1;
163  CHECK_DIF_OK(dif_csrng_init_from_dt(kDtCsrng, &csrng));
164  CHECK_DIF_OK(dif_edn_init_from_dt(kDtEdn0, &edn0));
165  CHECK_DIF_OK(dif_edn_init_from_dt(kDtEdn1, &edn1));
166 
167  TRY(dif_edn_stop(&edn0));
168  TRY(dif_edn_stop(&edn1));
169  TRY(dif_csrng_stop(&csrng));
170  return OK_STATUS();
171 }
172 
173 status_t entropy_testutils_stop_all(void) {
174  CHECK_STATUS_OK(entropy_testutils_stop_csrng_edn());
175 
176 #ifdef HAS_ENTROPY_SRC
177  dif_entropy_src_t entropy_src;
178  CHECK_DIF_OK(dif_entropy_src_init_from_dt(kDtEntropySrc, &entropy_src));
179  TRY(dif_entropy_src_stop(&entropy_src));
180 #endif
181 
182  return OK_STATUS();
183 }
184 
185 status_t entropy_testutils_error_check(const dif_csrng_t *csrng,
186  const dif_edn_t *edn0,
187  const dif_edn_t *edn1) {
188  uint32_t err_code;
189  bool found_error = false;
190 
191 #ifdef HAS_ENTROPY_SRC
192  dif_entropy_src_t entropy_src;
193  CHECK_DIF_OK(dif_entropy_src_init_from_dt(kDtEntropySrc, &entropy_src));
194  TRY(dif_entropy_src_get_errors(&entropy_src, &err_code));
195  if (err_code) {
196  found_error = true;
197  LOG_ERROR("entropy_src status. err: 0x%x", err_code);
198  }
199 #endif
200 
203  if (status.cmd_sts != kDifCsrngCmdStsSuccess) {
204  found_error = true;
205  LOG_ERROR("csrng error status. err: 0x%x, kind: 0x%x", status.cmd_sts,
206  status.kind);
207  }
208 
209  uint32_t fifo_errors;
210  TRY(dif_edn_get_errors(edn0, &fifo_errors, &err_code));
211  if (err_code || fifo_errors) {
212  found_error = true;
213  LOG_ERROR("end0 error status. err: 0x%x, fifo_err: 0x%x", err_code,
214  fifo_errors);
215  }
216 
217  TRY(dif_edn_get_errors(edn1, &fifo_errors, &err_code));
218  if (err_code || fifo_errors) {
219  found_error = true;
220  LOG_ERROR("end1 error status. err: 0x%x, fifo_err: 0x%x", err_code,
221  fifo_errors);
222  }
223  TRY_CHECK(!found_error, "entropy_testutils_error_check fail");
224  return OK_STATUS();
225 }