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