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