source: trunk/src-cryptopp/osrng.h

Last change on this file was e230cb0, checked in by David Stainton <dstainton415@…>, at 2016-10-12T13:27:29Z

Add cryptopp from tag CRYPTOPP_5_6_5

  • Property mode set to 100644
File size: 9.9 KB
Line 
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
21NAMESPACE_BEGIN(CryptoPP)
22
23//! \class OS_RNG_Err
24//! \brief Exception thrown when an operating system error is encountered
25class CRYPTOPP_DLL OS_RNG_Err : public Exception
26{
27public:
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
39class CRYPTOPP_DLL MicrosoftCryptoProvider
40{
41public:
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
69private:
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.
87class CRYPTOPP_DLL NonblockingRng : public RandomNumberGenerator
88{
89public:
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
100protected:
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.
115class CRYPTOPP_DLL BlockingRng : public RandomNumberGenerator
116{
117public:
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
128protected:
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.
144CRYPTOPP_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.
151class CRYPTOPP_DLL AutoSeededRandomPool : public RandomPool
152{
153public:
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
177template <class BLOCK_CIPHER>
178class AutoSeededX917RNG : public RandomNumberGenerator, public NotCopyable
179{
180public:
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
213private:
214        member_ptr<RandomNumberGenerator> m_rng;
215};
216
217template <class BLOCK_CIPHER>
218void 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
223template <class BLOCK_CIPHER>
224void 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
245CRYPTOPP_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.
253class DefaultAutoSeededRNG {}
254#else
255// AutoSeededX917RNG<AES> in FIPS mode, otherwise it's AutoSeededRandomPool
256#if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
257typedef AutoSeededX917RNG<AES> DefaultAutoSeededRNG;
258#else
259typedef AutoSeededRandomPool DefaultAutoSeededRNG;
260#endif
261#endif // CRYPTOPP_DOXYGEN_PROCESSING
262
263NAMESPACE_END
264
265#endif
266
267#endif
Note: See TracBrowser for help on using the repository browser.