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
17status_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));
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
37status_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.
52 TRY(dif_edn_set_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.
96 TRY(dif_edn_set_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
140status_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
159status_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
173status_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
185status_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
202 TRY(dif_csrng_get_cmd_interface_status(csrng, &status));
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}