blob: 0e013b740d4281458fe8d98cd0565d1149cbcc2b [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)
Paul Bakkerffbfb4c2016-06-01 15:36:18 +010063/*
64 * NV seed read/write functions that use a buffer instead of a file
65 */
66static unsigned char buffer_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
67
Gilles Peskine449bd832023-01-11 14:50:10 +010068int buffer_nv_seed_read(unsigned char *buf, size_t buf_len)
Paul Bakkerffbfb4c2016-06-01 15:36:18 +010069{
Gilles Peskine449bd832023-01-11 14:50:10 +010070 if (buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE) {
71 return -1;
72 }
Paul Bakkerffbfb4c2016-06-01 15:36:18 +010073
Gilles Peskine449bd832023-01-11 14:50:10 +010074 memcpy(buf, buffer_seed, MBEDTLS_ENTROPY_BLOCK_SIZE);
75 return 0;
Paul Bakkerffbfb4c2016-06-01 15:36:18 +010076}
77
Gilles Peskine449bd832023-01-11 14:50:10 +010078int buffer_nv_seed_write(unsigned char *buf, size_t buf_len)
Paul Bakkerffbfb4c2016-06-01 15:36:18 +010079{
Gilles Peskine449bd832023-01-11 14:50:10 +010080 if (buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE) {
81 return -1;
82 }
Paul Bakkerffbfb4c2016-06-01 15:36:18 +010083
Gilles Peskine449bd832023-01-11 14:50:10 +010084 memcpy(buffer_seed, buf, MBEDTLS_ENTROPY_BLOCK_SIZE);
85 return 0;
Paul Bakkerffbfb4c2016-06-01 15:36:18 +010086}
87
88/*
89 * NV seed read/write helpers that fill the base seedfile
90 */
Gilles Peskine449bd832023-01-11 14:50:10 +010091static int write_nv_seed(unsigned char *buf, size_t buf_len)
Paul Bakkerffbfb4c2016-06-01 15:36:18 +010092{
93 FILE *f;
94
Gilles Peskine449bd832023-01-11 14:50:10 +010095 if (buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE) {
96 return -1;
97 }
Paul Bakkerffbfb4c2016-06-01 15:36:18 +010098
Gilles Peskine449bd832023-01-11 14:50:10 +010099 if ((f = fopen(MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w")) == NULL) {
100 return -1;
101 }
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100102
Gilles Peskine449bd832023-01-11 14:50:10 +0100103 if (fwrite(buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f) !=
104 MBEDTLS_ENTROPY_BLOCK_SIZE) {
105 return -1;
106 }
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100107
Gilles Peskine449bd832023-01-11 14:50:10 +0100108 fclose(f);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100109
Gilles Peskine449bd832023-01-11 14:50:10 +0100110 return 0;
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100111}
112
Gilles Peskine449bd832023-01-11 14:50:10 +0100113int read_nv_seed(unsigned char *buf, size_t buf_len)
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100114{
115 FILE *f;
116
Gilles Peskine449bd832023-01-11 14:50:10 +0100117 if (buf_len != MBEDTLS_ENTROPY_BLOCK_SIZE) {
118 return -1;
119 }
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100120
Gilles Peskine449bd832023-01-11 14:50:10 +0100121 if ((f = fopen(MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb")) == NULL) {
122 return -1;
123 }
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100124
Gilles Peskine449bd832023-01-11 14:50:10 +0100125 if (fread(buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f) !=
126 MBEDTLS_ENTROPY_BLOCK_SIZE) {
127 return -1;
128 }
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100129
Gilles Peskine449bd832023-01-11 14:50:10 +0100130 fclose(f);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100131
Gilles Peskine449bd832023-01-11 14:50:10 +0100132 return 0;
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100133}
Paul Bakker4a6c6fc2016-06-01 16:34:25 +0100134#endif /* MBEDTLS_ENTROPY_NV_SEED */
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200135/* END_HEADER */
136
137/* BEGIN_DEPENDENCIES
Gilles Peskinec5484682023-04-28 23:41:38 +0200138 * depends_on:MBEDTLS_ENTROPY_C:!MBEDTLS_PSA_INJECT_ENTROPY
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200139 * END_DEPENDENCIES
140 */
141
Gilles Peskine3d979f72021-02-22 21:24:02 +0100142/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100143void entropy_init_free(int reinit)
Gilles Peskine3d979f72021-02-22 21:24:02 +0100144{
145 mbedtls_entropy_context ctx;
146
147 /* Double free is not explicitly documented to work, but it is convenient
148 * to call mbedtls_entropy_free() unconditionally on an error path without
149 * checking whether it has already been called in the success path. */
150
Gilles Peskine449bd832023-01-11 14:50:10 +0100151 mbedtls_entropy_init(&ctx);
152 mbedtls_entropy_free(&ctx);
Gilles Peskine3d979f72021-02-22 21:24:02 +0100153
Gilles Peskine449bd832023-01-11 14:50:10 +0100154 if (reinit) {
155 mbedtls_entropy_init(&ctx);
156 }
157 mbedtls_entropy_free(&ctx);
Gilles Peskine3d979f72021-02-22 21:24:02 +0100158
159 /* This test case always succeeds, functionally speaking. A plausible
160 * bug might trigger an invalid pointer dereference or a memory leak. */
161 goto exit;
162}
163/* END_CASE */
164
Simon Butcherb7f45c52016-09-15 18:42:26 +0100165/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
Gilles Peskine449bd832023-01-11 14:50:10 +0100166void entropy_seed_file(char *path, int ret)
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200167{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200168 mbedtls_entropy_context ctx;
Gilles Peskine6b901702023-07-26 18:43:39 +0200169 mbedtls_entropy_init(&ctx);
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200170
Manuel Pégourié-Gonnard5cd4b642023-02-02 13:14:59 +0100171 MD_PSA_INIT();
172
Gilles Peskine449bd832023-01-11 14:50:10 +0100173 TEST_ASSERT(mbedtls_entropy_write_seed_file(&ctx, path) == ret);
174 TEST_ASSERT(mbedtls_entropy_update_seed_file(&ctx, path) == ret);
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200175
Paul Bakkerbd51b262014-07-10 15:26:12 +0200176exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100177 mbedtls_entropy_free(&ctx);
Manuel Pégourié-Gonnard5cd4b642023-02-02 13:14:59 +0100178 MD_PSA_DONE();
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200179}
180/* END_CASE */
181
Victor Krasnoshchokb3129ba2020-08-29 22:54:37 +0300182/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
Gilles Peskine449bd832023-01-11 14:50:10 +0100183void entropy_write_base_seed_file(int ret)
Victor Krasnoshchokb3129ba2020-08-29 22:54:37 +0300184{
185 mbedtls_entropy_context ctx;
Gilles Peskine6b901702023-07-26 18:43:39 +0200186 mbedtls_entropy_init(&ctx);
Victor Krasnoshchokb3129ba2020-08-29 22:54:37 +0300187
Manuel Pégourié-Gonnard5cd4b642023-02-02 13:14:59 +0100188 MD_PSA_INIT();
189
Gilles Peskine449bd832023-01-11 14:50:10 +0100190 TEST_ASSERT(mbedtls_entropy_write_seed_file(&ctx, MBEDTLS_PLATFORM_STD_NV_SEED_FILE) == ret);
191 TEST_ASSERT(mbedtls_entropy_update_seed_file(&ctx, MBEDTLS_PLATFORM_STD_NV_SEED_FILE) == ret);
Victor Krasnoshchokb3129ba2020-08-29 22:54:37 +0300192
193exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100194 mbedtls_entropy_free(&ctx);
Manuel Pégourié-Gonnard5cd4b642023-02-02 13:14:59 +0100195 MD_PSA_DONE();
Victor Krasnoshchokb3129ba2020-08-29 22:54:37 +0300196}
197/* END_CASE */
198
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200199/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100200void entropy_no_sources()
Gilles Peskine7f246512019-10-08 14:51:49 +0200201{
202 mbedtls_entropy_context ctx;
203 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
204
Gilles Peskine449bd832023-01-11 14:50:10 +0100205 mbedtls_entropy_init(&ctx);
206 entropy_clear_sources(&ctx);
207 TEST_EQUAL(mbedtls_entropy_func(&ctx, buf, sizeof(buf)),
208 MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED);
Gilles Peskine7f246512019-10-08 14:51:49 +0200209
210exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100211 mbedtls_entropy_free(&ctx);
Gilles Peskine7f246512019-10-08 14:51:49 +0200212}
213/* END_CASE */
214
215/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100216void entropy_too_many_sources()
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200217{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200218 mbedtls_entropy_context ctx;
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200219 size_t i;
Gilles Peskine449bd832023-01-11 14:50:10 +0100220 entropy_dummy_context dummy = { DUMMY_REQUESTED_LENGTH, 0, 0 };
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200221
Gilles Peskine449bd832023-01-11 14:50:10 +0100222 mbedtls_entropy_init(&ctx);
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200223
224 /*
225 * It's hard to tell precisely when the error will occur,
226 * since we don't know how many sources were automatically added.
227 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100228 for (i = 0; i < MBEDTLS_ENTROPY_MAX_SOURCES; i++) {
229 (void) mbedtls_entropy_add_source(&ctx, entropy_dummy_source, &dummy,
230 16, MBEDTLS_ENTROPY_SOURCE_WEAK);
231 }
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200232
Gilles Peskine449bd832023-01-11 14:50:10 +0100233 TEST_ASSERT(mbedtls_entropy_add_source(&ctx, entropy_dummy_source, &dummy,
234 16, MBEDTLS_ENTROPY_SOURCE_WEAK)
235 == MBEDTLS_ERR_ENTROPY_MAX_SOURCES);
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200236
Paul Bakkerbd51b262014-07-10 15:26:12 +0200237exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100238 mbedtls_entropy_free(&ctx);
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200239}
240/* END_CASE */
241
Hanno Beckerd4a872e2017-09-07 08:09:33 +0100242/* BEGIN_CASE depends_on:ENTROPY_HAVE_STRONG */
Gilles Peskine449bd832023-01-11 14:50:10 +0100243void entropy_func_len(int len, int ret)
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200244{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200245 mbedtls_entropy_context ctx;
246 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE + 10] = { 0 };
247 unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE + 10] = { 0 };
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200248 size_t i, j;
249
Gilles Peskine449bd832023-01-11 14:50:10 +0100250 mbedtls_entropy_init(&ctx);
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200251
Gilles Peskine6b901702023-07-26 18:43:39 +0200252 MD_PSA_INIT();
253
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200254 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200255 * See comments in mbedtls_entropy_self_test()
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200256 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100257 for (i = 0; i < 8; i++) {
258 TEST_ASSERT(mbedtls_entropy_func(&ctx, buf, len) == ret);
259 for (j = 0; j < sizeof(buf); j++) {
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200260 acc[j] |= buf[j];
Gilles Peskine449bd832023-01-11 14:50:10 +0100261 }
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200262 }
263
Gilles Peskine449bd832023-01-11 14:50:10 +0100264 if (ret == 0) {
265 for (j = 0; j < (size_t) len; j++) {
266 TEST_ASSERT(acc[j] != 0);
267 }
268 }
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200269
Gilles Peskine449bd832023-01-11 14:50:10 +0100270 for (j = len; j < sizeof(buf); j++) {
271 TEST_ASSERT(acc[j] == 0);
272 }
Gilles Peskine7aba0362021-01-31 00:07:11 +0100273
274exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100275 mbedtls_entropy_free(&ctx);
Manuel Pégourié-Gonnard5cd4b642023-02-02 13:14:59 +0100276 MD_PSA_DONE();
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200277}
278/* END_CASE */
279
280/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100281void entropy_source_fail(char *path)
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200282{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200283 mbedtls_entropy_context ctx;
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200284 unsigned char buf[16];
Gilles Peskine449bd832023-01-11 14:50:10 +0100285 entropy_dummy_context dummy = { DUMMY_FAIL, 0, 0 };
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200286
Gilles Peskine449bd832023-01-11 14:50:10 +0100287 mbedtls_entropy_init(&ctx);
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200288
Gilles Peskine6b901702023-07-26 18:43:39 +0200289 MD_PSA_INIT();
290
Gilles Peskine449bd832023-01-11 14:50:10 +0100291 TEST_ASSERT(mbedtls_entropy_add_source(&ctx, entropy_dummy_source,
292 &dummy, 16,
293 MBEDTLS_ENTROPY_SOURCE_WEAK)
294 == 0);
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200295
Gilles Peskine449bd832023-01-11 14:50:10 +0100296 TEST_ASSERT(mbedtls_entropy_func(&ctx, buf, sizeof(buf))
297 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED);
298 TEST_ASSERT(mbedtls_entropy_gather(&ctx)
299 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED);
Simon Butcherb7f45c52016-09-15 18:42:26 +0100300#if defined(MBEDTLS_FS_IO) && defined(MBEDTLS_ENTROPY_NV_SEED)
Gilles Peskine449bd832023-01-11 14:50:10 +0100301 TEST_ASSERT(mbedtls_entropy_write_seed_file(&ctx, path)
302 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED);
303 TEST_ASSERT(mbedtls_entropy_update_seed_file(&ctx, path)
304 == MBEDTLS_ERR_ENTROPY_SOURCE_FAILED);
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200305#else
306 ((void) path);
307#endif
308
Paul Bakkerbd51b262014-07-10 15:26:12 +0200309exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100310 mbedtls_entropy_free(&ctx);
Manuel Pégourié-Gonnard5cd4b642023-02-02 13:14:59 +0100311 MD_PSA_DONE();
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200312}
313/* END_CASE */
314
Gilles Peskinecbd91e02019-11-25 19:50:54 +0100315/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100316void entropy_threshold(int threshold, int chunk_size, int result)
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200317{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200318 mbedtls_entropy_context ctx;
Gilles Peskinecbd91e02019-11-25 19:50:54 +0100319 entropy_dummy_context strong =
Gilles Peskine449bd832023-01-11 14:50:10 +0100320 { DUMMY_CONSTANT_LENGTH, MBEDTLS_ENTROPY_BLOCK_SIZE, 0 };
321 entropy_dummy_context weak = { DUMMY_CONSTANT_LENGTH, chunk_size, 0 };
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200322 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200323 int ret;
324
Gilles Peskine449bd832023-01-11 14:50:10 +0100325 mbedtls_entropy_init(&ctx);
326 entropy_clear_sources(&ctx);
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200327
Gilles Peskine6b901702023-07-26 18:43:39 +0200328 MD_PSA_INIT();
329
Gilles Peskinecbd91e02019-11-25 19:50:54 +0100330 /* Set strong source that reaches its threshold immediately and
331 * a weak source whose threshold is a test parameter. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100332 TEST_ASSERT(mbedtls_entropy_add_source(&ctx, entropy_dummy_source,
333 &strong, 1,
334 MBEDTLS_ENTROPY_SOURCE_STRONG) == 0);
335 TEST_ASSERT(mbedtls_entropy_add_source(&ctx, entropy_dummy_source,
336 &weak, threshold,
337 MBEDTLS_ENTROPY_SOURCE_WEAK) == 0);
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200338
Gilles Peskine449bd832023-01-11 14:50:10 +0100339 ret = mbedtls_entropy_func(&ctx, buf, sizeof(buf));
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200340
Gilles Peskine449bd832023-01-11 14:50:10 +0100341 if (result >= 0) {
342 TEST_ASSERT(ret == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100343#if defined(MBEDTLS_ENTROPY_NV_SEED)
Gilles Peskineae679392019-11-25 18:26:23 +0100344 /* If the NV seed functionality is enabled, there are two entropy
345 * updates: before and after updating the NV seed. */
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100346 result *= 2;
347#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100348 TEST_ASSERT(weak.calls == (size_t) result);
349 } else {
350 TEST_ASSERT(ret == result);
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200351 }
352
Paul Bakkerbd51b262014-07-10 15:26:12 +0200353exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100354 mbedtls_entropy_free(&ctx);
Manuel Pégourié-Gonnard5cd4b642023-02-02 13:14:59 +0100355 MD_PSA_DONE();
Manuel Pégourié-Gonnardc7c56b22014-05-30 11:42:01 +0200356}
357/* END_CASE */
358
Gilles Peskine65fc0682019-10-08 15:01:34 +0200359/* BEGIN_CASE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100360void entropy_calls(int strength1, int strength2,
361 int threshold, int chunk_size,
362 int result)
Gilles Peskine65fc0682019-10-08 15:01:34 +0200363{
364 /*
365 * if result >= 0: result = expected number of calls to source 1
366 * if result < 0: result = expected return code from mbedtls_entropy_func()
367 */
368
369 mbedtls_entropy_context ctx;
Gilles Peskine449bd832023-01-11 14:50:10 +0100370 entropy_dummy_context dummy1 = { DUMMY_CONSTANT_LENGTH, chunk_size, 0 };
371 entropy_dummy_context dummy2 = { DUMMY_CONSTANT_LENGTH, chunk_size, 0 };
Gilles Peskine65fc0682019-10-08 15:01:34 +0200372 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
373 int ret;
374
Gilles Peskine449bd832023-01-11 14:50:10 +0100375 mbedtls_entropy_init(&ctx);
376 entropy_clear_sources(&ctx);
Gilles Peskine65fc0682019-10-08 15:01:34 +0200377
Gilles Peskine6b901702023-07-26 18:43:39 +0200378 MD_PSA_INIT();
379
Gilles Peskine449bd832023-01-11 14:50:10 +0100380 TEST_ASSERT(mbedtls_entropy_add_source(&ctx, entropy_dummy_source,
381 &dummy1, threshold,
382 strength1) == 0);
383 TEST_ASSERT(mbedtls_entropy_add_source(&ctx, entropy_dummy_source,
384 &dummy2, threshold,
385 strength2) == 0);
Gilles Peskine65fc0682019-10-08 15:01:34 +0200386
Gilles Peskine449bd832023-01-11 14:50:10 +0100387 ret = mbedtls_entropy_func(&ctx, buf, sizeof(buf));
Gilles Peskine65fc0682019-10-08 15:01:34 +0200388
Gilles Peskine449bd832023-01-11 14:50:10 +0100389 if (result >= 0) {
390 TEST_ASSERT(ret == 0);
Gilles Peskineae679392019-11-25 18:26:23 +0100391#if defined(MBEDTLS_ENTROPY_NV_SEED)
392 /* If the NV seed functionality is enabled, there are two entropy
393 * updates: before and after updating the NV seed. */
394 result *= 2;
395#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100396 TEST_ASSERT(dummy1.calls == (size_t) result);
397 } else {
398 TEST_ASSERT(ret == result);
Gilles Peskine65fc0682019-10-08 15:01:34 +0200399 }
400
401exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100402 mbedtls_entropy_free(&ctx);
Manuel Pégourié-Gonnard5cd4b642023-02-02 13:14:59 +0100403 MD_PSA_DONE();
Gilles Peskine65fc0682019-10-08 15:01:34 +0200404}
405/* END_CASE */
406
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100407/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO */
Gilles Peskine449bd832023-01-11 14:50:10 +0100408void nv_seed_file_create()
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100409{
410 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
411
Gilles Peskine449bd832023-01-11 14:50:10 +0100412 memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100413
Gilles Peskine449bd832023-01-11 14:50:10 +0100414 TEST_ASSERT(write_nv_seed(buf, MBEDTLS_ENTROPY_BLOCK_SIZE) == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100415}
416/* END_CASE */
417
Paul Bakkerb598c292016-06-01 16:57:11 +0100418/* BEGIN_CASE depends_on:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_FS_IO:MBEDTLS_PLATFORM_NV_SEED_ALT */
Gilles Peskine449bd832023-01-11 14:50:10 +0100419void entropy_nv_seed_std_io()
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100420{
421 unsigned char io_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
422 unsigned char check_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
423
Gilles Peskine449bd832023-01-11 14:50:10 +0100424 memset(io_seed, 1, MBEDTLS_ENTROPY_BLOCK_SIZE);
425 memset(check_seed, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100426
Gilles Peskine449bd832023-01-11 14:50:10 +0100427 mbedtls_platform_set_nv_seed(mbedtls_platform_std_nv_seed_read,
428 mbedtls_platform_std_nv_seed_write);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100429
430 /* Check if platform NV read and write manipulate the same data */
Gilles Peskine449bd832023-01-11 14:50:10 +0100431 TEST_ASSERT(write_nv_seed(io_seed, MBEDTLS_ENTROPY_BLOCK_SIZE) == 0);
432 TEST_ASSERT(mbedtls_nv_seed_read(check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE) ==
433 MBEDTLS_ENTROPY_BLOCK_SIZE);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100434
Gilles Peskine449bd832023-01-11 14:50:10 +0100435 TEST_ASSERT(memcmp(io_seed, check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE) == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100436
Gilles Peskine449bd832023-01-11 14:50:10 +0100437 memset(check_seed, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100438
439 /* Check if platform NV write and raw read manipulate the same data */
Gilles Peskine449bd832023-01-11 14:50:10 +0100440 TEST_ASSERT(mbedtls_nv_seed_write(io_seed, MBEDTLS_ENTROPY_BLOCK_SIZE) ==
441 MBEDTLS_ENTROPY_BLOCK_SIZE);
442 TEST_ASSERT(read_nv_seed(check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE) == 0);
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}
446/* END_CASE */
447
Gilles Peskine66afcca2019-06-12 19:33:42 +0200448/* BEGIN_CASE depends_on:MBEDTLS_MD_C:MBEDTLS_ENTROPY_NV_SEED:MBEDTLS_PLATFORM_NV_SEED_ALT */
Gilles Peskine449bd832023-01-11 14:50:10 +0100449void entropy_nv_seed(data_t *read_seed)
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100450{
Gilles Peskine66afcca2019-06-12 19:33:42 +0200451#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
452 const mbedtls_md_info_t *md_info =
Gilles Peskine449bd832023-01-11 14:50:10 +0100453 mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
Gilles Peskine66afcca2019-06-12 19:33:42 +0200454#elif defined(MBEDTLS_ENTROPY_SHA256_ACCUMULATOR)
455 const mbedtls_md_info_t *md_info =
Gilles Peskine449bd832023-01-11 14:50:10 +0100456 mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
Gilles Peskine66afcca2019-06-12 19:33:42 +0200457#else
458#error "Unsupported entropy accumulator"
459#endif
460 mbedtls_md_context_t accumulator;
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100461 mbedtls_entropy_context ctx;
Gilles Peskine449bd832023-01-11 14:50:10 +0100462 int (*original_mbedtls_nv_seed_read)(unsigned char *buf, size_t buf_len) =
Gilles Peskinee39b9032019-06-12 19:31:29 +0200463 mbedtls_nv_seed_read;
Gilles Peskine449bd832023-01-11 14:50:10 +0100464 int (*original_mbedtls_nv_seed_write)(unsigned char *buf, size_t buf_len) =
Gilles Peskinee39b9032019-06-12 19:31:29 +0200465 mbedtls_nv_seed_write;
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100466
467 unsigned char header[2];
468 unsigned char entropy[MBEDTLS_ENTROPY_BLOCK_SIZE];
469 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
470 unsigned char empty[MBEDTLS_ENTROPY_BLOCK_SIZE];
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100471 unsigned char check_seed[MBEDTLS_ENTROPY_BLOCK_SIZE];
472 unsigned char check_entropy[MBEDTLS_ENTROPY_BLOCK_SIZE];
473
Gilles Peskine449bd832023-01-11 14:50:10 +0100474 memset(entropy, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
475 memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
476 memset(empty, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
477 memset(check_seed, 2, MBEDTLS_ENTROPY_BLOCK_SIZE);
478 memset(check_entropy, 3, MBEDTLS_ENTROPY_BLOCK_SIZE);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100479
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100480 // Make sure we read/write NV seed from our buffers
Gilles Peskine449bd832023-01-11 14:50:10 +0100481 mbedtls_platform_set_nv_seed(buffer_nv_seed_read, buffer_nv_seed_write);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100482
Gilles Peskine449bd832023-01-11 14:50:10 +0100483 mbedtls_md_init(&accumulator);
484 mbedtls_entropy_init(&ctx);
485 entropy_clear_sources(&ctx);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100486
Gilles Peskine6b901702023-07-26 18:43:39 +0200487 MD_PSA_INIT();
488
Gilles Peskine449bd832023-01-11 14:50:10 +0100489 TEST_ASSERT(mbedtls_entropy_add_source(&ctx, mbedtls_nv_seed_poll, NULL,
490 MBEDTLS_ENTROPY_BLOCK_SIZE,
491 MBEDTLS_ENTROPY_SOURCE_STRONG) == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100492
Gilles Peskine66afcca2019-06-12 19:33:42 +0200493 // Set the initial NV seed to read
Gilles Peskine449bd832023-01-11 14:50:10 +0100494 TEST_ASSERT(read_seed->len >= MBEDTLS_ENTROPY_BLOCK_SIZE);
495 memcpy(buffer_seed, read_seed->x, MBEDTLS_ENTROPY_BLOCK_SIZE);
Gilles Peskine66afcca2019-06-12 19:33:42 +0200496
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100497 // Do an entropy run
Gilles Peskine449bd832023-01-11 14:50:10 +0100498 TEST_ASSERT(mbedtls_entropy_func(&ctx, entropy, sizeof(entropy)) == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100499 // Determine what should have happened with manual entropy internal logic
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100500
501 // Init accumulator
502 header[1] = MBEDTLS_ENTROPY_BLOCK_SIZE;
Gilles Peskine449bd832023-01-11 14:50:10 +0100503 TEST_ASSERT(mbedtls_md_setup(&accumulator, md_info, 0) == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100504
505 // First run for updating write_seed
506 header[0] = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100507 TEST_ASSERT(mbedtls_md_starts(&accumulator) == 0);
508 TEST_ASSERT(mbedtls_md_update(&accumulator, header, 2) == 0);
509 TEST_ASSERT(mbedtls_md_update(&accumulator,
510 read_seed->x, MBEDTLS_ENTROPY_BLOCK_SIZE) == 0);
511 TEST_ASSERT(mbedtls_md_finish(&accumulator, buf) == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100512
Gilles Peskine449bd832023-01-11 14:50:10 +0100513 TEST_ASSERT(mbedtls_md_starts(&accumulator) == 0);
514 TEST_ASSERT(mbedtls_md_update(&accumulator,
515 buf, MBEDTLS_ENTROPY_BLOCK_SIZE) == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100516
Gilles Peskine449bd832023-01-11 14:50:10 +0100517 TEST_ASSERT(mbedtls_md(md_info, buf, MBEDTLS_ENTROPY_BLOCK_SIZE,
518 check_seed) == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100519
520 // Second run for actual entropy (triggers mbedtls_entropy_update_nv_seed)
521 header[0] = MBEDTLS_ENTROPY_SOURCE_MANUAL;
Gilles Peskine449bd832023-01-11 14:50:10 +0100522 TEST_ASSERT(mbedtls_md_update(&accumulator, header, 2) == 0);
523 TEST_ASSERT(mbedtls_md_update(&accumulator,
524 empty, MBEDTLS_ENTROPY_BLOCK_SIZE) == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100525
526 header[0] = 0;
Gilles Peskine449bd832023-01-11 14:50:10 +0100527 TEST_ASSERT(mbedtls_md_update(&accumulator, header, 2) == 0);
528 TEST_ASSERT(mbedtls_md_update(&accumulator,
529 check_seed, MBEDTLS_ENTROPY_BLOCK_SIZE) == 0);
530 TEST_ASSERT(mbedtls_md_finish(&accumulator, buf) == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100531
Gilles Peskine449bd832023-01-11 14:50:10 +0100532 TEST_ASSERT(mbedtls_md(md_info, buf, MBEDTLS_ENTROPY_BLOCK_SIZE,
533 check_entropy) == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100534
535 // Check result of both NV file and entropy received with the manual calculations
Gilles Peskine449bd832023-01-11 14:50:10 +0100536 TEST_ASSERT(memcmp(check_seed, buffer_seed, MBEDTLS_ENTROPY_BLOCK_SIZE) == 0);
537 TEST_ASSERT(memcmp(check_entropy, entropy, MBEDTLS_ENTROPY_BLOCK_SIZE) == 0);
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100538
Gilles Peskinee39b9032019-06-12 19:31:29 +0200539exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100540 mbedtls_md_free(&accumulator);
541 mbedtls_entropy_free(&ctx);
Gilles Peskinee39b9032019-06-12 19:31:29 +0200542 mbedtls_nv_seed_read = original_mbedtls_nv_seed_read;
543 mbedtls_nv_seed_write = original_mbedtls_nv_seed_write;
Manuel Pégourié-Gonnard5cd4b642023-02-02 13:14:59 +0100544 MD_PSA_DONE();
Paul Bakkerffbfb4c2016-06-01 15:36:18 +0100545}
546/* END_CASE */
547
Hanno Beckerd4a872e2017-09-07 08:09:33 +0100548/* BEGIN_CASE depends_on:ENTROPY_HAVE_STRONG:MBEDTLS_SELF_TEST */
Gilles Peskine449bd832023-01-11 14:50:10 +0100549void entropy_selftest(int result)
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200550{
Manuel Pégourié-Gonnard5cd4b642023-02-02 13:14:59 +0100551 MD_PSA_INIT();
552
Gilles Peskine449bd832023-01-11 14:50:10 +0100553 TEST_ASSERT(mbedtls_entropy_self_test(1) == result);
Manuel Pégourié-Gonnard5cd4b642023-02-02 13:14:59 +0100554
555exit:
556 MD_PSA_DONE();
Manuel Pégourié-Gonnard2c25eb02014-05-30 10:38:18 +0200557}
558/* END_CASE */