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