1 // osrng.h - originally written and placed in the public domain by Wei Dai
2 
3 /// \file osrng.h
4 /// \brief Classes for access to the operating system's random number generators
5 
6 #ifndef CRYPTOPP_OSRNG_H
7 #define CRYPTOPP_OSRNG_H
8 
9 #include "config.h"
10 
11 #if !defined(NO_OS_DEPENDENCE) && defined(OS_RNG_AVAILABLE)
12 
13 #include "cryptlib.h"
14 #include "randpool.h"
15 #include "smartptr.h"
16 #include "fips140.h"
17 #include "hkdf.h"
18 #include "rng.h"
19 #include "aes.h"
20 #include "sha.h"
21 
NAMESPACE_BEGIN(CryptoPP)22 NAMESPACE_BEGIN(CryptoPP)
23 
24 /// \brief Exception thrown when an operating system error is encountered
25 class CRYPTOPP_DLL OS_RNG_Err : public Exception
26 {
27 public:
28 	/// \brief Constructs an OS_RNG_Err
29 	/// \param operation the operation or API call when the error occurs
30 	OS_RNG_Err(const std::string &operation);
31 };
32 
33 #ifdef NONBLOCKING_RNG_AVAILABLE
34 
35 #ifdef CRYPTOPP_WIN32_AVAILABLE
36 /// \brief Wrapper for Microsoft crypto service provider
37 /// \sa \def USE_MS_CRYPTOAPI, \def USE_MS_CNGAPI
38 class CRYPTOPP_DLL MicrosoftCryptoProvider
39 {
40 public:
41 	/// \brief Construct a MicrosoftCryptoProvider
42 	MicrosoftCryptoProvider();
43 	~MicrosoftCryptoProvider();
44 
45 // type HCRYPTPROV and BCRYPT_ALG_HANDLE, avoid #include <windows.h>
46 #if defined(USE_MS_CRYPTOAPI)
47 # if defined(__CYGWIN__) && defined(__x86_64__)
48 	typedef unsigned long long ProviderHandle;
49 # elif defined(WIN64) || defined(_WIN64)
50 	typedef unsigned __int64 ProviderHandle;
51 # else
52 	typedef unsigned long ProviderHandle;
53 # endif
54 #elif defined(USE_MS_CNGAPI)
55 	typedef void *PVOID;
56 	typedef PVOID ProviderHandle;
57 #endif // USE_MS_CRYPTOAPI or USE_MS_CNGAPI
58 
59 	/// \brief Retrieves the provider handle
60 	/// \return CryptoAPI provider handle
61 	/// \details If USE_MS_CRYPTOAPI is in effect, then CryptAcquireContext()
62 	///  acquires then handle and CryptReleaseContext() releases the handle
63 	///  upon destruction. If USE_MS_CNGAPI is in effect, then
64 	///  BCryptOpenAlgorithmProvider() acquires then handle and
65 	///  BCryptCloseAlgorithmProvider() releases the handle upon destruction.
GetProviderHandle()66 	ProviderHandle GetProviderHandle() const {return m_hProvider;}
67 
68 private:
69 	ProviderHandle m_hProvider;
70 };
71 
72 #if defined(_MSC_VER) && defined(USE_MS_CRYPTOAPI)
73 # pragma comment(lib, "advapi32.lib")
74 #endif
75 
76 #if defined(_MSC_VER) && defined(USE_MS_CNGAPI)
77 # pragma comment(lib, "bcrypt.lib")
78 #endif
79 
80 #endif // CRYPTOPP_WIN32_AVAILABLE
81 
82 /// \brief Wrapper class for /dev/random and /dev/srandom
83 /// \details Encapsulates CryptoAPI's CryptGenRandom() or CryptoNG's BCryptGenRandom()
84 ///  on Windows, or /dev/urandom on Unix and compatibles.
85 class CRYPTOPP_DLL NonblockingRng : public RandomNumberGenerator
86 {
87 public:
StaticAlgorithmName()88 	CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "NonblockingRng"; }
89 
90 	~NonblockingRng();
91 
92 	/// \brief Construct a NonblockingRng
93 	NonblockingRng();
94 
95 	/// \brief Generate random array of bytes
96 	/// \param output the byte buffer
97 	/// \param size the length of the buffer, in bytes
98 	/// \details GenerateIntoBufferedTransformation() calls are routed to GenerateBlock().
99 	void GenerateBlock(byte *output, size_t size);
100 
101 protected:
102 #ifdef CRYPTOPP_WIN32_AVAILABLE
103 	MicrosoftCryptoProvider m_Provider;
104 #else
105 	int m_fd;
106 #endif
107 };
108 
109 #endif
110 
111 #if defined(BLOCKING_RNG_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
112 
113 /// \brief Wrapper class for /dev/random and /dev/srandom
114 /// \details Encapsulates /dev/random on Linux, OS X and Unix; and /dev/srandom on the BSDs.
115 /// \note On Linux the /dev/random interface is effectively deprecated. According to the
116 ///  Kernel Crypto developers, /dev/urandom or getrandom(2) should be used instead. Also
117 ///  see <A HREF="https://lkml.org/lkml/2017/7/20/993">[RFC PATCH v12 3/4] Linux Random
118 ///  Number Generator</A> on the kernel-crypto mailing list.
119 class CRYPTOPP_DLL BlockingRng : public RandomNumberGenerator
120 {
121 public:
StaticAlgorithmName()122 	CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "BlockingRng"; }
123 
124 	~BlockingRng();
125 
126 	/// \brief Construct a BlockingRng
127 	BlockingRng();
128 
129 	/// \brief Generate random array of bytes
130 	/// \param output the byte buffer
131 	/// \param size the length of the buffer, in bytes
132 	/// \details GenerateIntoBufferedTransformation() calls are routed to GenerateBlock().
133 	void GenerateBlock(byte *output, size_t size);
134 
135 protected:
136 	int m_fd;
137 };
138 
139 #endif
140 
141 /// OS_GenerateRandomBlock
142 /// \brief Generate random array of bytes
143 /// \param blocking specifies whether a blocking or non-blocking generator should be used
144 /// \param output the byte buffer
145 /// \param size the length of the buffer, in bytes
146 /// \details OS_GenerateRandomBlock() uses the underlying operating system's
147 ///  random number generator. On Windows, CryptGenRandom() is called using NonblockingRng.
148 /// \details On Unix and compatibles, /dev/urandom is called if blocking is false using
149 ///  NonblockingRng. If blocking is true, then either /dev/randomd or /dev/srandom is used
150 ///  by way of BlockingRng, if available.
151 CRYPTOPP_DLL void CRYPTOPP_API OS_GenerateRandomBlock(bool blocking, byte *output, size_t size);
152 
153 /// \brief Automatically Seeded Randomness Pool
154 /// \details This class seeds itself using an operating system provided RNG.
155 ///  AutoSeededRandomPool was suggested by Leonard Janke.
156 /// \details You should reseed the generator after a fork() to avoid multiple generators
157 ///  with the same internal state.
158 class CRYPTOPP_DLL AutoSeededRandomPool : public RandomPool
159 {
160 public:
StaticAlgorithmName()161 	CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "AutoSeededRandomPool"; }
162 
~AutoSeededRandomPool()163 	~AutoSeededRandomPool() {}
164 
165 	/// \brief Construct an AutoSeededRandomPool
166 	/// \param blocking controls seeding with BlockingRng or NonblockingRng
167 	/// \param seedSize the size of the seed, in bytes
168 	/// \details Use blocking to choose seeding with BlockingRng or NonblockingRng.
169 	///  The parameter is ignored if only one of these is available.
170 	explicit AutoSeededRandomPool(bool blocking = false, unsigned int seedSize = 32)
171 		{Reseed(blocking, seedSize);}
172 
173 	/// \brief Reseed an AutoSeededRandomPool
174 	/// \param blocking controls seeding with BlockingRng or NonblockingRng
175 	/// \param seedSize the size of the seed, in bytes
176 	void Reseed(bool blocking = false, unsigned int seedSize = 32);
177 };
178 
179 /// \tparam BLOCK_CIPHER a block cipher
180 /// \brief Automatically Seeded X9.17 RNG
181 /// \details AutoSeededX917RNG is from ANSI X9.17 Appendix C, seeded using an OS provided RNG.
182 ///  If 3-key TripleDES (DES_EDE3) is used, then its a X9.17 conforming generator. If AES is
183 ///  used, then its a X9.31 conforming generator.
184 /// \details Though ANSI X9 prescribes 3-key TripleDES, the template parameter BLOCK_CIPHER
185 ///  can be any BlockTransformation derived class.
186 /// \details You should reseed the generator after a fork() to avoid multiple generators
187 ///  with the same internal state.
188 /// \sa X917RNG, DefaultAutoSeededRNG
189 template <class BLOCK_CIPHER>
190 class AutoSeededX917RNG : public RandomNumberGenerator, public NotCopyable
191 {
192 public:
StaticAlgorithmName()193 	static std::string StaticAlgorithmName() {
194 		return std::string("AutoSeededX917RNG(") + BLOCK_CIPHER::StaticAlgorithmName() + std::string(")");
195 	}
196 
~AutoSeededX917RNG()197 	~AutoSeededX917RNG() {}
198 
199 	/// \brief Construct an AutoSeededX917RNG
200 	/// \param blocking controls seeding with BlockingRng or NonblockingRng
201 	/// \param autoSeed controls auto seeding of the generator
202 	/// \details Use blocking to choose seeding with BlockingRng or NonblockingRng.
203 	///  The parameter is ignored if only one of these is available.
204 	/// \sa X917RNG
205 	explicit AutoSeededX917RNG(bool blocking = false, bool autoSeed = true)
206 		{if (autoSeed) Reseed(blocking);}
207 
208 	/// \brief Reseed an AutoSeededX917RNG
209 	/// \param blocking controls seeding with BlockingRng or NonblockingRng
210 	/// \param input additional entropy to add to the generator
211 	/// \param length the size of the additional entropy, in bytes
212 	/// \details Internally, the generator uses SHA256 to extract the entropy from
213 	///  from the seed and then stretch the material for the block cipher's key
214 	///  and initialization vector.
215 	void Reseed(bool blocking = false, const byte *input = NULLPTR, size_t length = 0);
216 
217 	/// \brief Deterministically reseed an AutoSeededX917RNG for testing
218 	/// \param key the key to use for the deterministic reseeding
219 	/// \param keylength the size of the key, in bytes
220 	/// \param seed the seed to use for the deterministic reseeding
221 	/// \param timeVector a time vector to use for deterministic reseeding
222 	/// \details This is a testing interface for testing purposes, and should \a NOT
223 	///  be used in production.
224 	void Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector);
225 
CanIncorporateEntropy()226 	bool CanIncorporateEntropy() const {return true;}
IncorporateEntropy(const byte * input,size_t length)227 	void IncorporateEntropy(const byte *input, size_t length) {Reseed(false, input, length);}
GenerateIntoBufferedTransformation(BufferedTransformation & target,const std::string & channel,lword length)228 	void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length)
229 		{m_rng->GenerateIntoBufferedTransformation(target, channel, length);}
230 
231 	std::string AlgorithmProvider() const;
232 
233 private:
234 	member_ptr<RandomNumberGenerator> m_rng;
235 };
236 
237 template <class BLOCK_CIPHER>
Reseed(const byte * key,size_t keylength,const byte * seed,const byte * timeVector)238 void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector)
239 {
240 	m_rng.reset(new X917RNG(new typename BLOCK_CIPHER::Encryption(key, keylength), seed, timeVector));
241 }
242 
243 template <class BLOCK_CIPHER>
Reseed(bool blocking,const byte * input,size_t length)244 void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(bool blocking, const byte *input, size_t length)
245 {
246 	enum {BlockSize=BLOCK_CIPHER::BLOCKSIZE};
247 	enum {KeyLength=BLOCK_CIPHER::DEFAULT_KEYLENGTH};
248 	enum {SeedSize=BlockSize + KeyLength};
249 
250 	SecByteBlock seed(SeedSize), temp(SeedSize);
251 	const byte label[] = "X9.17 key generation";
252 	const byte *key=NULLPTR;
253 
254 	do
255 	{
256 		OS_GenerateRandomBlock(blocking, temp, temp.size());
257 
258 		HKDF<SHA256> hkdf;
259 		hkdf.DeriveKey(
260 			seed, seed.size(),  // derived secret
261 			temp, temp.size(),  // instance secret
262 			input, length,      // user secret
263 			label, 20           // unique label
264 		);
265 
266 		key = seed + BlockSize;
267 	}	// check that seed and key don't have same value
268 	while (memcmp(key, seed, STDMIN((size_t)BlockSize, (size_t)KeyLength)) == 0);
269 
270 	Reseed(key, KeyLength, seed, NULLPTR);
271 }
272 
273 template <class BLOCK_CIPHER>
AlgorithmProvider()274 std::string AutoSeededX917RNG<BLOCK_CIPHER>::AlgorithmProvider() const
275 {
276 	// Hack for now... We need to instantiate one
277 	typename BLOCK_CIPHER::Encryption bc;
278 	return bc.AlgorithmProvider();
279 }
280 
281 CRYPTOPP_DLL_TEMPLATE_CLASS AutoSeededX917RNG<AES>;
282 
283 #if defined(CRYPTOPP_DOXYGEN_PROCESSING)
284 /// \brief A typedef providing a default generator
285 /// \details DefaultAutoSeededRNG is a typedef of either AutoSeededX917RNG<AES> or AutoSeededRandomPool.
286 ///  If CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 is defined, then DefaultAutoSeededRNG is
287 ///  AutoSeededX917RNG<AES>. Otherwise, DefaultAutoSeededRNG is AutoSeededRandomPool.
288 /// \details You should reseed the generator after a fork() to avoid multiple generators
289 ///  with the same internal state.
290 class DefaultAutoSeededRNG {}
291 #else
292 // AutoSeededX917RNG<AES> in FIPS mode, otherwise it's AutoSeededRandomPool
293 #if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
294 typedef AutoSeededX917RNG<AES> DefaultAutoSeededRNG;
295 #else
296 typedef AutoSeededRandomPool DefaultAutoSeededRNG;
297 #endif
298 #endif // CRYPTOPP_DOXYGEN_PROCESSING
299 
300 NAMESPACE_END
301 
302 #endif
303 
304 #endif
305