00001
00002
00003
00004
00005 #include "pch.h"
00006
00007 #ifndef CRYPTOPP_IMPORTS
00008
00009 #include "osrng.h"
00010
00011 #ifdef OS_RNG_AVAILABLE
00012
00013 #include "rng.h"
00014
00015 #ifdef CRYPTOPP_WIN32_AVAILABLE
00016 #ifndef _WIN32_WINNT
00017 #define _WIN32_WINNT 0x0400
00018 #endif
00019 #include <windows.h>
00020 #include <wincrypt.h>
00021 #endif
00022
00023 #ifdef CRYPTOPP_UNIX_AVAILABLE
00024 #include <errno.h>
00025 #include <fcntl.h>
00026 #include <unistd.h>
00027 #endif
00028
00029 NAMESPACE_BEGIN(CryptoPP)
00030
00031 #if defined(NONBLOCKING_RNG_AVAILABLE) || defined(BLOCKING_RNG_AVAILABLE)
00032 OS_RNG_Err::OS_RNG_Err(const std::string &operation)
00033 : Exception(OTHER_ERROR, "OS_Rng: " + operation + " operation failed with error " +
00034 #ifdef CRYPTOPP_WIN32_AVAILABLE
00035 "0x" + IntToString(GetLastError(), 16)
00036 #else
00037 IntToString(errno)
00038 #endif
00039 )
00040 {
00041 }
00042 #endif
00043
00044 #ifdef NONBLOCKING_RNG_AVAILABLE
00045
00046 #ifdef CRYPTOPP_WIN32_AVAILABLE
00047
00048 MicrosoftCryptoProvider::MicrosoftCryptoProvider()
00049 {
00050 if (!CryptAcquireContext(&m_hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
00051 throw OS_RNG_Err("CryptAcquireContext");
00052 }
00053
00054 MicrosoftCryptoProvider::~MicrosoftCryptoProvider()
00055 {
00056 CryptReleaseContext(m_hProvider, 0);
00057 }
00058
00059 #endif
00060
00061 NonblockingRng::NonblockingRng()
00062 {
00063 #ifndef CRYPTOPP_WIN32_AVAILABLE
00064 m_fd = open("/dev/urandom",O_RDONLY);
00065 if (m_fd == -1)
00066 throw OS_RNG_Err("open /dev/urandom");
00067 #endif
00068 }
00069
00070 NonblockingRng::~NonblockingRng()
00071 {
00072 #ifndef CRYPTOPP_WIN32_AVAILABLE
00073 close(m_fd);
00074 #endif
00075 }
00076
00077 void NonblockingRng::GenerateBlock(byte *output, size_t size)
00078 {
00079 #ifdef CRYPTOPP_WIN32_AVAILABLE
00080 # ifdef WORKAROUND_MS_BUG_Q258000
00081 const MicrosoftCryptoProvider &m_Provider = Singleton<MicrosoftCryptoProvider>().Ref();
00082 # endif
00083 if (!CryptGenRandom(m_Provider.GetProviderHandle(), (DWORD)size, output))
00084 throw OS_RNG_Err("CryptGenRandom");
00085 #else
00086 while (size)
00087 {
00088 ssize_t len = read(m_fd, output, size);
00089
00090 if (len < 0)
00091 {
00092
00093 if (errno != EINTR && errno != EAGAIN)
00094 throw OS_RNG_Err("read /dev/urandom");
00095
00096 continue;
00097 }
00098
00099 output += len;
00100 size -= len;
00101 }
00102 #endif
00103 }
00104
00105 #endif
00106
00107
00108
00109 #ifdef BLOCKING_RNG_AVAILABLE
00110
00111 #ifndef CRYPTOPP_BLOCKING_RNG_FILENAME
00112 #ifdef __OpenBSD__
00113 #define CRYPTOPP_BLOCKING_RNG_FILENAME "/dev/srandom"
00114 #else
00115 #define CRYPTOPP_BLOCKING_RNG_FILENAME "/dev/random"
00116 #endif
00117 #endif
00118
00119 BlockingRng::BlockingRng()
00120 {
00121 m_fd = open(CRYPTOPP_BLOCKING_RNG_FILENAME,O_RDONLY);
00122 if (m_fd == -1)
00123 throw OS_RNG_Err("open " CRYPTOPP_BLOCKING_RNG_FILENAME);
00124 }
00125
00126 BlockingRng::~BlockingRng()
00127 {
00128 close(m_fd);
00129 }
00130
00131 void BlockingRng::GenerateBlock(byte *output, size_t size)
00132 {
00133 while (size)
00134 {
00135
00136
00137 ssize_t len = read(m_fd, output, size);
00138 if (len < 0)
00139 {
00140
00141 if (errno != EINTR && errno != EAGAIN)
00142 throw OS_RNG_Err("read " CRYPTOPP_BLOCKING_RNG_FILENAME);
00143
00144 continue;
00145 }
00146
00147 size -= len;
00148 output += len;
00149 if (size)
00150 sleep(1);
00151 }
00152 }
00153
00154 #endif
00155
00156
00157
00158 void OS_GenerateRandomBlock(bool blocking, byte *output, size_t size)
00159 {
00160 #ifdef NONBLOCKING_RNG_AVAILABLE
00161 if (blocking)
00162 #endif
00163 {
00164 #ifdef BLOCKING_RNG_AVAILABLE
00165 BlockingRng rng;
00166 rng.GenerateBlock(output, size);
00167 #endif
00168 }
00169
00170 #ifdef BLOCKING_RNG_AVAILABLE
00171 if (!blocking)
00172 #endif
00173 {
00174 #ifdef NONBLOCKING_RNG_AVAILABLE
00175 NonblockingRng rng;
00176 rng.GenerateBlock(output, size);
00177 #endif
00178 }
00179 }
00180
00181 void AutoSeededRandomPool::Reseed(bool blocking, unsigned int seedSize)
00182 {
00183 SecByteBlock seed(seedSize);
00184 OS_GenerateRandomBlock(blocking, seed, seedSize);
00185 IncorporateEntropy(seed, seedSize);
00186 }
00187
00188 NAMESPACE_END
00189
00190 #endif
00191
00192 #endif