1*62c56f98SSadaf Ebrahimi /*
2*62c56f98SSadaf Ebrahimi * Entropy accumulator implementation
3*62c56f98SSadaf Ebrahimi *
4*62c56f98SSadaf Ebrahimi * Copyright The Mbed TLS Contributors
5*62c56f98SSadaf Ebrahimi * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6*62c56f98SSadaf Ebrahimi */
7*62c56f98SSadaf Ebrahimi
8*62c56f98SSadaf Ebrahimi #include "common.h"
9*62c56f98SSadaf Ebrahimi
10*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ENTROPY_C)
11*62c56f98SSadaf Ebrahimi
12*62c56f98SSadaf Ebrahimi #include "mbedtls/entropy.h"
13*62c56f98SSadaf Ebrahimi #include "entropy_poll.h"
14*62c56f98SSadaf Ebrahimi #include "mbedtls/platform_util.h"
15*62c56f98SSadaf Ebrahimi #include "mbedtls/error.h"
16*62c56f98SSadaf Ebrahimi
17*62c56f98SSadaf Ebrahimi #include <string.h>
18*62c56f98SSadaf Ebrahimi
19*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_FS_IO)
20*62c56f98SSadaf Ebrahimi #include <stdio.h>
21*62c56f98SSadaf Ebrahimi #endif
22*62c56f98SSadaf Ebrahimi
23*62c56f98SSadaf Ebrahimi #include "mbedtls/platform.h"
24*62c56f98SSadaf Ebrahimi
25*62c56f98SSadaf Ebrahimi #define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */
26*62c56f98SSadaf Ebrahimi
mbedtls_entropy_init(mbedtls_entropy_context * ctx)27*62c56f98SSadaf Ebrahimi void mbedtls_entropy_init(mbedtls_entropy_context *ctx)
28*62c56f98SSadaf Ebrahimi {
29*62c56f98SSadaf Ebrahimi ctx->source_count = 0;
30*62c56f98SSadaf Ebrahimi memset(ctx->source, 0, sizeof(ctx->source));
31*62c56f98SSadaf Ebrahimi
32*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
33*62c56f98SSadaf Ebrahimi mbedtls_mutex_init(&ctx->mutex);
34*62c56f98SSadaf Ebrahimi #endif
35*62c56f98SSadaf Ebrahimi
36*62c56f98SSadaf Ebrahimi ctx->accumulator_started = 0;
37*62c56f98SSadaf Ebrahimi mbedtls_md_init(&ctx->accumulator);
38*62c56f98SSadaf Ebrahimi
39*62c56f98SSadaf Ebrahimi /* Reminder: Update ENTROPY_HAVE_STRONG in the test files
40*62c56f98SSadaf Ebrahimi * when adding more strong entropy sources here. */
41*62c56f98SSadaf Ebrahimi
42*62c56f98SSadaf Ebrahimi #if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES)
43*62c56f98SSadaf Ebrahimi #if !defined(MBEDTLS_NO_PLATFORM_ENTROPY)
44*62c56f98SSadaf Ebrahimi mbedtls_entropy_add_source(ctx, mbedtls_platform_entropy_poll, NULL,
45*62c56f98SSadaf Ebrahimi MBEDTLS_ENTROPY_MIN_PLATFORM,
46*62c56f98SSadaf Ebrahimi MBEDTLS_ENTROPY_SOURCE_STRONG);
47*62c56f98SSadaf Ebrahimi #endif
48*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
49*62c56f98SSadaf Ebrahimi mbedtls_entropy_add_source(ctx, mbedtls_hardware_poll, NULL,
50*62c56f98SSadaf Ebrahimi MBEDTLS_ENTROPY_MIN_HARDWARE,
51*62c56f98SSadaf Ebrahimi MBEDTLS_ENTROPY_SOURCE_STRONG);
52*62c56f98SSadaf Ebrahimi #endif
53*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ENTROPY_NV_SEED)
54*62c56f98SSadaf Ebrahimi mbedtls_entropy_add_source(ctx, mbedtls_nv_seed_poll, NULL,
55*62c56f98SSadaf Ebrahimi MBEDTLS_ENTROPY_BLOCK_SIZE,
56*62c56f98SSadaf Ebrahimi MBEDTLS_ENTROPY_SOURCE_STRONG);
57*62c56f98SSadaf Ebrahimi ctx->initial_entropy_run = 0;
58*62c56f98SSadaf Ebrahimi #endif
59*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */
60*62c56f98SSadaf Ebrahimi }
61*62c56f98SSadaf Ebrahimi
mbedtls_entropy_free(mbedtls_entropy_context * ctx)62*62c56f98SSadaf Ebrahimi void mbedtls_entropy_free(mbedtls_entropy_context *ctx)
63*62c56f98SSadaf Ebrahimi {
64*62c56f98SSadaf Ebrahimi /* If the context was already free, don't call free() again.
65*62c56f98SSadaf Ebrahimi * This is important for mutexes which don't allow double-free. */
66*62c56f98SSadaf Ebrahimi if (ctx->accumulator_started == -1) {
67*62c56f98SSadaf Ebrahimi return;
68*62c56f98SSadaf Ebrahimi }
69*62c56f98SSadaf Ebrahimi
70*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
71*62c56f98SSadaf Ebrahimi mbedtls_mutex_free(&ctx->mutex);
72*62c56f98SSadaf Ebrahimi #endif
73*62c56f98SSadaf Ebrahimi mbedtls_md_free(&ctx->accumulator);
74*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ENTROPY_NV_SEED)
75*62c56f98SSadaf Ebrahimi ctx->initial_entropy_run = 0;
76*62c56f98SSadaf Ebrahimi #endif
77*62c56f98SSadaf Ebrahimi ctx->source_count = 0;
78*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(ctx->source, sizeof(ctx->source));
79*62c56f98SSadaf Ebrahimi ctx->accumulator_started = -1;
80*62c56f98SSadaf Ebrahimi }
81*62c56f98SSadaf Ebrahimi
mbedtls_entropy_add_source(mbedtls_entropy_context * ctx,mbedtls_entropy_f_source_ptr f_source,void * p_source,size_t threshold,int strong)82*62c56f98SSadaf Ebrahimi int mbedtls_entropy_add_source(mbedtls_entropy_context *ctx,
83*62c56f98SSadaf Ebrahimi mbedtls_entropy_f_source_ptr f_source, void *p_source,
84*62c56f98SSadaf Ebrahimi size_t threshold, int strong)
85*62c56f98SSadaf Ebrahimi {
86*62c56f98SSadaf Ebrahimi int idx, ret = 0;
87*62c56f98SSadaf Ebrahimi
88*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
89*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
90*62c56f98SSadaf Ebrahimi return ret;
91*62c56f98SSadaf Ebrahimi }
92*62c56f98SSadaf Ebrahimi #endif
93*62c56f98SSadaf Ebrahimi
94*62c56f98SSadaf Ebrahimi idx = ctx->source_count;
95*62c56f98SSadaf Ebrahimi if (idx >= MBEDTLS_ENTROPY_MAX_SOURCES) {
96*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES;
97*62c56f98SSadaf Ebrahimi goto exit;
98*62c56f98SSadaf Ebrahimi }
99*62c56f98SSadaf Ebrahimi
100*62c56f98SSadaf Ebrahimi ctx->source[idx].f_source = f_source;
101*62c56f98SSadaf Ebrahimi ctx->source[idx].p_source = p_source;
102*62c56f98SSadaf Ebrahimi ctx->source[idx].threshold = threshold;
103*62c56f98SSadaf Ebrahimi ctx->source[idx].strong = strong;
104*62c56f98SSadaf Ebrahimi
105*62c56f98SSadaf Ebrahimi ctx->source_count++;
106*62c56f98SSadaf Ebrahimi
107*62c56f98SSadaf Ebrahimi exit:
108*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
109*62c56f98SSadaf Ebrahimi if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
110*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
111*62c56f98SSadaf Ebrahimi }
112*62c56f98SSadaf Ebrahimi #endif
113*62c56f98SSadaf Ebrahimi
114*62c56f98SSadaf Ebrahimi return ret;
115*62c56f98SSadaf Ebrahimi }
116*62c56f98SSadaf Ebrahimi
117*62c56f98SSadaf Ebrahimi /*
118*62c56f98SSadaf Ebrahimi * Entropy accumulator update
119*62c56f98SSadaf Ebrahimi */
entropy_update(mbedtls_entropy_context * ctx,unsigned char source_id,const unsigned char * data,size_t len)120*62c56f98SSadaf Ebrahimi static int entropy_update(mbedtls_entropy_context *ctx, unsigned char source_id,
121*62c56f98SSadaf Ebrahimi const unsigned char *data, size_t len)
122*62c56f98SSadaf Ebrahimi {
123*62c56f98SSadaf Ebrahimi unsigned char header[2];
124*62c56f98SSadaf Ebrahimi unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE];
125*62c56f98SSadaf Ebrahimi size_t use_len = len;
126*62c56f98SSadaf Ebrahimi const unsigned char *p = data;
127*62c56f98SSadaf Ebrahimi int ret = 0;
128*62c56f98SSadaf Ebrahimi
129*62c56f98SSadaf Ebrahimi if (use_len > MBEDTLS_ENTROPY_BLOCK_SIZE) {
130*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD),
131*62c56f98SSadaf Ebrahimi data, len, tmp)) != 0) {
132*62c56f98SSadaf Ebrahimi goto cleanup;
133*62c56f98SSadaf Ebrahimi }
134*62c56f98SSadaf Ebrahimi p = tmp;
135*62c56f98SSadaf Ebrahimi use_len = MBEDTLS_ENTROPY_BLOCK_SIZE;
136*62c56f98SSadaf Ebrahimi }
137*62c56f98SSadaf Ebrahimi
138*62c56f98SSadaf Ebrahimi header[0] = source_id;
139*62c56f98SSadaf Ebrahimi header[1] = use_len & 0xFF;
140*62c56f98SSadaf Ebrahimi
141*62c56f98SSadaf Ebrahimi /*
142*62c56f98SSadaf Ebrahimi * Start the accumulator if this has not already happened. Note that
143*62c56f98SSadaf Ebrahimi * it is sufficient to start the accumulator here only because all calls to
144*62c56f98SSadaf Ebrahimi * gather entropy eventually execute this code.
145*62c56f98SSadaf Ebrahimi */
146*62c56f98SSadaf Ebrahimi if (ctx->accumulator_started == 0) {
147*62c56f98SSadaf Ebrahimi ret = mbedtls_md_setup(&ctx->accumulator,
148*62c56f98SSadaf Ebrahimi mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD), 0);
149*62c56f98SSadaf Ebrahimi if (ret != 0) {
150*62c56f98SSadaf Ebrahimi goto cleanup;
151*62c56f98SSadaf Ebrahimi }
152*62c56f98SSadaf Ebrahimi ret = mbedtls_md_starts(&ctx->accumulator);
153*62c56f98SSadaf Ebrahimi if (ret != 0) {
154*62c56f98SSadaf Ebrahimi goto cleanup;
155*62c56f98SSadaf Ebrahimi }
156*62c56f98SSadaf Ebrahimi ctx->accumulator_started = 1;
157*62c56f98SSadaf Ebrahimi }
158*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_md_update(&ctx->accumulator, header, 2)) != 0) {
159*62c56f98SSadaf Ebrahimi goto cleanup;
160*62c56f98SSadaf Ebrahimi }
161*62c56f98SSadaf Ebrahimi ret = mbedtls_md_update(&ctx->accumulator, p, use_len);
162*62c56f98SSadaf Ebrahimi
163*62c56f98SSadaf Ebrahimi cleanup:
164*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(tmp, sizeof(tmp));
165*62c56f98SSadaf Ebrahimi
166*62c56f98SSadaf Ebrahimi return ret;
167*62c56f98SSadaf Ebrahimi }
168*62c56f98SSadaf Ebrahimi
mbedtls_entropy_update_manual(mbedtls_entropy_context * ctx,const unsigned char * data,size_t len)169*62c56f98SSadaf Ebrahimi int mbedtls_entropy_update_manual(mbedtls_entropy_context *ctx,
170*62c56f98SSadaf Ebrahimi const unsigned char *data, size_t len)
171*62c56f98SSadaf Ebrahimi {
172*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
173*62c56f98SSadaf Ebrahimi
174*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
175*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
176*62c56f98SSadaf Ebrahimi return ret;
177*62c56f98SSadaf Ebrahimi }
178*62c56f98SSadaf Ebrahimi #endif
179*62c56f98SSadaf Ebrahimi
180*62c56f98SSadaf Ebrahimi ret = entropy_update(ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len);
181*62c56f98SSadaf Ebrahimi
182*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
183*62c56f98SSadaf Ebrahimi if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
184*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
185*62c56f98SSadaf Ebrahimi }
186*62c56f98SSadaf Ebrahimi #endif
187*62c56f98SSadaf Ebrahimi
188*62c56f98SSadaf Ebrahimi return ret;
189*62c56f98SSadaf Ebrahimi }
190*62c56f98SSadaf Ebrahimi
191*62c56f98SSadaf Ebrahimi /*
192*62c56f98SSadaf Ebrahimi * Run through the different sources to add entropy to our accumulator
193*62c56f98SSadaf Ebrahimi */
entropy_gather_internal(mbedtls_entropy_context * ctx)194*62c56f98SSadaf Ebrahimi static int entropy_gather_internal(mbedtls_entropy_context *ctx)
195*62c56f98SSadaf Ebrahimi {
196*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
197*62c56f98SSadaf Ebrahimi int i;
198*62c56f98SSadaf Ebrahimi int have_one_strong = 0;
199*62c56f98SSadaf Ebrahimi unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER];
200*62c56f98SSadaf Ebrahimi size_t olen;
201*62c56f98SSadaf Ebrahimi
202*62c56f98SSadaf Ebrahimi if (ctx->source_count == 0) {
203*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED;
204*62c56f98SSadaf Ebrahimi }
205*62c56f98SSadaf Ebrahimi
206*62c56f98SSadaf Ebrahimi /*
207*62c56f98SSadaf Ebrahimi * Run through our entropy sources
208*62c56f98SSadaf Ebrahimi */
209*62c56f98SSadaf Ebrahimi for (i = 0; i < ctx->source_count; i++) {
210*62c56f98SSadaf Ebrahimi if (ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG) {
211*62c56f98SSadaf Ebrahimi have_one_strong = 1;
212*62c56f98SSadaf Ebrahimi }
213*62c56f98SSadaf Ebrahimi
214*62c56f98SSadaf Ebrahimi olen = 0;
215*62c56f98SSadaf Ebrahimi if ((ret = ctx->source[i].f_source(ctx->source[i].p_source,
216*62c56f98SSadaf Ebrahimi buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen)) != 0) {
217*62c56f98SSadaf Ebrahimi goto cleanup;
218*62c56f98SSadaf Ebrahimi }
219*62c56f98SSadaf Ebrahimi
220*62c56f98SSadaf Ebrahimi /*
221*62c56f98SSadaf Ebrahimi * Add if we actually gathered something
222*62c56f98SSadaf Ebrahimi */
223*62c56f98SSadaf Ebrahimi if (olen > 0) {
224*62c56f98SSadaf Ebrahimi if ((ret = entropy_update(ctx, (unsigned char) i,
225*62c56f98SSadaf Ebrahimi buf, olen)) != 0) {
226*62c56f98SSadaf Ebrahimi return ret;
227*62c56f98SSadaf Ebrahimi }
228*62c56f98SSadaf Ebrahimi ctx->source[i].size += olen;
229*62c56f98SSadaf Ebrahimi }
230*62c56f98SSadaf Ebrahimi }
231*62c56f98SSadaf Ebrahimi
232*62c56f98SSadaf Ebrahimi if (have_one_strong == 0) {
233*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE;
234*62c56f98SSadaf Ebrahimi }
235*62c56f98SSadaf Ebrahimi
236*62c56f98SSadaf Ebrahimi cleanup:
237*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(buf, sizeof(buf));
238*62c56f98SSadaf Ebrahimi
239*62c56f98SSadaf Ebrahimi return ret;
240*62c56f98SSadaf Ebrahimi }
241*62c56f98SSadaf Ebrahimi
242*62c56f98SSadaf Ebrahimi /*
243*62c56f98SSadaf Ebrahimi * Thread-safe wrapper for entropy_gather_internal()
244*62c56f98SSadaf Ebrahimi */
mbedtls_entropy_gather(mbedtls_entropy_context * ctx)245*62c56f98SSadaf Ebrahimi int mbedtls_entropy_gather(mbedtls_entropy_context *ctx)
246*62c56f98SSadaf Ebrahimi {
247*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
248*62c56f98SSadaf Ebrahimi
249*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
250*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
251*62c56f98SSadaf Ebrahimi return ret;
252*62c56f98SSadaf Ebrahimi }
253*62c56f98SSadaf Ebrahimi #endif
254*62c56f98SSadaf Ebrahimi
255*62c56f98SSadaf Ebrahimi ret = entropy_gather_internal(ctx);
256*62c56f98SSadaf Ebrahimi
257*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
258*62c56f98SSadaf Ebrahimi if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
259*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
260*62c56f98SSadaf Ebrahimi }
261*62c56f98SSadaf Ebrahimi #endif
262*62c56f98SSadaf Ebrahimi
263*62c56f98SSadaf Ebrahimi return ret;
264*62c56f98SSadaf Ebrahimi }
265*62c56f98SSadaf Ebrahimi
mbedtls_entropy_func(void * data,unsigned char * output,size_t len)266*62c56f98SSadaf Ebrahimi int mbedtls_entropy_func(void *data, unsigned char *output, size_t len)
267*62c56f98SSadaf Ebrahimi {
268*62c56f98SSadaf Ebrahimi int ret, count = 0, i, thresholds_reached;
269*62c56f98SSadaf Ebrahimi size_t strong_size;
270*62c56f98SSadaf Ebrahimi mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data;
271*62c56f98SSadaf Ebrahimi unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
272*62c56f98SSadaf Ebrahimi
273*62c56f98SSadaf Ebrahimi if (len > MBEDTLS_ENTROPY_BLOCK_SIZE) {
274*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
275*62c56f98SSadaf Ebrahimi }
276*62c56f98SSadaf Ebrahimi
277*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ENTROPY_NV_SEED)
278*62c56f98SSadaf Ebrahimi /* Update the NV entropy seed before generating any entropy for outside
279*62c56f98SSadaf Ebrahimi * use.
280*62c56f98SSadaf Ebrahimi */
281*62c56f98SSadaf Ebrahimi if (ctx->initial_entropy_run == 0) {
282*62c56f98SSadaf Ebrahimi ctx->initial_entropy_run = 1;
283*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_entropy_update_nv_seed(ctx)) != 0) {
284*62c56f98SSadaf Ebrahimi return ret;
285*62c56f98SSadaf Ebrahimi }
286*62c56f98SSadaf Ebrahimi }
287*62c56f98SSadaf Ebrahimi #endif
288*62c56f98SSadaf Ebrahimi
289*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
290*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_mutex_lock(&ctx->mutex)) != 0) {
291*62c56f98SSadaf Ebrahimi return ret;
292*62c56f98SSadaf Ebrahimi }
293*62c56f98SSadaf Ebrahimi #endif
294*62c56f98SSadaf Ebrahimi
295*62c56f98SSadaf Ebrahimi /*
296*62c56f98SSadaf Ebrahimi * Always gather extra entropy before a call
297*62c56f98SSadaf Ebrahimi */
298*62c56f98SSadaf Ebrahimi do {
299*62c56f98SSadaf Ebrahimi if (count++ > ENTROPY_MAX_LOOP) {
300*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
301*62c56f98SSadaf Ebrahimi goto exit;
302*62c56f98SSadaf Ebrahimi }
303*62c56f98SSadaf Ebrahimi
304*62c56f98SSadaf Ebrahimi if ((ret = entropy_gather_internal(ctx)) != 0) {
305*62c56f98SSadaf Ebrahimi goto exit;
306*62c56f98SSadaf Ebrahimi }
307*62c56f98SSadaf Ebrahimi
308*62c56f98SSadaf Ebrahimi thresholds_reached = 1;
309*62c56f98SSadaf Ebrahimi strong_size = 0;
310*62c56f98SSadaf Ebrahimi for (i = 0; i < ctx->source_count; i++) {
311*62c56f98SSadaf Ebrahimi if (ctx->source[i].size < ctx->source[i].threshold) {
312*62c56f98SSadaf Ebrahimi thresholds_reached = 0;
313*62c56f98SSadaf Ebrahimi }
314*62c56f98SSadaf Ebrahimi if (ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG) {
315*62c56f98SSadaf Ebrahimi strong_size += ctx->source[i].size;
316*62c56f98SSadaf Ebrahimi }
317*62c56f98SSadaf Ebrahimi }
318*62c56f98SSadaf Ebrahimi } while (!thresholds_reached || strong_size < MBEDTLS_ENTROPY_BLOCK_SIZE);
319*62c56f98SSadaf Ebrahimi
320*62c56f98SSadaf Ebrahimi memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
321*62c56f98SSadaf Ebrahimi
322*62c56f98SSadaf Ebrahimi /*
323*62c56f98SSadaf Ebrahimi * Note that at this stage it is assumed that the accumulator was started
324*62c56f98SSadaf Ebrahimi * in a previous call to entropy_update(). If this is not guaranteed, the
325*62c56f98SSadaf Ebrahimi * code below will fail.
326*62c56f98SSadaf Ebrahimi */
327*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_md_finish(&ctx->accumulator, buf)) != 0) {
328*62c56f98SSadaf Ebrahimi goto exit;
329*62c56f98SSadaf Ebrahimi }
330*62c56f98SSadaf Ebrahimi
331*62c56f98SSadaf Ebrahimi /*
332*62c56f98SSadaf Ebrahimi * Reset accumulator and counters and recycle existing entropy
333*62c56f98SSadaf Ebrahimi */
334*62c56f98SSadaf Ebrahimi mbedtls_md_free(&ctx->accumulator);
335*62c56f98SSadaf Ebrahimi mbedtls_md_init(&ctx->accumulator);
336*62c56f98SSadaf Ebrahimi ret = mbedtls_md_setup(&ctx->accumulator,
337*62c56f98SSadaf Ebrahimi mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD), 0);
338*62c56f98SSadaf Ebrahimi if (ret != 0) {
339*62c56f98SSadaf Ebrahimi goto exit;
340*62c56f98SSadaf Ebrahimi }
341*62c56f98SSadaf Ebrahimi ret = mbedtls_md_starts(&ctx->accumulator);
342*62c56f98SSadaf Ebrahimi if (ret != 0) {
343*62c56f98SSadaf Ebrahimi goto exit;
344*62c56f98SSadaf Ebrahimi }
345*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_md_update(&ctx->accumulator, buf,
346*62c56f98SSadaf Ebrahimi MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) {
347*62c56f98SSadaf Ebrahimi goto exit;
348*62c56f98SSadaf Ebrahimi }
349*62c56f98SSadaf Ebrahimi
350*62c56f98SSadaf Ebrahimi /*
351*62c56f98SSadaf Ebrahimi * Perform second hashing on entropy
352*62c56f98SSadaf Ebrahimi */
353*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_ENTROPY_MD),
354*62c56f98SSadaf Ebrahimi buf, MBEDTLS_ENTROPY_BLOCK_SIZE, buf)) != 0) {
355*62c56f98SSadaf Ebrahimi goto exit;
356*62c56f98SSadaf Ebrahimi }
357*62c56f98SSadaf Ebrahimi
358*62c56f98SSadaf Ebrahimi for (i = 0; i < ctx->source_count; i++) {
359*62c56f98SSadaf Ebrahimi ctx->source[i].size = 0;
360*62c56f98SSadaf Ebrahimi }
361*62c56f98SSadaf Ebrahimi
362*62c56f98SSadaf Ebrahimi memcpy(output, buf, len);
363*62c56f98SSadaf Ebrahimi
364*62c56f98SSadaf Ebrahimi ret = 0;
365*62c56f98SSadaf Ebrahimi
366*62c56f98SSadaf Ebrahimi exit:
367*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(buf, sizeof(buf));
368*62c56f98SSadaf Ebrahimi
369*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_THREADING_C)
370*62c56f98SSadaf Ebrahimi if (mbedtls_mutex_unlock(&ctx->mutex) != 0) {
371*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_THREADING_MUTEX_ERROR;
372*62c56f98SSadaf Ebrahimi }
373*62c56f98SSadaf Ebrahimi #endif
374*62c56f98SSadaf Ebrahimi
375*62c56f98SSadaf Ebrahimi return ret;
376*62c56f98SSadaf Ebrahimi }
377*62c56f98SSadaf Ebrahimi
378*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ENTROPY_NV_SEED)
mbedtls_entropy_update_nv_seed(mbedtls_entropy_context * ctx)379*62c56f98SSadaf Ebrahimi int mbedtls_entropy_update_nv_seed(mbedtls_entropy_context *ctx)
380*62c56f98SSadaf Ebrahimi {
381*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
382*62c56f98SSadaf Ebrahimi unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
383*62c56f98SSadaf Ebrahimi
384*62c56f98SSadaf Ebrahimi /* Read new seed and write it to NV */
385*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_entropy_func(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) {
386*62c56f98SSadaf Ebrahimi return ret;
387*62c56f98SSadaf Ebrahimi }
388*62c56f98SSadaf Ebrahimi
389*62c56f98SSadaf Ebrahimi if (mbedtls_nv_seed_write(buf, MBEDTLS_ENTROPY_BLOCK_SIZE) < 0) {
390*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
391*62c56f98SSadaf Ebrahimi }
392*62c56f98SSadaf Ebrahimi
393*62c56f98SSadaf Ebrahimi /* Manually update the remaining stream with a separator value to diverge */
394*62c56f98SSadaf Ebrahimi memset(buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE);
395*62c56f98SSadaf Ebrahimi ret = mbedtls_entropy_update_manual(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE);
396*62c56f98SSadaf Ebrahimi
397*62c56f98SSadaf Ebrahimi return ret;
398*62c56f98SSadaf Ebrahimi }
399*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_ENTROPY_NV_SEED */
400*62c56f98SSadaf Ebrahimi
401*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_FS_IO)
mbedtls_entropy_write_seed_file(mbedtls_entropy_context * ctx,const char * path)402*62c56f98SSadaf Ebrahimi int mbedtls_entropy_write_seed_file(mbedtls_entropy_context *ctx, const char *path)
403*62c56f98SSadaf Ebrahimi {
404*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
405*62c56f98SSadaf Ebrahimi FILE *f = NULL;
406*62c56f98SSadaf Ebrahimi unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE];
407*62c56f98SSadaf Ebrahimi
408*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_entropy_func(ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE)) != 0) {
409*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
410*62c56f98SSadaf Ebrahimi goto exit;
411*62c56f98SSadaf Ebrahimi }
412*62c56f98SSadaf Ebrahimi
413*62c56f98SSadaf Ebrahimi if ((f = fopen(path, "wb")) == NULL) {
414*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
415*62c56f98SSadaf Ebrahimi goto exit;
416*62c56f98SSadaf Ebrahimi }
417*62c56f98SSadaf Ebrahimi
418*62c56f98SSadaf Ebrahimi /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
419*62c56f98SSadaf Ebrahimi mbedtls_setbuf(f, NULL);
420*62c56f98SSadaf Ebrahimi
421*62c56f98SSadaf Ebrahimi if (fwrite(buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f) != MBEDTLS_ENTROPY_BLOCK_SIZE) {
422*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
423*62c56f98SSadaf Ebrahimi goto exit;
424*62c56f98SSadaf Ebrahimi }
425*62c56f98SSadaf Ebrahimi
426*62c56f98SSadaf Ebrahimi ret = 0;
427*62c56f98SSadaf Ebrahimi
428*62c56f98SSadaf Ebrahimi exit:
429*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(buf, sizeof(buf));
430*62c56f98SSadaf Ebrahimi
431*62c56f98SSadaf Ebrahimi if (f != NULL) {
432*62c56f98SSadaf Ebrahimi fclose(f);
433*62c56f98SSadaf Ebrahimi }
434*62c56f98SSadaf Ebrahimi
435*62c56f98SSadaf Ebrahimi return ret;
436*62c56f98SSadaf Ebrahimi }
437*62c56f98SSadaf Ebrahimi
mbedtls_entropy_update_seed_file(mbedtls_entropy_context * ctx,const char * path)438*62c56f98SSadaf Ebrahimi int mbedtls_entropy_update_seed_file(mbedtls_entropy_context *ctx, const char *path)
439*62c56f98SSadaf Ebrahimi {
440*62c56f98SSadaf Ebrahimi int ret = 0;
441*62c56f98SSadaf Ebrahimi FILE *f;
442*62c56f98SSadaf Ebrahimi size_t n;
443*62c56f98SSadaf Ebrahimi unsigned char buf[MBEDTLS_ENTROPY_MAX_SEED_SIZE];
444*62c56f98SSadaf Ebrahimi
445*62c56f98SSadaf Ebrahimi if ((f = fopen(path, "rb")) == NULL) {
446*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
447*62c56f98SSadaf Ebrahimi }
448*62c56f98SSadaf Ebrahimi
449*62c56f98SSadaf Ebrahimi /* Ensure no stdio buffering of secrets, as such buffers cannot be wiped. */
450*62c56f98SSadaf Ebrahimi mbedtls_setbuf(f, NULL);
451*62c56f98SSadaf Ebrahimi
452*62c56f98SSadaf Ebrahimi fseek(f, 0, SEEK_END);
453*62c56f98SSadaf Ebrahimi n = (size_t) ftell(f);
454*62c56f98SSadaf Ebrahimi fseek(f, 0, SEEK_SET);
455*62c56f98SSadaf Ebrahimi
456*62c56f98SSadaf Ebrahimi if (n > MBEDTLS_ENTROPY_MAX_SEED_SIZE) {
457*62c56f98SSadaf Ebrahimi n = MBEDTLS_ENTROPY_MAX_SEED_SIZE;
458*62c56f98SSadaf Ebrahimi }
459*62c56f98SSadaf Ebrahimi
460*62c56f98SSadaf Ebrahimi if (fread(buf, 1, n, f) != n) {
461*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR;
462*62c56f98SSadaf Ebrahimi } else {
463*62c56f98SSadaf Ebrahimi ret = mbedtls_entropy_update_manual(ctx, buf, n);
464*62c56f98SSadaf Ebrahimi }
465*62c56f98SSadaf Ebrahimi
466*62c56f98SSadaf Ebrahimi fclose(f);
467*62c56f98SSadaf Ebrahimi
468*62c56f98SSadaf Ebrahimi mbedtls_platform_zeroize(buf, sizeof(buf));
469*62c56f98SSadaf Ebrahimi
470*62c56f98SSadaf Ebrahimi if (ret != 0) {
471*62c56f98SSadaf Ebrahimi return ret;
472*62c56f98SSadaf Ebrahimi }
473*62c56f98SSadaf Ebrahimi
474*62c56f98SSadaf Ebrahimi return mbedtls_entropy_write_seed_file(ctx, path);
475*62c56f98SSadaf Ebrahimi }
476*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_FS_IO */
477*62c56f98SSadaf Ebrahimi
478*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_SELF_TEST)
479*62c56f98SSadaf Ebrahimi /*
480*62c56f98SSadaf Ebrahimi * Dummy source function
481*62c56f98SSadaf Ebrahimi */
entropy_dummy_source(void * data,unsigned char * output,size_t len,size_t * olen)482*62c56f98SSadaf Ebrahimi static int entropy_dummy_source(void *data, unsigned char *output,
483*62c56f98SSadaf Ebrahimi size_t len, size_t *olen)
484*62c56f98SSadaf Ebrahimi {
485*62c56f98SSadaf Ebrahimi ((void) data);
486*62c56f98SSadaf Ebrahimi
487*62c56f98SSadaf Ebrahimi memset(output, 0x2a, len);
488*62c56f98SSadaf Ebrahimi *olen = len;
489*62c56f98SSadaf Ebrahimi
490*62c56f98SSadaf Ebrahimi return 0;
491*62c56f98SSadaf Ebrahimi }
492*62c56f98SSadaf Ebrahimi
493*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
494*62c56f98SSadaf Ebrahimi
mbedtls_entropy_source_self_test_gather(unsigned char * buf,size_t buf_len)495*62c56f98SSadaf Ebrahimi static int mbedtls_entropy_source_self_test_gather(unsigned char *buf, size_t buf_len)
496*62c56f98SSadaf Ebrahimi {
497*62c56f98SSadaf Ebrahimi int ret = 0;
498*62c56f98SSadaf Ebrahimi size_t entropy_len = 0;
499*62c56f98SSadaf Ebrahimi size_t olen = 0;
500*62c56f98SSadaf Ebrahimi size_t attempts = buf_len;
501*62c56f98SSadaf Ebrahimi
502*62c56f98SSadaf Ebrahimi while (attempts > 0 && entropy_len < buf_len) {
503*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_hardware_poll(NULL, buf + entropy_len,
504*62c56f98SSadaf Ebrahimi buf_len - entropy_len, &olen)) != 0) {
505*62c56f98SSadaf Ebrahimi return ret;
506*62c56f98SSadaf Ebrahimi }
507*62c56f98SSadaf Ebrahimi
508*62c56f98SSadaf Ebrahimi entropy_len += olen;
509*62c56f98SSadaf Ebrahimi attempts--;
510*62c56f98SSadaf Ebrahimi }
511*62c56f98SSadaf Ebrahimi
512*62c56f98SSadaf Ebrahimi if (entropy_len < buf_len) {
513*62c56f98SSadaf Ebrahimi ret = 1;
514*62c56f98SSadaf Ebrahimi }
515*62c56f98SSadaf Ebrahimi
516*62c56f98SSadaf Ebrahimi return ret;
517*62c56f98SSadaf Ebrahimi }
518*62c56f98SSadaf Ebrahimi
519*62c56f98SSadaf Ebrahimi
mbedtls_entropy_source_self_test_check_bits(const unsigned char * buf,size_t buf_len)520*62c56f98SSadaf Ebrahimi static int mbedtls_entropy_source_self_test_check_bits(const unsigned char *buf,
521*62c56f98SSadaf Ebrahimi size_t buf_len)
522*62c56f98SSadaf Ebrahimi {
523*62c56f98SSadaf Ebrahimi unsigned char set = 0xFF;
524*62c56f98SSadaf Ebrahimi unsigned char unset = 0x00;
525*62c56f98SSadaf Ebrahimi size_t i;
526*62c56f98SSadaf Ebrahimi
527*62c56f98SSadaf Ebrahimi for (i = 0; i < buf_len; i++) {
528*62c56f98SSadaf Ebrahimi set &= buf[i];
529*62c56f98SSadaf Ebrahimi unset |= buf[i];
530*62c56f98SSadaf Ebrahimi }
531*62c56f98SSadaf Ebrahimi
532*62c56f98SSadaf Ebrahimi return set == 0xFF || unset == 0x00;
533*62c56f98SSadaf Ebrahimi }
534*62c56f98SSadaf Ebrahimi
535*62c56f98SSadaf Ebrahimi /*
536*62c56f98SSadaf Ebrahimi * A test to ensure that the entropy sources are functioning correctly
537*62c56f98SSadaf Ebrahimi * and there is no obvious failure. The test performs the following checks:
538*62c56f98SSadaf Ebrahimi * - The entropy source is not providing only 0s (all bits unset) or 1s (all
539*62c56f98SSadaf Ebrahimi * bits set).
540*62c56f98SSadaf Ebrahimi * - The entropy source is not providing values in a pattern. Because the
541*62c56f98SSadaf Ebrahimi * hardware could be providing data in an arbitrary length, this check polls
542*62c56f98SSadaf Ebrahimi * the hardware entropy source twice and compares the result to ensure they
543*62c56f98SSadaf Ebrahimi * are not equal.
544*62c56f98SSadaf Ebrahimi * - The error code returned by the entropy source is not an error.
545*62c56f98SSadaf Ebrahimi */
mbedtls_entropy_source_self_test(int verbose)546*62c56f98SSadaf Ebrahimi int mbedtls_entropy_source_self_test(int verbose)
547*62c56f98SSadaf Ebrahimi {
548*62c56f98SSadaf Ebrahimi int ret = 0;
549*62c56f98SSadaf Ebrahimi unsigned char buf0[2 * sizeof(unsigned long long int)];
550*62c56f98SSadaf Ebrahimi unsigned char buf1[2 * sizeof(unsigned long long int)];
551*62c56f98SSadaf Ebrahimi
552*62c56f98SSadaf Ebrahimi if (verbose != 0) {
553*62c56f98SSadaf Ebrahimi mbedtls_printf(" ENTROPY_BIAS test: ");
554*62c56f98SSadaf Ebrahimi }
555*62c56f98SSadaf Ebrahimi
556*62c56f98SSadaf Ebrahimi memset(buf0, 0x00, sizeof(buf0));
557*62c56f98SSadaf Ebrahimi memset(buf1, 0x00, sizeof(buf1));
558*62c56f98SSadaf Ebrahimi
559*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_entropy_source_self_test_gather(buf0, sizeof(buf0))) != 0) {
560*62c56f98SSadaf Ebrahimi goto cleanup;
561*62c56f98SSadaf Ebrahimi }
562*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_entropy_source_self_test_gather(buf1, sizeof(buf1))) != 0) {
563*62c56f98SSadaf Ebrahimi goto cleanup;
564*62c56f98SSadaf Ebrahimi }
565*62c56f98SSadaf Ebrahimi
566*62c56f98SSadaf Ebrahimi /* Make sure that the returned values are not all 0 or 1 */
567*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_entropy_source_self_test_check_bits(buf0, sizeof(buf0))) != 0) {
568*62c56f98SSadaf Ebrahimi goto cleanup;
569*62c56f98SSadaf Ebrahimi }
570*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_entropy_source_self_test_check_bits(buf1, sizeof(buf1))) != 0) {
571*62c56f98SSadaf Ebrahimi goto cleanup;
572*62c56f98SSadaf Ebrahimi }
573*62c56f98SSadaf Ebrahimi
574*62c56f98SSadaf Ebrahimi /* Make sure that the entropy source is not returning values in a
575*62c56f98SSadaf Ebrahimi * pattern */
576*62c56f98SSadaf Ebrahimi ret = memcmp(buf0, buf1, sizeof(buf0)) == 0;
577*62c56f98SSadaf Ebrahimi
578*62c56f98SSadaf Ebrahimi cleanup:
579*62c56f98SSadaf Ebrahimi if (verbose != 0) {
580*62c56f98SSadaf Ebrahimi if (ret != 0) {
581*62c56f98SSadaf Ebrahimi mbedtls_printf("failed\n");
582*62c56f98SSadaf Ebrahimi } else {
583*62c56f98SSadaf Ebrahimi mbedtls_printf("passed\n");
584*62c56f98SSadaf Ebrahimi }
585*62c56f98SSadaf Ebrahimi
586*62c56f98SSadaf Ebrahimi mbedtls_printf("\n");
587*62c56f98SSadaf Ebrahimi }
588*62c56f98SSadaf Ebrahimi
589*62c56f98SSadaf Ebrahimi return ret != 0;
590*62c56f98SSadaf Ebrahimi }
591*62c56f98SSadaf Ebrahimi
592*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */
593*62c56f98SSadaf Ebrahimi
594*62c56f98SSadaf Ebrahimi /*
595*62c56f98SSadaf Ebrahimi * The actual entropy quality is hard to test, but we can at least
596*62c56f98SSadaf Ebrahimi * test that the functions don't cause errors and write the correct
597*62c56f98SSadaf Ebrahimi * amount of data to buffers.
598*62c56f98SSadaf Ebrahimi */
mbedtls_entropy_self_test(int verbose)599*62c56f98SSadaf Ebrahimi int mbedtls_entropy_self_test(int verbose)
600*62c56f98SSadaf Ebrahimi {
601*62c56f98SSadaf Ebrahimi int ret = 1;
602*62c56f98SSadaf Ebrahimi mbedtls_entropy_context ctx;
603*62c56f98SSadaf Ebrahimi unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
604*62c56f98SSadaf Ebrahimi unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 };
605*62c56f98SSadaf Ebrahimi size_t i, j;
606*62c56f98SSadaf Ebrahimi
607*62c56f98SSadaf Ebrahimi if (verbose != 0) {
608*62c56f98SSadaf Ebrahimi mbedtls_printf(" ENTROPY test: ");
609*62c56f98SSadaf Ebrahimi }
610*62c56f98SSadaf Ebrahimi
611*62c56f98SSadaf Ebrahimi mbedtls_entropy_init(&ctx);
612*62c56f98SSadaf Ebrahimi
613*62c56f98SSadaf Ebrahimi /* First do a gather to make sure we have default sources */
614*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_entropy_gather(&ctx)) != 0) {
615*62c56f98SSadaf Ebrahimi goto cleanup;
616*62c56f98SSadaf Ebrahimi }
617*62c56f98SSadaf Ebrahimi
618*62c56f98SSadaf Ebrahimi ret = mbedtls_entropy_add_source(&ctx, entropy_dummy_source, NULL, 16,
619*62c56f98SSadaf Ebrahimi MBEDTLS_ENTROPY_SOURCE_WEAK);
620*62c56f98SSadaf Ebrahimi if (ret != 0) {
621*62c56f98SSadaf Ebrahimi goto cleanup;
622*62c56f98SSadaf Ebrahimi }
623*62c56f98SSadaf Ebrahimi
624*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_entropy_update_manual(&ctx, buf, sizeof(buf))) != 0) {
625*62c56f98SSadaf Ebrahimi goto cleanup;
626*62c56f98SSadaf Ebrahimi }
627*62c56f98SSadaf Ebrahimi
628*62c56f98SSadaf Ebrahimi /*
629*62c56f98SSadaf Ebrahimi * To test that mbedtls_entropy_func writes correct number of bytes:
630*62c56f98SSadaf Ebrahimi * - use the whole buffer and rely on ASan to detect overruns
631*62c56f98SSadaf Ebrahimi * - collect entropy 8 times and OR the result in an accumulator:
632*62c56f98SSadaf Ebrahimi * any byte should then be 0 with probably 2^(-64), so requiring
633*62c56f98SSadaf Ebrahimi * each of the 32 or 64 bytes to be non-zero has a false failure rate
634*62c56f98SSadaf Ebrahimi * of at most 2^(-58) which is acceptable.
635*62c56f98SSadaf Ebrahimi */
636*62c56f98SSadaf Ebrahimi for (i = 0; i < 8; i++) {
637*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_entropy_func(&ctx, buf, sizeof(buf))) != 0) {
638*62c56f98SSadaf Ebrahimi goto cleanup;
639*62c56f98SSadaf Ebrahimi }
640*62c56f98SSadaf Ebrahimi
641*62c56f98SSadaf Ebrahimi for (j = 0; j < sizeof(buf); j++) {
642*62c56f98SSadaf Ebrahimi acc[j] |= buf[j];
643*62c56f98SSadaf Ebrahimi }
644*62c56f98SSadaf Ebrahimi }
645*62c56f98SSadaf Ebrahimi
646*62c56f98SSadaf Ebrahimi for (j = 0; j < sizeof(buf); j++) {
647*62c56f98SSadaf Ebrahimi if (acc[j] == 0) {
648*62c56f98SSadaf Ebrahimi ret = 1;
649*62c56f98SSadaf Ebrahimi goto cleanup;
650*62c56f98SSadaf Ebrahimi }
651*62c56f98SSadaf Ebrahimi }
652*62c56f98SSadaf Ebrahimi
653*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ENTROPY_HARDWARE_ALT)
654*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_entropy_source_self_test(0)) != 0) {
655*62c56f98SSadaf Ebrahimi goto cleanup;
656*62c56f98SSadaf Ebrahimi }
657*62c56f98SSadaf Ebrahimi #endif
658*62c56f98SSadaf Ebrahimi
659*62c56f98SSadaf Ebrahimi cleanup:
660*62c56f98SSadaf Ebrahimi mbedtls_entropy_free(&ctx);
661*62c56f98SSadaf Ebrahimi
662*62c56f98SSadaf Ebrahimi if (verbose != 0) {
663*62c56f98SSadaf Ebrahimi if (ret != 0) {
664*62c56f98SSadaf Ebrahimi mbedtls_printf("failed\n");
665*62c56f98SSadaf Ebrahimi } else {
666*62c56f98SSadaf Ebrahimi mbedtls_printf("passed\n");
667*62c56f98SSadaf Ebrahimi }
668*62c56f98SSadaf Ebrahimi
669*62c56f98SSadaf Ebrahimi mbedtls_printf("\n");
670*62c56f98SSadaf Ebrahimi }
671*62c56f98SSadaf Ebrahimi
672*62c56f98SSadaf Ebrahimi return ret != 0;
673*62c56f98SSadaf Ebrahimi }
674*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_SELF_TEST */
675*62c56f98SSadaf Ebrahimi
676*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_ENTROPY_C */
677