Back to home page

EIC code displayed by LXR

 
 

    


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

0001 // drbg.h - written and placed in public domain by Jeffrey Walton.

0002 
0003 /// \file drbg.h

0004 /// \brief Classes for NIST DRBGs from SP 800-90A

0005 /// \sa <A HREF="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf">Recommendation

0006 ///  for Random Number Generation Using Deterministic Random Bit Generators, Rev 1 (June 2015)</A>

0007 /// \since Crypto++ 6.0

0008 
0009 #ifndef CRYPTOPP_NIST_DRBG_H
0010 #define CRYPTOPP_NIST_DRBG_H
0011 
0012 #include "cryptlib.h"
0013 #include "secblock.h"
0014 #include "hmac.h"
0015 #include "sha.h"
0016 
0017 NAMESPACE_BEGIN(CryptoPP)
0018 
0019 /// \brief Interface for NIST DRBGs from SP 800-90A

0020 /// \details NIST_DRBG is the base class interface for NIST DRBGs from SP 800-90A Rev 1 (June 2015)

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

0022 ///  with the same internal state.

0023 /// \sa <A HREF="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf">Recommendation

0024 ///  for Random Number Generation Using Deterministic Random Bit Generators, Rev 1 (June 2015)</A>

0025 /// \since Crypto++ 6.0

0026 class NIST_DRBG : public RandomNumberGenerator
0027 {
0028 public:
0029     /// \brief Exception thrown when a NIST DRBG encounters an error

0030     class Err : public Exception
0031     {
0032     public:
0033         explicit Err(const std::string &c, const std::string &m)
0034         : Exception(OTHER_ERROR, c + ": " + m) {}
0035     };
0036 
0037 public:
0038     virtual ~NIST_DRBG() {}
0039 
0040     /// \brief Determines if a generator can accept additional entropy

0041     /// \return true

0042     /// \details All NIST_DRBG return true

0043     virtual bool CanIncorporateEntropy() const {return true;}
0044 
0045     /// \brief Update RNG state with additional unpredictable values

0046     /// \param input the entropy to add to the generator

0047     /// \param length the size of the input buffer

0048     /// \throw NIST_DRBG::Err if the generator is reseeded with insufficient entropy

0049     /// \details NIST instantiation and reseed requirements demand the generator is constructed

0050     ///  with at least <tt>MINIMUM_ENTROPY</tt> entropy. The byte array for <tt>input</tt> must

0051     ///  meet <A HREF ="http://csrc.nist.gov/publications/PubsSPs.html">NIST SP 800-90B or

0052     ///  SP 800-90C</A> requirements.

0053     virtual void IncorporateEntropy(const byte *input, size_t length)=0;
0054 
0055     /// \brief Update RNG state with additional unpredictable values

0056     /// \param entropy the entropy to add to the generator

0057     /// \param entropyLength the size of the input buffer

0058     /// \param additional additional input to add to the generator

0059     /// \param additionaLength the size of the additional input buffer

0060     /// \throw NIST_DRBG::Err if the generator is reseeded with insufficient entropy

0061     /// \details IncorporateEntropy() is an overload provided to match NIST requirements. NIST

0062     ///  instantiation and reseed requirements demand the generator is constructed with at least

0063     ///  <tt>MINIMUM_ENTROPY</tt> entropy. The byte array for <tt>entropy</tt> must meet

0064     ///  <A HREF ="http://csrc.nist.gov/publications/PubsSPs.html">NIST SP 800-90B or

0065     ///!  SP 800-90C</A> requirements.

0066     virtual void IncorporateEntropy(const byte *entropy, size_t entropyLength, const byte* additional, size_t additionaLength)=0;
0067 
0068     /// \brief Generate random array of bytes

0069     /// \param output the byte buffer

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

0071     /// \throw NIST_DRBG::Err if a reseed is required

0072     /// \throw NIST_DRBG::Err if the size exceeds <tt>MAXIMUM_BYTES_PER_REQUEST</tt>

0073     virtual void GenerateBlock(byte *output, size_t size)=0;
0074 
0075     /// \brief Generate random array of bytes

0076     /// \param additional additional input to add to the generator

0077     /// \param additionaLength the size of the additional input buffer

0078     /// \param output the byte buffer

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

0080     /// \throw NIST_DRBG::Err if a reseed is required

0081     /// \throw NIST_DRBG::Err if the size exceeds <tt>MAXIMUM_BYTES_PER_REQUEST</tt>

0082     /// \details GenerateBlock() is an overload provided to match NIST requirements. The byte

0083     ///  array for <tt>additional</tt> input is optional. If present the additional randomness

0084     ///  is mixed before generating the output bytes.

0085     virtual void GenerateBlock(const byte* additional, size_t additionaLength, byte *output, size_t size)=0;
0086 
0087     /// \brief Provides the security strength

0088     /// \return The security strength of the generator, in bytes

0089     /// \details The equivalent class constant is <tt>SECURITY_STRENGTH</tt>

0090     virtual unsigned int SecurityStrength() const=0;
0091 
0092     /// \brief Provides the seed length

0093     /// \return The seed size of the generator, in bytes

0094     /// \details The equivalent class constant is <tt>SEED_LENGTH</tt>. The size is

0095     ///  used to maintain internal state of <tt>V</tt> and <tt>C</tt>.

0096     virtual unsigned int SeedLength() const=0;
0097 
0098     /// \brief Provides the minimum entropy size

0099     /// \return The minimum entropy size required by the generator, in bytes

0100     /// \details The equivalent class constant is <tt>MINIMUM_ENTROPY</tt>. All NIST DRBGs must

0101     ///  be instaniated with at least <tt>MINIMUM_ENTROPY</tt> bytes of entropy. The bytes must

0102     ///  meet <A HREF="http://csrc.nist.gov/publications/PubsSPs.html">NIST SP 800-90B or

0103     ///  SP 800-90C</A> requirements.

0104     virtual unsigned int MinEntropyLength() const=0;
0105 
0106     /// \brief Provides the maximum entropy size

0107     /// \return The maximum entropy size that can be consumed by the generator, in bytes

0108     /// \details The equivalent class constant is <tt>MAXIMUM_ENTROPY</tt>. The bytes must

0109     ///  meet <A HREF="http://csrc.nist.gov/publications/PubsSPs.html">NIST SP 800-90B or

0110     ///  SP 800-90C</A> requirements. <tt>MAXIMUM_ENTROPY</tt> has been reduced from

0111     ///  2<sup>35</sup> to <tt>INT_MAX</tt> to fit the underlying C++ datatype.

0112     virtual unsigned int MaxEntropyLength() const=0;
0113 
0114     /// \brief Provides the minimum nonce size

0115     /// \return The minimum nonce size recommended for the generator, in bytes

0116     /// \details The equivalent class constant is <tt>MINIMUM_NONCE</tt>. If a nonce is not

0117     ///  required then <tt>MINIMUM_NONCE</tt> is 0. <tt>Hash_DRBG</tt> does not require a

0118     ///  nonce, while <tt>HMAC_DRBG</tt> and <tt>CTR_DRBG</tt> require a nonce.

0119     virtual unsigned int MinNonceLength() const=0;
0120 
0121     /// \brief Provides the maximum nonce size

0122     /// \return The maximum nonce that can be consumed by the generator, in bytes

0123     /// \details The equivalent class constant is <tt>MAXIMUM_NONCE</tt>. <tt>MAXIMUM_NONCE</tt>

0124     ///  has been reduced from 2<sup>35</sup> to <tt>INT_MAX</tt> to fit the underlying C++ datatype.

0125     ///  If a nonce is not required then <tt>MINIMUM_NONCE</tt> is 0. <tt>Hash_DRBG</tt> does not

0126     ///  require a nonce, while <tt>HMAC_DRBG</tt> and <tt>CTR_DRBG</tt> require a nonce.

0127     virtual unsigned int MaxNonceLength() const=0;
0128 
0129     /// \brief Provides the maximum size of a request to GenerateBlock

0130     /// \return The maximum size of a request to GenerateBlock(), in bytes

0131     /// \details The equivalent class constant is <tt>MAXIMUM_BYTES_PER_REQUEST</tt>

0132     virtual unsigned int MaxBytesPerRequest() const=0;
0133 
0134     /// \brief Provides the maximum number of requests before a reseed

0135     /// \return The maximum number of requests before a reseed, in bytes

0136     /// \details The equivalent class constant is <tt>MAXIMUM_REQUESTS_BEFORE_RESEED</tt>.

0137     ///  <tt>MAXIMUM_REQUESTS_BEFORE_RESEED</tt> has been reduced from 2<sup>48</sup> to <tt>INT_MAX</tt>

0138     ///  to fit the underlying C++ datatype.

0139     virtual unsigned int MaxRequestBeforeReseed() const=0;
0140 
0141 protected:
0142     virtual void DRBG_Instantiate(const byte* entropy, size_t entropyLength,
0143         const byte* nonce, size_t nonceLength, const byte* personalization, size_t personalizationLength)=0;
0144 
0145     virtual void DRBG_Reseed(const byte* entropy, size_t entropyLength, const byte* additional, size_t additionaLength)=0;
0146 };
0147 
0148 // *************************************************************

0149 
0150 /// \tparam HASH NIST approved hash derived from HashTransformation

0151 /// \tparam STRENGTH security strength, in bytes

0152 /// \tparam SEEDLENGTH seed length, in bytes

0153 /// \brief Hash_DRBG from SP 800-90A Rev 1 (June 2015)

0154 /// \details The NIST Hash DRBG is instantiated with a number of parameters. Two of the parameters,

0155 ///  Security Strength and Seed Length, depend on the hash and are specified as template parameters.

0156 ///  The remaining parameters are included in the class. The parameters and their values are listed

0157 ///  in NIST SP 800-90A Rev. 1, Table 2: Definitions for Hash-Based DRBG Mechanisms (p.38).

0158 /// \details Some parameters have been reduce to fit C++ datatypes. For example, NIST allows upto

0159 ///  2<sup>48</sup> requests before a reseed. However, Hash_DRBG limits it to <tt>INT_MAX</tt> due

0160 ///  to the limited data range of an int.

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

0162 ///  with the same internal state.

0163 /// \sa <A HREF="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf">Recommendation

0164 ///  for Random Number Generation Using Deterministic Random Bit Generators, Rev 1 (June 2015)</A>

0165 /// \since Crypto++ 6.0

0166 template <typename HASH=SHA256, unsigned int STRENGTH=128/8, unsigned int SEEDLENGTH=440/8>
0167 class Hash_DRBG : public NIST_DRBG, public NotCopyable
0168 {
0169 public:
0170     CRYPTOPP_CONSTANT(SECURITY_STRENGTH=STRENGTH);
0171     CRYPTOPP_CONSTANT(SEED_LENGTH=SEEDLENGTH);
0172     CRYPTOPP_CONSTANT(MINIMUM_ENTROPY=STRENGTH);
0173     CRYPTOPP_CONSTANT(MINIMUM_NONCE=0);
0174     CRYPTOPP_CONSTANT(MINIMUM_ADDITIONAL=0);
0175     CRYPTOPP_CONSTANT(MINIMUM_PERSONALIZATION=0);
0176     CRYPTOPP_CONSTANT(MAXIMUM_ENTROPY=INT_MAX);
0177     CRYPTOPP_CONSTANT(MAXIMUM_NONCE=INT_MAX);
0178     CRYPTOPP_CONSTANT(MAXIMUM_ADDITIONAL=INT_MAX);
0179     CRYPTOPP_CONSTANT(MAXIMUM_PERSONALIZATION=INT_MAX);
0180     CRYPTOPP_CONSTANT(MAXIMUM_BYTES_PER_REQUEST=65536);
0181     CRYPTOPP_CONSTANT(MAXIMUM_REQUESTS_BEFORE_RESEED=INT_MAX);
0182 
0183     static std::string StaticAlgorithmName() { return std::string("Hash_DRBG(") + HASH::StaticAlgorithmName() + std::string(")"); }
0184 
0185     /// \brief Construct a Hash DRBG

0186     /// \param entropy the entropy to instantiate the generator

0187     /// \param entropyLength the size of the entropy buffer

0188     /// \param nonce additional input to instantiate the generator

0189     /// \param nonceLength the size of the nonce buffer

0190     /// \param personalization additional input to instantiate the generator

0191     /// \param personalizationLength the size of the personalization buffer

0192     /// \throw NIST_DRBG::Err if the generator is instantiated with insufficient entropy

0193     /// \details All NIST DRBGs must be instaniated with at least <tt>MINIMUM_ENTROPY</tt> bytes of entropy.

0194     ///  The byte array for <tt>entropy</tt> must meet <A HREF ="http://csrc.nist.gov/publications/PubsSPs.html">NIST

0195     ///  SP 800-90B or SP 800-90C</A> requirements.

0196     /// \details The <tt>nonce</tt> and <tt>personalization</tt> are optional byte arrays. If <tt>nonce</tt> is supplied,

0197     ///  then it should be at least <tt>MINIMUM_NONCE</tt> bytes of entropy.

0198     /// \details An example of instantiating a SHA256 generator is shown below.

0199     ///  The example provides more entropy than required for SHA256. The <tt>NonblockingRng</tt> meets the

0200     ///  requirements of <A HREF ="http://csrc.nist.gov/publications/PubsSPs.html">NIST SP 800-90B or SP 800-90C</A>.

0201     ///  RDRAND() and RDSEED() generators would work as well.

0202     /// <pre>

0203     ///   SecByteBlock entropy(48), result(128);

0204     ///   NonblockingRng prng;

0205     ///   RandomNumberSource rns(prng, entropy.size(), new ArraySink(entropy, entropy.size()));

0206     ///

0207     ///   Hash_DRBG<SHA256, 128/8, 440/8> drbg(entropy, 32, entropy+32, 16);

0208     ///   drbg.GenerateBlock(result, result.size());

0209     /// </pre>

0210     Hash_DRBG(const byte* entropy=NULLPTR, size_t entropyLength=STRENGTH, const byte* nonce=NULLPTR,
0211         size_t nonceLength=0, const byte* personalization=NULLPTR, size_t personalizationLength=0)
0212         : NIST_DRBG(), m_c(SEEDLENGTH), m_v(SEEDLENGTH), m_reseed(0)
0213     {
0214         if (m_c.data())  // GCC analyzer warning

0215             std::memset(m_c.data(), 0x00, m_c.size());
0216         if (m_v.data())  // GCC analyzer warning

0217             std::memset(m_v.data(), 0x00, m_v.size());
0218 
0219         if (entropy != NULLPTR && entropyLength != 0)
0220             DRBG_Instantiate(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength);
0221     }
0222 
0223     unsigned int SecurityStrength() const {return SECURITY_STRENGTH;}
0224     unsigned int SeedLength() const {return SEED_LENGTH;}
0225     unsigned int MinEntropyLength() const {return MINIMUM_ENTROPY;}
0226     unsigned int MaxEntropyLength() const {return MAXIMUM_ENTROPY;}
0227     unsigned int MinNonceLength() const {return MINIMUM_NONCE;}
0228     unsigned int MaxNonceLength() const {return MAXIMUM_NONCE;}
0229     unsigned int MaxBytesPerRequest() const {return MAXIMUM_BYTES_PER_REQUEST;}
0230     unsigned int MaxRequestBeforeReseed() const {return MAXIMUM_REQUESTS_BEFORE_RESEED;}
0231 
0232     void IncorporateEntropy(const byte *input, size_t length)
0233         {return DRBG_Reseed(input, length, NULLPTR, 0);}
0234 
0235     void IncorporateEntropy(const byte *entropy, size_t entropyLength, const byte* additional, size_t additionaLength)
0236         {return DRBG_Reseed(entropy, entropyLength, additional, additionaLength);}
0237 
0238     void GenerateBlock(byte *output, size_t size)
0239         {return Hash_Generate(NULLPTR, 0, output, size);}
0240 
0241     void GenerateBlock(const byte* additional, size_t additionaLength, byte *output, size_t size)
0242         {return Hash_Generate(additional, additionaLength, output, size);}
0243 
0244     std::string AlgorithmProvider() const
0245         {/*Hack*/HASH hash; return hash.AlgorithmProvider();}
0246 
0247 protected:
0248     // 10.1.1.2 Instantiation of Hash_DRBG (p.39)

0249     void DRBG_Instantiate(const byte* entropy, size_t entropyLength, const byte* nonce, size_t nonceLength,
0250         const byte* personalization, size_t personalizationLength);
0251 
0252     // 10.1.1.3 Reseeding a Hash_DRBG Instantiation (p.40)

0253     void DRBG_Reseed(const byte* entropy, size_t entropyLength, const byte* additional, size_t additionaLength);
0254 
0255     // 10.1.1.4 Generating Pseudorandom Bits Using Hash_DRBG (p.41)

0256     void Hash_Generate(const byte* additional, size_t additionaLength, byte *output, size_t size);
0257 
0258     // 10.3.1 Derivation Function Using a Hash Function (Hash_df) (p.49)

0259     void Hash_Update(const byte* input1, size_t inlen1, const byte* input2, size_t inlen2,
0260         const byte* input3, size_t inlen3, const byte* input4, size_t inlen4, byte* output, size_t outlen);
0261 
0262 private:
0263     HASH m_hash;
0264     SecByteBlock m_c, m_v, m_temp;
0265     word64 m_reseed;
0266 };
0267 
0268 // typedef Hash_DRBG<SHA1,   128/8, 440/8> Hash_SHA1_DRBG;

0269 // typedef Hash_DRBG<SHA256, 128/8, 440/8> Hash_SHA256_DRBG;

0270 // typedef Hash_DRBG<SHA384, 256/8, 888/8> Hash_SHA384_DRBG;

0271 // typedef Hash_DRBG<SHA512, 256/8, 888/8> Hash_SHA512_DRBG;

0272 
0273 // *************************************************************

0274 
0275 /// \tparam HASH NIST approved hash derived from HashTransformation

0276 /// \tparam STRENGTH security strength, in bytes

0277 /// \tparam SEEDLENGTH seed length, in bytes

0278 /// \brief HMAC_DRBG from SP 800-90A Rev 1 (June 2015)

0279 /// \details The NIST HMAC DRBG is instantiated with a number of parameters. Two of the parameters,

0280 ///  Security Strength and Seed Length, depend on the hash and are specified as template parameters.

0281 ///  The remaining parameters are included in the class. The parameters and their values are listed

0282 ///  in NIST SP 800-90A Rev. 1, Table 2: Definitions for Hash-Based DRBG Mechanisms (p.38).

0283 /// \details Some parameters have been reduce to fit C++ datatypes. For example, NIST allows upto 2<sup>48</sup> requests

0284 ///  before a reseed. However, HMAC_DRBG limits it to <tt>INT_MAX</tt> due to the limited data range of an int.

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

0286 ///  with the same internal state.

0287 /// \sa <A HREF="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf">Recommendation

0288 ///  for Random Number Generation Using Deterministic Random Bit Generators, Rev 1 (June 2015)</A>

0289 /// \since Crypto++ 6.0

0290 template <typename HASH=SHA256, unsigned int STRENGTH=128/8, unsigned int SEEDLENGTH=440/8>
0291 class HMAC_DRBG : public NIST_DRBG, public NotCopyable
0292 {
0293 public:
0294     CRYPTOPP_CONSTANT(SECURITY_STRENGTH=STRENGTH);
0295     CRYPTOPP_CONSTANT(SEED_LENGTH=SEEDLENGTH);
0296     CRYPTOPP_CONSTANT(MINIMUM_ENTROPY=STRENGTH);
0297     CRYPTOPP_CONSTANT(MINIMUM_NONCE=0);
0298     CRYPTOPP_CONSTANT(MINIMUM_ADDITIONAL=0);
0299     CRYPTOPP_CONSTANT(MINIMUM_PERSONALIZATION=0);
0300     CRYPTOPP_CONSTANT(MAXIMUM_ENTROPY=INT_MAX);
0301     CRYPTOPP_CONSTANT(MAXIMUM_NONCE=INT_MAX);
0302     CRYPTOPP_CONSTANT(MAXIMUM_ADDITIONAL=INT_MAX);
0303     CRYPTOPP_CONSTANT(MAXIMUM_PERSONALIZATION=INT_MAX);
0304     CRYPTOPP_CONSTANT(MAXIMUM_BYTES_PER_REQUEST=65536);
0305     CRYPTOPP_CONSTANT(MAXIMUM_REQUESTS_BEFORE_RESEED=INT_MAX);
0306 
0307     static std::string StaticAlgorithmName() { return std::string("HMAC_DRBG(") + HASH::StaticAlgorithmName() + std::string(")"); }
0308 
0309     /// \brief Construct a HMAC DRBG

0310     /// \param entropy the entropy to instantiate the generator

0311     /// \param entropyLength the size of the entropy buffer

0312     /// \param nonce additional input to instantiate the generator

0313     /// \param nonceLength the size of the nonce buffer

0314     /// \param personalization additional input to instantiate the generator

0315     /// \param personalizationLength the size of the personalization buffer

0316     /// \throw NIST_DRBG::Err if the generator is instantiated with insufficient entropy

0317     /// \details All NIST DRBGs must be instaniated with at least <tt>MINIMUM_ENTROPY</tt> bytes of entropy.

0318     ///  The byte array for <tt>entropy</tt> must meet <A HREF ="http://csrc.nist.gov/publications/PubsSPs.html">NIST

0319     ///  SP 800-90B or SP 800-90C</A> requirements.

0320     /// \details The <tt>nonce</tt> and <tt>personalization</tt> are optional byte arrays. If <tt>nonce</tt> is supplied,

0321     ///  then it should be at least <tt>MINIMUM_NONCE</tt> bytes of entropy.

0322     /// \details An example of instantiating a SHA256 generator is shown below.

0323     ///  The example provides more entropy than required for SHA256. The <tt>NonblockingRng</tt> meets the

0324     ///  requirements of <A HREF ="http://csrc.nist.gov/publications/PubsSPs.html">NIST SP 800-90B or SP 800-90C</A>.

0325     ///  RDRAND() and RDSEED() generators would work as well.

0326     /// <pre>

0327     ///   SecByteBlock entropy(48), result(128);

0328     ///   NonblockingRng prng;

0329     ///   RandomNumberSource rns(prng, entropy.size(), new ArraySink(entropy, entropy.size()));

0330     ///

0331     ///   HMAC_DRBG<SHA256, 128/8, 440/8> drbg(entropy, 32, entropy+32, 16);

0332     ///   drbg.GenerateBlock(result, result.size());

0333     /// </pre>

0334     HMAC_DRBG(const byte* entropy=NULLPTR, size_t entropyLength=STRENGTH, const byte* nonce=NULLPTR,
0335         size_t nonceLength=0, const byte* personalization=NULLPTR, size_t personalizationLength=0)
0336         : NIST_DRBG(), m_k(HASH::DIGESTSIZE), m_v(HASH::DIGESTSIZE), m_reseed(0)
0337     {
0338         if (m_k.data())  // GCC analyzer warning

0339             std::memset(m_k, 0x00, m_k.size());
0340         if (m_v.data())  // GCC analyzer warning

0341             std::memset(m_v, 0x00, m_v.size());
0342 
0343         if (entropy != NULLPTR && entropyLength != 0)
0344             DRBG_Instantiate(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength);
0345     }
0346 
0347     unsigned int SecurityStrength() const {return SECURITY_STRENGTH;}
0348     unsigned int SeedLength() const {return SEED_LENGTH;}
0349     unsigned int MinEntropyLength() const {return MINIMUM_ENTROPY;}
0350     unsigned int MaxEntropyLength() const {return MAXIMUM_ENTROPY;}
0351     unsigned int MinNonceLength() const {return MINIMUM_NONCE;}
0352     unsigned int MaxNonceLength() const {return MAXIMUM_NONCE;}
0353     unsigned int MaxBytesPerRequest() const {return MAXIMUM_BYTES_PER_REQUEST;}
0354     unsigned int MaxRequestBeforeReseed() const {return MAXIMUM_REQUESTS_BEFORE_RESEED;}
0355 
0356     void IncorporateEntropy(const byte *input, size_t length)
0357         {return DRBG_Reseed(input, length, NULLPTR, 0);}
0358 
0359     void IncorporateEntropy(const byte *entropy, size_t entropyLength, const byte* additional, size_t additionaLength)
0360         {return DRBG_Reseed(entropy, entropyLength, additional, additionaLength);}
0361 
0362     void GenerateBlock(byte *output, size_t size)
0363         {return HMAC_Generate(NULLPTR, 0, output, size);}
0364 
0365     void GenerateBlock(const byte* additional, size_t additionaLength, byte *output, size_t size)
0366         {return HMAC_Generate(additional, additionaLength, output, size);}
0367 
0368     std::string AlgorithmProvider() const
0369         {/*Hack*/HASH hash; return hash.AlgorithmProvider();}
0370 
0371 protected:
0372     // 10.1.2.3 Instantiation of HMAC_DRBG (p.45)

0373     void DRBG_Instantiate(const byte* entropy, size_t entropyLength, const byte* nonce, size_t nonceLength,
0374         const byte* personalization, size_t personalizationLength);
0375 
0376     // 10.1.2.4 Reseeding a HMAC_DRBG Instantiation (p.46)

0377     void DRBG_Reseed(const byte* entropy, size_t entropyLength, const byte* additional, size_t additionaLength);
0378 
0379     // 10.1.2.5 Generating Pseudorandom Bits Using HMAC_DRBG (p.46)

0380     void HMAC_Generate(const byte* additional, size_t additionaLength, byte *output, size_t size);
0381 
0382     // 10.1.2.2 Derivation Function Using a HMAC Function (HMAC_Update) (p.44)

0383     void HMAC_Update(const byte* input1, size_t inlen1, const byte* input2, size_t inlen2, const byte* input3, size_t inlen3);
0384 
0385 private:
0386     HMAC<HASH> m_hmac;
0387     SecByteBlock m_k, m_v;
0388     word64 m_reseed;
0389 };
0390 
0391 // typedef HMAC_DRBG<SHA1,   128/8, 440/8> HMAC_SHA1_DRBG;

0392 // typedef HMAC_DRBG<SHA256, 128/8, 440/8> HMAC_SHA256_DRBG;

0393 // typedef HMAC_DRBG<SHA384, 256/8, 888/8> HMAC_SHA384_DRBG;

0394 // typedef HMAC_DRBG<SHA512, 256/8, 888/8> HMAC_SHA512_DRBG;

0395 
0396 // *************************************************************

0397 
0398 // 10.1.1.2 Instantiation of Hash_DRBG (p.39)

0399 template <typename HASH, unsigned int STRENGTH, unsigned int SEEDLENGTH>
0400 void Hash_DRBG<HASH, STRENGTH, SEEDLENGTH>::DRBG_Instantiate(const byte* entropy, size_t entropyLength, const byte* nonce, size_t nonceLength,
0401     const byte* personalization, size_t personalizationLength)
0402 {
0403     //  SP 800-90A, 8.6.3: The entropy input shall have entropy that is equal to or greater than the security

0404     //  strength of the instantiation. Additional entropy may be provided in the nonce or the optional

0405     //  personalization string during instantiation, or in the additional input during reseeding and generation,

0406     //  but this is not required and does not increase the "official" security strength of the DRBG

0407     //  instantiation that is recorded in the internal state.

0408     CRYPTOPP_ASSERT(entropyLength >= MINIMUM_ENTROPY);
0409     if (entropyLength < MINIMUM_ENTROPY)
0410         throw NIST_DRBG::Err("Hash_DRBG", "Insufficient entropy during instantiate");
0411 
0412     // SP 800-90A, Section 9, says we should throw if we have too much entropy, too large a nonce,

0413     // or too large a persoanlization string. We warn in Debug builds, but do nothing in Release builds.

0414     CRYPTOPP_ASSERT(entropyLength <= MAXIMUM_ENTROPY);
0415     CRYPTOPP_ASSERT(nonceLength <= MAXIMUM_NONCE);
0416     CRYPTOPP_ASSERT(personalizationLength <= MAXIMUM_PERSONALIZATION);
0417 
0418     const byte zero = 0;
0419     SecByteBlock t1(SEEDLENGTH), t2(SEEDLENGTH);
0420     Hash_Update(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength, NULLPTR, 0, t1, t1.size());
0421     Hash_Update(&zero, 1, t1, t1.size(), NULLPTR, 0, NULLPTR, 0, t2, t2.size());
0422 
0423     m_v.swap(t1); m_c.swap(t2);
0424     m_reseed = 1;
0425 }
0426 
0427 // 10.1.1.3 Reseeding a Hash_DRBG Instantiation (p.40)

0428 template <typename HASH, unsigned int STRENGTH, unsigned int SEEDLENGTH>
0429 void Hash_DRBG<HASH, STRENGTH, SEEDLENGTH>::DRBG_Reseed(const byte* entropy, size_t entropyLength, const byte* additional, size_t additionaLength)
0430 {
0431     //  SP 800-90A, 8.6.3: The entropy input shall have entropy that is equal to or greater than the security

0432     //  strength of the instantiation. Additional entropy may be provided in the nonce or the optional

0433     //  personalization string during instantiation, or in the additional input during reseeding and generation,

0434     //  but this is not required and does not increase the "official" security strength of the DRBG

0435     //  instantiation that is recorded in the internal state..

0436     CRYPTOPP_ASSERT(entropyLength >= MINIMUM_ENTROPY);
0437     if (entropyLength < MINIMUM_ENTROPY)
0438         throw NIST_DRBG::Err("Hash_DRBG", "Insufficient entropy during reseed");
0439 
0440     // SP 800-90A, Section 9, says we should throw if we have too much entropy, too large a nonce,

0441     // or too large a persoanlization string. We warn in Debug builds, but do nothing in Release builds.

0442     CRYPTOPP_ASSERT(entropyLength <= MAXIMUM_ENTROPY);
0443     CRYPTOPP_ASSERT(additionaLength <= MAXIMUM_ADDITIONAL);
0444 
0445     const byte zero = 0, one = 1;
0446     SecByteBlock t1(SEEDLENGTH), t2(SEEDLENGTH);
0447     Hash_Update(&one, 1, m_v, m_v.size(), entropy, entropyLength, additional, additionaLength, t1, t1.size());
0448     Hash_Update(&zero, 1, t1, t1.size(), NULLPTR, 0, NULLPTR, 0, t2, t2.size());
0449 
0450     m_v.swap(t1); m_c.swap(t2);
0451     m_reseed = 1;
0452 }
0453 
0454 // 10.1.1.4 Generating Pseudorandom Bits Using Hash_DRBG (p.41)

0455 template <typename HASH, unsigned int STRENGTH, unsigned int SEEDLENGTH>
0456 void Hash_DRBG<HASH, STRENGTH, SEEDLENGTH>::Hash_Generate(const byte* additional, size_t additionaLength, byte *output, size_t size)
0457 {
0458     // Step 1

0459     if (static_cast<word64>(m_reseed) >= static_cast<word64>(MaxRequestBeforeReseed()))
0460         throw NIST_DRBG::Err("Hash_DRBG", "Reseed required");
0461 
0462     if (size > MaxBytesPerRequest())
0463         throw NIST_DRBG::Err("Hash_DRBG", "Request size exceeds limit");
0464 
0465     // SP 800-90A, Section 9, says we should throw if we have too much entropy, too large a nonce,

0466     // or too large a persoanlization string. We warn in Debug builds, but do nothing in Release builds.

0467     CRYPTOPP_ASSERT(additionaLength <= MAXIMUM_ADDITIONAL);
0468 
0469     // Step 2

0470     if (additional && additionaLength)
0471     {
0472         const byte two = 2;
0473         m_temp.New(HASH::DIGESTSIZE);
0474 
0475         m_hash.Update(&two, 1);
0476         m_hash.Update(m_v, m_v.size());
0477         m_hash.Update(additional, additionaLength);
0478         m_hash.Final(m_temp);
0479 
0480         CRYPTOPP_ASSERT(SEEDLENGTH >= HASH::DIGESTSIZE);
0481         int carry=0, j=HASH::DIGESTSIZE-1, i=SEEDLENGTH-1;
0482         while (j>=0)
0483         {
0484             carry = m_v[i] + m_temp[j] + carry;
0485             m_v[i] = static_cast<byte>(carry);
0486             i--; j--; carry >>= 8;
0487         }
0488         while (i>=0)
0489         {
0490             carry = m_v[i] + carry;
0491             m_v[i] = static_cast<byte>(carry);
0492             i--; carry >>= 8;
0493         }
0494     }
0495 
0496     // Step 3

0497     {
0498         m_temp.Assign(m_v);
0499         while (size)
0500         {
0501             m_hash.Update(m_temp, m_temp.size());
0502             size_t count = STDMIN(size, (size_t)HASH::DIGESTSIZE);
0503             m_hash.TruncatedFinal(output, count);
0504 
0505             IncrementCounterByOne(m_temp, static_cast<unsigned int>(m_temp.size()));
0506             size -= count; output += count;
0507         }
0508     }
0509 
0510     // Steps 4-7

0511     {
0512         const byte three = 3;
0513         m_temp.New(HASH::DIGESTSIZE);
0514 
0515         m_hash.Update(&three, 1);
0516         m_hash.Update(m_v, m_v.size());
0517         m_hash.Final(m_temp);
0518 
0519         CRYPTOPP_ASSERT(SEEDLENGTH >= HASH::DIGESTSIZE);
0520         CRYPTOPP_ASSERT(HASH::DIGESTSIZE >= sizeof(m_reseed));
0521         int carry=0, k=sizeof(m_reseed)-1, j=HASH::DIGESTSIZE-1, i=SEEDLENGTH-1;
0522 
0523         while (k>=0)
0524         {
0525             carry = m_v[i] + m_c[i] + m_temp[j] + GetByte<word64>(BIG_ENDIAN_ORDER, m_reseed, k) + carry;
0526             m_v[i] = static_cast<byte>(carry);
0527             i--; j--; k--; carry >>= 8;
0528         }
0529 
0530         while (j>=0)
0531         {
0532             carry = m_v[i] + m_c[i] + m_temp[j] + carry;
0533             m_v[i] = static_cast<byte>(carry);
0534             i--; j--; carry >>= 8;
0535         }
0536 
0537         while (i>=0)
0538         {
0539             carry = m_v[i] + m_c[i] + carry;
0540             m_v[i] = static_cast<byte>(carry);
0541             i--; carry >>= 8;
0542         }
0543     }
0544 
0545     m_reseed++;
0546 }
0547 
0548 // 10.3.1 Derivation Function Using a Hash Function (Hash_df) (p.49)

0549 template <typename HASH, unsigned int STRENGTH, unsigned int SEEDLENGTH>
0550 void Hash_DRBG<HASH, STRENGTH, SEEDLENGTH>::Hash_Update(const byte* input1, size_t inlen1, const byte* input2, size_t inlen2,
0551     const byte* input3, size_t inlen3, const byte* input4, size_t inlen4, byte* output, size_t outlen)
0552 {
0553     byte counter = 1;
0554     word32 bits = ConditionalByteReverse(BIG_ENDIAN_ORDER, static_cast<word32>(outlen*8));
0555 
0556     while (outlen)
0557     {
0558         m_hash.Update(&counter, 1);
0559         m_hash.Update(reinterpret_cast<const byte*>(&bits), 4);
0560 
0561         if (input1 && inlen1)
0562             m_hash.Update(input1, inlen1);
0563         if (input2 && inlen2)
0564             m_hash.Update(input2, inlen2);
0565         if (input3 && inlen3)
0566             m_hash.Update(input3, inlen3);
0567         if (input4 && inlen4)
0568             m_hash.Update(input4, inlen4);
0569 
0570         size_t count = STDMIN(outlen, (size_t)HASH::DIGESTSIZE);
0571         m_hash.TruncatedFinal(output, count);
0572 
0573         output += count; outlen -= count;
0574         counter++;
0575     }
0576 }
0577 
0578 // *************************************************************

0579 
0580 // 10.1.2.3 Instantiation of HMAC_DRBG (p.45)

0581 template <typename HASH, unsigned int STRENGTH, unsigned int SEEDLENGTH>
0582 void HMAC_DRBG<HASH, STRENGTH, SEEDLENGTH>::DRBG_Instantiate(const byte* entropy, size_t entropyLength, const byte* nonce, size_t nonceLength,
0583     const byte* personalization, size_t personalizationLength)
0584 {
0585     //  SP 800-90A, 8.6.3: The entropy input shall have entropy that is equal to or greater than the security

0586     //  strength of the instantiation. Additional entropy may be provided in the nonce or the optional

0587     //  personalization string during instantiation, or in the additional input during reseeding and generation,

0588     //  but this is not required and does not increase the "official" security strength of the DRBG

0589     //  instantiation that is recorded in the internal state.

0590     CRYPTOPP_ASSERT(entropyLength >= MINIMUM_ENTROPY);
0591     if (entropyLength < MINIMUM_ENTROPY)
0592         throw NIST_DRBG::Err("HMAC_DRBG", "Insufficient entropy during instantiate");
0593 
0594     // SP 800-90A, Section 9, says we should throw if we have too much entropy, too large a nonce,

0595     // or too large a persoanlization string. We warn in Debug builds, but do nothing in Release builds.

0596     CRYPTOPP_ASSERT(entropyLength <= MAXIMUM_ENTROPY);
0597     CRYPTOPP_ASSERT(nonceLength <= MAXIMUM_NONCE);
0598     CRYPTOPP_ASSERT(personalizationLength <= MAXIMUM_PERSONALIZATION);
0599 
0600     std::fill(m_k.begin(), m_k.begin()+m_k.size(), byte(0));
0601     std::fill(m_v.begin(), m_v.begin()+m_v.size(), byte(1));
0602 
0603     HMAC_Update(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength);
0604     m_reseed = 1;
0605 }
0606 
0607 // 10.1.2.4 Reseeding a HMAC_DRBG Instantiation (p.46)

0608 template <typename HASH, unsigned int STRENGTH, unsigned int SEEDLENGTH>
0609 void HMAC_DRBG<HASH, STRENGTH, SEEDLENGTH>::DRBG_Reseed(const byte* entropy, size_t entropyLength, const byte* additional, size_t additionaLength)
0610 {
0611     //  SP 800-90A, 8.6.3: The entropy input shall have entropy that is equal to or greater than the security

0612     //  strength of the instantiation. Additional entropy may be provided in the nonce or the optional

0613     //  personalization string during instantiation, or in the additional input during reseeding and generation,

0614     //  but this is not required and does not increase the "official" security strength of the DRBG

0615     //  instantiation that is recorded in the internal state..

0616     CRYPTOPP_ASSERT(entropyLength >= MINIMUM_ENTROPY);
0617     if (entropyLength < MINIMUM_ENTROPY)
0618         throw NIST_DRBG::Err("HMAC_DRBG", "Insufficient entropy during reseed");
0619 
0620     // SP 800-90A, Section 9, says we should throw if we have too much entropy, too large a nonce,

0621     // or too large a persoanlization string. We warn in Debug builds, but do nothing in Release builds.

0622     CRYPTOPP_ASSERT(entropyLength <= MAXIMUM_ENTROPY);
0623     CRYPTOPP_ASSERT(additionaLength <= MAXIMUM_ADDITIONAL);
0624 
0625     HMAC_Update(entropy, entropyLength, additional, additionaLength, NULLPTR, 0);
0626     m_reseed = 1;
0627 }
0628 
0629 // 10.1.2.5 Generating Pseudorandom Bits Using HMAC_DRBG (p.46)

0630 template <typename HASH, unsigned int STRENGTH, unsigned int SEEDLENGTH>
0631 void HMAC_DRBG<HASH, STRENGTH, SEEDLENGTH>::HMAC_Generate(const byte* additional, size_t additionaLength, byte *output, size_t size)
0632 {
0633     // Step 1

0634     if (static_cast<word64>(m_reseed) >= static_cast<word64>(MaxRequestBeforeReseed()))
0635         throw NIST_DRBG::Err("HMAC_DRBG", "Reseed required");
0636 
0637     if (size > MaxBytesPerRequest())
0638         throw NIST_DRBG::Err("HMAC_DRBG", "Request size exceeds limit");
0639 
0640     // SP 800-90A, Section 9, says we should throw if we have too much entropy, too large a nonce,

0641     // or too large a persoanlization string. We warn in Debug builds, but do nothing in Release builds.

0642     CRYPTOPP_ASSERT(additionaLength <= MAXIMUM_ADDITIONAL);
0643 
0644     // Step 2

0645     if (additional && additionaLength)
0646         HMAC_Update(additional, additionaLength, NULLPTR, 0, NULLPTR, 0);
0647 
0648     // Step 3

0649     m_hmac.SetKey(m_k, m_k.size());
0650 
0651     while (size)
0652     {
0653         m_hmac.Update(m_v, m_v.size());
0654         m_hmac.TruncatedFinal(m_v, m_v.size());
0655 
0656         size_t count = STDMIN(size, (size_t)HASH::DIGESTSIZE);
0657         std::memcpy(output, m_v, count);
0658         size -= count; output += count;
0659     }
0660 
0661     HMAC_Update(additional, additionaLength, NULLPTR, 0, NULLPTR, 0);
0662     m_reseed++;
0663 }
0664 
0665 // 10.1.2.2 Derivation Function Using a HMAC Function (HMAC_Update) (p.44)

0666 template <typename HASH, unsigned int STRENGTH, unsigned int SEEDLENGTH>
0667 void HMAC_DRBG<HASH, STRENGTH, SEEDLENGTH>::HMAC_Update(const byte* input1, size_t inlen1, const byte* input2, size_t inlen2, const byte* input3, size_t inlen3)
0668 {
0669     const byte zero = 0, one = 1;
0670 
0671     // Step 1

0672     m_hmac.SetKey(m_k, m_k.size());
0673     m_hmac.Update(m_v, m_v.size());
0674     m_hmac.Update(&zero, 1);
0675 
0676     if (input1 && inlen1)
0677         m_hmac.Update(input1, inlen1);
0678     if (input2 && inlen2)
0679         m_hmac.Update(input2, inlen2);
0680     if (input3 && inlen3)
0681         m_hmac.Update(input3, inlen3);
0682 
0683     m_hmac.TruncatedFinal(m_k, m_k.size());
0684 
0685     // Step 2

0686     m_hmac.SetKey(m_k, m_k.size());
0687     m_hmac.Update(m_v, m_v.size());
0688 
0689     m_hmac.TruncatedFinal(m_v, m_v.size());
0690 
0691     // Step 3

0692     if ((inlen1 | inlen2 | inlen3) == 0)
0693         return;
0694 
0695     // Step 4

0696     m_hmac.SetKey(m_k, m_k.size());
0697     m_hmac.Update(m_v, m_v.size());
0698     m_hmac.Update(&one, 1);
0699 
0700     if (input1 && inlen1)
0701         m_hmac.Update(input1, inlen1);
0702     if (input2 && inlen2)
0703         m_hmac.Update(input2, inlen2);
0704     if (input3 && inlen3)
0705         m_hmac.Update(input3, inlen3);
0706 
0707     m_hmac.TruncatedFinal(m_k, m_k.size());
0708 
0709     // Step 5

0710     m_hmac.SetKey(m_k, m_k.size());
0711     m_hmac.Update(m_v, m_v.size());
0712 
0713     m_hmac.TruncatedFinal(m_v, m_v.size());
0714 }
0715 
0716 NAMESPACE_END
0717 
0718 #endif  // CRYPTOPP_NIST_DRBG_H