diff options
Diffstat (limited to 'CryptoPP/osrng.h')
-rw-r--r-- | CryptoPP/osrng.h | 156 |
1 files changed, 156 insertions, 0 deletions
diff --git a/CryptoPP/osrng.h b/CryptoPP/osrng.h new file mode 100644 index 000000000..ae07d057b --- /dev/null +++ b/CryptoPP/osrng.h @@ -0,0 +1,156 @@ +#ifndef CRYPTOPP_OSRNG_H +#define CRYPTOPP_OSRNG_H + +//! \file + +#include "config.h" + +#ifdef OS_RNG_AVAILABLE + +#include "randpool.h" +#include "rng.h" +#include "aes.h" +#include "sha.h" +#include "fips140.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! Exception class for Operating-System Random Number Generator. +class CRYPTOPP_DLL OS_RNG_Err : public Exception +{ +public: + OS_RNG_Err(const std::string &operation); +}; + +#ifdef NONBLOCKING_RNG_AVAILABLE + +#ifdef CRYPTOPP_WIN32_AVAILABLE +class CRYPTOPP_DLL MicrosoftCryptoProvider +{ +public: + MicrosoftCryptoProvider(); + ~MicrosoftCryptoProvider(); +#if defined(_WIN64) + typedef unsigned __int64 ProviderHandle; // type HCRYPTPROV, avoid #include <windows.h> +#else + typedef unsigned long ProviderHandle; +#endif + ProviderHandle GetProviderHandle() const {return m_hProvider;} +private: + ProviderHandle m_hProvider; +}; + +#pragma comment(lib, "advapi32.lib") +#endif + +//! encapsulate CryptoAPI's CryptGenRandom or /dev/urandom +class CRYPTOPP_DLL NonblockingRng : public RandomNumberGenerator +{ +public: + NonblockingRng(); + ~NonblockingRng(); + void GenerateBlock(byte *output, size_t size); + +protected: +#ifdef CRYPTOPP_WIN32_AVAILABLE +# ifndef WORKAROUND_MS_BUG_Q258000 + MicrosoftCryptoProvider m_Provider; +# endif +#else + int m_fd; +#endif +}; + +#endif + +#ifdef BLOCKING_RNG_AVAILABLE + +//! encapsulate /dev/random, or /dev/srandom on OpenBSD +class CRYPTOPP_DLL BlockingRng : public RandomNumberGenerator +{ +public: + BlockingRng(); + ~BlockingRng(); + void GenerateBlock(byte *output, size_t size); + +protected: + int m_fd; +}; + +#endif + +CRYPTOPP_DLL void CRYPTOPP_API OS_GenerateRandomBlock(bool blocking, byte *output, size_t size); + +//! Automaticly Seeded Randomness Pool +/*! This class seeds itself using an operating system provided RNG. */ +class CRYPTOPP_DLL AutoSeededRandomPool : public RandomPool +{ +public: + //! use blocking to choose seeding with BlockingRng or NonblockingRng. the parameter is ignored if only one of these is available + explicit AutoSeededRandomPool(bool blocking = false, unsigned int seedSize = 32) + {Reseed(blocking, seedSize);} + void Reseed(bool blocking = false, unsigned int seedSize = 32); +}; + +//! RNG from ANSI X9.17 Appendix C, seeded using an OS provided RNG +template <class BLOCK_CIPHER> +class AutoSeededX917RNG : public RandomNumberGenerator, public NotCopyable +{ +public: + //! use blocking to choose seeding with BlockingRng or NonblockingRng. the parameter is ignored if only one of these is available + explicit AutoSeededX917RNG(bool blocking = false, bool autoSeed = true) + {if (autoSeed) Reseed(blocking);} + void Reseed(bool blocking = false, const byte *additionalEntropy = NULL, size_t length = 0); + // exposed for testing + void Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector); + + bool CanIncorporateEntropy() const {return true;} + void IncorporateEntropy(const byte *input, size_t length) {Reseed(false, input, length);} + void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length) {m_rng->GenerateIntoBufferedTransformation(target, channel, length);} + +private: + member_ptr<RandomNumberGenerator> m_rng; +}; + +template <class BLOCK_CIPHER> +void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector) +{ + m_rng.reset(new X917RNG(new typename BLOCK_CIPHER::Encryption(key, keylength), seed, timeVector)); +} + +template <class BLOCK_CIPHER> +void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(bool blocking, const byte *input, size_t length) +{ + SecByteBlock seed(BLOCK_CIPHER::BLOCKSIZE + BLOCK_CIPHER::DEFAULT_KEYLENGTH); + const byte *key; + do + { + OS_GenerateRandomBlock(blocking, seed, seed.size()); + if (length > 0) + { + SHA256 hash; + hash.Update(seed, seed.size()); + hash.Update(input, length); + hash.TruncatedFinal(seed, UnsignedMin(hash.DigestSize(), seed.size())); + } + key = seed + BLOCK_CIPHER::BLOCKSIZE; + } // check that seed and key don't have same value + while (memcmp(key, seed, STDMIN((unsigned int)BLOCK_CIPHER::BLOCKSIZE, (unsigned int)BLOCK_CIPHER::DEFAULT_KEYLENGTH)) == 0); + + Reseed(key, BLOCK_CIPHER::DEFAULT_KEYLENGTH, seed, NULL); +} + +CRYPTOPP_DLL_TEMPLATE_CLASS AutoSeededX917RNG<AES>; + +//! this is AutoSeededX917RNG\<AES\> in FIPS mode, otherwise it's AutoSeededRandomPool +#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 +typedef AutoSeededX917RNG<AES> DefaultAutoSeededRNG; +#else +typedef AutoSeededRandomPool DefaultAutoSeededRNG; +#endif + +NAMESPACE_END + +#endif + +#endif |