blob: e16200855d04650312bf3abf1545d9668a57ee5f [file] [log] [blame]
Paul Bakker6083fd22011-12-03 21:45:14 +00001/*
2 * Entropy accumulator implementation
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
Paul Bakker6083fd22011-12-03 21:45:14 +000018 */
19
Gilles Peskinedb09ef62020-06-03 01:43:33 +020020#include "common.h"
Paul Bakker6083fd22011-12-03 21:45:14 +000021
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020022#if defined(MBEDTLS_ENTROPY_C)
Paul Bakker6083fd22011-12-03 21:45:14 +000023
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020024# include "mbedtls/entropy.h"
25# include "entropy_poll.h"
26# include "mbedtls/platform_util.h"
27# include "mbedtls/error.h"
Paul Bakker6083fd22011-12-03 21:45:14 +000028
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020029# include <string.h>
Rich Evans00ab4702015-02-06 13:43:58 +000030
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020031# if defined(MBEDTLS_FS_IO)
32# include <stdio.h>
33# endif
Paul Bakker66ff70d2014-03-26 11:54:05 +010034
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020035# if defined(MBEDTLS_ENTROPY_NV_SEED)
36# include "mbedtls/platform.h"
37# endif
Paul Bakker217efbc2016-07-14 14:30:03 +010038
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020039# if defined(MBEDTLS_SELF_TEST)
40# if defined(MBEDTLS_PLATFORM_C)
41# include "mbedtls/platform.h"
42# else
43# include <stdio.h>
44# define mbedtls_printf printf
45# endif /* MBEDTLS_PLATFORM_C */
46# endif /* MBEDTLS_SELF_TEST */
Rich Evans00ab4702015-02-06 13:43:58 +000047
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020048# define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */
Paul Bakker28c7e7f2011-12-15 19:49:30 +000049
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020050void mbedtls_entropy_init(mbedtls_entropy_context *ctx)
Paul Bakker6083fd22011-12-03 21:45:14 +000051{
Andres Amaya Garciaa7559cb2017-06-29 16:12:31 +010052 ctx->source_count = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020053 memset(ctx->source, 0, sizeof(ctx->source));
Paul Bakker6083fd22011-12-03 21:45:14 +000054
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020055# if defined(MBEDTLS_THREADING_C)
56 mbedtls_mutex_init(&ctx->mutex);
57# endif
Paul Bakkerf4e7dc52013-09-28 15:23:57 +020058
Andres Amaya Garcia95869c42017-06-29 16:31:44 +010059 ctx->accumulator_started = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020060# if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
61 mbedtls_sha512_init(&ctx->accumulator);
62# else
63 mbedtls_sha256_init(&ctx->accumulator);
64# endif
Paul Bakker6083fd22011-12-03 21:45:14 +000065
Hanno Beckerd4a872e2017-09-07 08:09:33 +010066 /* Reminder: Update ENTROPY_HAVE_STRONG in the test files
Hanno Becker47deec42017-07-24 12:27:09 +010067 * when adding more strong entropy sources here. */
Hanno Beckerc6deafc2017-07-23 14:06:42 +010068
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020069# if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES)
70# if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
71 mbedtls_entropy_add_source(ctx, mbedtls_platform_entropy_poll, NULL,
72 MBEDTLS_ENTROPY_MIN_PLATFORM,
73 MBEDTLS_ENTROPY_SOURCE_STRONG);
74# endif
75# if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
76 mbedtls_entropy_add_source(ctx, mbedtls_hardware_poll, NULL,
77 MBEDTLS_ENTROPY_MIN_HARDWARE,
78 MBEDTLS_ENTROPY_SOURCE_STRONG);
79# endif
80# if defined(MBEDTLS_ENTROPY_NV_SEED)
81 mbedtls_entropy_add_source(ctx, mbedtls_nv_seed_poll, NULL,
82 MBEDTLS_ENTROPY_BLOCK_SIZE,
83 MBEDTLS_ENTROPY_SOURCE_STRONG);
Andres Amaya Garciaa7559cb2017-06-29 16:12:31 +010084 ctx->initial_entropy_run = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020085# endif
86# endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */
Paul Bakker6083fd22011-12-03 21:45:14 +000087}
88
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020089void mbedtls_entropy_free(mbedtls_entropy_context *ctx)
Paul Bakker1ffefac2013-09-28 15:23:03 +020090{
Gilles Peskineb1583212021-02-22 21:26:54 +010091 /* If the context was already free, don't call free() again.
92 * This is important for mutexes which don't allow double-free. */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020093 if (ctx->accumulator_started == -1)
Gilles Peskineb1583212021-02-22 21:26:54 +010094 return;
95
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +020096# if defined(MBEDTLS_THREADING_C)
97 mbedtls_mutex_free(&ctx->mutex);
98# endif
99# if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
100 mbedtls_sha512_free(&ctx->accumulator);
101# else
102 mbedtls_sha256_free(&ctx->accumulator);
103# endif
104# if defined(MBEDTLS_ENTROPY_NV_SEED)
Andres Amaya Garciaa7559cb2017-06-29 16:12:31 +0100105 ctx->initial_entropy_run = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200106# endif
Andres Amaya Garciaa7559cb2017-06-29 16:12:31 +0100107 ctx->source_count = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200108 mbedtls_platform_zeroize(ctx->source, sizeof(ctx->source));
Gilles Peskineb1583212021-02-22 21:26:54 +0100109 ctx->accumulator_started = -1;
Paul Bakker1ffefac2013-09-28 15:23:03 +0200110}
111
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200112int mbedtls_entropy_add_source(mbedtls_entropy_context *ctx,
113 mbedtls_entropy_f_source_ptr f_source,
114 void *p_source,
115 size_t threshold,
116 int strong)
Paul Bakker6083fd22011-12-03 21:45:14 +0000117{
Hanno Becker61937d42017-04-26 15:01:23 +0100118 int idx, ret = 0;
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000119
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200120# if defined(MBEDTLS_THREADING_C)
121 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0)
122 return ret;
123# endif
Paul Bakker47703a02014-02-06 15:01:20 +0100124
Hanno Becker61937d42017-04-26 15:01:23 +0100125 idx = ctx->source_count;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200126 if (idx >= MBEDTLS_ENTROPY_MAX_SOURCES) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200127 ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES;
Paul Bakker47703a02014-02-06 15:01:20 +0100128 goto exit;
129 }
Paul Bakker6083fd22011-12-03 21:45:14 +0000130
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200131 ctx->source[idx].f_source = f_source;
132 ctx->source[idx].p_source = p_source;
Hanno Becker61937d42017-04-26 15:01:23 +0100133 ctx->source[idx].threshold = threshold;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200134 ctx->source[idx].strong = strong;
Paul Bakker6083fd22011-12-03 21:45:14 +0000135
136 ctx->source_count++;
137
Paul Bakker47703a02014-02-06 15:01:20 +0100138exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200139# if defined(MBEDTLS_THREADING_C)
140 if (mbedtls_mutex_unlock(&ctx->mutex) != 0)
141 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
142# endif
Paul Bakker47703a02014-02-06 15:01:20 +0100143
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200144 return ret;
Paul Bakker6083fd22011-12-03 21:45:14 +0000145}
146
147/*
148 * Entropy accumulator update
149 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200150static int entropy_update(mbedtls_entropy_context *ctx,
151 unsigned char source_id,
152 const unsigned char *data,
153 size_t len)
Paul Bakker6083fd22011-12-03 21:45:14 +0000154{
155 unsigned char header[2];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200156 unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE];
Paul Bakker6083fd22011-12-03 21:45:14 +0000157 size_t use_len = len;
158 const unsigned char *p = data;
Jaeden Amero66954e12018-01-25 16:05:54 +0000159 int ret = 0;
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200160
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200161 if (use_len > MBEDTLS_ENTROPY_BLOCK_SIZE) {
162# if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
163 if ((ret = mbedtls_sha512(data, len, tmp, 0)) != 0)
Jaeden Amero66954e12018-01-25 16:05:54 +0000164 goto cleanup;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200165# else
166 if ((ret = mbedtls_sha256(data, len, tmp, 0)) != 0)
Jaeden Amero66954e12018-01-25 16:05:54 +0000167 goto cleanup;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200168# endif
Paul Bakker6083fd22011-12-03 21:45:14 +0000169 p = tmp;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200170 use_len = MBEDTLS_ENTROPY_BLOCK_SIZE;
Paul Bakker6083fd22011-12-03 21:45:14 +0000171 }
172
173 header[0] = source_id;
174 header[1] = use_len & 0xFF;
175
Andres Amaya Garcia95869c42017-06-29 16:31:44 +0100176 /*
177 * Start the accumulator if this has not already happened. Note that
178 * it is sufficient to start the accumulator here only because all calls to
179 * gather entropy eventually execute this code.
180 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200181# if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
182 if (ctx->accumulator_started == 0 &&
183 (ret = mbedtls_sha512_starts(&ctx->accumulator, 0)) != 0)
Jaeden Amero66954e12018-01-25 16:05:54 +0000184 goto cleanup;
Andres Amaya Garcia95869c42017-06-29 16:31:44 +0100185 else
186 ctx->accumulator_started = 1;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200187 if ((ret = mbedtls_sha512_update(&ctx->accumulator, header, 2)) != 0)
Jaeden Amero66954e12018-01-25 16:05:54 +0000188 goto cleanup;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200189 ret = mbedtls_sha512_update(&ctx->accumulator, p, use_len);
190# else
191 if (ctx->accumulator_started == 0 &&
192 (ret = mbedtls_sha256_starts(&ctx->accumulator, 0)) != 0)
Jaeden Amero66954e12018-01-25 16:05:54 +0000193 goto cleanup;
Andres Amaya Garcia95869c42017-06-29 16:31:44 +0100194 else
195 ctx->accumulator_started = 1;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200196 if ((ret = mbedtls_sha256_update(&ctx->accumulator, header, 2)) != 0)
Jaeden Amero66954e12018-01-25 16:05:54 +0000197 goto cleanup;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200198 ret = mbedtls_sha256_update(&ctx->accumulator, p, use_len);
199# endif
Paul Bakkerb6c5d2e2013-06-25 16:25:17 +0200200
Jaeden Amero66954e12018-01-25 16:05:54 +0000201cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200202 mbedtls_platform_zeroize(tmp, sizeof(tmp));
Andres Amaya Garcia65121932017-07-05 15:45:47 +0100203
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200204 return ret;
Paul Bakker6083fd22011-12-03 21:45:14 +0000205}
206
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200207int mbedtls_entropy_update_manual(mbedtls_entropy_context *ctx,
208 const unsigned char *data,
209 size_t len)
Paul Bakker6083fd22011-12-03 21:45:14 +0000210{
Janos Follath24eed8d2019-11-22 13:21:35 +0000211 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker47703a02014-02-06 15:01:20 +0100212
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200213# if defined(MBEDTLS_THREADING_C)
214 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0)
215 return ret;
216# endif
Paul Bakker47703a02014-02-06 15:01:20 +0100217
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200218 ret = entropy_update(ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len);
Paul Bakker47703a02014-02-06 15:01:20 +0100219
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200220# if defined(MBEDTLS_THREADING_C)
221 if (mbedtls_mutex_unlock(&ctx->mutex) != 0)
222 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
223# endif
Paul Bakker47703a02014-02-06 15:01:20 +0100224
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200225 return ret;
Paul Bakker6083fd22011-12-03 21:45:14 +0000226}
227
228/*
229 * Run through the different sources to add entropy to our accumulator
230 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200231static int entropy_gather_internal(mbedtls_entropy_context *ctx)
Paul Bakker6083fd22011-12-03 21:45:14 +0000232{
Gilles Peskine006c1b52019-09-30 17:29:54 +0200233 int ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
234 int i;
235 int have_one_strong = 0;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200236 unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER];
Paul Bakker6083fd22011-12-03 21:45:14 +0000237 size_t olen;
Paul Bakker47703a02014-02-06 15:01:20 +0100238
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200239 if (ctx->source_count == 0)
240 return MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED;
Paul Bakker43655f42011-12-15 20:11:16 +0000241
Paul Bakker6083fd22011-12-03 21:45:14 +0000242 /*
243 * Run through our entropy sources
244 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200245 for (i = 0; i < ctx->source_count; i++) {
246 if (ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG)
Manuel Pégourié-Gonnard7580ba42015-06-19 10:26:32 +0200247 have_one_strong = 1;
248
Paul Bakker6083fd22011-12-03 21:45:14 +0000249 olen = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200250 if ((ret = ctx->source[i].f_source(ctx->source[i].p_source, buf,
251 MBEDTLS_ENTROPY_MAX_GATHER,
252 &olen)) != 0) {
Andres Amaya Garcia1adcd952017-06-26 09:58:59 +0100253 goto cleanup;
Paul Bakker6083fd22011-12-03 21:45:14 +0000254 }
255
256 /*
257 * Add if we actually gathered something
258 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200259 if (olen > 0) {
260 if ((ret = entropy_update(ctx, (unsigned char)i, buf, olen)) != 0)
261 return ret;
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000262 ctx->source[i].size += olen;
263 }
Paul Bakker6083fd22011-12-03 21:45:14 +0000264 }
265
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200266 if (have_one_strong == 0)
Andres Amaya Garcia1adcd952017-06-26 09:58:59 +0100267 ret = MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE;
Manuel Pégourié-Gonnard7580ba42015-06-19 10:26:32 +0200268
Andres Amaya Garcia1adcd952017-06-26 09:58:59 +0100269cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200270 mbedtls_platform_zeroize(buf, sizeof(buf));
Andres Amaya Garcia1adcd952017-06-26 09:58:59 +0100271
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200272 return ret;
Paul Bakker6083fd22011-12-03 21:45:14 +0000273}
274
Paul Bakker47703a02014-02-06 15:01:20 +0100275/*
276 * Thread-safe wrapper for entropy_gather_internal()
277 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200278int mbedtls_entropy_gather(mbedtls_entropy_context *ctx)
Paul Bakker47703a02014-02-06 15:01:20 +0100279{
Janos Follath24eed8d2019-11-22 13:21:35 +0000280 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker47703a02014-02-06 15:01:20 +0100281
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200282# if defined(MBEDTLS_THREADING_C)
283 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0)
284 return ret;
285# endif
Paul Bakker47703a02014-02-06 15:01:20 +0100286
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200287 ret = entropy_gather_internal(ctx);
Paul Bakker47703a02014-02-06 15:01:20 +0100288
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200289# if defined(MBEDTLS_THREADING_C)
290 if (mbedtls_mutex_unlock(&ctx->mutex) != 0)
291 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
292# endif
Paul Bakker47703a02014-02-06 15:01:20 +0100293
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200294 return ret;
Paul Bakker47703a02014-02-06 15:01:20 +0100295}
296
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200297int mbedtls_entropy_func(void *data, unsigned char *output, size_t len)
Paul Bakker6083fd22011-12-03 21:45:14 +0000298{
Gilles Peskine85485c72019-10-08 15:04:16 +0200299 int ret, count = 0, i, thresholds_reached;
300 size_t strong_size;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200301 mbedtls_entropy_context *ctx = (mbedtls_entropy_context *)data;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200302 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
Paul Bakker6083fd22011-12-03 21:45:14 +0000303
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200304 if (len > MBEDTLS_ENTROPY_BLOCK_SIZE)
305 return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
Paul Bakker6083fd22011-12-03 21:45:14 +0000306
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200307# if defined(MBEDTLS_ENTROPY_NV_SEED)
Paul Bakkerd5c9f6d2016-06-01 11:30:54 +0100308 /* Update the NV entropy seed before generating any entropy for outside
309 * use.
310 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200311 if (ctx->initial_entropy_run == 0) {
Paul Bakkerfc9c7c82016-06-01 15:25:50 +0100312 ctx->initial_entropy_run = 1;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200313 if ((ret = mbedtls_entropy_update_nv_seed(ctx)) != 0)
314 return ret;
Paul Bakkerd5c9f6d2016-06-01 11:30:54 +0100315 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200316# endif
Paul Bakkerd5c9f6d2016-06-01 11:30:54 +0100317
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200318# if defined(MBEDTLS_THREADING_C)
319 if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0)
320 return ret;
321# endif
Paul Bakkerf4e7dc52013-09-28 15:23:57 +0200322
Paul Bakker6083fd22011-12-03 21:45:14 +0000323 /*
324 * Always gather extra entropy before a call
325 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200326 do {
327 if (count++ > ENTROPY_MAX_LOOP) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200328 ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
Paul Bakkerf4e7dc52013-09-28 15:23:57 +0200329 goto exit;
330 }
Paul Bakker6083fd22011-12-03 21:45:14 +0000331
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200332 if ((ret = entropy_gather_internal(ctx)) != 0)
Paul Bakkerf4e7dc52013-09-28 15:23:57 +0200333 goto exit;
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000334
Gilles Peskine85485c72019-10-08 15:04:16 +0200335 thresholds_reached = 1;
336 strong_size = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200337 for (i = 0; i < ctx->source_count; i++) {
338 if (ctx->source[i].size < ctx->source[i].threshold)
Gilles Peskine85485c72019-10-08 15:04:16 +0200339 thresholds_reached = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200340 if (ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG)
Gilles Peskine85485c72019-10-08 15:04:16 +0200341 strong_size += ctx->source[i].size;
342 }
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200343 } while (!thresholds_reached || strong_size < MBEDTLS_ENTROPY_BLOCK_SIZE);
Paul Bakker6083fd22011-12-03 21:45:14 +0000344
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200345 memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
Paul Bakker6083fd22011-12-03 21:45:14 +0000346
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200347# if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR)
Andres Amaya Garciab2b063f2017-07-20 16:45:24 +0100348 /*
349 * Note that at this stage it is assumed that the accumulator was started
350 * in a previous call to entropy_update(). If this is not guaranteed, the
351 * code below will fail.
352 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200353 if ((ret = mbedtls_sha512_finish(&ctx->accumulator, buf)) != 0)
Andres Amaya Garcia207cea52017-06-29 13:28:13 +0100354 goto exit;
Paul Bakker9e36f042013-06-30 14:34:05 +0200355
Paul Bakker6083fd22011-12-03 21:45:14 +0000356 /*
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000357 * Reset accumulator and counters and recycle existing entropy
Paul Bakker6083fd22011-12-03 21:45:14 +0000358 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200359 mbedtls_sha512_free(&ctx->accumulator);
360 mbedtls_sha512_init(&ctx->accumulator);
361 if ((ret = mbedtls_sha512_starts(&ctx->accumulator, 0)) != 0)
Andres Amaya Garcia207cea52017-06-29 13:28:13 +0100362 goto exit;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200363 if ((ret = mbedtls_sha512_update(&ctx->accumulator, buf,
364 MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0)
Andres Amaya Garcia207cea52017-06-29 13:28:13 +0100365 goto exit;
Paul Bakkerfb08fd22013-08-27 15:06:26 +0200366
367 /*
Paul Bakkerb13d3ff2014-03-26 12:51:25 +0100368 * Perform second SHA-512 on entropy
Paul Bakkerfb08fd22013-08-27 15:06:26 +0200369 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200370 if ((ret = mbedtls_sha512(buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf, 0)) != 0)
Andres Amaya Garcia207cea52017-06-29 13:28:13 +0100371 goto exit;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200372# else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */
373 if ((ret = mbedtls_sha256_finish(&ctx->accumulator, buf)) != 0)
Andres Amaya Garcia207cea52017-06-29 13:28:13 +0100374 goto exit;
Paul Bakkerfb08fd22013-08-27 15:06:26 +0200375
376 /*
377 * Reset accumulator and counters and recycle existing entropy
378 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200379 mbedtls_sha256_free(&ctx->accumulator);
380 mbedtls_sha256_init(&ctx->accumulator);
381 if ((ret = mbedtls_sha256_starts(&ctx->accumulator, 0)) != 0)
Andres Amaya Garcia207cea52017-06-29 13:28:13 +0100382 goto exit;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200383 if ((ret = mbedtls_sha256_update(&ctx->accumulator, buf,
384 MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0)
Andres Amaya Garcia207cea52017-06-29 13:28:13 +0100385 goto exit;
Paul Bakkerb13d3ff2014-03-26 12:51:25 +0100386
387 /*
388 * Perform second SHA-256 on entropy
389 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200390 if ((ret = mbedtls_sha256(buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf, 0)) != 0)
Andres Amaya Garcia207cea52017-06-29 13:28:13 +0100391 goto exit;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200392# endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000393
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200394 for (i = 0; i < ctx->source_count; i++)
Paul Bakkerbd4a9d02011-12-10 17:02:19 +0000395 ctx->source[i].size = 0;
Paul Bakker6083fd22011-12-03 21:45:14 +0000396
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200397 memcpy(output, buf, len);
Paul Bakker6083fd22011-12-03 21:45:14 +0000398
Paul Bakkerf4e7dc52013-09-28 15:23:57 +0200399 ret = 0;
400
401exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200402 mbedtls_platform_zeroize(buf, sizeof(buf));
Andres Amaya Garcia1adcd952017-06-26 09:58:59 +0100403
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200404# if defined(MBEDTLS_THREADING_C)
405 if (mbedtls_mutex_unlock(&ctx->mutex) != 0)
406 return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
407# endif
Paul Bakkerf4e7dc52013-09-28 15:23:57 +0200408
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200409 return ret;
Paul Bakker6083fd22011-12-03 21:45:14 +0000410}
411
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200412# if defined(MBEDTLS_ENTROPY_NV_SEED)
413int mbedtls_entropy_update_nv_seed(mbedtls_entropy_context *ctx)
Paul Bakkerd5c9f6d2016-06-01 11:30:54 +0100414{
415 int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
Andres Amaya Garciaaf0b31d2017-07-05 14:23:54 +0100416 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
Paul Bakkerd5c9f6d2016-06-01 11:30:54 +0100417
418 /* Read new seed and write it to NV */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200419 if ((ret = mbedtls_entropy_func(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0)
420 return ret;
Paul Bakkerd5c9f6d2016-06-01 11:30:54 +0100421
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200422 if (mbedtls_nv_seed_write(buf, MBEDTLS_ENTROPY_BLOCK_SIZE) < 0)
423 return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
Paul Bakkerd5c9f6d2016-06-01 11:30:54 +0100424
425 /* Manually update the remaining stream with a separator value to diverge */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200426 memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
427 ret = mbedtls_entropy_update_manual(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE);
Paul Bakkerd5c9f6d2016-06-01 11:30:54 +0100428
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200429 return ret;
Paul Bakkerd5c9f6d2016-06-01 11:30:54 +0100430}
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200431# endif /* MBEDTLS_ENTROPY_NV_SEED */
Paul Bakkerd5c9f6d2016-06-01 11:30:54 +0100432
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200433# if defined(MBEDTLS_FS_IO)
434int mbedtls_entropy_write_seed_file(mbedtls_entropy_context *ctx,
435 const char *path)
Paul Bakker66ff70d2014-03-26 11:54:05 +0100436{
Victor Krasnoshchoka0c2d192020-09-03 00:07:05 +0300437 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Victor Krasnoshchoke79812e2020-08-27 00:19:55 +0300438 FILE *f = NULL;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200439 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
Paul Bakker66ff70d2014-03-26 11:54:05 +0100440
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200441 if ((ret = mbedtls_entropy_func(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE)) !=
442 0) {
Victor Krasnoshchokb3129ba2020-08-29 22:54:37 +0300443 ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
Paul Bakker66ff70d2014-03-26 11:54:05 +0100444 goto exit;
Victor Krasnoshchokb3129ba2020-08-29 22:54:37 +0300445 }
446
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200447 if ((f = fopen(path, "wb")) == NULL) {
Victor Krasnoshchokb3129ba2020-08-29 22:54:37 +0300448 ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
449 goto exit;
450 }
Paul Bakker66ff70d2014-03-26 11:54:05 +0100451
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200452 if (fwrite(buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f) !=
453 MBEDTLS_ENTROPY_BLOCK_SIZE) {
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200454 ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
Paul Bakker66ff70d2014-03-26 11:54:05 +0100455 goto exit;
456 }
457
458 ret = 0;
459
460exit:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200461 mbedtls_platform_zeroize(buf, sizeof(buf));
Andres Amaya Garcia1adcd952017-06-26 09:58:59 +0100462
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200463 if (f != NULL)
464 fclose(f);
Victor Krasnoshchoke79812e2020-08-27 00:19:55 +0300465
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200466 return ret;
Paul Bakker66ff70d2014-03-26 11:54:05 +0100467}
468
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200469int mbedtls_entropy_update_seed_file(mbedtls_entropy_context *ctx,
470 const char *path)
Paul Bakker66ff70d2014-03-26 11:54:05 +0100471{
Andres Amaya Garcia1adcd952017-06-26 09:58:59 +0100472 int ret = 0;
Paul Bakker66ff70d2014-03-26 11:54:05 +0100473 FILE *f;
474 size_t n;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200475 unsigned char buf[MBEDTLS_ENTROPY_MAX_SEED_SIZE];
Paul Bakker66ff70d2014-03-26 11:54:05 +0100476
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200477 if ((f = fopen(path, "rb")) == NULL)
478 return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
Paul Bakker66ff70d2014-03-26 11:54:05 +0100479
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200480 fseek(f, 0, SEEK_END);
481 n = (size_t)ftell(f);
482 fseek(f, 0, SEEK_SET);
Paul Bakker66ff70d2014-03-26 11:54:05 +0100483
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200484 if (n > MBEDTLS_ENTROPY_MAX_SEED_SIZE)
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200485 n = MBEDTLS_ENTROPY_MAX_SEED_SIZE;
Paul Bakker66ff70d2014-03-26 11:54:05 +0100486
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200487 if (fread(buf, 1, n, f) != n)
Andres Amaya Garcia1adcd952017-06-26 09:58:59 +0100488 ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
489 else
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200490 ret = mbedtls_entropy_update_manual(ctx, buf, n);
Paul Bakker66ff70d2014-03-26 11:54:05 +0100491
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200492 fclose(f);
Paul Bakker66ff70d2014-03-26 11:54:05 +0100493
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200494 mbedtls_platform_zeroize(buf, sizeof(buf));
Andres Amaya Garcia1adcd952017-06-26 09:58:59 +0100495
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200496 if (ret != 0)
497 return ret;
Paul Bakker66ff70d2014-03-26 11:54:05 +0100498
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200499 return mbedtls_entropy_write_seed_file(ctx, path);
Paul Bakker66ff70d2014-03-26 11:54:05 +0100500}
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200501# endif /* MBEDTLS_FS_IO */
Paul Bakker66ff70d2014-03-26 11:54:05 +0100502
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200503# if defined(MBEDTLS_SELF_TEST)
Manuel Pégourié-Gonnard4dd73922014-05-30 10:34:15 +0200504/*
505 * Dummy source function
506 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200507static int entropy_dummy_source(void *data,
508 unsigned char *output,
509 size_t len,
510 size_t *olen)
Manuel Pégourié-Gonnard4dd73922014-05-30 10:34:15 +0200511{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200512 ((void)data);
Manuel Pégourié-Gonnard4dd73922014-05-30 10:34:15 +0200513
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200514 memset(output, 0x2a, len);
Manuel Pégourié-Gonnard4dd73922014-05-30 10:34:15 +0200515 *olen = len;
516
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200517 return 0;
Manuel Pégourié-Gonnard4dd73922014-05-30 10:34:15 +0200518}
519
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200520# if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
Andres AGb34e42e2016-08-22 11:08:50 +0100521
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200522static int mbedtls_entropy_source_self_test_gather(unsigned char *buf,
523 size_t buf_len)
Andres AGe7723ec2016-08-25 10:18:50 +0100524{
525 int ret = 0;
526 size_t entropy_len = 0;
527 size_t olen = 0;
528 size_t attempts = buf_len;
529
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200530 while (attempts > 0 && entropy_len < buf_len) {
531 if ((ret = mbedtls_hardware_poll(NULL, buf + entropy_len,
532 buf_len - entropy_len, &olen)) != 0)
533 return ret;
Andres AGe7723ec2016-08-25 10:18:50 +0100534
535 entropy_len += olen;
536 attempts--;
537 }
538
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200539 if (entropy_len < buf_len) {
Andres AGe7723ec2016-08-25 10:18:50 +0100540 ret = 1;
541 }
542
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200543 return ret;
Andres AGe7723ec2016-08-25 10:18:50 +0100544}
545
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200546static int mbedtls_entropy_source_self_test_check_bits(const unsigned char *buf,
547 size_t buf_len)
Andres AGe7723ec2016-08-25 10:18:50 +0100548{
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200549 unsigned char set = 0xFF;
Andres AGe7723ec2016-08-25 10:18:50 +0100550 unsigned char unset = 0x00;
551 size_t i;
552
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200553 for (i = 0; i < buf_len; i++) {
Andres AGe7723ec2016-08-25 10:18:50 +0100554 set &= buf[i];
555 unset |= buf[i];
556 }
557
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200558 return set == 0xFF || unset == 0x00;
Andres AGe7723ec2016-08-25 10:18:50 +0100559}
Andres AGb34e42e2016-08-22 11:08:50 +0100560
561/*
Andres AGe7723ec2016-08-25 10:18:50 +0100562 * A test to ensure hat the entropy sources are functioning correctly
563 * and there is no obvious failure. The test performs the following checks:
Andres AGb34e42e2016-08-22 11:08:50 +0100564 * - The entropy source is not providing only 0s (all bits unset) or 1s (all
565 * bits set).
566 * - The entropy source is not providing values in a pattern. Because the
Andres AGe7723ec2016-08-25 10:18:50 +0100567 * hardware could be providing data in an arbitrary length, this check polls
568 * the hardware entropy source twice and compares the result to ensure they
569 * are not equal.
Andres AGb34e42e2016-08-22 11:08:50 +0100570 * - The error code returned by the entropy source is not an error.
571 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200572int mbedtls_entropy_source_self_test(int verbose)
Andres AGb34e42e2016-08-22 11:08:50 +0100573{
574 int ret = 0;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200575 unsigned char buf0[2 * sizeof(unsigned long long int)];
576 unsigned char buf1[2 * sizeof(unsigned long long int)];
Andres AGb34e42e2016-08-22 11:08:50 +0100577
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200578 if (verbose != 0)
579 mbedtls_printf(" ENTROPY_BIAS test: ");
Andres AGb34e42e2016-08-22 11:08:50 +0100580
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200581 memset(buf0, 0x00, sizeof(buf0));
582 memset(buf1, 0x00, sizeof(buf1));
Andres AGb34e42e2016-08-22 11:08:50 +0100583
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200584 if ((ret = mbedtls_entropy_source_self_test_gather(buf0, sizeof(buf0))) !=
585 0)
Andres AGb34e42e2016-08-22 11:08:50 +0100586 goto cleanup;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200587 if ((ret = mbedtls_entropy_source_self_test_gather(buf1, sizeof(buf1))) !=
588 0)
Andres AGe7723ec2016-08-25 10:18:50 +0100589 goto cleanup;
590
591 /* Make sure that the returned values are not all 0 or 1 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200592 if ((ret = mbedtls_entropy_source_self_test_check_bits(buf0,
593 sizeof(buf0))) != 0)
Andres AGe7723ec2016-08-25 10:18:50 +0100594 goto cleanup;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200595 if ((ret = mbedtls_entropy_source_self_test_check_bits(buf1,
596 sizeof(buf1))) != 0)
Andres AGe7723ec2016-08-25 10:18:50 +0100597 goto cleanup;
Andres AGb34e42e2016-08-22 11:08:50 +0100598
599 /* Make sure that the entropy source is not returning values in a
600 * pattern */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200601 ret = memcmp(buf0, buf1, sizeof(buf0)) == 0;
Andres AGb34e42e2016-08-22 11:08:50 +0100602
603cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200604 if (verbose != 0) {
605 if (ret != 0)
606 mbedtls_printf("failed\n");
Andres AGb34e42e2016-08-22 11:08:50 +0100607 else
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200608 mbedtls_printf("passed\n");
Andres AGb34e42e2016-08-22 11:08:50 +0100609
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200610 mbedtls_printf("\n");
Andres AGb34e42e2016-08-22 11:08:50 +0100611 }
612
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200613 return ret != 0;
Andres AGb34e42e2016-08-22 11:08:50 +0100614}
Andres AGe7723ec2016-08-25 10:18:50 +0100615
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200616# endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */
Andres AGb34e42e2016-08-22 11:08:50 +0100617
Manuel Pégourié-Gonnard4dd73922014-05-30 10:34:15 +0200618/*
619 * The actual entropy quality is hard to test, but we can at least
620 * test that the functions don't cause errors and write the correct
621 * amount of data to buffers.
622 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200623int mbedtls_entropy_self_test(int verbose)
Manuel Pégourié-Gonnard4dd73922014-05-30 10:34:15 +0200624{
Andres Amaya Garciaa928e672016-09-13 13:30:02 +0100625 int ret = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200626 mbedtls_entropy_context ctx;
627 unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
628 unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
Manuel Pégourié-Gonnard4dd73922014-05-30 10:34:15 +0200629 size_t i, j;
630
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200631 if (verbose != 0)
632 mbedtls_printf(" ENTROPY test: ");
Manuel Pégourié-Gonnard4dd73922014-05-30 10:34:15 +0200633
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200634 mbedtls_entropy_init(&ctx);
Manuel Pégourié-Gonnard4dd73922014-05-30 10:34:15 +0200635
Manuel Pégourié-Gonnard7580ba42015-06-19 10:26:32 +0200636 /* First do a gather to make sure we have default sources */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200637 if ((ret = mbedtls_entropy_gather(&ctx)) != 0)
Manuel Pégourié-Gonnard4dd73922014-05-30 10:34:15 +0200638 goto cleanup;
639
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200640 ret = mbedtls_entropy_add_source(&ctx, entropy_dummy_source, NULL, 16,
641 MBEDTLS_ENTROPY_SOURCE_WEAK);
642 if (ret != 0)
Manuel Pégourié-Gonnard4dd73922014-05-30 10:34:15 +0200643 goto cleanup;
644
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200645 if ((ret = mbedtls_entropy_update_manual(&ctx, buf, sizeof(buf))) != 0)
Manuel Pégourié-Gonnard4dd73922014-05-30 10:34:15 +0200646 goto cleanup;
647
648 /*
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200649 * To test that mbedtls_entropy_func writes correct number of bytes:
Manuel Pégourié-Gonnard4dd73922014-05-30 10:34:15 +0200650 * - use the whole buffer and rely on ASan to detect overruns
651 * - collect entropy 8 times and OR the result in an accumulator:
652 * any byte should then be 0 with probably 2^(-64), so requiring
653 * each of the 32 or 64 bytes to be non-zero has a false failure rate
654 * of at most 2^(-58) which is acceptable.
655 */
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200656 for (i = 0; i < 8; i++) {
657 if ((ret = mbedtls_entropy_func(&ctx, buf, sizeof(buf))) != 0)
Manuel Pégourié-Gonnard4dd73922014-05-30 10:34:15 +0200658 goto cleanup;
659
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200660 for (j = 0; j < sizeof(buf); j++)
Manuel Pégourié-Gonnard4dd73922014-05-30 10:34:15 +0200661 acc[j] |= buf[j];
662 }
663
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200664 for (j = 0; j < sizeof(buf); j++) {
665 if (acc[j] == 0) {
Manuel Pégourié-Gonnard4dd73922014-05-30 10:34:15 +0200666 ret = 1;
667 goto cleanup;
668 }
669 }
670
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200671# if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
672 if ((ret = mbedtls_entropy_source_self_test(0)) != 0)
Andres AGe7723ec2016-08-25 10:18:50 +0100673 goto cleanup;
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200674# endif
Andres AGe7723ec2016-08-25 10:18:50 +0100675
Manuel Pégourié-Gonnard4dd73922014-05-30 10:34:15 +0200676cleanup:
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200677 mbedtls_entropy_free(&ctx);
Manuel Pégourié-Gonnard4dd73922014-05-30 10:34:15 +0200678
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200679 if (verbose != 0) {
680 if (ret != 0)
681 mbedtls_printf("failed\n");
Manuel Pégourié-Gonnard4dd73922014-05-30 10:34:15 +0200682 else
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200683 mbedtls_printf("passed\n");
Manuel Pégourié-Gonnard4dd73922014-05-30 10:34:15 +0200684
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200685 mbedtls_printf("\n");
Manuel Pégourié-Gonnard4dd73922014-05-30 10:34:15 +0200686 }
687
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200688 return ret != 0;
Manuel Pégourié-Gonnard4dd73922014-05-30 10:34:15 +0200689}
Mateusz Starzykc0eabdc2021-08-03 14:09:02 +0200690# endif /* MBEDTLS_SELF_TEST */
Manuel Pégourié-Gonnard4dd73922014-05-30 10:34:15 +0200691
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200692#endif /* MBEDTLS_ENTROPY_C */