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