Team Fortress 2 Source Code as on 22/4/2020
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.

256 lines
9.1 KiB

  1. // osrng.h - written and placed in the public domain by Wei Dai
  2. //! \file
  3. //! \headerfile osrng.h
  4. //! \brief Classes for access to the operating system's random number generators
  5. #ifndef CRYPTOPP_OSRNG_H
  6. #define CRYPTOPP_OSRNG_H
  7. #include "config.h"
  8. #ifdef OS_RNG_AVAILABLE
  9. #include "cryptlib.h"
  10. #include "randpool.h"
  11. #include "smartptr.h"
  12. #include "fips140.h"
  13. #include "rng.h"
  14. #include "aes.h"
  15. #include "sha.h"
  16. NAMESPACE_BEGIN(CryptoPP)
  17. //! \class OS_RNG_Err
  18. //! \brief Exception thrown when an operating system error is encountered
  19. class CRYPTOPP_DLL OS_RNG_Err : public Exception
  20. {
  21. public:
  22. //! \brief Constructs an OS_RNG_Err
  23. //! \param operation the operation or API call when the error occurs
  24. OS_RNG_Err(const std::string &operation);
  25. };
  26. #ifdef NONBLOCKING_RNG_AVAILABLE
  27. #ifdef CRYPTOPP_WIN32_AVAILABLE
  28. //! \class MicrosoftCryptoProvider
  29. //! \brief Wrapper for Microsoft crypto service provider
  30. //! \sa \def USE_MS_CRYPTOAPI, \def WORKAROUND_MS_BUG_Q258000
  31. class CRYPTOPP_DLL MicrosoftCryptoProvider
  32. {
  33. public:
  34. //! \brief Construct a MicrosoftCryptoProvider
  35. MicrosoftCryptoProvider();
  36. ~MicrosoftCryptoProvider();
  37. // type HCRYPTPROV, avoid #include <windows.h>
  38. #if defined(__CYGWIN__) && defined(__x86_64__)
  39. typedef unsigned long long ProviderHandle;
  40. #elif defined(WIN64) || defined(_WIN64)
  41. typedef unsigned __int64 ProviderHandle;
  42. #else
  43. typedef unsigned long ProviderHandle;
  44. #endif
  45. //! \brief Retrieves the CryptoAPI provider handle
  46. //! \returns CryptoAPI provider handle
  47. //! \details The handle is acquired by a call to CryptAcquireContext().
  48. //! CryptReleaseContext() is called upon destruction.
  49. ProviderHandle GetProviderHandle() const {return m_hProvider;}
  50. private:
  51. ProviderHandle m_hProvider;
  52. };
  53. #if defined(_MSC_VER)
  54. # pragma comment(lib, "advapi32.lib")
  55. #endif
  56. #endif //CRYPTOPP_WIN32_AVAILABLE
  57. //! \class NonblockingRng
  58. //! \brief Wrapper class for /dev/random and /dev/srandom
  59. //! \details Encapsulates CryptoAPI's CryptGenRandom() on Windows, or /dev/urandom on Unix and compatibles.
  60. class CRYPTOPP_DLL NonblockingRng : public RandomNumberGenerator
  61. {
  62. public:
  63. //! \brief Construct a NonblockingRng
  64. NonblockingRng();
  65. ~NonblockingRng();
  66. //! \brief Generate random array of bytes
  67. //! \param output the byte buffer
  68. //! \param size the length of the buffer, in bytes
  69. //! \details GenerateIntoBufferedTransformation() calls are routed to GenerateBlock().
  70. void GenerateBlock(byte *output, size_t size);
  71. protected:
  72. #ifdef CRYPTOPP_WIN32_AVAILABLE
  73. //# ifndef WORKAROUND_MS_BUG_Q258000
  74. // MicrosoftCryptoProvider m_Provider;
  75. //# endif
  76. #else
  77. int m_fd;
  78. #endif
  79. };
  80. #endif
  81. #if defined(BLOCKING_RNG_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
  82. //! \class BlockingRng
  83. //! \brief Wrapper class for /dev/random and /dev/srandom
  84. //! \details Encapsulates /dev/random on Linux, OS X and Unix; and /dev/srandom on the BSDs.
  85. class CRYPTOPP_DLL BlockingRng : public RandomNumberGenerator
  86. {
  87. public:
  88. //! \brief Construct a BlockingRng
  89. BlockingRng();
  90. ~BlockingRng();
  91. //! \brief Generate random array of bytes
  92. //! \param output the byte buffer
  93. //! \param size the length of the buffer, in bytes
  94. //! \details GenerateIntoBufferedTransformation() calls are routed to GenerateBlock().
  95. void GenerateBlock(byte *output, size_t size);
  96. protected:
  97. int m_fd;
  98. };
  99. #endif
  100. //! OS_GenerateRandomBlock
  101. //! \brief Generate random array of bytes
  102. //! \param blocking specifies whther a bobcking or non-blocking generator should be used
  103. //! \param output the byte buffer
  104. //! \param size the length of the buffer, in bytes
  105. //! \details OS_GenerateRandomBlock() uses the underlying operating system's
  106. //! random number generator. On Windows, CryptGenRandom() is called using NonblockingRng.
  107. //! \details On Unix and compatibles, /dev/urandom is called if blocking is false using
  108. //! NonblockingRng. If blocking is true, then either /dev/randomd or /dev/srandom is used
  109. //! by way of BlockingRng, if available.
  110. CRYPTOPP_DLL void CRYPTOPP_API OS_GenerateRandomBlock(bool blocking, byte *output, size_t size);
  111. //! \class AutoSeededRandomPool
  112. //! \brief Automatically Seeded Randomness Pool
  113. //! \details This class seeds itself using an operating system provided RNG.
  114. class CRYPTOPP_DLL AutoSeededRandomPool : public RandomPool
  115. {
  116. public:
  117. //! \brief Construct an AutoSeededRandomPool
  118. //! \param blocking controls seeding with BlockingRng or NonblockingRng
  119. //! \param seedSize the size of the seed, in bytes
  120. //! \details Use blocking to choose seeding with BlockingRng or NonblockingRng.
  121. //! The parameter is ignored if only one of these is available.
  122. explicit AutoSeededRandomPool(bool blocking = false, unsigned int seedSize = 32)
  123. {Reseed(blocking, seedSize);}
  124. //! \brief Reseed an AutoSeededRandomPool
  125. //! \param blocking controls seeding with BlockingRng or NonblockingRng
  126. //! \param seedSize the size of the seed, in bytes
  127. void Reseed(bool blocking = false, unsigned int seedSize = 32);
  128. };
  129. //! \class AutoSeededX917RNG
  130. //! \tparam BLOCK_CIPHER a block cipher
  131. //! \brief Automatically Seeded X9.17 RNG
  132. //! \details AutoSeededX917RNG is from ANSI X9.17 Appendix C, seeded using an OS provided RNG.
  133. //! If 3-key TripleDES (DES_EDE3) is used, then its a X9.17 conforming generator. If AES is
  134. //! used, then its a X9.31 conforming generator.
  135. //! \details Though ANSI X9 prescribes 3-key TripleDES, the template parameter BLOCK_CIPHER can be any
  136. //! BlockTransformation derived class.
  137. //! \sa X917RNG, DefaultAutoSeededRNG
  138. template <class BLOCK_CIPHER>
  139. class AutoSeededX917RNG : public RandomNumberGenerator, public NotCopyable
  140. {
  141. public:
  142. //! \brief Construct an AutoSeededX917RNG
  143. //! \param blocking controls seeding with BlockingRng or NonblockingRng
  144. //! \param autoSeed controls auto seeding of the generator
  145. //! \details Use blocking to choose seeding with BlockingRng or NonblockingRng.
  146. //! The parameter is ignored if only one of these is available.
  147. //! \sa X917RNG
  148. explicit AutoSeededX917RNG(bool blocking = false, bool autoSeed = true)
  149. {if (autoSeed) Reseed(blocking);}
  150. //! \brief Reseed an AutoSeededX917RNG
  151. //! \param blocking controls seeding with BlockingRng or NonblockingRng
  152. //! \param additionalEntropy additional entropy to add to the generator
  153. //! \param length the size of the additional entropy, in bytes
  154. //! \details Internally, the generator uses SHA256 to extract the entropy from
  155. //! from the seed and then stretch the material for the block cipher's key
  156. //! and initialization vector.
  157. void Reseed(bool blocking = false, const byte *additionalEntropy = NULL, size_t length = 0);
  158. //! \brief Deterministically reseed an AutoSeededX917RNG for testing
  159. //! \param key the key to use for the deterministic reseeding
  160. //! \param keylength the size of the key, in bytes
  161. //! \param seed the seed to use for the deterministic reseeding
  162. //! \param timeVector a time vector to use for deterministic reseeding
  163. //! \details This is a testing interface for testing purposes, and should \a NOT
  164. //! be used in production.
  165. void Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector);
  166. bool CanIncorporateEntropy() const {return true;}
  167. void IncorporateEntropy(const byte *input, size_t length) {Reseed(false, input, length);}
  168. void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length)
  169. {m_rng->GenerateIntoBufferedTransformation(target, channel, length);}
  170. private:
  171. member_ptr<RandomNumberGenerator> m_rng;
  172. };
  173. template <class BLOCK_CIPHER>
  174. void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector)
  175. {
  176. m_rng.reset(new X917RNG(new typename BLOCK_CIPHER::Encryption(key, keylength), seed, timeVector));
  177. }
  178. template <class BLOCK_CIPHER>
  179. void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(bool blocking, const byte *input, size_t length)
  180. {
  181. SecByteBlock seed(BLOCK_CIPHER::BLOCKSIZE + BLOCK_CIPHER::DEFAULT_KEYLENGTH);
  182. const byte *key;
  183. do
  184. {
  185. OS_GenerateRandomBlock(blocking, seed, seed.size());
  186. if (length > 0)
  187. {
  188. SHA256 hash;
  189. hash.Update(seed, seed.size());
  190. hash.Update(input, length);
  191. hash.TruncatedFinal(seed, UnsignedMin(hash.DigestSize(), seed.size()));
  192. }
  193. key = seed + BLOCK_CIPHER::BLOCKSIZE;
  194. } // check that seed and key don't have same value
  195. while (memcmp(key, seed, STDMIN((unsigned int)BLOCK_CIPHER::BLOCKSIZE, (unsigned int)BLOCK_CIPHER::DEFAULT_KEYLENGTH)) == 0);
  196. Reseed(key, BLOCK_CIPHER::DEFAULT_KEYLENGTH, seed, NULL);
  197. }
  198. CRYPTOPP_DLL_TEMPLATE_CLASS AutoSeededX917RNG<AES>;
  199. #if defined(CRYPTOPP_DOXYGEN_PROCESSING)
  200. //! \class DefaultAutoSeededRNG
  201. //! \brief A typedef providing a default generator
  202. //! \details DefaultAutoSeededRNG is a typedef of either AutoSeededX917RNG<AES> or AutoSeededRandomPool.
  203. //! If CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 is defined, then DefaultAutoSeededRNG is
  204. //! AutoSeededX917RNG<AES>. Otherwise, DefaultAutoSeededRNG is AutoSeededRandomPool.
  205. class DefaultAutoSeededRNG {}
  206. #else
  207. // AutoSeededX917RNG<AES> in FIPS mode, otherwise it's AutoSeededRandomPool
  208. #if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
  209. typedef AutoSeededX917RNG<AES> DefaultAutoSeededRNG;
  210. #else
  211. typedef AutoSeededRandomPool DefaultAutoSeededRNG;
  212. #endif
  213. #endif // CRYPTOPP_DOXYGEN_PROCESSING
  214. NAMESPACE_END
  215. #endif
  216. #endif