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