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