Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:55:08

0001 // rdrand.h - written and placed in public domain by Jeffrey Walton and Uri Blumenthal.

0002 
0003 /// \file rdrand.h

0004 /// \brief Classes for RDRAND and RDSEED

0005 /// \since Crypto++ 5.6.3

0006 
0007 #ifndef CRYPTOPP_RDRAND_H
0008 #define CRYPTOPP_RDRAND_H
0009 
0010 #include "cryptlib.h"
0011 
0012 // This class file provides both RDRAND and RDSEED. They were added at

0013 //   Crypto++ 5.6.3. At compile time, it uses CRYPTOPP_BOOL_{X86|X32|X64}

0014 //   to select an implementation or "throw NotImplemented". At runtime the

0015 //   constructor will throw RDRAND_Err or RDSEED_Err if a generator is

0016 //   is not available.

0017 // The original classes accepted a retry count. Retries were superfluous for

0018 //   RDRAND, and RDSEED encountered a failure about 1 in 256 bytes depending

0019 //   on the processor. Retries were removed at Crypto++ 6.0 because

0020 //   GenerateBlock unconditionally retries and always fulfills the request.

0021 
0022 // Throughput varies wildly depending on processor and manufacturer. A Core i5 or

0023 //   Core i7 RDRAND can generate at over 200 MiB/s. It is below theroetical

0024 //   maximum, but it takes about 5 instructions to generate, retry and store a

0025 //   result. A low-end Celeron may perform RDRAND at about 7 MiB/s. RDSEED

0026 //   performs at about 1/4 to 1/2 the rate of RDRAND. AMD RDRAND performed poorly

0027 //   during testing with Athlon X4 845. The Bulldozer v4 only performed at 1 MiB/s.

0028 
0029 // Microsoft added RDRAND in August 2012, VS2012; RDSEED in October 2013, VS2013.

0030 // GCC added RDRAND in December 2010, GCC 4.6. LLVM added RDRAND in July 2012,

0031 // Clang 3.2. Intel added RDRAND in September 2011, ICC 12.1.

0032 
0033 NAMESPACE_BEGIN(CryptoPP)
0034 
0035 /// \brief Exception thrown when a RDRAND generator encounters

0036 ///    a generator related error.

0037 /// \since Crypto++ 5.6.3

0038 class RDRAND_Err : public Exception
0039 {
0040 public:
0041     RDRAND_Err(const std::string &operation)
0042         : Exception(OTHER_ERROR, "RDRAND: " + operation + " operation failed") {}
0043 };
0044 
0045 /// \brief Hardware generated random numbers using RDRAND instruction

0046 /// \sa MaurerRandomnessTest() for random bit generators

0047 /// \since Crypto++ 5.6.3

0048 class RDRAND : public RandomNumberGenerator
0049 {
0050 public:
0051     CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "RDRAND"; }
0052 
0053     virtual ~RDRAND() {}
0054 
0055     /// \brief Construct a RDRAND generator

0056     /// \details According to DJ of Intel, the Intel RDRAND circuit does not underflow.

0057     ///   If it did hypothetically underflow, then it would return 0 for the random value.

0058     ///   AMD's RDRAND implementation appears to provide the same behavior.

0059      /// \throw RDRAND_Err if the random number generator is not available

0060     RDRAND();
0061 
0062     /// \brief Generate random array of bytes

0063     /// \param output the byte buffer

0064     /// \param size the length of the buffer, in bytes

0065     virtual void GenerateBlock(byte *output, size_t size);
0066 
0067     /// \brief Generate and discard n bytes

0068     /// \param n the number of bytes to generate and discard

0069     /// \details the RDSEED generator discards words, not bytes. If n is

0070     ///   not a multiple of a machine word, then it is rounded up to

0071     ///   that size.

0072     virtual void DiscardBytes(size_t n);
0073 
0074     /// \brief Update RNG state with additional unpredictable values

0075     /// \param input unused

0076     /// \param length unused

0077     /// \details The operation is a nop for this generator.

0078     virtual void IncorporateEntropy(const byte *input, size_t length)
0079     {
0080         // Override to avoid the base class' throw.

0081         CRYPTOPP_UNUSED(input); CRYPTOPP_UNUSED(length);
0082     }
0083 
0084     std::string AlgorithmProvider() const {
0085         return "RDRAND";
0086     }
0087 };
0088 
0089 /// \brief Exception thrown when a RDSEED generator encounters

0090 ///    a generator related error.

0091 /// \since Crypto++ 5.6.3

0092 class RDSEED_Err : public Exception
0093 {
0094 public:
0095     RDSEED_Err(const std::string &operation)
0096         : Exception(OTHER_ERROR, "RDSEED: " + operation + " operation failed") {}
0097 };
0098 
0099 /// \brief Hardware generated random numbers using RDSEED instruction

0100 /// \sa MaurerRandomnessTest() for random bit generators

0101 /// \since Crypto++ 5.6.3

0102 class RDSEED : public RandomNumberGenerator
0103 {
0104 public:
0105     CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "RDSEED"; }
0106 
0107     virtual ~RDSEED() {}
0108 
0109     /// \brief Construct a RDSEED generator

0110     /// \details Empirical testing under a 6th generation i7 (6200U) shows RDSEED fails

0111     ///   to fulfill requests at about once every for every 256 bytes requested.

0112     ///   The generator runs about 4 times slower than RDRAND.

0113      /// \throw RDSEED_Err if the random number generator is not available

0114     RDSEED();
0115 
0116     /// \brief Generate random array of bytes

0117     /// \param output the byte buffer

0118     /// \param size the length of the buffer, in bytes

0119     virtual void GenerateBlock(byte *output, size_t size);
0120 
0121     /// \brief Generate and discard n bytes

0122     /// \param n the number of bytes to generate and discard

0123     /// \details the RDSEED generator discards words, not bytes. If n is

0124     ///   not a multiple of a machine word, then it is rounded up to

0125     ///   that size.

0126     virtual void DiscardBytes(size_t n);
0127 
0128     /// \brief Update RNG state with additional unpredictable values

0129     /// \param input unused

0130     /// \param length unused

0131     /// \details The operation is a nop for this generator.

0132     virtual void IncorporateEntropy(const byte *input, size_t length)
0133     {
0134         // Override to avoid the base class' throw.

0135         CRYPTOPP_UNUSED(input); CRYPTOPP_UNUSED(length);
0136     }
0137 
0138     std::string AlgorithmProvider() const {
0139         return "RDSEED";
0140     }
0141 };
0142 
0143 NAMESPACE_END
0144 
0145 #endif // CRYPTOPP_RDRAND_H