| 636 | } |
| 637 | |
| 638 | bool Random_SanityCheck() |
| 639 | { |
| 640 | uint64_t start = GetPerformanceCounter(); |
| 641 | |
| 642 | /* This does not measure the quality of randomness, but it does test that |
| 643 | * GetOSRand() overwrites all 32 bytes of the output given a maximum |
| 644 | * number of tries. |
| 645 | */ |
| 646 | static const ssize_t MAX_TRIES = 1024; |
| 647 | uint8_t data[NUM_OS_RANDOM_BYTES]; |
| 648 | bool overwritten[NUM_OS_RANDOM_BYTES] = {}; /* Tracks which bytes have been overwritten at least once */ |
| 649 | int num_overwritten; |
| 650 | int tries = 0; |
| 651 | /* Loop until all bytes have been overwritten at least once, or max number tries reached */ |
| 652 | do { |
| 653 | memset(data, 0, NUM_OS_RANDOM_BYTES); |
| 654 | GetOSRand(data); |
| 655 | for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) { |
| 656 | overwritten[x] |= (data[x] != 0); |
| 657 | } |
| 658 | |
| 659 | num_overwritten = 0; |
| 660 | for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) { |
| 661 | if (overwritten[x]) { |
| 662 | num_overwritten += 1; |
| 663 | } |
| 664 | } |
| 665 | |
| 666 | tries += 1; |
| 667 | } while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES); |
| 668 | if (num_overwritten != NUM_OS_RANDOM_BYTES) return false; /* If this failed, bailed out after too many tries */ |
| 669 | |
| 670 | // Check that GetPerformanceCounter increases at least during a GetOSRand() call + 1ms sleep. |
| 671 | std::this_thread::sleep_for(std::chrono::milliseconds(1)); |
| 672 | uint64_t stop = GetPerformanceCounter(); |
| 673 | if (stop == start) return false; |
| 674 | |
| 675 | // We called GetPerformanceCounter. Use it as entropy. |
| 676 | CSHA512 to_add; |
| 677 | to_add.Write((const unsigned char*)&start, sizeof(start)); |
| 678 | to_add.Write((const unsigned char*)&stop, sizeof(stop)); |
| 679 | GetRNGState().MixExtract(nullptr, 0, std::move(to_add), false); |
| 680 | |
| 681 | return true; |
| 682 | } |
| 683 | |
| 684 | FastRandomContext::FastRandomContext(bool fDeterministic) noexcept : requires_seed(!fDeterministic), bytebuf_size(0), bitbuf_size(0) |
| 685 | { |