8 #ifndef CRYPTOPP_IMPORTS
15 #if defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(OS_RNG_AVAILABLE)
16 # pragma message("WARNING: Compiling for Windows but an OS RNG is not available. This is likely a Windows Phone 8 or Windows Store 8 app.")
19 #if !defined(NO_OS_DEPENDENCE) && defined(OS_RNG_AVAILABLE)
31 # define DONT_USE_O_NOFOLLOW 1
32 # define USE_FREEBSD_ARC4RANDOM 1
39 # define DONT_USE_O_NOFOLLOW 1
44 # define DONT_USE_O_NOFOLLOW 1
47 #ifdef CRYPTOPP_WIN32_AVAILABLE
48 #define WIN32_LEAN_AND_MEAN
50 #ifndef ERROR_INCORRECT_SIZE
51 # define ERROR_INCORRECT_SIZE 0x000005B6
53 #if defined(USE_MS_CRYPTOAPI)
55 #ifndef CRYPT_NEWKEYSET
56 # define CRYPT_NEWKEYSET 0x00000008
58 #ifndef CRYPT_MACHINE_KEYSET
59 # define CRYPT_MACHINE_KEYSET 0x00000020
61 #elif defined(USE_MS_CNGAPI)
63 #ifndef BCRYPT_SUCCESS
64 # define BCRYPT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
66 #ifndef STATUS_INVALID_PARAMETER
67 # define STATUS_INVALID_PARAMETER 0xC000000D
69 #ifndef STATUS_INVALID_HANDLE
70 # define STATUS_INVALID_HANDLE 0xC0000008
75 #ifdef CRYPTOPP_UNIX_AVAILABLE
83 #if defined(NONBLOCKING_RNG_AVAILABLE) || defined(BLOCKING_RNG_AVAILABLE)
85 :
Exception(OTHER_ERROR,
"OS_Rng: " + operation +
" operation failed with error " +
86 #ifdef CRYPTOPP_WIN32_AVAILABLE
96 #ifdef NONBLOCKING_RNG_AVAILABLE
98 #ifdef CRYPTOPP_WIN32_AVAILABLE
100 #if defined(USE_MS_CNGAPI)
101 inline DWORD NtStatusToErrorCode(NTSTATUS status)
103 if (status ==
static_cast<NTSTATUS
>(STATUS_INVALID_PARAMETER))
104 return ERROR_INVALID_PARAMETER;
105 else if (status ==
static_cast<NTSTATUS
>(STATUS_INVALID_HANDLE))
106 return ERROR_INVALID_HANDLE;
108 return static_cast<DWORD
>(status);
112 #if defined(UNICODE) || defined(_UNICODE)
113 # define CRYPTOPP_CONTAINER L"Crypto++ RNG"
115 # define CRYPTOPP_CONTAINER "Crypto++ RNG"
120 #if defined(USE_MS_CRYPTOAPI)
122 if (!CryptAcquireContext(&m_hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
124 const DWORD firstErr = GetLastError();
125 if (!CryptAcquireContext(&m_hProvider, CRYPTOPP_CONTAINER, 0, PROV_RSA_FULL, CRYPT_NEWKEYSET ) &&
126 !CryptAcquireContext(&m_hProvider, CRYPTOPP_CONTAINER, 0, PROV_RSA_FULL, CRYPT_MACHINE_KEYSET|CRYPT_NEWKEYSET))
129 SetLastError(firstErr);
133 #elif defined(USE_MS_CNGAPI)
134 NTSTATUS ret = BCryptOpenAlgorithmProvider(&m_hProvider, BCRYPT_RNG_ALGORITHM, MS_PRIMITIVE_PROVIDER, 0);
135 if (!(BCRYPT_SUCCESS(ret)))
138 SetLastError(NtStatusToErrorCode(ret));
139 throw OS_RNG_Err(
"BCryptOpenAlgorithmProvider");
144 MicrosoftCryptoProvider::~MicrosoftCryptoProvider()
146 #if defined(USE_MS_CRYPTOAPI)
148 CryptReleaseContext(m_hProvider, 0);
149 #elif defined(USE_MS_CNGAPI)
151 BCryptCloseAlgorithmProvider(m_hProvider, 0);
155 #endif // CRYPTOPP_WIN32_AVAILABLE
159 #if !defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(USE_FREEBSD_ARC4RANDOM)
160 # ifndef DONT_USE_O_NOFOLLOW
161 const int flags = O_RDONLY|O_NOFOLLOW;
163 const int flags = O_RDONLY;
166 m_fd = open(
"/dev/urandom", flags);
173 NonblockingRng::~NonblockingRng()
175 #if !defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(USE_FREEBSD_ARC4RANDOM)
182 #ifdef CRYPTOPP_WIN32_AVAILABLE
184 # if defined(CRYPTOPP_CXX11_STATIC_INIT)
189 # if defined(USE_MS_CRYPTOAPI)
194 SetLastError(ERROR_INCORRECT_SIZE);
201 # elif defined(USE_MS_CNGAPI)
206 SetLastError(ERROR_INCORRECT_SIZE);
209 NTSTATUS ret = BCryptGenRandom(hProvider.
GetProviderHandle(), output, ulSize, 0);
211 if (!(BCRYPT_SUCCESS(ret)))
214 SetLastError(NtStatusToErrorCode(ret));
220 # if defined(USE_FREEBSD_ARC4RANDOM)
223 arc4random_buf(output, size);
227 ssize_t len = read(m_fd, output, size);
231 if (errno != EINTR && errno != EAGAIN)
239 # endif // USE_FREEBSD_ARC4RANDOM
241 #endif // CRYPTOPP_WIN32_AVAILABLE
244 #endif // NONBLOCKING_RNG_AVAILABLE
248 #ifdef BLOCKING_RNG_AVAILABLE
250 #ifndef CRYPTOPP_BLOCKING_RNG_FILENAME
252 # define CRYPTOPP_BLOCKING_RNG_FILENAME "/dev/srandom"
254 # define CRYPTOPP_BLOCKING_RNG_FILENAME "/dev/random"
260 #ifndef DONT_USE_O_NOFOLLOW
261 const int flags = O_RDONLY|O_NOFOLLOW;
263 const int flags = O_RDONLY;
266 m_fd = open(CRYPTOPP_BLOCKING_RNG_FILENAME, flags);
268 throw OS_RNG_Err(
"open " CRYPTOPP_BLOCKING_RNG_FILENAME);
271 BlockingRng::~BlockingRng()
282 ssize_t len = read(m_fd, output, size);
286 if (errno != EINTR && errno != EAGAIN)
287 throw OS_RNG_Err(
"read " CRYPTOPP_BLOCKING_RNG_FILENAME);
299 #endif // BLOCKING_RNG_AVAILABLE
305 #ifdef NONBLOCKING_RNG_AVAILABLE
309 #ifdef BLOCKING_RNG_AVAILABLE
315 #ifdef BLOCKING_RNG_AVAILABLE
319 #ifdef NONBLOCKING_RNG_AVAILABLE
335 #endif // OS_RNG_AVAILABLE
337 #endif // CRYPTOPP_IMPORTS