Crypto++
|
00001 #ifndef CRYPTOPP_OSRNG_H 00002 #define CRYPTOPP_OSRNG_H 00003 00004 //! \file 00005 00006 #include "config.h" 00007 00008 #ifdef OS_RNG_AVAILABLE 00009 00010 #include "randpool.h" 00011 #include "rng.h" 00012 #include "aes.h" 00013 #include "sha.h" 00014 #include "fips140.h" 00015 00016 NAMESPACE_BEGIN(CryptoPP) 00017 00018 //! Exception class for Operating-System Random Number Generator. 00019 class CRYPTOPP_DLL OS_RNG_Err : public Exception 00020 { 00021 public: 00022 OS_RNG_Err(const std::string &operation); 00023 }; 00024 00025 #ifdef NONBLOCKING_RNG_AVAILABLE 00026 00027 #ifdef CRYPTOPP_WIN32_AVAILABLE 00028 class CRYPTOPP_DLL MicrosoftCryptoProvider 00029 { 00030 public: 00031 MicrosoftCryptoProvider(); 00032 ~MicrosoftCryptoProvider(); 00033 #if defined(_WIN64) 00034 typedef unsigned __int64 ProviderHandle; // type HCRYPTPROV, avoid #include <windows.h> 00035 #else 00036 typedef unsigned long ProviderHandle; 00037 #endif 00038 ProviderHandle GetProviderHandle() const {return m_hProvider;} 00039 private: 00040 ProviderHandle m_hProvider; 00041 }; 00042 00043 #pragma comment(lib, "advapi32.lib") 00044 #endif 00045 00046 //! encapsulate CryptoAPI's CryptGenRandom or /dev/urandom 00047 class CRYPTOPP_DLL NonblockingRng : public RandomNumberGenerator 00048 { 00049 public: 00050 NonblockingRng(); 00051 ~NonblockingRng(); 00052 void GenerateBlock(byte *output, size_t size); 00053 00054 protected: 00055 #ifdef CRYPTOPP_WIN32_AVAILABLE 00056 # ifndef WORKAROUND_MS_BUG_Q258000 00057 MicrosoftCryptoProvider m_Provider; 00058 # endif 00059 #else 00060 int m_fd; 00061 #endif 00062 }; 00063 00064 #endif 00065 00066 #ifdef BLOCKING_RNG_AVAILABLE 00067 00068 //! encapsulate /dev/random, or /dev/srandom on OpenBSD 00069 class CRYPTOPP_DLL BlockingRng : public RandomNumberGenerator 00070 { 00071 public: 00072 BlockingRng(); 00073 ~BlockingRng(); 00074 void GenerateBlock(byte *output, size_t size); 00075 00076 protected: 00077 int m_fd; 00078 }; 00079 00080 #endif 00081 00082 CRYPTOPP_DLL void CRYPTOPP_API OS_GenerateRandomBlock(bool blocking, byte *output, size_t size); 00083 00084 //! Automaticly Seeded Randomness Pool 00085 /*! This class seeds itself using an operating system provided RNG. */ 00086 class CRYPTOPP_DLL AutoSeededRandomPool : public RandomPool 00087 { 00088 public: 00089 //! use blocking to choose seeding with BlockingRng or NonblockingRng. the parameter is ignored if only one of these is available 00090 explicit AutoSeededRandomPool(bool blocking = false, unsigned int seedSize = 32) 00091 {Reseed(blocking, seedSize);} 00092 void Reseed(bool blocking = false, unsigned int seedSize = 32); 00093 }; 00094 00095 //! RNG from ANSI X9.17 Appendix C, seeded using an OS provided RNG 00096 template <class BLOCK_CIPHER> 00097 class AutoSeededX917RNG : public RandomNumberGenerator, public NotCopyable 00098 { 00099 public: 00100 //! use blocking to choose seeding with BlockingRng or NonblockingRng. the parameter is ignored if only one of these is available 00101 explicit AutoSeededX917RNG(bool blocking = false, bool autoSeed = true) 00102 {if (autoSeed) Reseed(blocking);} 00103 void Reseed(bool blocking = false, const byte *additionalEntropy = NULL, size_t length = 0); 00104 // exposed for testing 00105 void Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector); 00106 00107 bool CanIncorporateEntropy() const {return true;} 00108 void IncorporateEntropy(const byte *input, size_t length) {Reseed(false, input, length);} 00109 void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length) {m_rng->GenerateIntoBufferedTransformation(target, channel, length);} 00110 00111 private: 00112 member_ptr<RandomNumberGenerator> m_rng; 00113 }; 00114 00115 template <class BLOCK_CIPHER> 00116 void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector) 00117 { 00118 m_rng.reset(new X917RNG(new typename BLOCK_CIPHER::Encryption(key, keylength), seed, timeVector)); 00119 } 00120 00121 template <class BLOCK_CIPHER> 00122 void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(bool blocking, const byte *input, size_t length) 00123 { 00124 SecByteBlock seed(BLOCK_CIPHER::BLOCKSIZE + BLOCK_CIPHER::DEFAULT_KEYLENGTH); 00125 const byte *key; 00126 do 00127 { 00128 OS_GenerateRandomBlock(blocking, seed, seed.size()); 00129 if (length > 0) 00130 { 00131 SHA256 hash; 00132 hash.Update(seed, seed.size()); 00133 hash.Update(input, length); 00134 hash.TruncatedFinal(seed, UnsignedMin(hash.DigestSize(), seed.size())); 00135 } 00136 key = seed + BLOCK_CIPHER::BLOCKSIZE; 00137 } // check that seed and key don't have same value 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, NULL); 00141 } 00142 00143 CRYPTOPP_DLL_TEMPLATE_CLASS AutoSeededX917RNG<AES>; 00144 00145 //! this is AutoSeededX917RNG<AES> in FIPS mode, otherwise it's AutoSeededRandomPool 00146 #if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 00147 typedef AutoSeededX917RNG<AES> DefaultAutoSeededRNG; 00148 #else 00149 typedef AutoSeededRandomPool DefaultAutoSeededRNG; 00150 #endif 00151 00152 NAMESPACE_END 00153 00154 #endif 00155 00156 #endif