/* */ #include "SimpleRandomizer.h" #include #include #include #include #include #include "a2time.h" #include "a2functional.h" #include "LogFactory.h" #include "fmt.h" #ifdef HAVE_GETRANDOM_INTERFACE #include #include #include "getrandom_linux.h" #endif namespace aria2 { std::unique_ptr SimpleRandomizer::randomizer_; const std::unique_ptr& SimpleRandomizer::getInstance() { if (!randomizer_) { randomizer_.reset(new SimpleRandomizer()); } return randomizer_; } namespace { std::random_device rd; } // namespace #ifdef __MINGW32__ SimpleRandomizer::SimpleRandomizer() { BOOL r = ::CryptAcquireContext(&provider_, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT); assert(r); } #else // !__MINGW32__ SimpleRandomizer::SimpleRandomizer() : gen_(rd()) {} #endif // !__MINGW32__ SimpleRandomizer::~SimpleRandomizer() { #ifdef __MINGW32__ CryptReleaseContext(provider_, 0); #endif } long int SimpleRandomizer::getRandomNumber(long int to) { assert(to > 0); return std::uniform_int_distribution(0, to - 1)(*this); } void SimpleRandomizer::getRandomBytes(unsigned char* buf, size_t len) { #ifdef __MINGW32__ BOOL r = CryptGenRandom(provider_, len, reinterpret_cast(buf)); assert(r); #else // ! __MINGW32__ #if defined(HAVE_GETRANDOM_INTERFACE) static bool have_random_support = true; if (have_random_support) { auto rv = getrandom_linux(buf, len); if (rv != -1) { // getrandom is not supposed to fail, ever, so, we want to assert here. assert(rv >= 0 && (size_t)rv == len); return; } have_random_support = false; A2_LOG_INFO("Disabled getrandom support, because kernel does not " "implement this feature (ENOSYS)"); } // Fall through to generic implementation #endif // defined(HAVE_GETRANDOM_INTERFACE) auto ubuf = reinterpret_cast(buf); size_t q = len / sizeof(result_type); auto dis = std::uniform_int_distribution(); for (; q > 0; --q, ++ubuf) { *ubuf = dis(gen_); } const size_t r = len % sizeof(result_type); auto last = dis(gen_); memcpy(ubuf, &last, r); #endif // ! __MINGW32__ } } // namespace aria2