You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
156 lines
4.4 KiB
156 lines
4.4 KiB
#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
|
|
|