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