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