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