00001 #ifndef CRYPTOPP_OSRNG_H
00002 #define CRYPTOPP_OSRNG_H
00003
00004 #include "cryptopp_config.h"
00005
00006 #ifdef OS_RNG_AVAILABLE
00007
00008 #include "randpool.h"
00009 #include "rng.h"
00010
00011 NAMESPACE_BEGIN(CryptoPP)
00012
00013
00014 class OS_RNG_Err : public Exception
00015 {
00016 public:
00017 OS_RNG_Err(const std::string &operation);
00018 };
00019
00020 #ifdef NONBLOCKING_RNG_AVAILABLE
00021
00022 #ifdef CRYPTOPP_WIN32_AVAILABLE
00023 class MicrosoftCryptoProvider
00024 {
00025 public:
00026 MicrosoftCryptoProvider();
00027 ~MicrosoftCryptoProvider();
00028 #if defined(_WIN64)
00029 typedef unsigned __int64 ProviderHandle;
00030 #else
00031 typedef unsigned long ProviderHandle;
00032 #endif
00033 ProviderHandle GetProviderHandle() const {return m_hProvider;}
00034 private:
00035 ProviderHandle m_hProvider;
00036 };
00037 #endif
00038
00039
00040 class NonblockingRng : public RandomNumberGenerator
00041 {
00042 public:
00043 NonblockingRng();
00044 ~NonblockingRng();
00045 byte GenerateByte();
00046 void GenerateBlock(byte *output, unsigned int size);
00047
00048 protected:
00049 #ifdef CRYPTOPP_WIN32_AVAILABLE
00050 # ifndef WORKAROUND_MS_BUG_Q258000
00051 MicrosoftCryptoProvider m_Provider;
00052 # endif
00053 #else
00054 int m_fd;
00055 #endif
00056 };
00057
00058 #endif
00059
00060 #ifdef BLOCKING_RNG_AVAILABLE
00061
00062
00063 class BlockingRng : public RandomNumberGenerator
00064 {
00065 public:
00066 BlockingRng();
00067 ~BlockingRng();
00068 byte GenerateByte();
00069 void GenerateBlock(byte *output, unsigned int size);
00070
00071 protected:
00072 int m_fd;
00073 };
00074
00075 #endif
00076
00077 void OS_GenerateRandomBlock(bool blocking, byte *output, unsigned int size);
00078
00079
00080
00081 class AutoSeededRandomPool : public RandomPool
00082 {
00083 public:
00084
00085 explicit AutoSeededRandomPool(bool blocking = false, unsigned int seedSize = 32)
00086 {Reseed(blocking, seedSize);}
00087 void Reseed(bool blocking = false, unsigned int seedSize = 32);
00088 };
00089
00090
00091 template <class BLOCK_CIPHER>
00092 class AutoSeededX917RNG : public RandomNumberGenerator
00093 {
00094 public:
00095
00096 explicit AutoSeededX917RNG(bool blocking = false)
00097 {Reseed(blocking);}
00098 void Reseed(bool blocking = false);
00099
00100 void Reseed(const byte *key, unsigned int keylength, const byte *seed, unsigned long timeVector);
00101
00102 byte GenerateByte();
00103
00104 private:
00105 member_ptr<RandomNumberGenerator> m_rng;
00106 SecByteBlock m_lastBlock;
00107 bool m_isDifferent;
00108 unsigned int m_counter;
00109 };
00110
00111 template <class BLOCK_CIPHER>
00112 void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(const byte *key, unsigned int keylength, const byte *seed, unsigned long timeVector)
00113 {
00114 m_rng.reset(new X917RNG(new typename BLOCK_CIPHER::Encryption(key, keylength), seed, timeVector));
00115
00116
00117 m_lastBlock.resize(16);
00118 m_rng->GenerateBlock(m_lastBlock, m_lastBlock.size());
00119 m_counter = 0;
00120 m_isDifferent = false;
00121 }
00122
00123 template <class BLOCK_CIPHER>
00124 void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(bool blocking)
00125 {
00126 SecByteBlock seed(BLOCK_CIPHER::BLOCKSIZE + BLOCK_CIPHER::DEFAULT_KEYLENGTH);
00127 const byte *key;
00128 do
00129 {
00130 OS_GenerateRandomBlock(blocking, seed, seed.size());
00131 key = seed + BLOCK_CIPHER::BLOCKSIZE;
00132 }
00133 while (memcmp(key, seed, STDMIN((unsigned int)BLOCK_CIPHER::BLOCKSIZE, (unsigned int)BLOCK_CIPHER::DEFAULT_KEYLENGTH)) == 0);
00134
00135 Reseed(key, BLOCK_CIPHER::DEFAULT_KEYLENGTH, seed, 0);
00136 }
00137
00138 template <class BLOCK_CIPHER>
00139 byte AutoSeededX917RNG<BLOCK_CIPHER>::GenerateByte()
00140 {
00141 byte b = m_rng->GenerateByte();
00142
00143
00144 m_isDifferent = m_isDifferent || b != m_lastBlock[m_counter];
00145 m_lastBlock[m_counter] = b;
00146 ++m_counter;
00147 if (m_counter == m_lastBlock.size())
00148 {
00149 if (!m_isDifferent)
00150 throw SelfTestFailure("AutoSeededX917RNG: Continuous random number generator test failed.");
00151 m_counter = 0;
00152 m_isDifferent = false;
00153 }
00154
00155 return b;
00156 }
00157
00158 NAMESPACE_END
00159
00160 #endif
00161
00162 #endif