class Hash_DRBG : public NIST_DRBG
@@ -65,20 +140,56 @@ public:
CRYPTOPP_CONSTANT(SECURITY_STRENGTH=STRENGTH)
CRYPTOPP_CONSTANT(SEED_LENGTH=SEEDLENGTH)
CRYPTOPP_CONSTANT(MINIMUM_ENTROPY=STRENGTH)
+ CRYPTOPP_CONSTANT(MINIMUM_NONCE=STRENGTH/2)
+ CRYPTOPP_CONSTANT(MINIMUM_ADDITIONAL=0)
+ CRYPTOPP_CONSTANT(MINIMUM_PERSONALIZATION=0)
+ CRYPTOPP_CONSTANT(MAXIMUM_ENTROPY=UINT_MAX)
+ CRYPTOPP_CONSTANT(MAXIMUM_NONCE=UINT_MAX)
+ CRYPTOPP_CONSTANT(MAXIMUM_ADDITIONAL=UINT_MAX)
+ CRYPTOPP_CONSTANT(MAXIMUM_PERSONALIZATION=UINT_MAX)
+ CRYPTOPP_CONSTANT(MAXIMUM_BYTES_PER_REQUEST=65536)
+ CRYPTOPP_CONSTANT(MAXIMUM_REQUESTS_BEFORE_RESEED=UINT_MAX)
+ //! \brief Construct a Hash DRBG
+ //! \param entropy the entropy to instantiate the generator
+ //! \param entropyLength the size of the entropy buffer
+ //! \param nonce additional entropy to instantiate the generator
+ //! \param nonceLength the size of the nonce buffer
+ //! \param personalization additional entropy to instantiate the generator
+ //! \param personalizationLength the size of the additional buffer
+ //! \details All NIST DRBGs must be instaniated with at least MINIMUM_ENTROPY bytes of entropy. The byte array for entropy must meet NIST
+ //! SP 800-90B requirements.
+ //! \details The nonce and personalization are optional byte arrays. If nonce is supplied, then it should include MINIMUM_NONCE bytes of entropy.
+ //! \details NIST instantiation requirements demand the generator is constructed with at least MINIMUM_ENTROPY entropy.
+ //! The generator has the same requirements during reseed operations.
+ //! \details An example of instantiating a SHA256 generator is shown below.
+ //! The example provides more entropy than required for SHA256. The NonblockingRng meets the
+ //! requirements of NIST SP 800-90B.
+ //! RDRAND() and RDSEED() generators would work as well.
+ //!
+ //! SecByteBlock entropy(48), result(128);
+ //! NonblockingRng prng;
+ //! RandomNumberSource rns(prng, entropy.size(), new ArraySink(entropy, entropy.size()));
+ //!
+ //! Hash_DRBG drbg(entropy, 32, entropy+32, 16);
+ //! drbg.GenerateBlock(result, result.size());
+ //!
Hash_DRBG(const byte* entropy, size_t entropyLength=STRENGTH, const byte* nonce=NULL,
- size_t nonceLength=0, const byte* persoanlization=NULL, size_t persoanlizationLength=0)
+ size_t nonceLength=0, const byte* personalization=NULL, size_t personalizationLength=0)
: NIST_DRBG(), m_c(SEEDLENGTH), m_v(SEEDLENGTH)
{
- DRBG_Instantiate(entropy, entropyLength, nonce, nonceLength, persoanlization, persoanlizationLength);
+ CRYPTOPP_ASSERT(entropyLength + nonceLength/2 >= GetMinEntropy());
+ DRBG_Instantiate(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength);
}
unsigned int GetSecurityStrength() const {return SECURITY_STRENGTH;}
unsigned int GetSeedLength() const {return SEED_LENGTH;}
- unsigned int GetMinEntropy() const {return SECURITY_STRENGTH;}
- unsigned int GetMaxEntropy() const {return (unsigned int)STDMIN((word64)UINT_MAX, W64LIT(4294967296));}
- unsigned int GetMaxRequest() const {return 65536;} // 2^16 bytes per request
- unsigned int GetMaxReseed() const {return (unsigned int)STDMIN((word64)UINT_MAX, W64LIT(35184372088832));}
+ unsigned int GetMinEntropy() const {return MINIMUM_ENTROPY;}
+ unsigned int GetMaxEntropy() const {return static_cast(MAXIMUM_ENTROPY);}
+ unsigned int GetMinNonce() const {return MINIMUM_NONCE;}
+ unsigned int GetMaxNonce() const {return static_cast(MAXIMUM_NONCE);}
+ unsigned int GetMaxBytesPerRequest() const {return MAXIMUM_BYTES_PER_REQUEST;} // 2^16 bytes per request
+ unsigned int GetMaxRequestBeforeReseed() const {return static_cast(MAXIMUM_REQUESTS_BEFORE_RESEED);}
void IncorporateEntropy(const byte *input, size_t length)
{return DRBG_Reseed(input, length, NULL, 0);}
@@ -123,13 +234,13 @@ protected:
// 10.1.1.2 Instantiation of Hash_DRBG (p.48)
void DRBG_Instantiate(const byte* entropy, size_t entropyLength, const byte* nonce, size_t nonceLength,
- const byte* persoanlization, size_t persoanlizationLength)
+ const byte* personalization, size_t personalizationLength)
{
- CRYPTOPP_ASSERT(entropyLength+nonceLength+persoanlizationLength >= GetMinEntropy());
+ CRYPTOPP_ASSERT(entropyLength+nonceLength+personalizationLength >= GetMinEntropy());
const byte zero = 0;
SecByteBlock t1(SEEDLENGTH), t2(SEEDLENGTH);
- Hash_df(entropy, entropyLength, nonce, nonceLength, persoanlization, persoanlizationLength, NULL, 0, t1, t1.size());
+ Hash_df(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength, NULL, 0, t1, t1.size());
Hash_df(&zero, 1, t1, t1.size(), NULL, 0, NULL, 0, t2, t2.size());
m_v.swap(t1); m_c.swap(t2);
@@ -152,7 +263,7 @@ protected:
void Hash_Generate(const byte* additional, size_t additionaLength, byte *output, size_t size)
{
// Step 1
- if (static_cast(m_reseed) >= static_cast(GetMaxReseed()))
+ if (static_cast(m_reseed) >= static_cast(GetMaxRequestBeforeReseed()))
throw Exception(Exception::OTHER_ERROR, "Reseed required");
// Step 2
@@ -242,4 +353,5 @@ private:
NAMESPACE_END
-#endif // CRYPTOPP_NIST_DETERMINISTIC_RANDOM_BIT_GENERATORS_H
+#endif // CRYPTOPP_NIST_DRBG_H
+