summaryrefslogtreecommitdiffstats
path: root/CryptoPP/osrng.h
diff options
context:
space:
mode:
Diffstat (limited to 'CryptoPP/osrng.h')
-rw-r--r--CryptoPP/osrng.h156
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