File: osrng.h

package info (click to toggle)
libcrypto++ 5.6.4-8
  • links: PTS
  • area: main
  • in suites: buster, sid
  • size: 11,896 kB
  • ctags: 13,256
  • sloc: cpp: 69,231; sh: 4,117; asm: 4,090; makefile: 373
file content (267 lines) | stat: -rw-r--r-- 10,168 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
// osrng.h - written and placed in the public domain by Wei Dai

//! \file osrng.h
//! \brief Classes for access to the operating system's random number generators

#ifndef CRYPTOPP_OSRNG_H
#define CRYPTOPP_OSRNG_H

#include "config.h"

#if !defined(OS_NO_DEPENDENCE) && defined(OS_RNG_AVAILABLE)

#include "cryptlib.h"
#include "randpool.h"
#include "smartptr.h"
#include "fips140.h"
#include "rng.h"
#include "aes.h"
#include "sha.h"

NAMESPACE_BEGIN(CryptoPP)

//! \class OS_RNG_Err
//! \brief Exception thrown when an operating system error is encountered
class CRYPTOPP_DLL OS_RNG_Err : public Exception
{
public:
	//! \brief Constructs an OS_RNG_Err
	//! \param operation the operation or API call when the error occurs
	OS_RNG_Err(const std::string &operation);
};

#ifdef NONBLOCKING_RNG_AVAILABLE

#ifdef CRYPTOPP_WIN32_AVAILABLE
//! \class MicrosoftCryptoProvider
//! \brief Wrapper for Microsoft crypto service provider
//! \sa \def USE_MS_CRYPTOAPI, \def USE_MS_CNGAPI, \def WORKAROUND_MS_BUG_Q258000
class CRYPTOPP_DLL MicrosoftCryptoProvider
{
public:
	//! \brief Construct a MicrosoftCryptoProvider
	MicrosoftCryptoProvider();
	~MicrosoftCryptoProvider();

// type HCRYPTPROV and BCRYPT_ALG_HANDLE, avoid #include <windows.h>
#if defined(USE_MS_CRYPTOAPI)
# if defined(__CYGWIN__) && defined(__x86_64__)
	typedef unsigned long long ProviderHandle;
# elif defined(WIN64) || defined(_WIN64)
	typedef unsigned __int64 ProviderHandle;
# else
	typedef unsigned long ProviderHandle;
# endif
#elif defined(USE_MS_CNGAPI)
	typedef void *PVOID;
	typedef PVOID ProviderHandle;
#endif // USE_MS_CRYPTOAPI or USE_MS_CNGAPI

	//! \brief Retrieves the provider handle
	//! \returns CryptoAPI provider handle
	//! \details If USE_MS_CRYPTOAPI is in effect, then CryptAcquireContext()
	//!   acquires then handle and CryptReleaseContext() releases the handle
	//!   upon destruction. If USE_MS_CNGAPI is in effect, then
	//!   BCryptOpenAlgorithmProvider() acquires then handle and
	//!   BCryptCloseAlgorithmProvider() releases the handle upon destruction.
	ProviderHandle GetProviderHandle() const {return m_hProvider;}

private:
	ProviderHandle m_hProvider;
};

#if defined(_MSC_VER) && defined(USE_MS_CRYPTOAPI)
# pragma comment(lib, "advapi32.lib")
#endif

#if defined(_MSC_VER) && defined(USE_MS_CNGAPI)
# pragma comment(lib, "bcrypt.lib")
#endif

#endif //CRYPTOPP_WIN32_AVAILABLE

//! \class NonblockingRng
//! \brief Wrapper class for /dev/random and /dev/srandom
//! \details Encapsulates CryptoAPI's CryptGenRandom() or CryptoNG's BCryptGenRandom()
//!   on Windows, or /dev/urandom on Unix and compatibles.
class CRYPTOPP_DLL NonblockingRng : public RandomNumberGenerator
{
public:
	//! \brief Construct a NonblockingRng
	NonblockingRng();
	~NonblockingRng();

	//! \brief Generate random array of bytes
	//! \param output the byte buffer
	//! \param size the length of the buffer, in bytes
	//! \details GenerateIntoBufferedTransformation() calls are routed to GenerateBlock().
	void GenerateBlock(byte *output, size_t size);

protected:
#ifdef CRYPTOPP_WIN32_AVAILABLE
	MicrosoftCryptoProvider m_Provider;
#else
	int m_fd;
#endif
};

#endif

#if defined(BLOCKING_RNG_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING)

//! \class BlockingRng
//! \brief Wrapper class for /dev/random and /dev/srandom
//! \details Encapsulates /dev/random on Linux, OS X and Unix; and /dev/srandom on the BSDs.
class CRYPTOPP_DLL BlockingRng : public RandomNumberGenerator
{
public:
	//! \brief Construct a BlockingRng
	BlockingRng();
	~BlockingRng();

	//! \brief Generate random array of bytes
	//! \param output the byte buffer
	//! \param size the length of the buffer, in bytes
	//! \details GenerateIntoBufferedTransformation() calls are routed to GenerateBlock().
	void GenerateBlock(byte *output, size_t size);

protected:
	int m_fd;
};

#endif

//! OS_GenerateRandomBlock
//! \brief Generate random array of bytes
//! \param blocking specifies whther a bobcking or non-blocking generator should be used
//! \param output the byte buffer
//! \param size the length of the buffer, in bytes
//! \details OS_GenerateRandomBlock() uses the underlying operating system's
//!   random number generator. On Windows, CryptGenRandom() is called using NonblockingRng.
//! \details On Unix and compatibles, /dev/urandom is called if blocking is false using
//!   NonblockingRng. If blocking is true, then either /dev/randomd or /dev/srandom is used
//!  by way of BlockingRng, if available.
CRYPTOPP_DLL void CRYPTOPP_API OS_GenerateRandomBlock(bool blocking, byte *output, size_t size);


//! \class AutoSeededRandomPool
//! \brief Automatically Seeded Randomness Pool
//! \details This class seeds itself using an operating system provided RNG.
//!    AutoSeededRandomPool was suggested by Leonard Janke.
class CRYPTOPP_DLL AutoSeededRandomPool : public RandomPool
{
public:
	//! \brief Construct an AutoSeededRandomPool
	//! \param blocking controls seeding with BlockingRng or NonblockingRng
	//! \param seedSize the size of the seed, in bytes
	//! \details Use blocking to choose seeding with BlockingRng or NonblockingRng.
	//!   The parameter is ignored if only one of these is available.
	explicit AutoSeededRandomPool(bool blocking = false, unsigned int seedSize = 32)
		{Reseed(blocking, seedSize);}

	//! \brief Reseed an AutoSeededRandomPool
	//! \param blocking controls seeding with BlockingRng or NonblockingRng
	//! \param seedSize the size of the seed, in bytes
	void Reseed(bool blocking = false, unsigned int seedSize = 32);
};

//! \class AutoSeededX917RNG
//! \tparam BLOCK_CIPHER a block cipher
//! \brief Automatically Seeded X9.17 RNG
//! \details AutoSeededX917RNG is from ANSI X9.17 Appendix C, seeded using an OS provided RNG.
//!   If 3-key TripleDES (DES_EDE3) is used, then its a X9.17 conforming generator. If AES is
//!   used, then its a X9.31 conforming generator.
//! \details Though ANSI X9 prescribes 3-key TripleDES, the template parameter BLOCK_CIPHER can be any
//!   BlockTransformation derived class.
//! \sa X917RNG, DefaultAutoSeededRNG
template <class BLOCK_CIPHER>
class AutoSeededX917RNG : public RandomNumberGenerator, public NotCopyable
{
public:
	//! \brief Construct an AutoSeededX917RNG
	//! \param blocking controls seeding with BlockingRng or NonblockingRng
	//! \param autoSeed controls auto seeding of the generator
	//! \details Use blocking to choose seeding with BlockingRng or NonblockingRng.
	//!   The parameter is ignored if only one of these is available.
	//! \sa X917RNG
	explicit AutoSeededX917RNG(bool blocking = false, bool autoSeed = true)
		{if (autoSeed) Reseed(blocking);}

	//! \brief Reseed an AutoSeededX917RNG
	//! \param blocking controls seeding with BlockingRng or NonblockingRng
	//! \param additionalEntropy additional entropy to add to the generator
	//! \param length the size of the additional entropy, in bytes
	//! \details Internally, the generator uses SHA256 to extract the entropy from
	//!   from the seed and then stretch the material for the block cipher's key
	//!   and initialization vector.
	void Reseed(bool blocking = false, const byte *additionalEntropy = NULL, size_t length = 0);

	//! \brief Deterministically reseed an AutoSeededX917RNG for testing
	//! \param key the key to use for the deterministic reseeding
	//! \param keylength the size of the key, in bytes
	//! \param seed the seed to use for the deterministic reseeding
	//! \param timeVector a time vector to use for deterministic reseeding
	//! \details This is a testing interface for testing purposes, and should \a NOT
	//!   be used in production.
	void Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector);

	bool CanIncorporateEntropy() const {return true;}
	void IncorporateEntropy(const byte *input, size_t length) {Reseed(false, input, length);}
	void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length)
		{m_rng->GenerateIntoBufferedTransformation(target, channel, length);}

private:
	member_ptr<RandomNumberGenerator> m_rng;
};

template <class BLOCK_CIPHER>
void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector)
{
	m_rng.reset(new X917RNG(new typename BLOCK_CIPHER::Encryption(key, keylength), seed, timeVector));
}

template <class BLOCK_CIPHER>
void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(bool blocking, const byte *input, size_t length)
{
	SecByteBlock seed(BLOCK_CIPHER::BLOCKSIZE + BLOCK_CIPHER::DEFAULT_KEYLENGTH);
	const byte *key;
	do
	{
		OS_GenerateRandomBlock(blocking, seed, seed.size());
		if (length > 0)
		{
			SHA256 hash;
			hash.Update(seed, seed.size());
			hash.Update(input, length);
			hash.TruncatedFinal(seed, UnsignedMin(hash.DigestSize(), seed.size()));
		}
		key = seed + BLOCK_CIPHER::BLOCKSIZE;
	}	// check that seed and key don't have same value
	while (memcmp(key, seed, STDMIN((unsigned int)BLOCK_CIPHER::BLOCKSIZE, (unsigned int)BLOCK_CIPHER::DEFAULT_KEYLENGTH)) == 0);

	Reseed(key, BLOCK_CIPHER::DEFAULT_KEYLENGTH, seed, NULL);
}

CRYPTOPP_DLL_TEMPLATE_CLASS AutoSeededX917RNG<AES>;

#if defined(CRYPTOPP_DOXYGEN_PROCESSING)
//! \class DefaultAutoSeededRNG
//! \brief A typedef providing a default generator
//! \details DefaultAutoSeededRNG is a typedef of either AutoSeededX917RNG<AES> or AutoSeededRandomPool.
//!   If CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 is defined, then DefaultAutoSeededRNG is
//!   AutoSeededX917RNG<AES>. Otherwise, DefaultAutoSeededRNG is AutoSeededRandomPool.
class DefaultAutoSeededRNG {}
#else
// AutoSeededX917RNG<AES> in FIPS mode, otherwise it's AutoSeededRandomPool
#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
typedef AutoSeededX917RNG<AES> DefaultAutoSeededRNG;
#else
typedef AutoSeededRandomPool DefaultAutoSeededRNG;
#endif
#endif // CRYPTOPP_DOXYGEN_PROCESSING

NAMESPACE_END

#endif

#endif