Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

osrng.cpp

00001 // osrng.cpp - written and placed in the public domain by Wei Dai 00002 00003 // Thanks to Leonard Janke for the suggestion for AutoSeededRandomPool. 00004 00005 #include "pch.h" 00006 #include "osrng.h" 00007 00008 #ifdef OS_RNG_AVAILABLE 00009 00010 #include "rng.h" 00011 00012 #ifdef CRYPTOPP_WIN32_AVAILABLE 00013 #ifndef _WIN32_WINNT 00014 #define _WIN32_WINNT 0x0400 00015 #endif 00016 #include <windows.h> 00017 #include <wincrypt.h> 00018 #endif 00019 00020 #ifdef CRYPTOPP_UNIX_AVAILABLE 00021 #include <errno.h> 00022 #include <fcntl.h> 00023 #include <unistd.h> 00024 #endif 00025 00026 NAMESPACE_BEGIN(CryptoPP) 00027 00028 #if defined(NONBLOCKING_RNG_AVAILABLE) || defined(BLOCKING_RNG_AVAILABLE) 00029 OS_RNG_Err::OS_RNG_Err(const std::string &operation) 00030 : Exception(OTHER_ERROR, "OS_Rng: " + operation + " operation failed with error " + 00031 #ifdef CRYPTOPP_WIN32_AVAILABLE 00032 "0x" + IntToString(GetLastError(), 16) 00033 #else 00034 IntToString(errno) 00035 #endif 00036 ) 00037 { 00038 } 00039 #endif 00040 00041 #ifdef NONBLOCKING_RNG_AVAILABLE 00042 00043 #ifdef CRYPTOPP_WIN32_AVAILABLE 00044 00045 MicrosoftCryptoProvider::MicrosoftCryptoProvider() 00046 { 00047 if(!CryptAcquireContext(&m_hProvider, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) 00048 throw OS_RNG_Err("CryptAcquireContext"); 00049 } 00050 00051 MicrosoftCryptoProvider::~MicrosoftCryptoProvider() 00052 { 00053 CryptReleaseContext(m_hProvider, 0); 00054 } 00055 00056 #endif 00057 00058 NonblockingRng::NonblockingRng() 00059 { 00060 #ifndef CRYPTOPP_WIN32_AVAILABLE 00061 m_fd = open("/dev/urandom",O_RDONLY); 00062 if (m_fd == -1) 00063 throw OS_RNG_Err("open /dev/urandom"); 00064 #endif 00065 } 00066 00067 NonblockingRng::~NonblockingRng() 00068 { 00069 #ifndef CRYPTOPP_WIN32_AVAILABLE 00070 close(m_fd); 00071 #endif 00072 } 00073 00074 byte NonblockingRng::GenerateByte() 00075 { 00076 byte b; 00077 GenerateBlock(&b, 1); 00078 return b; 00079 } 00080 00081 void NonblockingRng::GenerateBlock(byte *output, unsigned int size) 00082 { 00083 #ifdef CRYPTOPP_WIN32_AVAILABLE 00084 # ifdef WORKAROUND_MS_BUG_Q258000 00085 static MicrosoftCryptoProvider m_Provider; 00086 # endif 00087 if (!CryptGenRandom(m_Provider.GetProviderHandle(), size, output)) 00088 throw OS_RNG_Err("CryptGenRandom"); 00089 #else 00090 if (read(m_fd, output, size) != size) 00091 throw OS_RNG_Err("read /dev/urandom"); 00092 #endif 00093 } 00094 00095 #endif 00096 00097 // ************************************************************* 00098 00099 #ifdef BLOCKING_RNG_AVAILABLE 00100 00101 BlockingRng::BlockingRng() 00102 { 00103 m_fd = open("/dev/random",O_RDONLY); 00104 if (m_fd == -1) 00105 throw OS_RNG_Err("open /dev/random"); 00106 } 00107 00108 BlockingRng::~BlockingRng() 00109 { 00110 close(m_fd); 00111 } 00112 00113 byte BlockingRng::GenerateByte() 00114 { 00115 byte b; 00116 GenerateBlock(&b, 1); 00117 return b; 00118 } 00119 00120 void BlockingRng::GenerateBlock(byte *output, unsigned int size) 00121 { 00122 while (size) 00123 { 00124 // on some systems /dev/random will block until all bytes 00125 // are available, on others it will returns immediately 00126 int len = read(m_fd, output, STDMIN(size, (unsigned int)INT_MAX)); 00127 if (len == -1) 00128 throw OS_RNG_Err("read /dev/random"); 00129 size -= len; 00130 output += len; 00131 if (size) 00132 sleep(1); 00133 } 00134 } 00135 00136 #endif 00137 00138 // ************************************************************* 00139 00140 void OS_GenerateRandomBlock(bool blocking, byte *output, unsigned int size) 00141 { 00142 #ifdef NONBLOCKING_RNG_AVAILABLE 00143 if (blocking) 00144 #endif 00145 { 00146 #ifdef BLOCKING_RNG_AVAILABLE 00147 BlockingRng rng; 00148 rng.GenerateBlock(output, size); 00149 #endif 00150 } 00151 00152 #ifdef BLOCKING_RNG_AVAILABLE 00153 if (!blocking) 00154 #endif 00155 { 00156 #ifdef NONBLOCKING_RNG_AVAILABLE 00157 NonblockingRng rng; 00158 rng.GenerateBlock(output, size); 00159 #endif 00160 } 00161 } 00162 00163 void AutoSeededRandomPool::Reseed(bool blocking, unsigned int seedSize) 00164 { 00165 SecByteBlock seed(seedSize); 00166 OS_GenerateRandomBlock(blocking, seed, seedSize); 00167 Put(seed, seedSize); 00168 } 00169 00170 NAMESPACE_END 00171 00172 #endif

Generated on Fri Aug 13 09:56:54 2004 for Crypto++ by doxygen 1.3.7