diff options
author | weidai <weidai@57ff6487-cd31-0410-9ec3-f628ee90f5f0> | 2002-10-04 17:31:41 +0000 |
---|---|---|
committer | weidai <weidai@57ff6487-cd31-0410-9ec3-f628ee90f5f0> | 2002-10-04 17:31:41 +0000 |
commit | b21162cf8e06f40baa1f58be6a8c17435cebc34d (patch) | |
tree | 8b045309c238226c32a563b1df6b9c30a2f0e0b3 /osrng.h | |
download | cryptopp-b21162cf8e06f40baa1f58be6a8c17435cebc34d.tar.gz |
Initial revision
git-svn-id: svn://svn.code.sf.net/p/cryptopp/code/trunk/c5@2 57ff6487-cd31-0410-9ec3-f628ee90f5f0
Diffstat (limited to 'osrng.h')
-rw-r--r-- | osrng.h | 157 |
1 files changed, 157 insertions, 0 deletions
@@ -0,0 +1,157 @@ +#ifndef CRYPTOPP_OSRNG_H +#define CRYPTOPP_OSRNG_H + +#include "config.h" + +#ifdef OS_RNG_AVAILABLE + +#include "randpool.h" +#include "rng.h" + +NAMESPACE_BEGIN(CryptoPP) + +//! Exception class for Operating-System Random Number Generator. +class OS_RNG_Err : public Exception +{ +public: + OS_RNG_Err(const std::string &operation); +}; + +#ifdef NONBLOCKING_RNG_AVAILABLE + +#ifdef CRYPTOPP_WIN32_AVAILABLE +class 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; +}; +#endif + +//! encapsulate CryptoAPI's CryptGenRandom or /dev/urandom +class NonblockingRng : public RandomNumberGenerator +{ +public: + NonblockingRng(); + ~NonblockingRng(); + byte GenerateByte(); + void GenerateBlock(byte *output, unsigned int 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 +class BlockingRng : public RandomNumberGenerator +{ +public: + BlockingRng(); + ~BlockingRng(); + byte GenerateByte(); + void GenerateBlock(byte *output, unsigned int size); + +protected: + int m_fd; +}; + +#endif + +void OS_GenerateRandomBlock(bool blocking, byte *output, unsigned int size); + +//! Automaticly Seeded Randomness Pool +/*! This class seeds itself using an operating system provided RNG. */ +class AutoSeededRandomPool : public RandomPool +{ +public: + //! blocking will be ignored if the prefered RNG isn't 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: + //! blocking will be ignored if the prefered RNG isn't available + explicit AutoSeededX917RNG(bool blocking = false) + {Reseed(blocking);} + void Reseed(bool blocking = false); + + byte GenerateByte(); + +private: + member_ptr<RandomNumberGenerator> m_rng; + SecByteBlock m_lastBlock; + bool m_isDifferent; + unsigned int m_counter; +}; + +template <class BLOCK_CIPHER> +void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(bool blocking) +{ + SecByteBlock seed(BLOCK_CIPHER::BLOCKSIZE + BLOCK_CIPHER::DEFAULT_KEYLENGTH); + const byte *key; + do + { + OS_GenerateRandomBlock(blocking, seed, 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); + m_rng.reset(new X917RNG(new typename BLOCK_CIPHER::Encryption(key, BLOCK_CIPHER::DEFAULT_KEYLENGTH), seed)); + + if (FIPS_140_2_ComplianceEnabled()) + { + m_lastBlock.resize(16); + m_rng->GenerateBlock(m_lastBlock, m_lastBlock.size()); + m_counter = 0; + m_isDifferent = false; + } +} + +template <class BLOCK_CIPHER> +byte AutoSeededX917RNG<BLOCK_CIPHER>::GenerateByte() +{ + byte b = m_rng->GenerateByte(); + + if (FIPS_140_2_ComplianceEnabled()) + { + m_isDifferent = m_isDifferent || b != m_lastBlock[m_counter]; + m_lastBlock[m_counter] = b; + ++m_counter; + if (m_counter == m_lastBlock.size()) + { + if (!m_isDifferent) + throw SelfTestFailure("AutoSeededX917RNG: Continuous random number generator test failed."); + m_counter = 0; + m_isDifferent = false; + } + } + + return b; +} + +NAMESPACE_END + +#endif + +#endif |