Add documentation for NIST_DRBG base class and Hash_DRBG generator
parent
5c932fcc3b
commit
ef185fa013
164
drbg.h
164
drbg.h
|
|
@ -2,46 +2,118 @@
|
||||||
// Copyright assigned to Crypto++ project.
|
// Copyright assigned to Crypto++ project.
|
||||||
|
|
||||||
//! \file drbg.h
|
//! \file drbg.h
|
||||||
//! \brief Classes for NIST DRBGs from 800-90A Rev 1 (June 2015)
|
//! \brief Classes for NIST DRBGs from SP 800-90A
|
||||||
//! \sa <A HREF="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf">Recommendation
|
//! \sa <A HREF="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf">Recommendation
|
||||||
//! for Random Number Generation Using Deterministic Random Bit Generators</A>
|
//! for Random Number Generation Using Deterministic Random Bit Generators,
|
||||||
|
//! Rev 1 (June 2015)</A>
|
||||||
//! \since Crypto++ 5.7
|
//! \since Crypto++ 5.7
|
||||||
|
|
||||||
#ifndef CRYPTOPP_NIST_DETERMINISTIC_RANDOM_BIT_GENERATORS_H
|
#ifndef CRYPTOPP_NIST_DRBG_H
|
||||||
#define CRYPTOPP_NIST_DETERMINISTIC_RANDOM_BIT_GENERATORS_H
|
#define CRYPTOPP_NIST_DRBG_H
|
||||||
|
|
||||||
#include "cryptlib.h"
|
#include "cryptlib.h"
|
||||||
#include "secblock.h"
|
#include "secblock.h"
|
||||||
|
|
||||||
NAMESPACE_BEGIN(CryptoPP)
|
NAMESPACE_BEGIN(CryptoPP)
|
||||||
|
|
||||||
|
//! \class NIST_DRBG
|
||||||
|
//! \brief Interface for NIST DRBGs from SP 800-90A
|
||||||
|
//! \details NIST_DRBG is the base class interface for NIST DRBGs from SP 800-90A Rev 1 (June 2015)
|
||||||
|
//! \sa <A HREF="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf">Recommendation
|
||||||
|
//! for Random Number Generation Using Deterministic Random Bit Generators,
|
||||||
|
//! Rev 1 (June 2015)</A>
|
||||||
|
//! \since Crypto++ 5.7
|
||||||
class NIST_DRBG : public RandomNumberGenerator
|
class NIST_DRBG : public RandomNumberGenerator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~NIST_DRBG() {}
|
virtual ~NIST_DRBG() {}
|
||||||
|
|
||||||
// RandomNumberGenerator
|
//! \brief Determines if a generator can accept additional entropy
|
||||||
|
//! \return true
|
||||||
|
//! \details All NIST_DRBG return true
|
||||||
virtual bool CanIncorporateEntropy() const {return true;}
|
virtual bool CanIncorporateEntropy() const {return true;}
|
||||||
// RandomNumberGenerator
|
|
||||||
|
//! \brief Update RNG state with additional unpredictable values
|
||||||
|
//! \param input the entropy to add to the generator
|
||||||
|
//! \param length the size of the input buffer
|
||||||
|
//! \details NIST instantiation and reseed requirements demand the generator is constructed with at least <tt>MINIMUM_ENTROPY</tt> entropy.
|
||||||
|
//! The byte array for <tt>input</tt> must meet <A HREF ="http://csrc.nist.gov/publications/PubsSPs.html">NIST
|
||||||
|
//! SP 800-90B</A> requirements.
|
||||||
virtual void IncorporateEntropy(const byte *input, size_t length)=0;
|
virtual void IncorporateEntropy(const byte *input, size_t length)=0;
|
||||||
// RandomNumberGenerator NIST overload
|
|
||||||
|
//! \brief Update RNG state with additional unpredictable values
|
||||||
|
//! \param entropy the entropy to add to the generator
|
||||||
|
//! \param entropyLength the size of the input buffer
|
||||||
|
//! \param additional additional entropy to add to the generator
|
||||||
|
//! \param additionaLength the size of the additional entropy buffer
|
||||||
|
//! \details IncorporateEntropy() is an overload provided to match NIST requirements. NIST instantiation and
|
||||||
|
//! reseed requirements demand the generator is constructed with at least <tt>MINIMUM_ENTROPY</tt> entropy.
|
||||||
|
//! The byte array for <tt>input</tt> must meet <A HREF ="http://csrc.nist.gov/publications/PubsSPs.html">NIST
|
||||||
|
//! SP 800-90B</A> requirements.
|
||||||
virtual void IncorporateEntropy(const byte *entropy, size_t entropyLength, const byte* additional, size_t additionaLength)=0;
|
virtual void IncorporateEntropy(const byte *entropy, size_t entropyLength, const byte* additional, size_t additionaLength)=0;
|
||||||
// RandomNumberGenerator
|
|
||||||
|
//! \brief Generate random array of bytes
|
||||||
|
//! \param output the byte buffer
|
||||||
|
//! \param size the length of the buffer, in bytes
|
||||||
virtual void GenerateBlock(byte *output, size_t size)=0;
|
virtual void GenerateBlock(byte *output, size_t size)=0;
|
||||||
// RandomNumberGenerator NIST overload
|
|
||||||
|
//! \brief Generate random array of bytes
|
||||||
|
//! \param additional additional entropy to add to the generator
|
||||||
|
//! \param additionaLength the size of the additional entropy buffer
|
||||||
|
//! \param output the byte buffer
|
||||||
|
//! \param size the length of the buffer, in bytes
|
||||||
|
//! \details GenerateBlock() is an overload provided to match NIST requirements. The byte array for <tt>additional</tt> is optional. If present
|
||||||
|
//! the additional randomness is mixed before generating the output bytes.
|
||||||
virtual void GenerateBlock(const byte* additional, size_t additionaLength, byte *output, size_t size)=0;
|
virtual void GenerateBlock(const byte* additional, size_t additionaLength, byte *output, size_t size)=0;
|
||||||
|
|
||||||
|
//! \brief Provides the security strength
|
||||||
|
//! \returns The security strength of the generator, in bytes
|
||||||
|
//! \details The equivalent class constant is <tt>SECURITY_STRENGTH</tt>
|
||||||
virtual unsigned int GetSecurityStrength() const=0;
|
virtual unsigned int GetSecurityStrength() const=0;
|
||||||
|
|
||||||
|
//! \brief Provides the seed length
|
||||||
|
//! \returns The seed size of the generator, in bytes
|
||||||
|
//! \details The equivalent class constant is <tt>SEED_LENGTH</tt>. The size is
|
||||||
|
//! used to maintain internal state of <tt>V</tt> and <tt>C</tt>.
|
||||||
virtual unsigned int GetSeedLength() const=0;
|
virtual unsigned int GetSeedLength() const=0;
|
||||||
|
|
||||||
|
//! \brief Provides the minimum entropy
|
||||||
|
//! \returns The minimum entropy size required by the generator, in bytes
|
||||||
|
//! \details The equivalent class constant is <tt>MINIMUM_ENTROPY</tt>. All NIST DRBGs must be instaniated with at least
|
||||||
|
//! <tt>MINIMUM_ENTROPY</tt> bytes of entropy. The bytes must meet <A
|
||||||
|
//! HREF="http://csrc.nist.gov/publications/PubsSPs.html">NIST SP 800-90B</A> requirements.
|
||||||
virtual unsigned int GetMinEntropy() const=0;
|
virtual unsigned int GetMinEntropy() const=0;
|
||||||
|
|
||||||
|
//! \brief Provides the maximum entropy
|
||||||
|
//! \returns The maximum entropy size that can be consumed by the generator, in bytes
|
||||||
|
//! \details The equivalent class constant is <tt>MAXIMUM_ENTROPY</tt>. <tt>MAXIMUM_ENTROPY</tt> has been reduced
|
||||||
|
//! from 2<sup>35</sup> to <tt>UINT_MAX</tt> to fit the C++ unsigned int datatype.
|
||||||
virtual unsigned int GetMaxEntropy() const=0;
|
virtual unsigned int GetMaxEntropy() const=0;
|
||||||
virtual unsigned int GetMaxRequest() const=0;
|
|
||||||
virtual unsigned int GetMaxReseed() const=0;
|
//! \brief Provides the minimum nonce
|
||||||
|
//! \returns The minimum nonce size recommended for the generator, in bytes
|
||||||
|
//! \details The equivalent class constant is <tt>MINIMUM_NONCE</tt>. The nonce is optional but recommended
|
||||||
|
virtual unsigned int GetMinNonce() const=0;
|
||||||
|
|
||||||
|
//! \brief Provides the maximum nonce
|
||||||
|
//! \returns The maximum nonce that can be consumed by the generator, in bytes
|
||||||
|
//! \details The equivalent class constant is <tt>MAXIMUM_NONCE</tt>. The nonce is optional but recommended.
|
||||||
|
//! <tt>MAXIMUM_NONCE</tt> has been reduced from 2<sup>35</sup> to <tt>UINT_MAX</tt> to fit the C++ unsigned int datatype.
|
||||||
|
virtual unsigned int GetMaxNonce() const=0;
|
||||||
|
|
||||||
|
//! \brief Provides the maximum size of a request to GenerateBlock
|
||||||
|
//! \returns The the maximum size of a request to GenerateBlock(), in bytes
|
||||||
|
//! \details The equivalent class constant is <tt>MAXIMUM_BYTES_PER_REQUEST</tt>
|
||||||
|
virtual unsigned int GetMaxBytesPerRequest() const=0;
|
||||||
|
|
||||||
|
//! \brief Provides the maximum number of requests before a reseed
|
||||||
|
//! \returns The the maximum number of requests before a reseed, in bytes
|
||||||
|
//! \details The equivalent class constant is <tt>MAXIMUM_REQUESTS_BEFORE_RESEED</tt>
|
||||||
|
virtual unsigned int GetMaxRequestBeforeReseed() const=0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual void DRBG_Instantiate(const byte* entropy, size_t entropyLength,
|
virtual void DRBG_Instantiate(const byte* entropy, size_t entropyLength,
|
||||||
const byte* nonce, size_t nonceLength, const byte* persoanlization, size_t personalizationLength)=0;
|
const byte* nonce, size_t nonceLength, const byte* personalization, size_t personalizationLength)=0;
|
||||||
|
|
||||||
virtual void DRBG_Reseed(const byte* entropy, size_t entropyLength, const byte* additional, size_t additionaLength)=0;
|
virtual void DRBG_Reseed(const byte* entropy, size_t entropyLength, const byte* additional, size_t additionaLength)=0;
|
||||||
};
|
};
|
||||||
|
|
@ -50,13 +122,16 @@ protected:
|
||||||
//! \tparam HASH NIST approved hash derived from HashTransformation
|
//! \tparam HASH NIST approved hash derived from HashTransformation
|
||||||
//! \tparam STRENGTH security strength, in bytes
|
//! \tparam STRENGTH security strength, in bytes
|
||||||
//! \tparam SEEDLENGTH seed length, in bytes
|
//! \tparam SEEDLENGTH seed length, in bytes
|
||||||
//! \brief Classes for NIST DRBGs from 800-90A Rev 1 (June 2015)
|
//! \brief Hash_DRBG from SP 800-90A Rev 1 (June 2015)
|
||||||
//! \details The NIST Hash DRBG is instantiated with a number of parameters. Two of the parameters,
|
//! \details The NIST Hash DRBG is instantiated with a number of parameters. Two of the parameters,
|
||||||
//! Security Strength and Seed Length, depend on the hash and are specified as template parameters.
|
//! Security Strength and Seed Length, depend on the hash and are specified as template parameters.
|
||||||
//! The remaining parameters are included in the class. The parameters and their values are listed
|
//! The remaining parameters are included in the class. The parameters and their values are listed
|
||||||
//! in NIST SP 800-90A Rev. 1, Table 2: Definitions for Hash-Based DRBG Mechanisms (p.38).
|
//! in NIST SP 800-90A Rev. 1, Table 2: Definitions for Hash-Based DRBG Mechanisms (p.38).
|
||||||
|
//! \details Some parameters have been reduce to fit C++ datatypes. For example, NIST allows upto 2<sup>48</sup> requests
|
||||||
|
//! before a reseed. However, Hash_DRBG limits it to <tt>UINT_MAX</tt> due to the limited data range of an unsigned int.
|
||||||
//! \sa <A HREF="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf">Recommendation
|
//! \sa <A HREF="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-90Ar1.pdf">Recommendation
|
||||||
//! for Random Number Generation Using Deterministic Random Bit Generators</A>
|
//! for Random Number Generation Using Deterministic Random Bit Generators,
|
||||||
|
//! Rev 1 (June 2015)</A>
|
||||||
//! \since Crypto++ 5.7
|
//! \since Crypto++ 5.7
|
||||||
template <typename HASH=SHA256, unsigned int STRENGTH=128/8, unsigned int SEEDLENGTH=440/8>
|
template <typename HASH=SHA256, unsigned int STRENGTH=128/8, unsigned int SEEDLENGTH=440/8>
|
||||||
class Hash_DRBG : public NIST_DRBG
|
class Hash_DRBG : public NIST_DRBG
|
||||||
|
|
@ -65,20 +140,56 @@ public:
|
||||||
CRYPTOPP_CONSTANT(SECURITY_STRENGTH=STRENGTH)
|
CRYPTOPP_CONSTANT(SECURITY_STRENGTH=STRENGTH)
|
||||||
CRYPTOPP_CONSTANT(SEED_LENGTH=SEEDLENGTH)
|
CRYPTOPP_CONSTANT(SEED_LENGTH=SEEDLENGTH)
|
||||||
CRYPTOPP_CONSTANT(MINIMUM_ENTROPY=STRENGTH)
|
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 <tt>MINIMUM_ENTROPY</tt> bytes of entropy. The byte array for <tt>entropy</tt> must meet <A HREF ="http://csrc.nist.gov/publications/PubsSPs.html">NIST
|
||||||
|
//! SP 800-90B</A> requirements.
|
||||||
|
//! \details The <tt>nonce</tt> and <tt>personalization</tt> are optional byte arrays. If <tt>nonce</tt> is supplied, then it should include <tt>MINIMUM_NONCE</tt> bytes of entropy.
|
||||||
|
//! \details NIST instantiation requirements demand the generator is constructed with at least <tt>MINIMUM_ENTROPY</tt> 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 <tt>NonblockingRng</tt> meets the
|
||||||
|
//! requirements of <A HREF ="http://csrc.nist.gov/publications/PubsSPs.html">NIST SP 800-90B</A>.
|
||||||
|
//! RDRAND() and RDSEED() generators would work as well.
|
||||||
|
//! <pre>
|
||||||
|
//! SecByteBlock entropy(48), result(128);
|
||||||
|
//! NonblockingRng prng;
|
||||||
|
//! RandomNumberSource rns(prng, entropy.size(), new ArraySink(entropy, entropy.size()));
|
||||||
|
//!
|
||||||
|
//! Hash_DRBG<SHA256, 256/8, 440/8> drbg(entropy, 32, entropy+32, 16);
|
||||||
|
//! drbg.GenerateBlock(result, result.size());
|
||||||
|
//! </pre>
|
||||||
Hash_DRBG(const byte* entropy, size_t entropyLength=STRENGTH, const byte* nonce=NULL,
|
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)
|
: 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 GetSecurityStrength() const {return SECURITY_STRENGTH;}
|
||||||
unsigned int GetSeedLength() const {return SEED_LENGTH;}
|
unsigned int GetSeedLength() const {return SEED_LENGTH;}
|
||||||
unsigned int GetMinEntropy() const {return SECURITY_STRENGTH;}
|
unsigned int GetMinEntropy() const {return MINIMUM_ENTROPY;}
|
||||||
unsigned int GetMaxEntropy() const {return (unsigned int)STDMIN((word64)UINT_MAX, W64LIT(4294967296));}
|
unsigned int GetMaxEntropy() const {return static_cast<unsigned int>(MAXIMUM_ENTROPY);}
|
||||||
unsigned int GetMaxRequest() const {return 65536;} // 2^16 bytes per request
|
unsigned int GetMinNonce() const {return MINIMUM_NONCE;}
|
||||||
unsigned int GetMaxReseed() const {return (unsigned int)STDMIN((word64)UINT_MAX, W64LIT(35184372088832));}
|
unsigned int GetMaxNonce() const {return static_cast<unsigned int>(MAXIMUM_NONCE);}
|
||||||
|
unsigned int GetMaxBytesPerRequest() const {return MAXIMUM_BYTES_PER_REQUEST;} // 2^16 bytes per request
|
||||||
|
unsigned int GetMaxRequestBeforeReseed() const {return static_cast<unsigned int>(MAXIMUM_REQUESTS_BEFORE_RESEED);}
|
||||||
|
|
||||||
void IncorporateEntropy(const byte *input, size_t length)
|
void IncorporateEntropy(const byte *input, size_t length)
|
||||||
{return DRBG_Reseed(input, length, NULL, 0);}
|
{return DRBG_Reseed(input, length, NULL, 0);}
|
||||||
|
|
@ -123,13 +234,13 @@ protected:
|
||||||
|
|
||||||
// 10.1.1.2 Instantiation of Hash_DRBG (p.48)
|
// 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,
|
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;
|
const byte zero = 0;
|
||||||
SecByteBlock t1(SEEDLENGTH), t2(SEEDLENGTH);
|
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());
|
Hash_df(&zero, 1, t1, t1.size(), NULL, 0, NULL, 0, t2, t2.size());
|
||||||
|
|
||||||
m_v.swap(t1); m_c.swap(t2);
|
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)
|
void Hash_Generate(const byte* additional, size_t additionaLength, byte *output, size_t size)
|
||||||
{
|
{
|
||||||
// Step 1
|
// Step 1
|
||||||
if (static_cast<word64>(m_reseed) >= static_cast<word64>(GetMaxReseed()))
|
if (static_cast<word64>(m_reseed) >= static_cast<word64>(GetMaxRequestBeforeReseed()))
|
||||||
throw Exception(Exception::OTHER_ERROR, "Reseed required");
|
throw Exception(Exception::OTHER_ERROR, "Reseed required");
|
||||||
|
|
||||||
// Step 2
|
// Step 2
|
||||||
|
|
@ -242,4 +353,5 @@ private:
|
||||||
|
|
||||||
NAMESPACE_END
|
NAMESPACE_END
|
||||||
|
|
||||||
#endif // CRYPTOPP_NIST_DETERMINISTIC_RANDOM_BIT_GENERATORS_H
|
#endif // CRYPTOPP_NIST_DRBG_H
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue