diff options
author | Wladimir J. van der Laan <laanwj@gmail.com> | 2017-02-21 17:36:37 +0100 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2017-02-21 20:57:34 +0100 |
commit | 224e6eb089a0f4977d22f3803fc27e44b5e7eea5 (patch) | |
tree | 4bbac190c5858510347bc40f825d514a594c1d35 /src/test | |
parent | 5f0556d0326bf6f4d34f7e8b9ada7bbb09cb1df2 (diff) |
util: Specific GetOSRandom for Linux/FreeBSD/OpenBSD
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: #9676
Diffstat (limited to 'src/test')
-rw-r--r-- | src/test/random_tests.cpp | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/src/test/random_tests.cpp b/src/test/random_tests.cpp new file mode 100644 index 0000000000..4f67415c7c --- /dev/null +++ b/src/test/random_tests.cpp @@ -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() + |