Crypto++  5.6.4
Free C++ class library of cryptographic schemes
rdrand.h
Go to the documentation of this file.
1 // rdrand.h - written and placed in public domain by Jeffrey Walton and Uri Blumenthal.
2 // Copyright assigned to Crypto++ project.
3 
4 //! \file rdrand.h
5 //! \brief Classes for RDRAND and RDSEED
6 //! \since Crypto++ 5.6.3
7 
8 #ifndef CRYPTOPP_RDRAND_H
9 #define CRYPTOPP_RDRAND_H
10 
11 #include "cryptlib.h"
12 
13 // This file (and friends) provides both RDRAND and RDSEED, but its somewhat
14 // experimental. They were added at Crypto++ 5.6.3. At compile time, it
15 // indirectly uses CRYPTOPP_BOOL_{X86|X32|X64} (via CRYPTOPP_CPUID_AVAILABLE)
16 // to select an implementation or "throw NotImplemented". At runtime, the
17 // class uses the result of CPUID to determine if RDRAND or RDSEED are
18 // available. If not available, a lazy throw strategy is used. I.e., the
19 // throw is deferred until GenerateBlock() is called.
20 
21 // Microsoft added RDRAND in August 2012, VS2012. GCC added RDRAND in December 2010, GCC 4.6.
22 // Clang added RDRAND in July 2012, Clang 3.2. Intel added RDRAND in September 2011, ICC 12.1.
23 
24 NAMESPACE_BEGIN(CryptoPP)
25 
26 //! \brief Exception thrown when a RDRAND generator encounters
27 //! a generator related error.
28 //! \since Crypto++ 5.6.3
29 class RDRAND_Err : public Exception
30 {
31 public:
32  RDRAND_Err(const std::string &operation)
33  : Exception(OTHER_ERROR, "RDRAND: " + operation + " operation failed") {}
34 };
35 
36 //! \brief Hardware generated random numbers using RDRAND instruction
37 //! \sa MaurerRandomnessTest() for random bit generators
38 //! \since Crypto++ 5.6.3
40 {
41 public:
42  std::string AlgorithmName() const {return "RDRAND";}
43 
44  //! \brief Construct a RDRAND generator
45  //! \param retries the number of retries for failed calls to the hardware
46  //! \details RDRAND() constructs a generator with a maximum number of retires
47  //! for failed generation attempts.
48  //! \details According to DJ of Intel, the Intel RDRAND circuit does not underflow.
49  //! If it did hypothetically underflow, then it would return 0 for the random value.
50  //! Its not clear what AMD's behavior will be, and what the returned value will be if
51  //! underflow occurs.
52  //! Also see <A HREF="https://lists.randombit.net/pipermail/cryptography/2016-June/007702.html">RDRAND
53  //! not really random with Oracle Studio 12.3 + patches</A>
54  RDRAND(unsigned int retries = 4) : m_retries(retries) {}
55 
56  virtual ~RDRAND() {}
57 
58  //! \brief Retrieve the number of retries used by the generator
59  //! \returns the number of times GenerateBlock() will attempt to recover from a failed generation
60  unsigned int GetRetries() const
61  {
62  return m_retries;
63  }
64 
65  //! \brief Set the number of retries used by the generator
66  //! \param retries number of times GenerateBlock() will attempt to recover from a failed generation
67  void SetRetries(unsigned int retries)
68  {
69  m_retries = retries;
70  }
71 
72  //! \brief Generate random array of bytes
73  //! \param output the byte buffer
74  //! \param size the length of the buffer, in bytes
75 #if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
76  virtual void GenerateBlock(byte *output, size_t size);
77 #else
78  virtual void GenerateBlock(byte *output, size_t size) {
79  CRYPTOPP_UNUSED(output), CRYPTOPP_UNUSED(size);
80  throw NotImplemented("RDRAND: rdrand is not available on this platform");
81  }
82 #endif
83 
84  //! \brief Generate and discard n bytes
85  //! \param n the number of bytes to generate and discard
86  //! \details the RDSEED generator discards words, not bytes. If n is
87  //! not a multiple of a machine word, then it is rounded up to
88  //! that size.
89 #if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
90  virtual void DiscardBytes(size_t n);
91 #else
92  virtual void DiscardBytes(size_t n) {
93  CRYPTOPP_UNUSED(n);
94  throw NotImplemented("RDRAND: rdrand is not available on this platform");
95  }
96 #endif
97 
98  //! \brief Update RNG state with additional unpredictable values
99  //! \param input unused
100  //! \param length unused
101  //! \details The operation is a nop for this generator.
102  virtual void IncorporateEntropy(const byte *input, size_t length)
103  {
104  // Override to avoid the base class' throw.
105  CRYPTOPP_UNUSED(input); CRYPTOPP_UNUSED(length);
106  // assert(0); // warn in debug builds
107  }
108 
109 private:
110  unsigned int m_retries;
111 };
112 
113 //! \brief Exception thrown when a RDSEED generator encounters
114 //! a generator related error.
115 //! \since Crypto++ 5.6.3
116 class RDSEED_Err : public Exception
117 {
118 public:
119  RDSEED_Err(const std::string &operation)
120  : Exception(OTHER_ERROR, "RDSEED: " + operation + " operation failed") {}
121 };
122 
123 //! \brief Hardware generated random numbers using RDSEED instruction
124 //! \sa MaurerRandomnessTest() for random bit generators
125 //! \since Crypto++ 5.6.3
127 {
128 public:
129  std::string AlgorithmName() const {return "RDSEED";}
130 
131  //! \brief Construct a RDSEED generator
132  //! \param retries the number of retries for failed calls to the hardware
133  //! \details RDSEED() constructs a generator with a maximum number of retires
134  //! for failed generation attempts.
135  //! \details Empirical testing under a 6th generaton i7 (6200U) shows RDSEED fails
136  //! to fulfill requests at about 6 to 8 times the rate of RDRAND. The default
137  //! retries reflects the difference.
138  RDSEED(unsigned int retries = 64) : m_retries(retries) {}
139 
140  virtual ~RDSEED() {}
141 
142  //! \brief Retrieve the number of retries used by the generator
143  //! \returns the number of times GenerateBlock() will attempt to recover from a failed generation
144  unsigned int GetRetries() const
145  {
146  return m_retries;
147  }
148 
149  //! \brief Set the number of retries used by the generator
150  //! \param retries number of times GenerateBlock() will attempt to recover from a failed generation
151  void SetRetries(unsigned int retries)
152  {
153  m_retries = retries;
154  }
155 
156  //! \brief Generate random array of bytes
157  //! \param output the byte buffer
158  //! \param size the length of the buffer, in bytes
159 #if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
160  virtual void GenerateBlock(byte *output, size_t size);
161 #else
162  virtual void GenerateBlock(byte *output, size_t size) {
163  CRYPTOPP_UNUSED(output), CRYPTOPP_UNUSED(size);
164  throw NotImplemented("RDSEED: rdseed is not available on this platform");
165  }
166 #endif
167 
168  //! \brief Generate and discard n bytes
169  //! \param n the number of bytes to generate and discard
170  //! \details the RDSEED generator discards words, not bytes. If n is
171  //! not a multiple of a machine word, then it is rounded up to
172  //! that size.
173 #if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
174  virtual void DiscardBytes(size_t n);
175 #else
176  virtual void DiscardBytes(size_t n) {
177  CRYPTOPP_UNUSED(n);
178  throw NotImplemented("RDSEED: rdseed is not available on this platform");
179  }
180 #endif
181 
182  //! \brief Update RNG state with additional unpredictable values
183  //! \param input unused
184  //! \param length unused
185  //! \details The operation is a nop for this generator.
186  virtual void IncorporateEntropy(const byte *input, size_t length)
187  {
188  // Override to avoid the base class' throw.
189  CRYPTOPP_UNUSED(input); CRYPTOPP_UNUSED(length);
190  // assert(0); // warn in debug builds
191  }
192 
193 private:
194  unsigned int m_retries;
195 };
196 
197 NAMESPACE_END
198 
199 #endif // CRYPTOPP_RDRAND_H
Base class for all exceptions thrown by the library.
Definition: cryptlib.h:139
virtual void GenerateBlock(byte *output, size_t size)
Generate random array of bytes.
Definition: rdrand.h:162
virtual void GenerateBlock(byte *output, size_t size)
Generate random array of bytes.
Definition: rdrand.h:78
Hardware generated random numbers using RDRAND instruction.
Definition: rdrand.h:39
virtual void IncorporateEntropy(const byte *input, size_t length)
Update RNG state with additional unpredictable values.
Definition: rdrand.h:186
Abstract base classes that provide a uniform interface to this library.
RDSEED(unsigned int retries=64)
Construct a RDSEED generator.
Definition: rdrand.h:138
Interface for random number generators.
Definition: cryptlib.h:1186
virtual void IncorporateEntropy(const byte *input, size_t length)
Update RNG state with additional unpredictable values.
Definition: rdrand.h:102
void SetRetries(unsigned int retries)
Set the number of retries used by the generator.
Definition: rdrand.h:151
Exception thrown when a RDRAND generator encounters a generator related error.
Definition: rdrand.h:29
virtual void DiscardBytes(size_t n)
Generate and discard n bytes.
Definition: rdrand.h:176
A method was called which was not implemented.
Definition: cryptlib.h:203
virtual void DiscardBytes(size_t n)
Generate and discard n bytes.
Definition: rdrand.h:92
unsigned int GetRetries() const
Retrieve the number of retries used by the generator.
Definition: rdrand.h:144
std::string AlgorithmName() const
Provides the name of this algorithm.
Definition: rdrand.h:42
Hardware generated random numbers using RDSEED instruction.
Definition: rdrand.h:126
RDRAND(unsigned int retries=4)
Construct a RDRAND generator.
Definition: rdrand.h:54
void SetRetries(unsigned int retries)
Set the number of retries used by the generator.
Definition: rdrand.h:67
Crypto++ library namespace.
unsigned int GetRetries() const
Retrieve the number of retries used by the generator.
Definition: rdrand.h:60
std::string AlgorithmName() const
Provides the name of this algorithm.
Definition: rdrand.h:129
Exception thrown when a RDSEED generator encounters a generator related error.
Definition: rdrand.h:116