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)
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
81NAMESPACE_BEGIN(CryptoPP)
83#if defined(NONBLOCKING_RNG_AVAILABLE) || defined(BLOCKING_RNG_AVAILABLE)
84OS_RNG_Err::OS_RNG_Err(
const std::string &operation)
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)
101inline DWORD NtStatusToErrorCode(NTSTATUS status)
103 if (status == STATUS_INVALID_PARAMETER)
104 return ERROR_INVALID_PARAMETER;
105 else if (status == STATUS_INVALID_HANDLE)
106 return ERROR_INVALID_HANDLE;
108 return (DWORD)status;
112#if defined(UNICODE) || defined(_UNICODE)
113# define CRYPTOPP_CONTAINER L"Crypto++ RNG"
115# define CRYPTOPP_CONTAINER "Crypto++ RNG"
118MicrosoftCryptoProvider::MicrosoftCryptoProvider() : m_hProvider(0)
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);
130 throw OS_RNG_Err(
"CryptAcquireContext");
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");
144MicrosoftCryptoProvider::~MicrosoftCryptoProvider()
146#if defined(USE_MS_CRYPTOAPI)
148 CryptReleaseContext(m_hProvider, 0);
149#elif defined(USE_MS_CNGAPI)
151 BCryptCloseAlgorithmProvider(m_hProvider, 0);
157NonblockingRng::NonblockingRng()
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);
168 throw OS_RNG_Err(
"open /dev/urandom");
173NonblockingRng::~NonblockingRng()
175#if !defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(USE_FREEBSD_ARC4RANDOM)
180void NonblockingRng::GenerateBlock(
byte *output,
size_t size)
182#ifdef CRYPTOPP_WIN32_AVAILABLE
184# if defined(CRYPTOPP_CXX11_STATIC_INIT)
185 static const MicrosoftCryptoProvider hProvider = MicrosoftCryptoProvider();
189# if defined(USE_MS_CRYPTOAPI)
194 SetLastError(ERROR_INCORRECT_SIZE);
195 throw OS_RNG_Err(
"GenerateBlock size");
197 BOOL ret = CryptGenRandom(hProvider.GetProviderHandle(), dwSize, output);
198 CRYPTOPP_ASSERT(ret != FALSE);
200 throw OS_RNG_Err(
"CryptGenRandom");
201# elif defined(USE_MS_CNGAPI)
206 SetLastError(ERROR_INCORRECT_SIZE);
207 throw OS_RNG_Err(
"GenerateBlock size");
209 NTSTATUS ret = BCryptGenRandom(hProvider.GetProviderHandle(), output, ulSize, 0);
210 CRYPTOPP_ASSERT(BCRYPT_SUCCESS(ret));
211 if (!(BCRYPT_SUCCESS(ret)))
214 SetLastError(NtStatusToErrorCode(ret));
215 throw OS_RNG_Err(
"BCryptGenRandom");
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)
232 throw OS_RNG_Err(
"read /dev/urandom");
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"
258BlockingRng::BlockingRng()
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);
271BlockingRng::~BlockingRng()
276void BlockingRng::GenerateBlock(
byte *output,
size_t size)
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);
303void OS_GenerateRandomBlock(
bool blocking,
byte *output,
size_t size)
305#ifdef NONBLOCKING_RNG_AVAILABLE
309#ifdef BLOCKING_RNG_AVAILABLE
311 rng.GenerateBlock(output, size);
315#ifdef BLOCKING_RNG_AVAILABLE
319#ifdef NONBLOCKING_RNG_AVAILABLE
321 rng.GenerateBlock(output, size);
326void AutoSeededRandomPool::Reseed(
bool blocking,
unsigned int seedSize)
329 OS_GenerateRandomBlock(blocking, seed, seedSize);
330 IncorporateEntropy(seed, seedSize);
Base class for all exceptions thrown by the library.
Restricts the instantiation of a class to one static object without locks.
CRYPTOPP_NOINLINE const T & Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const
Return a reference to the inner Singleton object.
Library configuration file.
std::string IntToString(T value, unsigned int base=10)
Converts a value to a string.
bool SafeConvert(T1 from, T2 &to)
Tests whether a conversion from -> to is safe to perform.
Classes for access to the operating system's random number generators.
Miscellaneous classes for RNGs.