X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=folly%2FRandom.cpp;h=8f5e3128d2036952f31ba8efcc73791a139e333b;hb=ad2f228ab1359952d37acdc4f3032e1405cca221;hp=06b3d5aea0b20a7f60e4f52d8b3b407119357957;hpb=651eb23ca2cfb7b64481f3091160cc8a1112dbc9;p=folly.git diff --git a/folly/Random.cpp b/folly/Random.cpp index 06b3d5ae..8f5e3128 100644 --- a/folly/Random.cpp +++ b/folly/Random.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2014 Facebook, Inc. + * Copyright 2016 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,23 +17,51 @@ #include #include -#include -#include +#include #include #include #include +#include #include #include +#include +#include +#include + +#ifdef _MSC_VER +# include +#endif namespace folly { namespace { void readRandomDevice(void* data, size_t size) { - // Keep it open for the duration of the program - static File randomDevice("/dev/urandom"); - PCHECK(readFull(randomDevice.fd(), data, size) == size); +#ifdef _MSC_VER + static folly::once_flag flag; + static HCRYPTPROV cryptoProv; + folly::call_once(flag, [&] { + if (!CryptAcquireContext(&cryptoProv, nullptr, nullptr, PROV_RSA_FULL, 0)) { + if (GetLastError() == NTE_BAD_KEYSET) { + // Mostly likely cause of this is that no key container + // exists yet, so try to create one. + PCHECK(CryptAcquireContext( + &cryptoProv, nullptr, nullptr, PROV_RSA_FULL, CRYPT_NEWKEYSET)); + } else { + LOG(FATAL) << "Failed to acquire the default crypto context."; + } + } + }); + CHECK(size <= std::numeric_limits::max()); + PCHECK(CryptGenRandom(cryptoProv, (DWORD)size, (BYTE*)data)); +#else + // Keep the random device open for the duration of the program. + static int randomFd = ::open("/dev/urandom", O_RDONLY); + PCHECK(randomFd >= 0); + auto bytesRead = readFull(randomFd, data, size); + PCHECK(bytesRead >= 0 && size_t(bytesRead) == size); +#endif } class BufferedRandomDevice { @@ -90,19 +118,14 @@ void BufferedRandomDevice::getSlow(unsigned char* data, size_t size) { ptr_ += size; } -ThreadLocal bufferedRandomDevice; } // namespace void Random::secureRandom(void* data, size_t size) { + static ThreadLocal bufferedRandomDevice; bufferedRandomDevice->get(data, size); } -ThreadLocalPRNG::ThreadLocalPRNG() { - static folly::ThreadLocal localInstance; - local_ = localInstance.get(); -} - class ThreadLocalPRNG::LocalInstancePRNG { public: LocalInstancePRNG() : rng(Random::create()) { } @@ -110,6 +133,11 @@ class ThreadLocalPRNG::LocalInstancePRNG { Random::DefaultGenerator rng; }; +ThreadLocalPRNG::ThreadLocalPRNG() { + static folly::ThreadLocal localInstance; + local_ = localInstance.get(); +} + uint32_t ThreadLocalPRNG::getImpl(LocalInstancePRNG* local) { return local->rng(); }