Line | Count | Source (jump to first uncovered line) |
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 | | |
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. |
66 | | ProviderHandle GetProviderHandle() const {return m_hProvider;} |
67 | | |
68 | | private: |
69 | | ProviderHandle m_hProvider; |
70 | | }; |
71 | | |
72 | | #if defined(CRYPTOPP_MSC_VERSION) && defined(USE_MS_CRYPTOAPI) |
73 | | # pragma comment(lib, "advapi32.lib") |
74 | | #endif |
75 | | |
76 | | #if defined(CRYPTOPP_MSC_VERSION) && 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: |
88 | 0 | 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: |
122 | 0 | 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: |
161 | 0 | CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "AutoSeededRandomPool"; } |
162 | | |
163 | 0 | ~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 | 28 | {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: |
193 | 0 | static std::string StaticAlgorithmName() { |
194 | 0 | return std::string("AutoSeededX917RNG(") + BLOCK_CIPHER::StaticAlgorithmName() + std::string(")"); |
195 | 0 | } |
196 | | |
197 | 0 | ~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 | 0 | {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 | | |
226 | 0 | bool CanIncorporateEntropy() const {return true;} |
227 | 0 | void IncorporateEntropy(const byte *input, size_t length) {Reseed(false, input, length);} |
228 | | void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length) |
229 | 0 | {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> |
238 | | void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector) |
239 | 0 | { |
240 | 0 | m_rng.reset(new X917RNG(new typename BLOCK_CIPHER::Encryption(key, keylength), seed, timeVector)); |
241 | 0 | } |
242 | | |
243 | | template <class BLOCK_CIPHER> |
244 | | void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(bool blocking, const byte *input, size_t length) |
245 | 0 | { |
246 | 0 | enum {BlockSize=BLOCK_CIPHER::BLOCKSIZE}; |
247 | 0 | enum {KeyLength=BLOCK_CIPHER::DEFAULT_KEYLENGTH}; |
248 | 0 | enum {SeedSize=EnumToInt(BlockSize)+EnumToInt(KeyLength)}; |
249 | |
|
250 | 0 | SecByteBlock seed(SeedSize), temp(SeedSize); |
251 | 0 | const byte label[] = "X9.17 key generation"; |
252 | 0 | const byte *key=NULLPTR; |
253 | |
|
254 | 0 | do |
255 | 0 | { |
256 | 0 | OS_GenerateRandomBlock(blocking, temp, temp.size()); |
257 | |
|
258 | 0 | HKDF<SHA256> hkdf; |
259 | 0 | hkdf.DeriveKey( |
260 | 0 | seed, seed.size(), // derived secret |
261 | 0 | temp, temp.size(), // instance secret |
262 | 0 | input, length, // user secret |
263 | 0 | label, 20 // unique label |
264 | 0 | ); |
265 | |
|
266 | 0 | key = seed + BlockSize; |
267 | 0 | } // check that seed and key don't have same value |
268 | 0 | while (std::memcmp(key, seed, STDMIN((size_t)BlockSize, (size_t)KeyLength)) == 0); |
269 | |
|
270 | 0 | Reseed(key, KeyLength, seed, NULLPTR); |
271 | 0 | } |
272 | | |
273 | | template <class BLOCK_CIPHER> |
274 | | std::string AutoSeededX917RNG<BLOCK_CIPHER>::AlgorithmProvider() const |
275 | 0 | { |
276 | | // Hack for now... We need to instantiate one |
277 | 0 | typename BLOCK_CIPHER::Encryption bc; |
278 | 0 | return bc.AlgorithmProvider(); |
279 | 0 | } |
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 |