| 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 |
|---|