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