blob: 7dcf067a526eaa75e2d1daccfd0fda303bc85c47 [file] [log] [blame]
Jens Wiklander817466c2018-05-22 13:49:31 +02001/*
2 * Entropy accumulator implementation
3 *
Jerome Forissier79013242021-07-28 10:24:04 +02004 * Copyright The Mbed TLS Contributors
Tom Van Eyckb0563632024-06-13 16:20:14 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Jens Wiklander817466c2018-05-22 13:49:31 +02006 */
7
Jerome Forissier79013242021-07-28 10:24:04 +02008#include "common.h"
Jens Wiklander817466c2018-05-22 13:49:31 +02009
10#if defined(MBEDTLS_ENTROPY_C)
11
Jens Wiklander817466c2018-05-22 13:49:31 +020012#include "mbedtls/entropy.h"
Jens Wiklander32b31802023-10-06 16:59:46 +020013#include "entropy_poll.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010014#include "mbedtls/platform_util.h"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020015#include "mbedtls/error.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020016
17#include <string.h>
18
19#if defined(MBEDTLS_FS_IO)
20#include <stdio.h>
21#endif
22
Jens Wiklander817466c2018-05-22 13:49:31 +020023#include "mbedtls/platform.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020024
Jens Wiklander817466c2018-05-22 13:49:31 +020025#define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */
26
Jens Wiklander32b31802023-10-06 16:59:46 +020027void mbedtls_entropy_init(mbedtls_entropy_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +020028{
Jens Wiklander3d3b0592019-03-20 15:30:29 +010029 ctx->source_count = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +020030 memset(ctx->source, 0, sizeof(ctx->source));
Jens Wiklander817466c2018-05-22 13:49:31 +020031
32#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +020033 mbedtls_mutex_init(&ctx->mutex);
Jens Wiklander817466c2018-05-22 13:49:31 +020034#endif
35
Jens Wiklander3d3b0592019-03-20 15:30:29 +010036 ctx->accumulator_started = 0;
Tom Van Eyckb0563632024-06-13 16:20:14 +020037 mbedtls_md_init(&ctx->accumulator);
Jens Wiklander817466c2018-05-22 13:49:31 +020038
Jens Wiklander3d3b0592019-03-20 15:30:29 +010039 /* Reminder: Update ENTROPY_HAVE_STRONG in the test files
40 * when adding more strong entropy sources here. */
41
Jens Wiklander817466c2018-05-22 13:49:31 +020042#if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES)
43#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
Jens Wiklander32b31802023-10-06 16:59:46 +020044 mbedtls_entropy_add_source(ctx, mbedtls_platform_entropy_poll, NULL,
45 MBEDTLS_ENTROPY_MIN_PLATFORM,
46 MBEDTLS_ENTROPY_SOURCE_STRONG);
Jens Wiklander817466c2018-05-22 13:49:31 +020047#endif
48#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
Jens Wiklander32b31802023-10-06 16:59:46 +020049 mbedtls_entropy_add_source(ctx, mbedtls_hardware_poll, NULL,
50 MBEDTLS_ENTROPY_MIN_HARDWARE,
51 MBEDTLS_ENTROPY_SOURCE_STRONG);
Jens Wiklander817466c2018-05-22 13:49:31 +020052#endif
53#if defined(MBEDTLS_ENTROPY_NV_SEED)
Jens Wiklander32b31802023-10-06 16:59:46 +020054 mbedtls_entropy_add_source(ctx, mbedtls_nv_seed_poll, NULL,
55 MBEDTLS_ENTROPY_BLOCK_SIZE,
56 MBEDTLS_ENTROPY_SOURCE_STRONG);
Jens Wiklander3d3b0592019-03-20 15:30:29 +010057 ctx->initial_entropy_run = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +020058#endif
59#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */
60}
61
Jens Wiklander32b31802023-10-06 16:59:46 +020062void mbedtls_entropy_free(mbedtls_entropy_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +020063{
Sungbae Yoo4d211f32024-11-19 02:47:55 +000064 if (ctx == NULL) {
65 return;
66 }
67
Jerome Forissier79013242021-07-28 10:24:04 +020068 /* If the context was already free, don't call free() again.
69 * This is important for mutexes which don't allow double-free. */
Jens Wiklander32b31802023-10-06 16:59:46 +020070 if (ctx->accumulator_started == -1) {
Jerome Forissier79013242021-07-28 10:24:04 +020071 return;
Jens Wiklander32b31802023-10-06 16:59:46 +020072 }
Jerome Forissier79013242021-07-28 10:24:04 +020073
Jens Wiklander817466c2018-05-22 13:49:31 +020074#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +020075 mbedtls_mutex_free(&ctx->mutex);
Jens Wiklander817466c2018-05-22 13:49:31 +020076#endif
Tom Van Eyckb0563632024-06-13 16:20:14 +020077 mbedtls_md_free(&ctx->accumulator);
Jens Wiklander3d3b0592019-03-20 15:30:29 +010078#if defined(MBEDTLS_ENTROPY_NV_SEED)
79 ctx->initial_entropy_run = 0;
80#endif
81 ctx->source_count = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +020082 mbedtls_platform_zeroize(ctx->source, sizeof(ctx->source));
Jerome Forissier79013242021-07-28 10:24:04 +020083 ctx->accumulator_started = -1;
Jens Wiklander817466c2018-05-22 13:49:31 +020084}
85
Jens Wiklander32b31802023-10-06 16:59:46 +020086int mbedtls_entropy_add_source(mbedtls_entropy_context *ctx,
87 mbedtls_entropy_f_source_ptr f_source, void *p_source,
88 size_t threshold, int strong)
Jens Wiklander817466c2018-05-22 13:49:31 +020089{
90 int idx, ret = 0;
91
92#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +020093 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
94 return ret;
95 }
Jens Wiklander817466c2018-05-22 13:49:31 +020096#endif
97
98 idx = ctx->source_count;
Jens Wiklander32b31802023-10-06 16:59:46 +020099 if (idx >= MBEDTLS_ENTROPY_MAX_SOURCES) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200100 ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES;
101 goto exit;
102 }
103
104 ctx->source[idx].f_source = f_source;
105 ctx->source[idx].p_source = p_source;
106 ctx->source[idx].threshold = threshold;
107 ctx->source[idx].strong = strong;
108
109 ctx->source_count++;
110
111exit:
112#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200113 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
114 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
115 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200116#endif
117
Jens Wiklander32b31802023-10-06 16:59:46 +0200118 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200119}
120
121/*
122 * Entropy accumulator update
123 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200124static int entropy_update(mbedtls_entropy_context *ctx, unsigned char source_id,
125 const unsigned char *data, size_t len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200126{
127 unsigned char header[2];
128 unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE];
129 size_t use_len = len;
130 const unsigned char *p = data;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100131 int ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200132
Jens Wiklander32b31802023-10-06 16:59:46 +0200133 if (use_len > MBEDTLS_ENTROPY_BLOCK_SIZE) {
Tom Van Eyckb0563632024-06-13 16:20:14 +0200134 if ((ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD),
135 data, len, tmp)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100136 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +0200137 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200138 p = tmp;
139 use_len = MBEDTLS_ENTROPY_BLOCK_SIZE;
140 }
141
142 header[0] = source_id;
143 header[1] = use_len & 0xFF;
144
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100145 /*
146 * Start the accumulator if this has not already happened. Note that
147 * it is sufficient to start the accumulator here only because all calls to
148 * gather entropy eventually execute this code.
149 */
Tom Van Eyckb0563632024-06-13 16:20:14 +0200150 if (ctx->accumulator_started == 0) {
151 ret = mbedtls_md_setup(&ctx->accumulator,
152 mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD), 0);
153 if (ret != 0) {
154 goto cleanup;
155 }
156 ret = mbedtls_md_starts(&ctx->accumulator);
157 if (ret != 0) {
158 goto cleanup;
159 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100160 ctx->accumulator_started = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +0200161 }
Tom Van Eyckb0563632024-06-13 16:20:14 +0200162 if ((ret = mbedtls_md_update(&ctx->accumulator, header, 2)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100163 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +0200164 }
Tom Van Eyckb0563632024-06-13 16:20:14 +0200165 ret = mbedtls_md_update(&ctx->accumulator, p, use_len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200166
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100167cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200168 mbedtls_platform_zeroize(tmp, sizeof(tmp));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100169
Jens Wiklander32b31802023-10-06 16:59:46 +0200170 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200171}
172
Jens Wiklander32b31802023-10-06 16:59:46 +0200173int mbedtls_entropy_update_manual(mbedtls_entropy_context *ctx,
174 const unsigned char *data, size_t len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200175{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200176 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200177
178#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200179 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
180 return ret;
181 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200182#endif
183
Jens Wiklander32b31802023-10-06 16:59:46 +0200184 ret = entropy_update(ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200185
186#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200187 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
188 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
189 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200190#endif
191
Jens Wiklander32b31802023-10-06 16:59:46 +0200192 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200193}
194
195/*
196 * Run through the different sources to add entropy to our accumulator
197 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200198static int entropy_gather_internal(mbedtls_entropy_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +0200199{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200200 int ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
201 int i;
202 int have_one_strong = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200203 unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER];
204 size_t olen;
205
Jens Wiklander32b31802023-10-06 16:59:46 +0200206 if (ctx->source_count == 0) {
207 return MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED;
208 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200209
210 /*
211 * Run through our entropy sources
212 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200213 for (i = 0; i < ctx->source_count; i++) {
214 if (ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200215 have_one_strong = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +0200216 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200217
218 olen = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +0200219 if ((ret = ctx->source[i].f_source(ctx->source[i].p_source,
220 buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100221 goto cleanup;
Jens Wiklander817466c2018-05-22 13:49:31 +0200222 }
223
224 /*
225 * Add if we actually gathered something
226 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200227 if (olen > 0) {
228 if ((ret = entropy_update(ctx, (unsigned char) i,
229 buf, olen)) != 0) {
230 return ret;
231 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200232 ctx->source[i].size += olen;
233 }
234 }
235
Jens Wiklander32b31802023-10-06 16:59:46 +0200236 if (have_one_strong == 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100237 ret = MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE;
Jens Wiklander32b31802023-10-06 16:59:46 +0200238 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200239
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100240cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200241 mbedtls_platform_zeroize(buf, sizeof(buf));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100242
Jens Wiklander32b31802023-10-06 16:59:46 +0200243 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200244}
245
246/*
247 * Thread-safe wrapper for entropy_gather_internal()
248 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200249int mbedtls_entropy_gather(mbedtls_entropy_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +0200250{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200251 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200252
253#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200254 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
255 return ret;
256 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200257#endif
258
Jens Wiklander32b31802023-10-06 16:59:46 +0200259 ret = entropy_gather_internal(ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200260
261#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200262 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
263 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
264 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200265#endif
266
Jens Wiklander32b31802023-10-06 16:59:46 +0200267 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200268}
269
Jens Wiklander32b31802023-10-06 16:59:46 +0200270int mbedtls_entropy_func(void *data, unsigned char *output, size_t len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200271{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200272 int ret, count = 0, i, thresholds_reached;
273 size_t strong_size;
Jens Wiklander817466c2018-05-22 13:49:31 +0200274 mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data;
275 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
276
Jens Wiklander32b31802023-10-06 16:59:46 +0200277 if (len > MBEDTLS_ENTROPY_BLOCK_SIZE) {
278 return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
279 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200280
281#if defined(MBEDTLS_ENTROPY_NV_SEED)
282 /* Update the NV entropy seed before generating any entropy for outside
283 * use.
284 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200285 if (ctx->initial_entropy_run == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200286 ctx->initial_entropy_run = 1;
Jens Wiklander32b31802023-10-06 16:59:46 +0200287 if ((ret = mbedtls_entropy_update_nv_seed(ctx)) != 0) {
288 return ret;
289 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200290 }
291#endif
292
293#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200294 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
295 return ret;
296 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200297#endif
298
299 /*
300 * Always gather extra entropy before a call
301 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200302 do {
303 if (count++ > ENTROPY_MAX_LOOP) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200304 ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
305 goto exit;
306 }
307
Jens Wiklander32b31802023-10-06 16:59:46 +0200308 if ((ret = entropy_gather_internal(ctx)) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200309 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200310 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200311
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200312 thresholds_reached = 1;
313 strong_size = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +0200314 for (i = 0; i < ctx->source_count; i++) {
315 if (ctx->source[i].size < ctx->source[i].threshold) {
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200316 thresholds_reached = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +0200317 }
318 if (ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG) {
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200319 strong_size += ctx->source[i].size;
Jens Wiklander32b31802023-10-06 16:59:46 +0200320 }
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200321 }
Jens Wiklander32b31802023-10-06 16:59:46 +0200322 } while (!thresholds_reached || strong_size < MBEDTLS_ENTROPY_BLOCK_SIZE);
Jens Wiklander817466c2018-05-22 13:49:31 +0200323
Jens Wiklander32b31802023-10-06 16:59:46 +0200324 memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
Jens Wiklander817466c2018-05-22 13:49:31 +0200325
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100326 /*
327 * Note that at this stage it is assumed that the accumulator was started
328 * in a previous call to entropy_update(). If this is not guaranteed, the
329 * code below will fail.
330 */
Tom Van Eyckb0563632024-06-13 16:20:14 +0200331 if ((ret = mbedtls_md_finish(&ctx->accumulator, buf)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100332 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200333 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200334
335 /*
336 * Reset accumulator and counters and recycle existing entropy
337 */
Tom Van Eyckb0563632024-06-13 16:20:14 +0200338 mbedtls_md_free(&ctx->accumulator);
339 mbedtls_md_init(&ctx->accumulator);
340 ret = mbedtls_md_setup(&ctx->accumulator,
341 mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD), 0);
342 if (ret != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100343 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200344 }
Tom Van Eyckb0563632024-06-13 16:20:14 +0200345 ret = mbedtls_md_starts(&ctx->accumulator);
346 if (ret != 0) {
347 goto exit;
348 }
349 if ((ret = mbedtls_md_update(&ctx->accumulator, buf,
350 MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100351 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200352 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200353
354 /*
Tom Van Eyckb0563632024-06-13 16:20:14 +0200355 * Perform second hashing on entropy
Jens Wiklander817466c2018-05-22 13:49:31 +0200356 */
Tom Van Eyckb0563632024-06-13 16:20:14 +0200357 if ((ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD),
358 buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100359 goto exit;
Jens Wiklander32b31802023-10-06 16:59:46 +0200360 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200361
Jens Wiklander32b31802023-10-06 16:59:46 +0200362 for (i = 0; i < ctx->source_count; i++) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200363 ctx->source[i].size = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +0200364 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200365
Jens Wiklander32b31802023-10-06 16:59:46 +0200366 memcpy(output, buf, len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200367
368 ret = 0;
369
370exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200371 mbedtls_platform_zeroize(buf, sizeof(buf));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100372
Jens Wiklander817466c2018-05-22 13:49:31 +0200373#if defined(MBEDTLS_THREADING_C)
Jens Wiklander32b31802023-10-06 16:59:46 +0200374 if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
375 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
376 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200377#endif
378
Jens Wiklander32b31802023-10-06 16:59:46 +0200379 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200380}
381
382#if defined(MBEDTLS_ENTROPY_NV_SEED)
Jens Wiklander32b31802023-10-06 16:59:46 +0200383int mbedtls_entropy_update_nv_seed(mbedtls_entropy_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +0200384{
385 int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100386 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
Jens Wiklander817466c2018-05-22 13:49:31 +0200387
388 /* Read new seed and write it to NV */
Jens Wiklander32b31802023-10-06 16:59:46 +0200389 if ((ret = mbedtls_entropy_func(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) {
390 return ret;
391 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200392
Jens Wiklander32b31802023-10-06 16:59:46 +0200393 if (mbedtls_nv_seed_write(buf, MBEDTLS_ENTROPY_BLOCK_SIZE) < 0) {
394 return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
395 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200396
397 /* Manually update the remaining stream with a separator value to diverge */
Jens Wiklander32b31802023-10-06 16:59:46 +0200398 memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
399 ret = mbedtls_entropy_update_manual(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE);
Jens Wiklander817466c2018-05-22 13:49:31 +0200400
Jens Wiklander32b31802023-10-06 16:59:46 +0200401 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200402}
403#endif /* MBEDTLS_ENTROPY_NV_SEED */
404
405#if defined(MBEDTLS_FS_IO)
Jens Wiklander32b31802023-10-06 16:59:46 +0200406int mbedtls_entropy_write_seed_file(mbedtls_entropy_context *ctx, const char *path)
Jens Wiklander817466c2018-05-22 13:49:31 +0200407{
Jerome Forissier79013242021-07-28 10:24:04 +0200408 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
409 FILE *f = NULL;
Jens Wiklander817466c2018-05-22 13:49:31 +0200410 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
411
Jens Wiklander32b31802023-10-06 16:59:46 +0200412 if ((ret = mbedtls_entropy_func(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) {
Jerome Forissier79013242021-07-28 10:24:04 +0200413 ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200414 goto exit;
Jerome Forissier79013242021-07-28 10:24:04 +0200415 }
416
Jens Wiklander32b31802023-10-06 16:59:46 +0200417 if ((f = fopen(path, "wb")) == NULL) {
Jerome Forissier79013242021-07-28 10:24:04 +0200418 ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
419 goto exit;
420 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200421
Jens Wiklander32b31802023-10-06 16:59:46 +0200422 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
423 mbedtls_setbuf(f, NULL);
424
425 if (fwrite(buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f) != MBEDTLS_ENTROPY_BLOCK_SIZE) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200426 ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
427 goto exit;
428 }
429
430 ret = 0;
431
432exit:
Jens Wiklander32b31802023-10-06 16:59:46 +0200433 mbedtls_platform_zeroize(buf, sizeof(buf));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100434
Jens Wiklander32b31802023-10-06 16:59:46 +0200435 if (f != NULL) {
436 fclose(f);
437 }
Jerome Forissier79013242021-07-28 10:24:04 +0200438
Jens Wiklander32b31802023-10-06 16:59:46 +0200439 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200440}
441
Jens Wiklander32b31802023-10-06 16:59:46 +0200442int mbedtls_entropy_update_seed_file(mbedtls_entropy_context *ctx, const char *path)
Jens Wiklander817466c2018-05-22 13:49:31 +0200443{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100444 int ret = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200445 FILE *f;
446 size_t n;
Jens Wiklander32b31802023-10-06 16:59:46 +0200447 unsigned char buf[MBEDTLS_ENTROPY_MAX_SEED_SIZE];
Jens Wiklander817466c2018-05-22 13:49:31 +0200448
Jens Wiklander32b31802023-10-06 16:59:46 +0200449 if ((f = fopen(path, "rb")) == NULL) {
450 return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
451 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200452
Jens Wiklander32b31802023-10-06 16:59:46 +0200453 /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
454 mbedtls_setbuf(f, NULL);
Jens Wiklander817466c2018-05-22 13:49:31 +0200455
Jens Wiklander32b31802023-10-06 16:59:46 +0200456 fseek(f, 0, SEEK_END);
457 n = (size_t) ftell(f);
458 fseek(f, 0, SEEK_SET);
459
460 if (n > MBEDTLS_ENTROPY_MAX_SEED_SIZE) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200461 n = MBEDTLS_ENTROPY_MAX_SEED_SIZE;
Jens Wiklander32b31802023-10-06 16:59:46 +0200462 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200463
Jens Wiklander32b31802023-10-06 16:59:46 +0200464 if (fread(buf, 1, n, f) != n) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100465 ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
Jens Wiklander32b31802023-10-06 16:59:46 +0200466 } else {
467 ret = mbedtls_entropy_update_manual(ctx, buf, n);
468 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200469
Jens Wiklander32b31802023-10-06 16:59:46 +0200470 fclose(f);
Jens Wiklander817466c2018-05-22 13:49:31 +0200471
Jens Wiklander32b31802023-10-06 16:59:46 +0200472 mbedtls_platform_zeroize(buf, sizeof(buf));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100473
Jens Wiklander32b31802023-10-06 16:59:46 +0200474 if (ret != 0) {
475 return ret;
476 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200477
Jens Wiklander32b31802023-10-06 16:59:46 +0200478 return mbedtls_entropy_write_seed_file(ctx, path);
Jens Wiklander817466c2018-05-22 13:49:31 +0200479}
480#endif /* MBEDTLS_FS_IO */
481
482#if defined(MBEDTLS_SELF_TEST)
Jens Wiklander817466c2018-05-22 13:49:31 +0200483/*
484 * Dummy source function
485 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200486static int entropy_dummy_source(void *data, unsigned char *output,
487 size_t len, size_t *olen)
Jens Wiklander817466c2018-05-22 13:49:31 +0200488{
489 ((void) data);
490
Jens Wiklander32b31802023-10-06 16:59:46 +0200491 memset(output, 0x2a, len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200492 *olen = len;
493
Jens Wiklander32b31802023-10-06 16:59:46 +0200494 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200495}
Jens Wiklander817466c2018-05-22 13:49:31 +0200496
497#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
498
Jens Wiklander32b31802023-10-06 16:59:46 +0200499static int mbedtls_entropy_source_self_test_gather(unsigned char *buf, size_t buf_len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200500{
501 int ret = 0;
502 size_t entropy_len = 0;
503 size_t olen = 0;
504 size_t attempts = buf_len;
505
Jens Wiklander32b31802023-10-06 16:59:46 +0200506 while (attempts > 0 && entropy_len < buf_len) {
507 if ((ret = mbedtls_hardware_poll(NULL, buf + entropy_len,
508 buf_len - entropy_len, &olen)) != 0) {
509 return ret;
510 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200511
512 entropy_len += olen;
513 attempts--;
514 }
515
Jens Wiklander32b31802023-10-06 16:59:46 +0200516 if (entropy_len < buf_len) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200517 ret = 1;
518 }
519
Jens Wiklander32b31802023-10-06 16:59:46 +0200520 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200521}
522
523
Jens Wiklander32b31802023-10-06 16:59:46 +0200524static int mbedtls_entropy_source_self_test_check_bits(const unsigned char *buf,
525 size_t buf_len)
Jens Wiklander817466c2018-05-22 13:49:31 +0200526{
Jens Wiklander32b31802023-10-06 16:59:46 +0200527 unsigned char set = 0xFF;
Jens Wiklander817466c2018-05-22 13:49:31 +0200528 unsigned char unset = 0x00;
529 size_t i;
530
Jens Wiklander32b31802023-10-06 16:59:46 +0200531 for (i = 0; i < buf_len; i++) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200532 set &= buf[i];
533 unset |= buf[i];
534 }
535
Jens Wiklander32b31802023-10-06 16:59:46 +0200536 return set == 0xFF || unset == 0x00;
Jens Wiklander817466c2018-05-22 13:49:31 +0200537}
538
539/*
Jens Wiklander32b31802023-10-06 16:59:46 +0200540 * A test to ensure that the entropy sources are functioning correctly
Jens Wiklander817466c2018-05-22 13:49:31 +0200541 * and there is no obvious failure. The test performs the following checks:
542 * - The entropy source is not providing only 0s (all bits unset) or 1s (all
543 * bits set).
544 * - The entropy source is not providing values in a pattern. Because the
545 * hardware could be providing data in an arbitrary length, this check polls
546 * the hardware entropy source twice and compares the result to ensure they
547 * are not equal.
548 * - The error code returned by the entropy source is not an error.
549 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200550int mbedtls_entropy_source_self_test(int verbose)
Jens Wiklander817466c2018-05-22 13:49:31 +0200551{
552 int ret = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +0200553 unsigned char buf0[2 * sizeof(unsigned long long int)];
554 unsigned char buf1[2 * sizeof(unsigned long long int)];
Jens Wiklander817466c2018-05-22 13:49:31 +0200555
Jens Wiklander32b31802023-10-06 16:59:46 +0200556 if (verbose != 0) {
557 mbedtls_printf(" ENTROPY_BIAS test: ");
558 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200559
Jens Wiklander32b31802023-10-06 16:59:46 +0200560 memset(buf0, 0x00, sizeof(buf0));
561 memset(buf1, 0x00, sizeof(buf1));
Jens Wiklander817466c2018-05-22 13:49:31 +0200562
Jens Wiklander32b31802023-10-06 16:59:46 +0200563 if ((ret = mbedtls_entropy_source_self_test_gather(buf0, sizeof(buf0))) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200564 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +0200565 }
566 if ((ret = mbedtls_entropy_source_self_test_gather(buf1, sizeof(buf1))) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200567 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +0200568 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200569
570 /* Make sure that the returned values are not all 0 or 1 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200571 if ((ret = mbedtls_entropy_source_self_test_check_bits(buf0, sizeof(buf0))) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200572 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +0200573 }
574 if ((ret = mbedtls_entropy_source_self_test_check_bits(buf1, sizeof(buf1))) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200575 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +0200576 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200577
578 /* Make sure that the entropy source is not returning values in a
579 * pattern */
Jens Wiklander32b31802023-10-06 16:59:46 +0200580 ret = memcmp(buf0, buf1, sizeof(buf0)) == 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200581
582cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200583 if (verbose != 0) {
584 if (ret != 0) {
585 mbedtls_printf("failed\n");
586 } else {
587 mbedtls_printf("passed\n");
588 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200589
Jens Wiklander32b31802023-10-06 16:59:46 +0200590 mbedtls_printf("\n");
Jens Wiklander817466c2018-05-22 13:49:31 +0200591 }
592
Jens Wiklander32b31802023-10-06 16:59:46 +0200593 return ret != 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200594}
595
596#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */
597
598/*
599 * The actual entropy quality is hard to test, but we can at least
600 * test that the functions don't cause errors and write the correct
601 * amount of data to buffers.
602 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200603int mbedtls_entropy_self_test(int verbose)
Jens Wiklander817466c2018-05-22 13:49:31 +0200604{
605 int ret = 1;
Jens Wiklander817466c2018-05-22 13:49:31 +0200606 mbedtls_entropy_context ctx;
607 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
608 unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
609 size_t i, j;
Jens Wiklander817466c2018-05-22 13:49:31 +0200610
Jens Wiklander32b31802023-10-06 16:59:46 +0200611 if (verbose != 0) {
612 mbedtls_printf(" ENTROPY test: ");
613 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200614
Jens Wiklander32b31802023-10-06 16:59:46 +0200615 mbedtls_entropy_init(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200616
617 /* First do a gather to make sure we have default sources */
Jens Wiklander32b31802023-10-06 16:59:46 +0200618 if ((ret = mbedtls_entropy_gather(&ctx)) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200619 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +0200620 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200621
Jens Wiklander32b31802023-10-06 16:59:46 +0200622 ret = mbedtls_entropy_add_source(&ctx, entropy_dummy_source, NULL, 16,
623 MBEDTLS_ENTROPY_SOURCE_WEAK);
624 if (ret != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200625 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +0200626 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200627
Jens Wiklander32b31802023-10-06 16:59:46 +0200628 if ((ret = mbedtls_entropy_update_manual(&ctx, buf, sizeof(buf))) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200629 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +0200630 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200631
632 /*
633 * To test that mbedtls_entropy_func writes correct number of bytes:
634 * - use the whole buffer and rely on ASan to detect overruns
635 * - collect entropy 8 times and OR the result in an accumulator:
636 * any byte should then be 0 with probably 2^(-64), so requiring
637 * each of the 32 or 64 bytes to be non-zero has a false failure rate
638 * of at most 2^(-58) which is acceptable.
639 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200640 for (i = 0; i < 8; i++) {
641 if ((ret = mbedtls_entropy_func(&ctx, buf, sizeof(buf))) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200642 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +0200643 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200644
Jens Wiklander32b31802023-10-06 16:59:46 +0200645 for (j = 0; j < sizeof(buf); j++) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200646 acc[j] |= buf[j];
Jens Wiklander32b31802023-10-06 16:59:46 +0200647 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200648 }
649
Jens Wiklander32b31802023-10-06 16:59:46 +0200650 for (j = 0; j < sizeof(buf); j++) {
651 if (acc[j] == 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200652 ret = 1;
653 goto cleanup;
654 }
655 }
656
657#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
Jens Wiklander32b31802023-10-06 16:59:46 +0200658 if ((ret = mbedtls_entropy_source_self_test(0)) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200659 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +0200660 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200661#endif
662
663cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200664 mbedtls_entropy_free(&ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200665
Jens Wiklander32b31802023-10-06 16:59:46 +0200666 if (verbose != 0) {
667 if (ret != 0) {
668 mbedtls_printf("failed\n");
669 } else {
670 mbedtls_printf("passed\n");
671 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200672
Jens Wiklander32b31802023-10-06 16:59:46 +0200673 mbedtls_printf("\n");
Jens Wiklander817466c2018-05-22 13:49:31 +0200674 }
675
Jens Wiklander32b31802023-10-06 16:59:46 +0200676 return ret != 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200677}
678#endif /* MBEDTLS_SELF_TEST */
679
680#endif /* MBEDTLS_ENTROPY_C */