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