/* */ #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_; } SimpleRandomizer::SimpleRandomizer() { #ifdef __MINGW32__ BOOL r = ::CryptAcquireContext( &provider_, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT); assert(r); #endif } 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 #ifdef ENOSYS /* If the system does not know ENOSYS at this point, just leave the * check out. If the call failed, we'll not take this branch at all * and disable support below. */ || errno != ENOSYS #endif ) { if (rv < -1) { A2_LOG_ERROR(fmt("Failed to produce randomness: %d", errno)); } // 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 gen = std::uniform_int_distribution(); for(; q > 0; --q, ++ubuf) { *ubuf = gen(dev_); } const size_t r = len % sizeof(result_type); auto last = gen(dev_); memcpy(ubuf, &last, r); #endif // ! __MINGW32__ } } // namespace aria2