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.

186 lines
6.3 KiB

  1. // rdrand.h - written and placed in public domain by Jeffrey Walton and Uri Blumenthal.
  2. // Copyright assigned to Crypto++ project.
  3. //! \file
  4. //! \headerfile rdrand.h
  5. //! \brief Classes for RDRAND and RDSEED
  6. #ifndef CRYPTOPP_RDRAND_H
  7. #define CRYPTOPP_RDRAND_H
  8. #include "cryptlib.h"
  9. // This file (and friends) provides both RDRAND and RDSEED, but its somewhat
  10. // experimental. They were added at Crypto++ 5.6.3. At compile time, it
  11. // indirectly uses CRYPTOPP_BOOL_{X86|X32|X64} (via CRYPTOPP_CPUID_AVAILABLE)
  12. // to select an implementation or "throw NotImplemented". At runtime, the
  13. // class uses the result of CPUID to determine if RDRAND or RDSEED are
  14. // available. A lazy throw strategy is used in case the CPU does not support
  15. // the instruction. I.e., the throw is deferred until GenerateBlock() is called.
  16. // Microsoft added RDRAND in August 2012, VS2012. GCC added RDRAND in December 2010, GCC 4.6.
  17. // Clang added RDRAND in July 2012, Clang 3.2. Intel added RDRAND in September 2011, ICC 12.1.
  18. NAMESPACE_BEGIN(CryptoPP)
  19. //! \brief Exception thrown when a RDRAND generator encounters
  20. //! a generator related error.
  21. class RDRAND_Err : public Exception
  22. {
  23. public:
  24. RDRAND_Err(const std::string &operation)
  25. : Exception(OTHER_ERROR, "RDRAND: " + operation + " operation failed") {}
  26. };
  27. //! \brief Hardware generated random numbers using RDRAND instruction
  28. //! \sa MaurerRandomnessTest() for random bit generators
  29. class RDRAND : public RandomNumberGenerator
  30. {
  31. public:
  32. std::string AlgorithmName() const {return "RDRAND";}
  33. //! \brief Construct a RDRAND generator
  34. //! \param retries the number of retries for failed calls to the hardware
  35. //! \details RDRAND() constructs a generator with a maximum number of retires
  36. //! for failed generation attempts.
  37. RDRAND(unsigned int retries = 8) : m_retries(retries) {}
  38. virtual ~RDRAND() {}
  39. //! \brief Retrieve the number of retries used by the generator
  40. //! \returns the number of times GenerateBlock() will attempt to recover from a failed generation
  41. unsigned int GetRetries() const
  42. {
  43. return m_retries;
  44. }
  45. //! \brief Set the number of retries used by the generator
  46. //! \param retries number of times GenerateBlock() will attempt to recover from a failed generation
  47. void SetRetries(unsigned int retries)
  48. {
  49. m_retries = retries;
  50. }
  51. //! \brief Generate random array of bytes
  52. //! \param output the byte buffer
  53. //! \param size the length of the buffer, in bytes
  54. #if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
  55. virtual void GenerateBlock(byte *output, size_t size);
  56. #else
  57. virtual void GenerateBlock(byte *output, size_t size) {
  58. CRYPTOPP_UNUSED(output), CRYPTOPP_UNUSED(size);
  59. throw NotImplemented("RDRAND: rdrand is not available on this platform");
  60. }
  61. #endif
  62. //! \brief Generate and discard n bytes
  63. //! \param n the number of bytes to generate and discard
  64. //! \details the RDSEED generator discards words, not bytes. If n is
  65. //! not a multiple of a machine word, then it is rounded up to
  66. //! that size.
  67. #if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
  68. virtual void DiscardBytes(size_t n);
  69. #else
  70. virtual void DiscardBytes(size_t n) {
  71. CRYPTOPP_UNUSED(n);
  72. throw NotImplemented("RDRAND: rdrand is not available on this platform");
  73. }
  74. #endif
  75. //! Update RNG state with additional unpredictable values
  76. //! \param input unused
  77. //! \param length unused
  78. //! \details The operation is a nop for this generator.
  79. virtual void IncorporateEntropy(const byte *input, size_t length)
  80. {
  81. // Override to avoid the base class' throw.
  82. CRYPTOPP_UNUSED(input); CRYPTOPP_UNUSED(length);
  83. assert(0); // warn in debug builds
  84. }
  85. private:
  86. unsigned int m_retries;
  87. };
  88. //! \brief Exception thrown when a RDSEED generator encounters
  89. //! a generator related error.
  90. class RDSEED_Err : public Exception
  91. {
  92. public:
  93. RDSEED_Err(const std::string &operation)
  94. : Exception(OTHER_ERROR, "RDSEED: " + operation + " operation failed") {}
  95. };
  96. //! \brief Hardware generated random numbers using RDSEED instruction
  97. //! \sa MaurerRandomnessTest() for random bit generators
  98. class RDSEED : public RandomNumberGenerator
  99. {
  100. public:
  101. std::string AlgorithmName() const {return "RDSEED";}
  102. //! \brief Construct a RDSEED generator
  103. //! \param retries the number of retries for failed calls to the hardware
  104. //! \details RDSEED() constructs a generator with a maximum number of retires
  105. //! for failed generation attempts.
  106. RDSEED(unsigned int retries = 8) : m_retries(retries) {}
  107. virtual ~RDSEED() {}
  108. //! \brief Retrieve the number of retries used by the generator
  109. //! \returns the number of times GenerateBlock() will attempt to recover from a failed generation
  110. unsigned int GetRetries() const
  111. {
  112. return m_retries;
  113. }
  114. //! \brief Set the number of retries used by the generator
  115. //! \param retries number of times GenerateBlock() will attempt to recover from a failed generation
  116. void SetRetries(unsigned int retries)
  117. {
  118. m_retries = retries;
  119. }
  120. //! \brief Generate random array of bytes
  121. //! \param output the byte buffer
  122. //! \param size the length of the buffer, in bytes
  123. #if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
  124. virtual void GenerateBlock(byte *output, size_t size);
  125. #else
  126. virtual void GenerateBlock(byte *output, size_t size) {
  127. CRYPTOPP_UNUSED(output), CRYPTOPP_UNUSED(size);
  128. throw NotImplemented("RDSEED: rdseed is not available on this platform");
  129. }
  130. #endif
  131. //! \brief Generate and discard n bytes
  132. //! \param n the number of bytes to generate and discard
  133. //! \details the RDSEED generator discards words, not bytes. If n is
  134. //! not a multiple of a machine word, then it is rounded up to
  135. //! that size.
  136. #if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
  137. virtual void DiscardBytes(size_t n);
  138. #else
  139. virtual void DiscardBytes(size_t n) {
  140. CRYPTOPP_UNUSED(n);
  141. throw NotImplemented("RDSEED: rdseed is not available on this platform");
  142. }
  143. #endif
  144. //! Update RNG state with additional unpredictable values
  145. //! \param input unused
  146. //! \param length unused
  147. //! \details The operation is a nop for this generator.
  148. virtual void IncorporateEntropy(const byte *input, size_t length)
  149. {
  150. // Override to avoid the base class' throw.
  151. CRYPTOPP_UNUSED(input); CRYPTOPP_UNUSED(length);
  152. assert(0); // warn in debug builds
  153. }
  154. private:
  155. unsigned int m_retries;
  156. };
  157. NAMESPACE_END
  158. #endif // CRYPTOPP_RDRAND_H