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 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 byte NonblockingRng::GenerateByte() 00078 { 00079 byte b; 00080 GenerateBlock(&b, 1); 00081 return b; 00082 } 00083 00084 void NonblockingRng::GenerateBlock(byte *output, unsigned int size) 00085 { 00086 #ifdef CRYPTOPP_WIN32_AVAILABLE 00087 # ifdef WORKAROUND_MS_BUG_Q258000 00088 static MicrosoftCryptoProvider m_Provider; 00089 # endif 00090 if (!CryptGenRandom(m_Provider.GetProviderHandle(), size, output)) 00091 throw OS_RNG_Err("CryptGenRandom"); 00092 #else 00093 if (read(m_fd, output, size) != size) 00094 throw OS_RNG_Err("read /dev/urandom"); 00095 #endif 00096 } 00097 00098 #endif 00099 00100 // ************************************************************* 00101 00102 #ifdef BLOCKING_RNG_AVAILABLE 00103 00104 BlockingRng::BlockingRng() 00105 { 00106 m_fd = open("/dev/random",O_RDONLY); 00107 if (m_fd == -1) 00108 throw OS_RNG_Err("open /dev/random"); 00109 } 00110 00111 BlockingRng::~BlockingRng() 00112 { 00113 close(m_fd); 00114 } 00115 00116 byte BlockingRng::GenerateByte() 00117 { 00118 byte b; 00119 GenerateBlock(&b, 1); 00120 return b; 00121 } 00122 00123 void BlockingRng::GenerateBlock(byte *output, unsigned int size) 00124 { 00125 while (size) 00126 { 00127 // on some systems /dev/random will block until all bytes 00128 // are available, on others it will returns immediately 00129 int len = read(m_fd, output, STDMIN(size, (unsigned int)INT_MAX)); 00130 if (len == -1) 00131 throw OS_RNG_Err("read /dev/random"); 00132 size -= len; 00133 output += len; 00134 if (size) 00135 sleep(1); 00136 } 00137 } 00138 00139 #endif 00140 00141 // ************************************************************* 00142 00143 void OS_GenerateRandomBlock(bool blocking, byte *output, unsigned int size) 00144 { 00145 #ifdef NONBLOCKING_RNG_AVAILABLE 00146 if (blocking) 00147 #endif 00148 { 00149 #ifdef BLOCKING_RNG_AVAILABLE 00150 BlockingRng rng; 00151 rng.GenerateBlock(output, size); 00152 #endif 00153 } 00154 00155 #ifdef BLOCKING_RNG_AVAILABLE 00156 if (!blocking) 00157 #endif 00158 { 00159 #ifdef NONBLOCKING_RNG_AVAILABLE 00160 NonblockingRng rng; 00161 rng.GenerateBlock(output, size); 00162 #endif 00163 } 00164 } 00165 00166 void AutoSeededRandomPool::Reseed(bool blocking, unsigned int seedSize) 00167 { 00168 SecByteBlock seed(seedSize); 00169 OS_GenerateRandomBlock(blocking, seed, seedSize); 00170 Put(seed, seedSize); 00171 } 00172 00173 NAMESPACE_END 00174 00175 #endif 00176 00177 #endif

Generated on Fri Aug 27 16:09:27 2004 for Crypto++ by doxygen 1.3.8