blob: a4f3b1bd7c62aebe47db7c61f55e52352539c253 [file] [log] [blame]
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +02001/* BEGIN_HEADER */
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +00002#include "mbedtls/entropy.h"
Chris Jonesea0a8652021-03-09 19:11:19 +00003#include "entropy_poll.h"
Gilles Peskine72d40fc2020-04-14 21:28:42 +02004#include "mbedtls/md.h"
Mohammad Azim Khan67735d52017-04-06 11:55:43 +01005#include "string.h"
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +02006
Gilles Peskine449bd832023-01-11 14:50:10 +01007typedef enum {
Gilles Peskineed04a672019-10-08 14:37:27 +02008 DUMMY_CONSTANT_LENGTH, /* Output context->length bytes */
9 DUMMY_REQUESTED_LENGTH, /* Output whatever length was requested */
10 DUMMY_FAIL, /* Return an error code */
11} entropy_dummy_instruction;
12
Gilles Peskine449bd832023-01-11 14:50:10 +010013typedef struct {
Gilles Peskineed04a672019-10-08 14:37:27 +020014 entropy_dummy_instruction instruction;
15 size_t length; /* Length to return for DUMMY_CONSTANT_LENGTH */
16 size_t calls; /* Incremented at each call */
17} entropy_dummy_context;
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +020018
19/*
20 * Dummy entropy source
21 *
22 * If data is NULL, write exactly the requested length.
23 * Otherwise, write the length indicated by data or error if negative
24 */
Gilles Peskine449bd832023-01-11 14:50:10 +010025static int entropy_dummy_source(void *arg, unsigned char *output,
26 size_t len, size_t *olen)
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +020027{
Gilles Peskineed04a672019-10-08 14:37:27 +020028 entropy_dummy_context *context = arg;
29 ++context->calls;
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +020030
Gilles Peskine449bd832023-01-11 14:50:10 +010031 switch (context->instruction) {
Gilles Peskineed04a672019-10-08 14:37:27 +020032 case DUMMY_CONSTANT_LENGTH:
33 *olen = context->length;
34 break;
35 case DUMMY_REQUESTED_LENGTH:
36 *olen = len;
37 break;
38 case DUMMY_FAIL:
Gilles Peskine449bd832023-01-11 14:50:10 +010039 return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +020040 }
41
Gilles Peskine449bd832023-01-11 14:50:10 +010042 memset(output, 0x2a, *olen);
43 return 0;
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +020044}
Paul Bakkerffbfb4c2016-06-01 15:36:18 +010045
46/*
47 * Ability to clear entropy sources to allow testing with just predefined
48 * entropy sources. This function or tests depending on it might break if there
49 * are internal changes to how entropy sources are registered.
50 *
51 * To be called immediately after mbedtls_entropy_init().
52 *
53 * Just resetting the counter. New sources will overwrite existing ones.
54 * This might break memory checks in the future if sources need 'free-ing' then
55 * as well.
56 */
Gilles Peskine449bd832023-01-11 14:50:10 +010057static void entropy_clear_sources(mbedtls_entropy_context *ctx)
Paul Bakkerffbfb4c2016-06-01 15:36:18 +010058{
59 ctx->source_count = 0;
60}
61
Gilles Peskine7f246512019-10-08 14:51:49 +020062#if defined(MBEDTLS_ENTROPY_NV_SEED)
Michael Schuster275b6982024-06-07 01:51:54 +020063
64#if defined(MBEDTLS_MD_LIGHT) && defined(MBEDTLS_PLATFORM_NV_SEED_ALT)
Paul Bakkerffbfb4c2016-06-01 15:36:18 +010065/*
66 * NV seed read/write functions that use a buffer instead of a file
67 */
68static unsigned char buffer_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
69
Michael Schusterb1e33fb2024-06-04 02:30:22 +020070static int buffer_nv_seed_read(unsigned char *buf, size_t buf_len)
Paul Bakkerffbfb4c2016-06-01 15:36:18 +010071{
Gilles Peskine449bd832023-01-11 14:50:10 +010072 if (buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE) {
73 return -1;
74 }
Paul Bakkerffbfb4c2016-06-01 15:36:18 +010075
Gilles Peskine449bd832023-01-11 14:50:10 +010076 memcpy(buf, buffer_seed, MBEDTLS_ENTROPY_BLOCK_SIZE);
77 return 0;
Paul Bakkerffbfb4c2016-06-01 15:36:18 +010078}
79
Michael Schusterb1e33fb2024-06-04 02:30:22 +020080static int buffer_nv_seed_write(unsigned char *buf, size_t buf_len)
Paul Bakkerffbfb4c2016-06-01 15:36:18 +010081{
Gilles Peskine449bd832023-01-11 14:50:10 +010082 if (buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE) {
83 return -1;
84 }
Paul Bakkerffbfb4c2016-06-01 15:36:18 +010085
Gilles Peskine449bd832023-01-11 14:50:10 +010086 memcpy(buffer_seed, buf, MBEDTLS_ENTROPY_BLOCK_SIZE);
87 return 0;
Paul Bakkerffbfb4c2016-06-01 15:36:18 +010088}
Michael Schuster275b6982024-06-07 01:51:54 +020089#endif /* MBEDTLS_MD_LIGHT && MBEDTLS_PLATFORM_NV_SEED_ALT */
Paul Bakkerffbfb4c2016-06-01 15:36:18 +010090
Michael Schuster275b6982024-06-07 01:51:54 +020091#if defined(MBEDTLS_FS_IO)
Paul Bakkerffbfb4c2016-06-01 15:36:18 +010092/*
93 * NV seed read/write helpers that fill the base seedfile
94 */
Gilles Peskine449bd832023-01-11 14:50:10 +010095static int write_nv_seed(unsigned char *buf, size_t buf_len)
Paul Bakkerffbfb4c2016-06-01 15:36:18 +010096{
97 FILE *f;
98
Gilles Peskine449bd832023-01-11 14:50:10 +010099 if (buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE) {
100 return -1;
101 }
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100102
Gilles Peskine449bd832023-01-11 14:50:10 +0100103 if ((f = fopen(MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w")) == NULL) {
104 return -1;
105 }
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100106
Gilles Peskine449bd832023-01-11 14:50:10 +0100107 if (fwrite(buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f) !=
108 MBEDTLS_ENTROPY_BLOCK_SIZE) {
Gilles Peskinebbd92912023-10-17 18:08:24 +0200109 fclose(f);
Gilles Peskine449bd832023-01-11 14:50:10 +0100110 return -1;
111 }
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100112
Gilles Peskine449bd832023-01-11 14:50:10 +0100113 fclose(f);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100114
Gilles Peskine449bd832023-01-11 14:50:10 +0100115 return 0;
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100116}
117
Michael Schuster275b6982024-06-07 01:51:54 +0200118#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT)
Michael Schusterb1e33fb2024-06-04 02:30:22 +0200119static int read_nv_seed(unsigned char *buf, size_t buf_len)
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100120{
121 FILE *f;
122
Gilles Peskine449bd832023-01-11 14:50:10 +0100123 if (buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE) {
124 return -1;
125 }
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100126
Gilles Peskine449bd832023-01-11 14:50:10 +0100127 if ((f = fopen(MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb")) == NULL) {
128 return -1;
129 }
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100130
Gilles Peskine449bd832023-01-11 14:50:10 +0100131 if (fread(buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f) !=
132 MBEDTLS_ENTROPY_BLOCK_SIZE) {
Gilles Peskinebbd92912023-10-17 18:08:24 +0200133 fclose(f);
Gilles Peskine449bd832023-01-11 14:50:10 +0100134 return -1;
135 }
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100136
Gilles Peskine449bd832023-01-11 14:50:10 +0100137 fclose(f);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100138
Gilles Peskine449bd832023-01-11 14:50:10 +0100139 return 0;
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100140}
Michael Schuster275b6982024-06-07 01:51:54 +0200141#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */
142#endif /* MBEDTLS_FS_IO */
Paul Bakker4a6c6fc2016-06-01 16:34:25 +0100143#endif /* MBEDTLS_ENTROPY_NV_SEED */
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200144/* END_HEADER */
145
146/* BEGIN_DEPENDENCIES
Gilles Peskinec5484682023-04-28 23:41:38 +0200147 * depends_on:MBEDTLS_ENTROPY_C:!MBEDTLS_PSA_INJECT_ENTROPY
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200148 * END_DEPENDENCIES
149 */
150
Gilles Peskine3d979f72021-02-22 21:24:02 +0100151/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100152void entropy_init_free(int reinit)
Gilles Peskine3d979f72021-02-22 21:24:02 +0100153{
154 mbedtls_entropy_context ctx;
155
156 /* Double free is not explicitly documented to work, but it is convenient
157 * to call mbedtls_entropy_free() unconditionally on an error path without
158 * checking whether it has already been called in the success path. */
159
Gilles Peskine449bd832023-01-11 14:50:10 +0100160 mbedtls_entropy_init(&ctx);
161 mbedtls_entropy_free(&ctx);
Gilles Peskine3d979f72021-02-22 21:24:02 +0100162
Gilles Peskine449bd832023-01-11 14:50:10 +0100163 if (reinit) {
164 mbedtls_entropy_init(&ctx);
165 }
166 mbedtls_entropy_free(&ctx);
Gilles Peskine3d979f72021-02-22 21:24:02 +0100167
168 /* This test case always succeeds, functionally speaking. A plausible
169 * bug might trigger an invalid pointer dereference or a memory leak. */
170 goto exit;
171}
172/* END_CASE */
173
Simon Butcherb7f45c52016-09-15 18:42:26 +0100174/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
Gilles Peskine449bd832023-01-11 14:50:10 +0100175void entropy_seed_file(char *path, int ret)
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200176{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200177 mbedtls_entropy_context ctx;
Gilles Peskine6b901702023-07-26 18:43:39 +0200178 mbedtls_entropy_init(&ctx);
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200179
Manuel Pégourié-Gonnard5cd4b642023-02-02 13:14:59 +0100180 MD_PSA_INIT();
181
Gilles Peskine449bd832023-01-11 14:50:10 +0100182 TEST_ASSERT(mbedtls_entropy_write_seed_file(&ctx, path) == ret);
183 TEST_ASSERT(mbedtls_entropy_update_seed_file(&ctx, path) == ret);
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200184
Paul Bakkerbd51b262014-07-10 15:26:12 +0200185exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100186 mbedtls_entropy_free(&ctx);
Manuel Pégourié-Gonnard5cd4b642023-02-02 13:14:59 +0100187 MD_PSA_DONE();
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200188}
189/* END_CASE */
190
Victor Krasnoshchokb3129ba2020-08-29 22:54:37 +0300191/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
Gilles Peskine449bd832023-01-11 14:50:10 +0100192void entropy_write_base_seed_file(int ret)
Victor Krasnoshchokb3129ba2020-08-29 22:54:37 +0300193{
194 mbedtls_entropy_context ctx;
Gilles Peskine6b901702023-07-26 18:43:39 +0200195 mbedtls_entropy_init(&ctx);
Victor Krasnoshchokb3129ba2020-08-29 22:54:37 +0300196
Manuel Pégourié-Gonnard5cd4b642023-02-02 13:14:59 +0100197 MD_PSA_INIT();
198
Gilles Peskine449bd832023-01-11 14:50:10 +0100199 TEST_ASSERT(mbedtls_entropy_write_seed_file(&ctx, MBEDTLS_PLATFORM_STD_NV_SEED_FILE) == ret);
200 TEST_ASSERT(mbedtls_entropy_update_seed_file(&ctx, MBEDTLS_PLATFORM_STD_NV_SEED_FILE) == ret);
Victor Krasnoshchokb3129ba2020-08-29 22:54:37 +0300201
202exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100203 mbedtls_entropy_free(&ctx);
Manuel Pégourié-Gonnard5cd4b642023-02-02 13:14:59 +0100204 MD_PSA_DONE();
Victor Krasnoshchokb3129ba2020-08-29 22:54:37 +0300205}
206/* END_CASE */
207
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200208/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100209void entropy_no_sources()
Gilles Peskine7f246512019-10-08 14:51:49 +0200210{
211 mbedtls_entropy_context ctx;
212 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
213
Gilles Peskine449bd832023-01-11 14:50:10 +0100214 mbedtls_entropy_init(&ctx);
215 entropy_clear_sources(&ctx);
216 TEST_EQUAL(mbedtls_entropy_func(&ctx, buf, sizeof(buf)),
217 MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED);
Gilles Peskine7f246512019-10-08 14:51:49 +0200218
219exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100220 mbedtls_entropy_free(&ctx);
Gilles Peskine7f246512019-10-08 14:51:49 +0200221}
222/* END_CASE */
223
224/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100225void entropy_too_many_sources()
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200226{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200227 mbedtls_entropy_context ctx;
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200228 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100229 entropy_dummy_context dummy = { DUMMY_REQUESTED_LENGTH, 0, 0 };
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200230
Gilles Peskine449bd832023-01-11 14:50:10 +0100231 mbedtls_entropy_init(&ctx);
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200232
233 /*
234 * It's hard to tell precisely when the error will occur,
235 * since we don't know how many sources were automatically added.
236 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100237 for (i = 0; i < MBEDTLS_ENTROPY_MAX_SOURCES; i++) {
238 (void) mbedtls_entropy_add_source(&ctx, entropy_dummy_source, &dummy,
239 16, MBEDTLS_ENTROPY_SOURCE_WEAK);
240 }
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200241
Gilles Peskine449bd832023-01-11 14:50:10 +0100242 TEST_ASSERT(mbedtls_entropy_add_source(&ctx, entropy_dummy_source, &dummy,
243 16, MBEDTLS_ENTROPY_SOURCE_WEAK)
244 == MBEDTLS_ERR_ENTROPY_MAX_SOURCES);
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200245
Paul Bakkerbd51b262014-07-10 15:26:12 +0200246exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100247 mbedtls_entropy_free(&ctx);
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200248}
249/* END_CASE */
250
Hanno Beckerd4a872e2017-09-07 08:09:33 +0100251/* BEGIN_CASE depends_on:ENTROPY_HAVE_STRONG */
Gilles Peskine449bd832023-01-11 14:50:10 +0100252void entropy_func_len(int len, int ret)
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200253{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200254 mbedtls_entropy_context ctx;
255 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE + 10] = { 0 };
256 unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE + 10] = { 0 };
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200257 size_t i, j;
258
Gilles Peskine449bd832023-01-11 14:50:10 +0100259 mbedtls_entropy_init(&ctx);
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200260
Gilles Peskine6b901702023-07-26 18:43:39 +0200261 MD_PSA_INIT();
262
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200263 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200264 * See comments in mbedtls_entropy_self_test()
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200265 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100266 for (i = 0; i < 8; i++) {
267 TEST_ASSERT(mbedtls_entropy_func(&ctx, buf, len) == ret);
268 for (j = 0; j < sizeof(buf); j++) {
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200269 acc[j] |= buf[j];
Gilles Peskine449bd832023-01-11 14:50:10 +0100270 }
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200271 }
272
Gilles Peskine449bd832023-01-11 14:50:10 +0100273 if (ret == 0) {
274 for (j = 0; j < (size_t) len; j++) {
275 TEST_ASSERT(acc[j] != 0);
276 }
277 }
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200278
Gilles Peskine449bd832023-01-11 14:50:10 +0100279 for (j = len; j < sizeof(buf); j++) {
280 TEST_ASSERT(acc[j] == 0);
281 }
Gilles Peskine7aba0362021-01-31 00:07:11 +0100282
283exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100284 mbedtls_entropy_free(&ctx);
Manuel Pégourié-Gonnard5cd4b642023-02-02 13:14:59 +0100285 MD_PSA_DONE();
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200286}
287/* END_CASE */
288
289/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100290void entropy_source_fail(char *path)
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200291{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200292 mbedtls_entropy_context ctx;
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200293 unsigned char buf[16];
Gilles Peskine449bd832023-01-11 14:50:10 +0100294 entropy_dummy_context dummy = { DUMMY_FAIL, 0, 0 };
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200295
Gilles Peskine449bd832023-01-11 14:50:10 +0100296 mbedtls_entropy_init(&ctx);
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200297
Gilles Peskine6b901702023-07-26 18:43:39 +0200298 MD_PSA_INIT();
299
Gilles Peskine449bd832023-01-11 14:50:10 +0100300 TEST_ASSERT(mbedtls_entropy_add_source(&ctx, entropy_dummy_source,
301 &dummy, 16,
302 MBEDTLS_ENTROPY_SOURCE_WEAK)
303 == 0);
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200304
Gilles Peskine449bd832023-01-11 14:50:10 +0100305 TEST_ASSERT(mbedtls_entropy_func(&ctx, buf, sizeof(buf))
306 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED);
307 TEST_ASSERT(mbedtls_entropy_gather(&ctx)
308 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED);
Simon Butcherb7f45c52016-09-15 18:42:26 +0100309#if defined(MBEDTLS_FS_IO) && defined(MBEDTLS_ENTROPY_NV_SEED)
Gilles Peskine449bd832023-01-11 14:50:10 +0100310 TEST_ASSERT(mbedtls_entropy_write_seed_file(&ctx, path)
311 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED);
312 TEST_ASSERT(mbedtls_entropy_update_seed_file(&ctx, path)
313 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED);
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200314#else
315 ((void) path);
316#endif
317
Paul Bakkerbd51b262014-07-10 15:26:12 +0200318exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100319 mbedtls_entropy_free(&ctx);
Manuel Pégourié-Gonnard5cd4b642023-02-02 13:14:59 +0100320 MD_PSA_DONE();
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200321}
322/* END_CASE */
323
Gilles Peskinecbd91e02019-11-25 19:50:54 +0100324/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100325void entropy_threshold(int threshold, int chunk_size, int result)
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200326{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200327 mbedtls_entropy_context ctx;
Gilles Peskinecbd91e02019-11-25 19:50:54 +0100328 entropy_dummy_context strong =
Gilles Peskine449bd832023-01-11 14:50:10 +0100329 { DUMMY_CONSTANT_LENGTH, MBEDTLS_ENTROPY_BLOCK_SIZE, 0 };
330 entropy_dummy_context weak = { DUMMY_CONSTANT_LENGTH, chunk_size, 0 };
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200331 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200332 int ret;
333
Gilles Peskine449bd832023-01-11 14:50:10 +0100334 mbedtls_entropy_init(&ctx);
335 entropy_clear_sources(&ctx);
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200336
Gilles Peskine6b901702023-07-26 18:43:39 +0200337 MD_PSA_INIT();
338
Gilles Peskinecbd91e02019-11-25 19:50:54 +0100339 /* Set strong source that reaches its threshold immediately and
340 * a weak source whose threshold is a test parameter. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100341 TEST_ASSERT(mbedtls_entropy_add_source(&ctx, entropy_dummy_source,
342 &strong, 1,
343 MBEDTLS_ENTROPY_SOURCE_STRONG) == 0);
344 TEST_ASSERT(mbedtls_entropy_add_source(&ctx, entropy_dummy_source,
345 &weak, threshold,
346 MBEDTLS_ENTROPY_SOURCE_WEAK) == 0);
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200347
Gilles Peskine449bd832023-01-11 14:50:10 +0100348 ret = mbedtls_entropy_func(&ctx, buf, sizeof(buf));
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200349
Gilles Peskine449bd832023-01-11 14:50:10 +0100350 if (result >= 0) {
351 TEST_ASSERT(ret == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100352#if defined(MBEDTLS_ENTROPY_NV_SEED)
Gilles Peskineae679392019-11-25 18:26:23 +0100353 /* If the NV seed functionality is enabled, there are two entropy
354 * updates: before and after updating the NV seed. */
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100355 result *= 2;
356#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100357 TEST_ASSERT(weak.calls == (size_t) result);
358 } else {
359 TEST_ASSERT(ret == result);
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200360 }
361
Paul Bakkerbd51b262014-07-10 15:26:12 +0200362exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100363 mbedtls_entropy_free(&ctx);
Manuel Pégourié-Gonnard5cd4b642023-02-02 13:14:59 +0100364 MD_PSA_DONE();
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200365}
366/* END_CASE */
367
Gilles Peskine65fc0682019-10-08 15:01:34 +0200368/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100369void entropy_calls(int strength1, int strength2,
370 int threshold, int chunk_size,
371 int result)
Gilles Peskine65fc0682019-10-08 15:01:34 +0200372{
373 /*
374 * if result >= 0: result = expected number of calls to source 1
375 * if result < 0: result = expected return code from mbedtls_entropy_func()
376 */
377
378 mbedtls_entropy_context ctx;
Gilles Peskine449bd832023-01-11 14:50:10 +0100379 entropy_dummy_context dummy1 = { DUMMY_CONSTANT_LENGTH, chunk_size, 0 };
380 entropy_dummy_context dummy2 = { DUMMY_CONSTANT_LENGTH, chunk_size, 0 };
Gilles Peskine65fc0682019-10-08 15:01:34 +0200381 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
382 int ret;
383
Gilles Peskine449bd832023-01-11 14:50:10 +0100384 mbedtls_entropy_init(&ctx);
385 entropy_clear_sources(&ctx);
Gilles Peskine65fc0682019-10-08 15:01:34 +0200386
Gilles Peskine6b901702023-07-26 18:43:39 +0200387 MD_PSA_INIT();
388
Gilles Peskine449bd832023-01-11 14:50:10 +0100389 TEST_ASSERT(mbedtls_entropy_add_source(&ctx, entropy_dummy_source,
390 &dummy1, threshold,
391 strength1) == 0);
392 TEST_ASSERT(mbedtls_entropy_add_source(&ctx, entropy_dummy_source,
393 &dummy2, threshold,
394 strength2) == 0);
Gilles Peskine65fc0682019-10-08 15:01:34 +0200395
Gilles Peskine449bd832023-01-11 14:50:10 +0100396 ret = mbedtls_entropy_func(&ctx, buf, sizeof(buf));
Gilles Peskine65fc0682019-10-08 15:01:34 +0200397
Gilles Peskine449bd832023-01-11 14:50:10 +0100398 if (result >= 0) {
399 TEST_ASSERT(ret == 0);
Gilles Peskineae679392019-11-25 18:26:23 +0100400#if defined(MBEDTLS_ENTROPY_NV_SEED)
401 /* If the NV seed functionality is enabled, there are two entropy
402 * updates: before and after updating the NV seed. */
403 result *= 2;
404#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100405 TEST_ASSERT(dummy1.calls == (size_t) result);
406 } else {
407 TEST_ASSERT(ret == result);
Gilles Peskine65fc0682019-10-08 15:01:34 +0200408 }
409
410exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100411 mbedtls_entropy_free(&ctx);
Manuel Pégourié-Gonnard5cd4b642023-02-02 13:14:59 +0100412 MD_PSA_DONE();
Gilles Peskine65fc0682019-10-08 15:01:34 +0200413}
414/* END_CASE */
415
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100416/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
Gilles Peskine449bd832023-01-11 14:50:10 +0100417void nv_seed_file_create()
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100418{
419 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
420
Gilles Peskine449bd832023-01-11 14:50:10 +0100421 memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100422
Gilles Peskine449bd832023-01-11 14:50:10 +0100423 TEST_ASSERT(write_nv_seed(buf, MBEDTLS_ENTROPY_BLOCK_SIZE) == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100424}
425/* END_CASE */
426
Paul Bakkerb598c292016-06-01 16:57:11 +0100427/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO:MBEDTLS_PLATFORM_NV_SEED_ALT */
Gilles Peskine449bd832023-01-11 14:50:10 +0100428void entropy_nv_seed_std_io()
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100429{
430 unsigned char io_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
431 unsigned char check_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
432
Gilles Peskine449bd832023-01-11 14:50:10 +0100433 memset(io_seed, 1, MBEDTLS_ENTROPY_BLOCK_SIZE);
434 memset(check_seed, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100435
Gilles Peskine449bd832023-01-11 14:50:10 +0100436 mbedtls_platform_set_nv_seed(mbedtls_platform_std_nv_seed_read,
437 mbedtls_platform_std_nv_seed_write);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100438
439 /* Check if platform NV read and write manipulate the same data */
Gilles Peskine449bd832023-01-11 14:50:10 +0100440 TEST_ASSERT(write_nv_seed(io_seed, MBEDTLS_ENTROPY_BLOCK_SIZE) == 0);
441 TEST_ASSERT(mbedtls_nv_seed_read(check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE) ==
442 MBEDTLS_ENTROPY_BLOCK_SIZE);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100443
Gilles Peskine449bd832023-01-11 14:50:10 +0100444 TEST_ASSERT(memcmp(io_seed, check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE) == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100445
Gilles Peskine449bd832023-01-11 14:50:10 +0100446 memset(check_seed, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100447
448 /* Check if platform NV write and raw read manipulate the same data */
Gilles Peskine449bd832023-01-11 14:50:10 +0100449 TEST_ASSERT(mbedtls_nv_seed_write(io_seed, MBEDTLS_ENTROPY_BLOCK_SIZE) ==
450 MBEDTLS_ENTROPY_BLOCK_SIZE);
451 TEST_ASSERT(read_nv_seed(check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE) == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100452
Gilles Peskine449bd832023-01-11 14:50:10 +0100453 TEST_ASSERT(memcmp(io_seed, check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE) == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100454}
455/* END_CASE */
456
Valerio Setti1626cc72024-01-22 16:29:46 +0100457/* BEGIN_CASE depends_on:MBEDTLS_MD_LIGHT:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_PLATFORM_NV_SEED_ALT */
Gilles Peskine449bd832023-01-11 14:50:10 +0100458void entropy_nv_seed(data_t *read_seed)
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100459{
Gilles Peskine66afcca2019-06-12 19:33:42 +0200460#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
461 const mbedtls_md_info_t *md_info =
Gilles Peskine449bd832023-01-11 14:50:10 +0100462 mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
Gilles Peskine66afcca2019-06-12 19:33:42 +0200463#elif defined(MBEDTLS_ENTROPY_SHA256_ACCUMULATOR)
464 const mbedtls_md_info_t *md_info =
Gilles Peskine449bd832023-01-11 14:50:10 +0100465 mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
Gilles Peskine66afcca2019-06-12 19:33:42 +0200466#else
467#error "Unsupported entropy accumulator"
468#endif
469 mbedtls_md_context_t accumulator;
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100470 mbedtls_entropy_context ctx;
Gilles Peskine449bd832023-01-11 14:50:10 +0100471 int (*original_mbedtls_nv_seed_read)(unsigned char *buf, size_t buf_len) =
Gilles Peskinee39b9032019-06-12 19:31:29 +0200472 mbedtls_nv_seed_read;
Gilles Peskine449bd832023-01-11 14:50:10 +0100473 int (*original_mbedtls_nv_seed_write)(unsigned char *buf, size_t buf_len) =
Gilles Peskinee39b9032019-06-12 19:31:29 +0200474 mbedtls_nv_seed_write;
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100475
476 unsigned char header[2];
477 unsigned char entropy[MBEDTLS_ENTROPY_BLOCK_SIZE];
478 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
479 unsigned char empty[MBEDTLS_ENTROPY_BLOCK_SIZE];
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100480 unsigned char check_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
481 unsigned char check_entropy[MBEDTLS_ENTROPY_BLOCK_SIZE];
482
Gilles Peskine449bd832023-01-11 14:50:10 +0100483 memset(entropy, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
484 memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
485 memset(empty, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
486 memset(check_seed, 2, MBEDTLS_ENTROPY_BLOCK_SIZE);
487 memset(check_entropy, 3, MBEDTLS_ENTROPY_BLOCK_SIZE);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100488
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100489 // Make sure we read/write NV seed from our buffers
Gilles Peskine449bd832023-01-11 14:50:10 +0100490 mbedtls_platform_set_nv_seed(buffer_nv_seed_read, buffer_nv_seed_write);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100491
Gilles Peskine449bd832023-01-11 14:50:10 +0100492 mbedtls_md_init(&accumulator);
493 mbedtls_entropy_init(&ctx);
494 entropy_clear_sources(&ctx);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100495
Gilles Peskine6b901702023-07-26 18:43:39 +0200496 MD_PSA_INIT();
497
Gilles Peskine449bd832023-01-11 14:50:10 +0100498 TEST_ASSERT(mbedtls_entropy_add_source(&ctx, mbedtls_nv_seed_poll, NULL,
499 MBEDTLS_ENTROPY_BLOCK_SIZE,
500 MBEDTLS_ENTROPY_SOURCE_STRONG) == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100501
Gilles Peskine66afcca2019-06-12 19:33:42 +0200502 // Set the initial NV seed to read
Gilles Peskine449bd832023-01-11 14:50:10 +0100503 TEST_ASSERT(read_seed->len >= MBEDTLS_ENTROPY_BLOCK_SIZE);
504 memcpy(buffer_seed, read_seed->x, MBEDTLS_ENTROPY_BLOCK_SIZE);
Gilles Peskine66afcca2019-06-12 19:33:42 +0200505
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100506 // Do an entropy run
Gilles Peskine449bd832023-01-11 14:50:10 +0100507 TEST_ASSERT(mbedtls_entropy_func(&ctx, entropy, sizeof(entropy)) == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100508 // Determine what should have happened with manual entropy internal logic
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100509
510 // Init accumulator
511 header[1] = MBEDTLS_ENTROPY_BLOCK_SIZE;
Gilles Peskine449bd832023-01-11 14:50:10 +0100512 TEST_ASSERT(mbedtls_md_setup(&accumulator, md_info, 0) == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100513
514 // First run for updating write_seed
515 header[0] = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100516 TEST_ASSERT(mbedtls_md_starts(&accumulator) == 0);
517 TEST_ASSERT(mbedtls_md_update(&accumulator, header, 2) == 0);
518 TEST_ASSERT(mbedtls_md_update(&accumulator,
519 read_seed->x, MBEDTLS_ENTROPY_BLOCK_SIZE) == 0);
520 TEST_ASSERT(mbedtls_md_finish(&accumulator, buf) == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100521
Gilles Peskine449bd832023-01-11 14:50:10 +0100522 TEST_ASSERT(mbedtls_md_starts(&accumulator) == 0);
523 TEST_ASSERT(mbedtls_md_update(&accumulator,
524 buf, MBEDTLS_ENTROPY_BLOCK_SIZE) == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100525
Gilles Peskine449bd832023-01-11 14:50:10 +0100526 TEST_ASSERT(mbedtls_md(md_info, buf, MBEDTLS_ENTROPY_BLOCK_SIZE,
527 check_seed) == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100528
529 // Second run for actual entropy (triggers mbedtls_entropy_update_nv_seed)
530 header[0] = MBEDTLS_ENTROPY_SOURCE_MANUAL;
Gilles Peskine449bd832023-01-11 14:50:10 +0100531 TEST_ASSERT(mbedtls_md_update(&accumulator, header, 2) == 0);
532 TEST_ASSERT(mbedtls_md_update(&accumulator,
533 empty, MBEDTLS_ENTROPY_BLOCK_SIZE) == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100534
535 header[0] = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100536 TEST_ASSERT(mbedtls_md_update(&accumulator, header, 2) == 0);
537 TEST_ASSERT(mbedtls_md_update(&accumulator,
538 check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE) == 0);
539 TEST_ASSERT(mbedtls_md_finish(&accumulator, buf) == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100540
Gilles Peskine449bd832023-01-11 14:50:10 +0100541 TEST_ASSERT(mbedtls_md(md_info, buf, MBEDTLS_ENTROPY_BLOCK_SIZE,
542 check_entropy) == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100543
544 // Check result of both NV file and entropy received with the manual calculations
Gilles Peskine449bd832023-01-11 14:50:10 +0100545 TEST_ASSERT(memcmp(check_seed, buffer_seed, MBEDTLS_ENTROPY_BLOCK_SIZE) == 0);
546 TEST_ASSERT(memcmp(check_entropy, entropy, MBEDTLS_ENTROPY_BLOCK_SIZE) == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100547
Gilles Peskinee39b9032019-06-12 19:31:29 +0200548exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100549 mbedtls_md_free(&accumulator);
550 mbedtls_entropy_free(&ctx);
Gilles Peskinee39b9032019-06-12 19:31:29 +0200551 mbedtls_nv_seed_read = original_mbedtls_nv_seed_read;
552 mbedtls_nv_seed_write = original_mbedtls_nv_seed_write;
Manuel Pégourié-Gonnard5cd4b642023-02-02 13:14:59 +0100553 MD_PSA_DONE();
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100554}
555/* END_CASE */
556
Hanno Beckerd4a872e2017-09-07 08:09:33 +0100557/* BEGIN_CASE depends_on:ENTROPY_HAVE_STRONG:MBEDTLS_SELF_TEST */
Gilles Peskine449bd832023-01-11 14:50:10 +0100558void entropy_selftest(int result)
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200559{
Manuel Pégourié-Gonnard5cd4b642023-02-02 13:14:59 +0100560 MD_PSA_INIT();
561
Gilles Peskine449bd832023-01-11 14:50:10 +0100562 TEST_ASSERT(mbedtls_entropy_self_test(1) == result);
Manuel Pégourié-Gonnard5cd4b642023-02-02 13:14:59 +0100563
564exit:
565 MD_PSA_DONE();
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200566}
567/* END_CASE */