diff options
| author | Nils Maier <maierman@web.de> | 2014-12-30 18:17:44 +0100 |
|---|---|---|
| committer | Nils Maier <maierman@web.de> | 2015-01-20 22:37:24 +0100 |
| commit | 81bdd5f61a8f8da53e22d68190be700902b7dbae (patch) | |
| tree | f706934a5e5e208d8d09490d216fe03f10b38654 /src/SimpleRandomizer.cc | |
| parent | 747131a06c1f1d92a5312a103f4446fabedb6cf7 (diff) | |
Revise getRandom facilities
Use one of the following to provide random bytes:
- Windows CryptGenRandom
- Linux getrandom (syscall interface to urandom, without nasty corner
cases such as file descriptor exhaustion or re-linked /dev/urandom)
- std::device_random (C++ random device, which usually will be urandom)
This also equalizes util::getRandom and SimpleRandomizer (the former
will now use the latter) instead of having essentially two different
PRNG interfaces with potentially different quality.
Closes GH-320
Diffstat (limited to 'src/SimpleRandomizer.cc')
| -rw-r--r-- | src/SimpleRandomizer.cc | 78 |
1 files changed, 28 insertions, 50 deletions
diff --git a/src/SimpleRandomizer.cc b/src/SimpleRandomizer.cc index 713a5b5e..746491f1 100644 --- a/src/SimpleRandomizer.cc +++ b/src/SimpleRandomizer.cc @@ -43,6 +43,10 @@ #include "a2time.h" #include "a2functional.h" +#ifdef HAVE_GETRANDOM_INTERFACE +# include "getrandom_linux.h" +#endif + namespace aria2 { std::unique_ptr<SimpleRandomizer> SimpleRandomizer::randomizer_; @@ -55,75 +59,49 @@ const std::unique_ptr<SimpleRandomizer>& SimpleRandomizer::getInstance() return randomizer_; } -void SimpleRandomizer::init() -{ -#ifndef __MINGW32__ - // Just in case std::random_device() is fixed, add time and pid too. - eng_.seed(std::random_device()()^time(nullptr)^getpid()); -#endif // !__MINGW32__ -} - SimpleRandomizer::SimpleRandomizer() { #ifdef __MINGW32__ - BOOL r = CryptAcquireContext(&cryProvider_, 0, 0, PROV_RSA_FULL, - CRYPT_VERIFYCONTEXT|CRYPT_SILENT); + BOOL r = ::CryptAcquireContext( + &provider_, + 0, 0, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT | CRYPT_SILENT); assert(r); -#endif // __MINGW32__ +#endif } SimpleRandomizer::~SimpleRandomizer() { #ifdef __MINGW32__ - CryptReleaseContext(cryProvider_, 0); -#endif // __MINGW32__ + CryptReleaseContext(provider_, 0); +#endif } long int SimpleRandomizer::getRandomNumber(long int to) { assert(to > 0); -#ifdef __MINGW32__ - int32_t val; - BOOL r = CryptGenRandom(cryProvider_, sizeof(val), - reinterpret_cast<BYTE*>(&val)); - assert(r); - if(val == INT32_MIN) { - val = INT32_MAX; - } else if(val < 0) { - val = -val; - } - return val % to; -#else // !__MINGW32__ - return std::uniform_int_distribution<long int>(0, to - 1)(eng_); -#endif // !__MINGW32__ -} - -long int SimpleRandomizer::operator()(long int to) -{ - return getRandomNumber(to); + return std::uniform_int_distribution<long int>(0, to - 1)(*this); } -void SimpleRandomizer::getRandomBytes(unsigned char *buf, size_t len) +void SimpleRandomizer::getRandomBytes(unsigned char* buf, size_t len) { #ifdef __MINGW32__ - if (!CryptGenRandom(cryProvider_, len, (PBYTE)buf)) { - throw std::bad_alloc(); - } -#else - uint32_t val; - size_t q = len / sizeof(val); - size_t r = len % sizeof(val); - auto gen = std::bind(std::uniform_int_distribution<uint32_t> - (0, std::numeric_limits<uint32_t>::max()), - eng_); - for(; q > 0; --q) { - val = gen(); - memcpy(buf, &val, sizeof(val)); - buf += sizeof(val); + BOOL r = CryptGenRandom(provider_, len, reinterpret_cast<BYTE*>(buf)); + assert(r); +#elif defined(HAVE_GETRANDOM_INTERFACE) + auto rv = getrandom_linux(buf, len); + assert(rv >= 0 && (size_t)rv == len); +#else // ! __MINGW32__ + auto ubuf = reinterpret_cast<result_type*>(buf); + size_t q = len / sizeof(result_type); + auto gen = std::uniform_int_distribution<result_type>(); + for(; q > 0; --q, ++ubuf) { + *ubuf = gen(dev_); } - val = gen(); - memcpy(buf, &val, r); -#endif + const size_t r = len % sizeof(result_type); + auto last = gen(dev_); + memcpy(ubuf, &last, r); +#endif // ! __MINGW32__ } } // namespace aria2 |
