Crypto++
osrng.h
Go to the documentation of this file.
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