rdrand.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. // rdrand.h - written and placed in public domain by Jeffrey Walton and Uri Blumenthal.
  2. /// \file rdrand.h
  3. /// \brief Classes for RDRAND and RDSEED
  4. /// \since Crypto++ 5.6.3
  5. #ifndef CRYPTOPP_RDRAND_H
  6. #define CRYPTOPP_RDRAND_H
  7. #include "cryptlib.h"
  8. // This class file provides both RDRAND and RDSEED. They were added at
  9. // Crypto++ 5.6.3. At compile time, it uses CRYPTOPP_BOOL_{X86|X32|X64}
  10. // to select an implementation or "throw NotImplemented". At runtime the
  11. // constructor will throw RDRAND_Err or RDSEED_Err if a generator is
  12. // is not available.
  13. // The original classes accepted a retry count. Retries were superfluous for
  14. // RDRAND, and RDSEED encountered a failure about 1 in 256 bytes depending
  15. // on the processor. Retries were removed at Crypto++ 6.0 because
  16. // GenerateBlock unconditionally retries and always fulfills the request.
  17. // Throughput varies wildly depending on processor and manufacturer. A Core i5 or
  18. // Core i7 RDRAND can generate at over 200 MiB/s. It is below theroetical
  19. // maximum, but it takes about 5 instructions to generate, retry and store a
  20. // result. A low-end Celeron may perform RDRAND at about 7 MiB/s. RDSEED
  21. // performs at about 1/4 to 1/2 the rate of RDRAND. AMD RDRAND performed poorly
  22. // during testing with Athlon X4 845. The Bulldozer v4 only performed at 1 MiB/s.
  23. // Microsoft added RDRAND in August 2012, VS2012; RDSEED in October 2013, VS2013.
  24. // GCC added RDRAND in December 2010, GCC 4.6. LLVM added RDRAND in July 2012,
  25. // Clang 3.2. Intel added RDRAND in September 2011, ICC 12.1.
  26. NAMESPACE_BEGIN(CryptoPP)
  27. /// \brief Exception thrown when a RDRAND generator encounters
  28. /// a generator related error.
  29. /// \since Crypto++ 5.6.3
  30. class RDRAND_Err : public Exception
  31. {
  32. public:
  33. RDRAND_Err(const std::string &operation)
  34. : Exception(OTHER_ERROR, "RDRAND: " + operation + " operation failed") {}
  35. };
  36. /// \brief Hardware generated random numbers using RDRAND instruction
  37. /// \sa MaurerRandomnessTest() for random bit generators
  38. /// \since Crypto++ 5.6.3
  39. class RDRAND : public RandomNumberGenerator
  40. {
  41. public:
  42. CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "RDRAND"; }
  43. virtual ~RDRAND() {}
  44. /// \brief Construct a RDRAND generator
  45. /// \details According to DJ of Intel, the Intel RDRAND circuit does not underflow.
  46. /// If it did hypothetically underflow, then it would return 0 for the random value.
  47. /// AMD's RDRAND implementation appears to provide the same behavior.
  48. /// \throw RDRAND_Err if the random number generator is not available
  49. RDRAND();
  50. /// \brief Generate random array of bytes
  51. /// \param output the byte buffer
  52. /// \param size the length of the buffer, in bytes
  53. virtual void GenerateBlock(byte *output, size_t size);
  54. /// \brief Generate and discard n bytes
  55. /// \param n the number of bytes to generate and discard
  56. /// \details the RDSEED generator discards words, not bytes. If n is
  57. /// not a multiple of a machine word, then it is rounded up to
  58. /// that size.
  59. virtual void DiscardBytes(size_t n);
  60. /// \brief Update RNG state with additional unpredictable values
  61. /// \param input unused
  62. /// \param length unused
  63. /// \details The operation is a nop for this generator.
  64. virtual void IncorporateEntropy(const byte *input, size_t length)
  65. {
  66. // Override to avoid the base class' throw.
  67. CRYPTOPP_UNUSED(input); CRYPTOPP_UNUSED(length);
  68. }
  69. std::string AlgorithmProvider() const {
  70. return "RDRAND";
  71. }
  72. };
  73. /// \brief Exception thrown when a RDSEED generator encounters
  74. /// a generator related error.
  75. /// \since Crypto++ 5.6.3
  76. class RDSEED_Err : public Exception
  77. {
  78. public:
  79. RDSEED_Err(const std::string &operation)
  80. : Exception(OTHER_ERROR, "RDSEED: " + operation + " operation failed") {}
  81. };
  82. /// \brief Hardware generated random numbers using RDSEED instruction
  83. /// \sa MaurerRandomnessTest() for random bit generators
  84. /// \since Crypto++ 5.6.3
  85. class RDSEED : public RandomNumberGenerator
  86. {
  87. public:
  88. CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "RDSEED"; }
  89. virtual ~RDSEED() {}
  90. /// \brief Construct a RDSEED generator
  91. /// \details Empirical testing under a 6th generation i7 (6200U) shows RDSEED fails
  92. /// to fulfill requests at about once every for every 256 bytes requested.
  93. /// The generator runs about 4 times slower than RDRAND.
  94. /// \throw RDSEED_Err if the random number generator is not available
  95. RDSEED();
  96. /// \brief Generate random array of bytes
  97. /// \param output the byte buffer
  98. /// \param size the length of the buffer, in bytes
  99. virtual void GenerateBlock(byte *output, size_t size);
  100. /// \brief Generate and discard n bytes
  101. /// \param n the number of bytes to generate and discard
  102. /// \details the RDSEED generator discards words, not bytes. If n is
  103. /// not a multiple of a machine word, then it is rounded up to
  104. /// that size.
  105. virtual void DiscardBytes(size_t n);
  106. /// \brief Update RNG state with additional unpredictable values
  107. /// \param input unused
  108. /// \param length unused
  109. /// \details The operation is a nop for this generator.
  110. virtual void IncorporateEntropy(const byte *input, size_t length)
  111. {
  112. // Override to avoid the base class' throw.
  113. CRYPTOPP_UNUSED(input); CRYPTOPP_UNUSED(length);
  114. }
  115. std::string AlgorithmProvider() const {
  116. return "RDSEED";
  117. }
  118. };
  119. NAMESPACE_END
  120. #endif // CRYPTOPP_RDRAND_H