Browse Source
These are available in sandboxes without access to files or devices. Also [they are safer and more straightforward](https://en.wikipedia.org/wiki/Entropy-supplying_system_calls) to use than `/dev/urandom` as reading from a file has quite a few edge cases: - Linux: `getrandom(buf, buflen, 0)`. [getrandom(2)](http://man7.org/linux/man-pages/man2/getrandom.2.html) was introduced in version 3.17 of the Linux kernel. - OpenBSD: `getentropy(buf, buflen)`. The [getentropy(2)](http://man.openbsd.org/cgi-bin/man.cgi/OpenBSD-current/man2/getentropy.2) function appeared in OpenBSD 5.6. - FreeBSD and NetBSD: `sysctl(KERN_ARND)`. Not sure when this was added but it has existed for quite a while. Alternatives: - Linux has sysctl `CTL_KERN` / `KERN_RANDOM` / `RANDOM_UUID` which gives 16 bytes of randomness. This may be available on older kernels, however [sysctl is deprecated on Linux](https://lwn.net/Articles/605392/) and even removed in some distros so we shouldn't use it. Add tests for `GetOSRand()`: - Test that no error happens (otherwise `RandFailure()` which aborts) - Test that all 32 bytes are overwritten (initialize with zeros, try multiple times) Discussion: - When to use these? Currently they are always used when available. Another option would be to use them only when `/dev/urandom` is not available. But this would mean these code paths receive less testing, and I'm not sure there is any reason to prefer `/dev/urandom`. Closes: #96760.15
Wladimir J. van der Laan
8 years ago
5 changed files with 132 additions and 6 deletions
@ -0,0 +1,46 @@ |
|||||||
|
// Copyright (c) 2017 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include "random.h" |
||||||
|
|
||||||
|
#include "test/test_bitcoin.h" |
||||||
|
|
||||||
|
#include <boost/test/unit_test.hpp> |
||||||
|
|
||||||
|
BOOST_FIXTURE_TEST_SUITE(random_tests, BasicTestingSetup) |
||||||
|
|
||||||
|
static const ssize_t MAX_TRIES = 1024; |
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(osrandom_tests) |
||||||
|
{ |
||||||
|
/* This does not measure the quality of randomness, but it does test that
|
||||||
|
* OSRandom() overwrites all 32 bytes of the output given a maximum |
||||||
|
* number of tries. |
||||||
|
*/ |
||||||
|
uint8_t data[NUM_OS_RANDOM_BYTES]; |
||||||
|
bool overwritten[NUM_OS_RANDOM_BYTES] = {}; /* Tracks which bytes have been overwritten at least once */ |
||||||
|
int num_overwritten; |
||||||
|
int tries = 0; |
||||||
|
/* Loop until all bytes have been overwritten at least once */ |
||||||
|
do { |
||||||
|
memset(data, 0, NUM_OS_RANDOM_BYTES); |
||||||
|
GetOSRand(data); |
||||||
|
for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) { |
||||||
|
overwritten[x] |= (data[x] != 0); |
||||||
|
} |
||||||
|
|
||||||
|
num_overwritten = 0; |
||||||
|
for (int x=0; x < NUM_OS_RANDOM_BYTES; ++x) { |
||||||
|
if (overwritten[x]) { |
||||||
|
num_overwritten += 1; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
tries += 1; |
||||||
|
} while (num_overwritten < NUM_OS_RANDOM_BYTES && tries < MAX_TRIES); |
||||||
|
BOOST_CHECK(num_overwritten == NUM_OS_RANDOM_BYTES); /* If this failed, bailed out after too many tries */ |
||||||
|
} |
||||||
|
|
||||||
|
BOOST_AUTO_TEST_SUITE_END() |
||||||
|
|
Loading…
Reference in new issue