Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:55:06

0001 // osrng.h - originally written and placed in the public domain by Wei Dai

0002 
0003 /// \file osrng.h

0004 /// \brief Classes for access to the operating system's random number generators

0005 
0006 #ifndef CRYPTOPP_OSRNG_H
0007 #define CRYPTOPP_OSRNG_H
0008 
0009 #include "config.h"
0010 
0011 #if !defined(NO_OS_DEPENDENCE) && defined(OS_RNG_AVAILABLE)
0012 
0013 #include "cryptlib.h"
0014 #include "randpool.h"
0015 #include "smartptr.h"
0016 #include "fips140.h"
0017 #include "hkdf.h"
0018 #include "rng.h"
0019 #include "aes.h"
0020 #include "sha.h"
0021 
0022 NAMESPACE_BEGIN(CryptoPP)
0023 
0024 /// \brief Exception thrown when an operating system error is encountered

0025 class CRYPTOPP_DLL OS_RNG_Err : public Exception
0026 {
0027 public:
0028     /// \brief Constructs an OS_RNG_Err

0029     /// \param operation the operation or API call when the error occurs

0030     OS_RNG_Err(const std::string &operation);
0031 };
0032 
0033 #ifdef NONBLOCKING_RNG_AVAILABLE
0034 
0035 #ifdef CRYPTOPP_WIN32_AVAILABLE
0036 /// \brief Wrapper for Microsoft crypto service provider

0037 /// \sa \def USE_MS_CRYPTOAPI, \def USE_MS_CNGAPI

0038 class CRYPTOPP_DLL MicrosoftCryptoProvider
0039 {
0040 public:
0041     /// \brief Construct a MicrosoftCryptoProvider

0042     MicrosoftCryptoProvider();
0043     ~MicrosoftCryptoProvider();
0044 
0045 // type HCRYPTPROV and BCRYPT_ALG_HANDLE, avoid #include <windows.h>

0046 #if defined(USE_MS_CRYPTOAPI)
0047 # if defined(__CYGWIN__) && defined(__x86_64__)
0048     typedef unsigned long long ProviderHandle;
0049 # elif defined(WIN64) || defined(_WIN64)
0050     typedef unsigned __int64 ProviderHandle;
0051 # else
0052     typedef unsigned long ProviderHandle;
0053 # endif
0054 #elif defined(USE_MS_CNGAPI)
0055     typedef void *PVOID;
0056     typedef PVOID ProviderHandle;
0057 #endif // USE_MS_CRYPTOAPI or USE_MS_CNGAPI

0058 
0059     /// \brief Retrieves the provider handle

0060     /// \return CryptoAPI provider handle

0061     /// \details If USE_MS_CRYPTOAPI is in effect, then CryptAcquireContext()

0062     ///  acquires then handle and CryptReleaseContext() releases the handle

0063     ///  upon destruction. If USE_MS_CNGAPI is in effect, then

0064     ///  BCryptOpenAlgorithmProvider() acquires then handle and

0065     ///  BCryptCloseAlgorithmProvider() releases the handle upon destruction.

0066     ProviderHandle GetProviderHandle() const {return m_hProvider;}
0067 
0068 private:
0069     ProviderHandle m_hProvider;
0070 };
0071 
0072 #if defined(CRYPTOPP_MSC_VERSION) && defined(USE_MS_CRYPTOAPI)
0073 # pragma comment(lib, "advapi32.lib")
0074 #endif
0075 
0076 #if defined(CRYPTOPP_MSC_VERSION) && defined(USE_MS_CNGAPI)
0077 # pragma comment(lib, "bcrypt.lib")
0078 #endif
0079 
0080 #endif // CRYPTOPP_WIN32_AVAILABLE

0081 
0082 /// \brief Wrapper class for /dev/random and /dev/srandom

0083 /// \details Encapsulates CryptoAPI's CryptGenRandom() or CryptoNG's BCryptGenRandom()

0084 ///  on Windows, or /dev/urandom on Unix and compatibles.

0085 class CRYPTOPP_DLL NonblockingRng : public RandomNumberGenerator
0086 {
0087 public:
0088     CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "NonblockingRng"; }
0089 
0090     ~NonblockingRng();
0091 
0092     /// \brief Construct a NonblockingRng

0093     NonblockingRng();
0094 
0095     /// \brief Generate random array of bytes

0096     /// \param output the byte buffer

0097     /// \param size the length of the buffer, in bytes

0098     /// \details GenerateIntoBufferedTransformation() calls are routed to GenerateBlock().

0099     void GenerateBlock(byte *output, size_t size);
0100 
0101 protected:
0102 #ifdef CRYPTOPP_WIN32_AVAILABLE
0103     MicrosoftCryptoProvider m_Provider;
0104 #else
0105     int m_fd;
0106 #endif
0107 };
0108 
0109 #endif
0110 
0111 #if defined(BLOCKING_RNG_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
0112 
0113 /// \brief Wrapper class for /dev/random and /dev/srandom

0114 /// \details Encapsulates /dev/random on Linux, OS X and Unix; and /dev/srandom on the BSDs.

0115 /// \note On Linux the /dev/random interface is effectively deprecated. According to the

0116 ///  Kernel Crypto developers, /dev/urandom or getrandom(2) should be used instead. Also

0117 ///  see <A HREF="https://lkml.org/lkml/2017/7/20/993">[RFC PATCH v12 3/4] Linux Random

0118 ///  Number Generator</A> on the kernel-crypto mailing list.

0119 class CRYPTOPP_DLL BlockingRng : public RandomNumberGenerator
0120 {
0121 public:
0122     CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "BlockingRng"; }
0123 
0124     ~BlockingRng();
0125 
0126     /// \brief Construct a BlockingRng

0127     BlockingRng();
0128 
0129     /// \brief Generate random array of bytes

0130     /// \param output the byte buffer

0131     /// \param size the length of the buffer, in bytes

0132     /// \details GenerateIntoBufferedTransformation() calls are routed to GenerateBlock().

0133     void GenerateBlock(byte *output, size_t size);
0134 
0135 protected:
0136     int m_fd;
0137 };
0138 
0139 #endif
0140 
0141 /// OS_GenerateRandomBlock

0142 /// \brief Generate random array of bytes

0143 /// \param blocking specifies whether a blocking or non-blocking generator should be used

0144 /// \param output the byte buffer

0145 /// \param size the length of the buffer, in bytes

0146 /// \details OS_GenerateRandomBlock() uses the underlying operating system's

0147 ///  random number generator. On Windows, CryptGenRandom() is called using NonblockingRng.

0148 /// \details On Unix and compatibles, /dev/urandom is called if blocking is false using

0149 ///  NonblockingRng. If blocking is true, then either /dev/randomd or /dev/srandom is used

0150 ///  by way of BlockingRng, if available.

0151 CRYPTOPP_DLL void CRYPTOPP_API OS_GenerateRandomBlock(bool blocking, byte *output, size_t size);
0152 
0153 /// \brief Automatically Seeded Randomness Pool

0154 /// \details This class seeds itself using an operating system provided RNG.

0155 ///  AutoSeededRandomPool was suggested by Leonard Janke.

0156 /// \details You should reseed the generator after a fork() to avoid multiple generators

0157 ///  with the same internal state.

0158 class CRYPTOPP_DLL AutoSeededRandomPool : public RandomPool
0159 {
0160 public:
0161     CRYPTOPP_STATIC_CONSTEXPR const char* StaticAlgorithmName() { return "AutoSeededRandomPool"; }
0162 
0163     ~AutoSeededRandomPool() {}
0164 
0165     /// \brief Construct an AutoSeededRandomPool

0166     /// \param blocking controls seeding with BlockingRng or NonblockingRng

0167     /// \param seedSize the size of the seed, in bytes

0168     /// \details Use blocking to choose seeding with BlockingRng or NonblockingRng.

0169     ///  The parameter is ignored if only one of these is available.

0170     explicit AutoSeededRandomPool(bool blocking = false, unsigned int seedSize = 32)
0171         {Reseed(blocking, seedSize);}
0172 
0173     /// \brief Reseed an AutoSeededRandomPool

0174     /// \param blocking controls seeding with BlockingRng or NonblockingRng

0175     /// \param seedSize the size of the seed, in bytes

0176     void Reseed(bool blocking = false, unsigned int seedSize = 32);
0177 };
0178 
0179 /// \tparam BLOCK_CIPHER a block cipher

0180 /// \brief Automatically Seeded X9.17 RNG

0181 /// \details AutoSeededX917RNG is from ANSI X9.17 Appendix C, seeded using an OS provided RNG.

0182 ///  If 3-key TripleDES (DES_EDE3) is used, then its a X9.17 conforming generator. If AES is

0183 ///  used, then its a X9.31 conforming generator.

0184 /// \details Though ANSI X9 prescribes 3-key TripleDES, the template parameter BLOCK_CIPHER

0185 ///  can be any BlockTransformation derived class.

0186 /// \details You should reseed the generator after a fork() to avoid multiple generators

0187 ///  with the same internal state.

0188 /// \sa X917RNG, DefaultAutoSeededRNG

0189 template <class BLOCK_CIPHER>
0190 class AutoSeededX917RNG : public RandomNumberGenerator, public NotCopyable
0191 {
0192 public:
0193     static std::string StaticAlgorithmName() {
0194         return std::string("AutoSeededX917RNG(") + BLOCK_CIPHER::StaticAlgorithmName() + std::string(")");
0195     }
0196 
0197     ~AutoSeededX917RNG() {}
0198 
0199     /// \brief Construct an AutoSeededX917RNG

0200     /// \param blocking controls seeding with BlockingRng or NonblockingRng

0201     /// \param autoSeed controls auto seeding of the generator

0202     /// \details Use blocking to choose seeding with BlockingRng or NonblockingRng.

0203     ///  The parameter is ignored if only one of these is available.

0204     /// \sa X917RNG

0205     explicit AutoSeededX917RNG(bool blocking = false, bool autoSeed = true)
0206         {if (autoSeed) Reseed(blocking);}
0207 
0208     /// \brief Reseed an AutoSeededX917RNG

0209     /// \param blocking controls seeding with BlockingRng or NonblockingRng

0210     /// \param input additional entropy to add to the generator

0211     /// \param length the size of the additional entropy, in bytes

0212     /// \details Internally, the generator uses SHA256 to extract the entropy from

0213     ///  from the seed and then stretch the material for the block cipher's key

0214     ///  and initialization vector.

0215     void Reseed(bool blocking = false, const byte *input = NULLPTR, size_t length = 0);
0216 
0217     /// \brief Deterministically reseed an AutoSeededX917RNG for testing

0218     /// \param key the key to use for the deterministic reseeding

0219     /// \param keylength the size of the key, in bytes

0220     /// \param seed the seed to use for the deterministic reseeding

0221     /// \param timeVector a time vector to use for deterministic reseeding

0222     /// \details This is a testing interface for testing purposes, and should \a NOT

0223     ///  be used in production.

0224     void Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector);
0225 
0226     bool CanIncorporateEntropy() const {return true;}
0227     void IncorporateEntropy(const byte *input, size_t length) {Reseed(false, input, length);}
0228     void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length)
0229         {m_rng->GenerateIntoBufferedTransformation(target, channel, length);}
0230 
0231     std::string AlgorithmProvider() const;
0232 
0233 private:
0234     member_ptr<RandomNumberGenerator> m_rng;
0235 };
0236 
0237 template <class BLOCK_CIPHER>
0238 void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(const byte *key, size_t keylength, const byte *seed, const byte *timeVector)
0239 {
0240     m_rng.reset(new X917RNG(new typename BLOCK_CIPHER::Encryption(key, keylength), seed, timeVector));
0241 }
0242 
0243 template <class BLOCK_CIPHER>
0244 void AutoSeededX917RNG<BLOCK_CIPHER>::Reseed(bool blocking, const byte *input, size_t length)
0245 {
0246     enum {BlockSize=BLOCK_CIPHER::BLOCKSIZE};
0247     enum {KeyLength=BLOCK_CIPHER::DEFAULT_KEYLENGTH};
0248     enum {SeedSize=EnumToInt(BlockSize)+EnumToInt(KeyLength)};
0249 
0250     SecByteBlock seed(SeedSize), temp(SeedSize);
0251     const byte label[] = "X9.17 key generation";
0252     const byte *key=NULLPTR;
0253 
0254     do
0255     {
0256         OS_GenerateRandomBlock(blocking, temp, temp.size());
0257 
0258         HKDF<SHA256> hkdf;
0259         hkdf.DeriveKey(
0260             seed, seed.size(),  // derived secret

0261             temp, temp.size(),  // instance secret

0262             input, length,      // user secret

0263             label, 20           // unique label

0264         );
0265 
0266         key = seed + BlockSize;
0267     }   // check that seed and key don't have same value

0268     while (std::memcmp(key, seed, STDMIN((size_t)BlockSize, (size_t)KeyLength)) == 0);
0269 
0270     Reseed(key, KeyLength, seed, NULLPTR);
0271 }
0272 
0273 template <class BLOCK_CIPHER>
0274 std::string AutoSeededX917RNG<BLOCK_CIPHER>::AlgorithmProvider() const
0275 {
0276     // Hack for now... We need to instantiate one

0277     typename BLOCK_CIPHER::Encryption bc;
0278     return bc.AlgorithmProvider();
0279 }
0280 
0281 CRYPTOPP_DLL_TEMPLATE_CLASS AutoSeededX917RNG<AES>;
0282 
0283 #if defined(CRYPTOPP_DOXYGEN_PROCESSING)
0284 /// \brief A typedef providing a default generator

0285 /// \details DefaultAutoSeededRNG is a typedef of either AutoSeededX917RNG<AES> or AutoSeededRandomPool.

0286 ///  If CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2 is defined, then DefaultAutoSeededRNG is

0287 ///  AutoSeededX917RNG<AES>. Otherwise, DefaultAutoSeededRNG is AutoSeededRandomPool.

0288 /// \details You should reseed the generator after a fork() to avoid multiple generators

0289 ///  with the same internal state.

0290 class DefaultAutoSeededRNG {}
0291 #else
0292 // AutoSeededX917RNG<AES> in FIPS mode, otherwise it's AutoSeededRandomPool

0293 #if CRYPTOPP_ENABLE_COMPLIANCE_WITH_FIPS_140_2
0294 typedef AutoSeededX917RNG<AES> DefaultAutoSeededRNG;
0295 #else
0296 typedef AutoSeededRandomPool DefaultAutoSeededRNG;
0297 #endif
0298 #endif // CRYPTOPP_DOXYGEN_PROCESSING

0299 
0300 NAMESPACE_END
0301 
0302 #endif
0303 
0304 #endif