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.
145 lines
5.6 KiB
145 lines
5.6 KiB
// rdrand.h - written and placed in public domain by Jeffrey Walton and Uri Blumenthal. |
|
|
|
/// \file rdrand.h |
|
/// \brief Classes for RDRAND and RDSEED |
|
/// \since Crypto++ 5.6.3 |
|
|
|
#ifndef CRYPTOPP_RDRAND_H |
|
#define CRYPTOPP_RDRAND_H |
|
|
|
#include "cryptlib.h" |
|
|
|
// This class file provides both RDRAND and RDSEED. They were added at |
|
// Crypto++ 5.6.3. At compile time, it uses CRYPTOPP_BOOL_{X86|X32|X64} |
|
// to select an implementation or "throw NotImplemented". At runtime the |
|
// constructor will throw RDRAND_Err or RDSEED_Err if a generator is |
|
// is not available. |
|
// The original classes accepted a retry count. Retries were superflous for |
|
// RDRAND, and RDSEED encountered a failure about 1 in 256 bytes depending |
|
// on the processor. Retries were removed at Crypto++ 6.0 because |
|
// GenerateBlock unconditionally retries and always fulfills the request. |
|
|
|
// Throughput varies wildly depending on processor and manufacturer. A Core i5 or |
|
// Core i7 RDRAND can generate at over 200 MiB/s. It is below the theroetical |
|
// maximum, but it takes about 5 instructions to generate, retry and store a |
|
// result. A low-end Celeron may perform RDRAND at about 7 MiB/s. RDSEED |
|
// performs at about 1/4 to 1/2 the rate of RDRAND. AMD RDRAND performed poorly |
|
// during testing with Athlon X4 845. The Bulldozer v4 only performed at 1 MiB/s. |
|
|
|
// Microsoft added RDRAND in August 2012, VS2012; RDSEED in October 2013, VS2013. |
|
// GCC added RDRAND in December 2010, GCC 4.6. LLVM added RDRAND in July 2012, |
|
// Clang 3.2. Intel added RDRAND in September 2011, ICC 12.1. |
|
|
|
NAMESPACE_BEGIN(CryptoPP) |
|
|
|
/// \brief Exception thrown when a RDRAND generator encounters |
|
/// a generator related error. |
|
/// \since Crypto++ 5.6.3 |
|
class RDRAND_Err : public Exception |
|
{ |
|
public: |
|
RDRAND_Err(const std::string &operation) |
|
: Exception(OTHER_ERROR, "RDRAND: " + operation + " operation failed") {} |
|
}; |
|
|
|
/// \brief Hardware generated random numbers using RDRAND instruction |
|
/// \sa MaurerRandomnessTest() for random bit generators |
|
/// \since Crypto++ 5.6.3 |
|
class RDRAND : public RandomNumberGenerator |
|
{ |
|
public: |
|
CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "RDRAND"; } |
|
|
|
virtual ~RDRAND() {} |
|
|
|
/// \brief Construct a RDRAND generator |
|
/// \details According to DJ of Intel, the Intel RDRAND circuit does not underflow. |
|
/// If it did hypothetically underflow, then it would return 0 for the random value. |
|
/// AMD's RDRAND implementation appears to provide the same behavior. |
|
/// \throws RDRAND_Err if the random number generator is not available |
|
RDRAND(); |
|
|
|
/// \brief Generate random array of bytes |
|
/// \param output the byte buffer |
|
/// \param size the length of the buffer, in bytes |
|
virtual void GenerateBlock(byte *output, size_t size); |
|
|
|
/// \brief Generate and discard n bytes |
|
/// \param n the number of bytes to generate and discard |
|
/// \details the RDSEED generator discards words, not bytes. If n is |
|
/// not a multiple of a machine word, then it is rounded up to |
|
/// that size. |
|
virtual void DiscardBytes(size_t n); |
|
|
|
/// \brief Update RNG state with additional unpredictable values |
|
/// \param input unused |
|
/// \param length unused |
|
/// \details The operation is a nop for this generator. |
|
virtual void IncorporateEntropy(const byte *input, size_t length) |
|
{ |
|
// Override to avoid the base class' throw. |
|
CRYPTOPP_UNUSED(input); CRYPTOPP_UNUSED(length); |
|
} |
|
|
|
std::string AlgorithmProvider() const { |
|
return "RDRAND"; |
|
} |
|
}; |
|
|
|
/// \brief Exception thrown when a RDSEED generator encounters |
|
/// a generator related error. |
|
/// \since Crypto++ 5.6.3 |
|
class RDSEED_Err : public Exception |
|
{ |
|
public: |
|
RDSEED_Err(const std::string &operation) |
|
: Exception(OTHER_ERROR, "RDSEED: " + operation + " operation failed") {} |
|
}; |
|
|
|
/// \brief Hardware generated random numbers using RDSEED instruction |
|
/// \sa MaurerRandomnessTest() for random bit generators |
|
/// \since Crypto++ 5.6.3 |
|
class RDSEED : public RandomNumberGenerator |
|
{ |
|
public: |
|
CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "RDSEED"; } |
|
|
|
virtual ~RDSEED() {} |
|
|
|
/// \brief Construct a RDSEED generator |
|
/// \details Empirical testing under a 6th generaton i7 (6200U) shows RDSEED fails |
|
/// to fulfill requests at about once every for every 256 bytes requested. |
|
/// The generator runs about 4 times slower than RDRAND. |
|
/// \throws RDSEED_Err if the random number generator is not available |
|
RDSEED(); |
|
|
|
/// \brief Generate random array of bytes |
|
/// \param output the byte buffer |
|
/// \param size the length of the buffer, in bytes |
|
virtual void GenerateBlock(byte *output, size_t size); |
|
|
|
/// \brief Generate and discard n bytes |
|
/// \param n the number of bytes to generate and discard |
|
/// \details the RDSEED generator discards words, not bytes. If n is |
|
/// not a multiple of a machine word, then it is rounded up to |
|
/// that size. |
|
virtual void DiscardBytes(size_t n); |
|
|
|
/// \brief Update RNG state with additional unpredictable values |
|
/// \param input unused |
|
/// \param length unused |
|
/// \details The operation is a nop for this generator. |
|
virtual void IncorporateEntropy(const byte *input, size_t length) |
|
{ |
|
// Override to avoid the base class' throw. |
|
CRYPTOPP_UNUSED(input); CRYPTOPP_UNUSED(length); |
|
} |
|
|
|
std::string AlgorithmProvider() const { |
|
return "RDSEED"; |
|
} |
|
}; |
|
|
|
NAMESPACE_END |
|
|
|
#endif // CRYPTOPP_RDRAND_H
|
|
|