xref: /reactos/dll/3rdparty/mbedtls/entropy.c (revision 58588b76)
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 */
728