1 | // osrng.h - 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(OS_NO_DEPENDENCE) && defined(OS_RNG_AVAILABLE) |
---|
12 | |
---|
13 | #include "cryptlib.h" |
---|
14 | #include "randpool.h" |
---|
15 | #include "smartptr.h" |
---|
16 | #include "fips140.h" |
---|
17 | #include "rng.h" |
---|
18 | #include "aes.h" |
---|
19 | #include "sha.h" |
---|
20 | |
---|
21 | NAMESPACE_BEGIN(CryptoPP) |
---|
22 | |
---|
23 | //! \class OS_RNG_Err |
---|
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 | //! \class MicrosoftCryptoProvider |
---|
37 | //! \brief Wrapper for Microsoft crypto service provider |
---|
38 | //! \sa \def USE_MS_CRYPTOAPI, \def USE_MS_CNGAPI, \def WORKAROUND_MS_BUG_Q258000 |
---|
39 | class CRYPTOPP_DLL MicrosoftCryptoProvider |
---|
40 | { |
---|
41 | public: |
---|
42 | //! \brief Construct a MicrosoftCryptoProvider |
---|
43 | MicrosoftCryptoProvider(); |
---|
44 | ~MicrosoftCryptoProvider(); |
---|
45 | |
---|
46 | // type HCRYPTPROV and BCRYPT_ALG_HANDLE, avoid #include <windows.h> |
---|
47 | #if defined(USE_MS_CRYPTOAPI) |
---|
48 | # if defined(__CYGWIN__) && defined(__x86_64__) |
---|
49 | typedef unsigned long long ProviderHandle; |
---|
50 | # elif defined(WIN64) || defined(_WIN64) |
---|
51 | typedef unsigned __int64 ProviderHandle; |
---|
52 | # else |
---|
53 | typedef unsigned long ProviderHandle; |
---|
54 | # endif |
---|
55 | #elif defined(USE_MS_CNGAPI) |
---|
56 | typedef void *PVOID; |
---|
57 | typedef PVOID ProviderHandle; |
---|
58 | #endif // USE_MS_CRYPTOAPI or USE_MS_CNGAPI |
---|
59 | |
---|
60 | //! \brief Retrieves the provider handle |
---|
61 | //! \returns CryptoAPI provider handle |
---|
62 | //! \details If USE_MS_CRYPTOAPI is in effect, then CryptAcquireContext() |
---|
63 | //! acquires then handle and CryptReleaseContext() releases the handle |
---|
64 | //! upon destruction. If USE_MS_CNGAPI is in effect, then |
---|
65 | //! BCryptOpenAlgorithmProvider() acquires then handle and |
---|
66 | //! BCryptCloseAlgorithmProvider() releases the handle upon destruction. |
---|
67 | ProviderHandle GetProviderHandle() const {return m_hProvider;} |
---|
68 | |
---|
69 | private: |
---|
70 | ProviderHandle m_hProvider; |
---|
71 | }; |
---|
72 | |
---|
73 | #if defined(_MSC_VER) && defined(USE_MS_CRYPTOAPI) |
---|
74 | # pragma comment(lib, "advapi32.lib") |
---|
75 | #endif |
---|
76 | |
---|
77 | #if defined(_MSC_VER) && defined(USE_MS_CNGAPI) |
---|
78 | # pragma comment(lib, "bcrypt.lib") |
---|
79 | #endif |
---|
80 | |
---|
81 | #endif //CRYPTOPP_WIN32_AVAILABLE |
---|
82 | |
---|
83 | //! \class NonblockingRng |
---|
84 | //! \brief Wrapper class for /dev/random and /dev/srandom |
---|
85 | //! \details Encapsulates CryptoAPI's CryptGenRandom() or CryptoNG's BCryptGenRandom() |
---|
86 | //! on Windows, or /dev/urandom on Unix and compatibles. |
---|
87 | class CRYPTOPP_DLL NonblockingRng : public RandomNumberGenerator |
---|
88 | { |
---|
89 | public: |
---|
90 | //! \brief Construct a NonblockingRng |
---|
91 | NonblockingRng(); |
---|
92 | ~NonblockingRng(); |
---|
93 | |
---|
94 | //! \brief Generate random array of bytes |
---|
95 | //! \param output the byte buffer |
---|
96 | //! \param size the length of the buffer, in bytes |
---|
97 | //! \details GenerateIntoBufferedTransformation() calls are routed to GenerateBlock(). |
---|
98 | void GenerateBlock(byte *output, size_t size); |
---|
99 | |
---|
100 | protected: |
---|
101 | #ifdef CRYPTOPP_WIN32_AVAILABLE |
---|
102 | MicrosoftCryptoProvider m_Provider; |
---|
103 | #else |
---|
104 | int m_fd; |
---|
105 | #endif |
---|
106 | }; |
---|
107 | |
---|
108 | #endif |
---|
109 | |
---|
110 | #if defined(BLOCKING_RNG_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING) |
---|
111 | |
---|
112 | //! \class BlockingRng |
---|
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 | class CRYPTOPP_DLL BlockingRng : public RandomNumberGenerator |
---|
116 | { |
---|
117 | public: |
---|
118 | //! \brief Construct a BlockingRng |
---|
119 | BlockingRng(); |
---|
120 | ~BlockingRng(); |
---|
121 | |
---|
122 | //! \brief Generate random array of bytes |
---|
123 | //! \param output the byte buffer |
---|
124 | //! \param size the length of the buffer, in bytes |
---|
125 | //! \details GenerateIntoBufferedTransformation() calls are routed to GenerateBlock(). |
---|
126 | void GenerateBlock(byte *output, size_t size); |
---|
127 | |
---|
128 | protected: |
---|
129 | int m_fd; |
---|
130 | }; |
---|
131 | |
---|
132 | #endif |
---|
133 | |
---|
134 | //! OS_GenerateRandomBlock |
---|
135 | //! \brief Generate random array of bytes |
---|
136 | //! \param blocking specifies whther a bobcking or non-blocking generator should be used |
---|
137 | //! \param output the byte buffer |
---|
138 | //! \param size the length of the buffer, in bytes |
---|
139 | //! \details OS_GenerateRandomBlock() uses the underlying operating system's |
---|
140 | //! random number generator. On Windows, CryptGenRandom() is called using NonblockingRng. |
---|
141 | //! \details On Unix and compatibles, /dev/urandom is called if blocking is false using |
---|
142 | //! NonblockingRng. If blocking is true, then either /dev/randomd or /dev/srandom is used |
---|
143 | //! by way of BlockingRng, if available. |
---|
144 | CRYPTOPP_DLL void CRYPTOPP_API OS_GenerateRandomBlock(bool blocking, byte *output, size_t size); |
---|
145 | |
---|
146 | |
---|
147 | //! \class AutoSeededRandomPool |
---|
148 | //! \brief Automatically Seeded Randomness Pool |
---|
149 | //! \details This class seeds itself using an operating system provided RNG. |
---|
150 | //! AutoSeededRandomPool was suggested by Leonard Janke. |
---|
151 | class CRYPTOPP_DLL AutoSeededRandomPool : public RandomPool |
---|
152 | { |
---|
153 | public: |
---|
154 | //! \brief Construct an AutoSeededRandomPool |
---|
155 | //! \param blocking controls seeding with BlockingRng or NonblockingRng |
---|
156 | //! \param seedSize the size of the seed, in bytes |
---|
157 | //! \details Use blocking to choose seeding with BlockingRng or NonblockingRng. |
---|
158 | //! The parameter is ignored if only one of these is available. |
---|
159 | explicit AutoSeededRandomPool(bool blocking = false, unsigned int seedSize = 32) |
---|
160 | {Reseed(blocking, seedSize);} |
---|
161 | |
---|
162 | //! \brief Reseed an AutoSeededRandomPool |
---|
163 | //! \param blocking controls seeding with BlockingRng or NonblockingRng |
---|
164 | //! \param seedSize the size of the seed, in bytes |
---|
165 | void Reseed(bool blocking = false, unsigned int seedSize = 32); |
---|
166 | }; |
---|
167 | |
---|
168 | //! \class AutoSeededX917RNG |
---|
169 | //! \tparam BLOCK_CIPHER a block cipher |
---|
170 | //! \brief Automatically Seeded X9.17 RNG |
---|
171 | //! \details AutoSeededX917RNG is from ANSI X9.17 Appendix C, seeded using an OS provided RNG. |
---|
172 | //! If 3-key TripleDES (DES_EDE3) is used, then its a X9.17 conforming generator. If AES is |
---|
173 | //! used, then its a X9.31 conforming generator. |
---|
174 | //! \details Though ANSI X9 prescribes 3-key TripleDES, the template parameter BLOCK_CIPHER can be any |
---|
175 | //! BlockTransformation derived class. |
---|
176 | //! \sa X917RNG, DefaultAutoSeededRNG |
---|
177 | template <class BLOCK_CIPHER> |
---|
178 | class AutoSeededX917RNG : public RandomNumberGenerator, public NotCopyable |
---|
179 | { |
---|
180 | public: |
---|
181 | //! \brief Construct an AutoSeededX917RNG |
---|
182 | //! \param blocking controls seeding with BlockingRng or NonblockingRng |
---|
183 | //! \param autoSeed controls auto seeding of the generator |
---|
184 | //! \details Use blocking to choose seeding with BlockingRng or NonblockingRng. |
---|
185 | //! The parameter is ignored if only one of these is available. |
---|
186 | //! \sa X917RNG |
---|
187 | explicit AutoSeededX917RNG(bool blocking = false, bool autoSeed = true) |
---|
188 | {if (autoSeed) Reseed(blocking);} |
---|
189 | |
---|
190 | //! \brief Reseed an AutoSeededX917RNG |
---|
191 | //! \param blocking controls seeding with BlockingRng or NonblockingRng |
---|
192 | //! \param additionalEntropy additional entropy to add to the generator |
---|
193 | //! \param length the size of the additional entropy, in bytes |
---|
194 | //! \details Internally, the generator uses SHA256 to extract the entropy from |
---|
195 | //! from the seed and then stretch the material for the block cipher's key |
---|
196 | //! and initialization vector. |
---|
197 | void Reseed(bool blocking = false, const byte *additionalEntropy = NULL, size_t length = 0); |
---|
198 | |
---|
199 | //! \brief Deterministically reseed an AutoSeededX917RNG for testing |
---|
200 | //! \param key the key to use for the deterministic reseeding |
---|
201 | //! \param keylength the size of the key, in bytes |
---|
202 | //! \param seed the seed to use for the deterministic reseeding |
---|
203 | //! \param timeVector a time vector to use for deterministic reseeding |
---|
204 | //! \details This is a testing interface for testing purposes, and should \a NOT |
---|
205 | //! be used in production. |
---|
206 | void Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector); |
---|
207 | |
---|
208 | bool CanIncorporateEntropy() const {return true;} |
---|
209 | void IncorporateEntropy(const byte *input, size_t length) {Reseed(false, input, length);} |
---|
210 | void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length) |
---|
211 | {m_rng->GenerateIntoBufferedTransformation(target, channel, length);} |
---|
212 | |
---|
213 | private: |
---|
214 | member_ptr<RandomNumberGenerator> m_rng; |
---|
215 | }; |
---|
216 | |
---|
217 | template <class BLOCK_CIPHER> |
---|
218 | void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector) |
---|
219 | { |
---|
220 | m_rng.reset(new X917RNG(new typename BLOCK_CIPHER::Encryption(key, keylength), seed, timeVector)); |
---|
221 | } |
---|
222 | |
---|
223 | template <class BLOCK_CIPHER> |
---|
224 | void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(bool blocking, const byte *input, size_t length) |
---|
225 | { |
---|
226 | SecByteBlock seed(BLOCK_CIPHER::BLOCKSIZE + BLOCK_CIPHER::DEFAULT_KEYLENGTH); |
---|
227 | const byte *key; |
---|
228 | do |
---|
229 | { |
---|
230 | OS_GenerateRandomBlock(blocking, seed, seed.size()); |
---|
231 | if (length > 0) |
---|
232 | { |
---|
233 | SHA256 hash; |
---|
234 | hash.Update(seed, seed.size()); |
---|
235 | hash.Update(input, length); |
---|
236 | hash.TruncatedFinal(seed, UnsignedMin(hash.DigestSize(), seed.size())); |
---|
237 | } |
---|
238 | key = seed + BLOCK_CIPHER::BLOCKSIZE; |
---|
239 | } // check that seed and key don't have same value |
---|
240 | while (memcmp(key, seed, STDMIN((unsigned int)BLOCK_CIPHER::BLOCKSIZE, (unsigned int)BLOCK_CIPHER::DEFAULT_KEYLENGTH)) == 0); |
---|
241 | |
---|
242 | Reseed(key, BLOCK_CIPHER::DEFAULT_KEYLENGTH, seed, NULL); |
---|
243 | } |
---|
244 | |
---|
245 | CRYPTOPP_DLL_TEMPLATE_CLASS AutoSeededX917RNG<AES>; |
---|
246 | |
---|
247 | #if defined(CRYPTOPP_DOXYGEN_PROCESSING) |
---|
248 | //! \class DefaultAutoSeededRNG |
---|
249 | //! \brief A typedef providing a default generator |
---|
250 | //! \details DefaultAutoSeededRNG is a typedef of either AutoSeededX917RNG<AES> or AutoSeededRandomPool. |
---|
251 | //! If CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 is defined, then DefaultAutoSeededRNG is |
---|
252 | //! AutoSeededX917RNG<AES>. Otherwise, DefaultAutoSeededRNG is AutoSeededRandomPool. |
---|
253 | class DefaultAutoSeededRNG {} |
---|
254 | #else |
---|
255 | // AutoSeededX917RNG<AES> in FIPS mode, otherwise it's AutoSeededRandomPool |
---|
256 | #if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 |
---|
257 | typedef AutoSeededX917RNG<AES> DefaultAutoSeededRNG; |
---|
258 | #else |
---|
259 | typedef AutoSeededRandomPool DefaultAutoSeededRNG; |
---|
260 | #endif |
---|
261 | #endif // CRYPTOPP_DOXYGEN_PROCESSING |
---|
262 | |
---|
263 | NAMESPACE_END |
---|
264 | |
---|
265 | #endif |
---|
266 | |
---|
267 | #endif |
---|