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