mirror of
https://github.com/shadps4-emu/ext-cryptopp.git
synced 2024-11-23 09:59:42 +00:00
Add NIST SP800-90A HMAC_DRBG generator
Move bodies out-of-line Whitespace
This commit is contained in:
parent
8e088b4865
commit
2868452193
934
drbg.h
934
drbg.h
@ -24,120 +24,122 @@ NAMESPACE_BEGIN(CryptoPP)
|
||||
class NIST_DRBG : public RandomNumberGenerator
|
||||
{
|
||||
public:
|
||||
//! \brief Exception thrown when a NIST DRBG encounters an error
|
||||
class Err : public Exception
|
||||
{
|
||||
public:
|
||||
explicit Err(const std::string &c, const std::string &m)
|
||||
: Exception(OTHER_ERROR, c + ": " + m) {}
|
||||
};
|
||||
//! \brief Exception thrown when a NIST DRBG encounters an error
|
||||
class Err : public Exception
|
||||
{
|
||||
public:
|
||||
explicit Err(const std::string &c, const std::string &m)
|
||||
: Exception(OTHER_ERROR, c + ": " + m) {}
|
||||
};
|
||||
|
||||
public:
|
||||
virtual ~NIST_DRBG() {}
|
||||
virtual ~NIST_DRBG() {}
|
||||
|
||||
//! \brief Determines if a generator can accept additional entropy
|
||||
//! \return true
|
||||
//! \details All NIST_DRBG return true
|
||||
virtual bool CanIncorporateEntropy() const {return true;}
|
||||
//! \brief Determines if a generator can accept additional entropy
|
||||
//! \return true
|
||||
//! \details All NIST_DRBG return true
|
||||
virtual bool CanIncorporateEntropy() const {return true;}
|
||||
|
||||
//! \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
|
||||
//! \throws NIST_DRBG::Err if the generator is reseeded with insufficient entropy
|
||||
//! \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 or SP 800-90C</A> requirements.
|
||||
virtual void IncorporateEntropy(const byte *input, size_t length)=0;
|
||||
//! \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
|
||||
//! \throws NIST_DRBG::Err if the generator is reseeded with insufficient entropy
|
||||
//! \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 or SP 800-90C</A> requirements.
|
||||
virtual void IncorporateEntropy(const byte *input, size_t length)=0;
|
||||
|
||||
//! \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 input to add to the generator
|
||||
//! \param additionaLength the size of the additional input buffer
|
||||
//! \throws NIST_DRBG::Err if the generator is reseeded with insufficient entropy
|
||||
//! \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>entropy</tt> must meet <A HREF ="http://csrc.nist.gov/publications/PubsSPs.html">NIST
|
||||
//! SP 800-90B or SP 800-90C</A> requirements.
|
||||
virtual void IncorporateEntropy(const byte *entropy, size_t entropyLength, const byte* additional, size_t additionaLength)=0;
|
||||
//! \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 input to add to the generator
|
||||
//! \param additionaLength the size of the additional input buffer
|
||||
//! \throws NIST_DRBG::Err if the generator is reseeded with insufficient entropy
|
||||
//! \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>entropy</tt> must meet <A HREF ="http://csrc.nist.gov/publications/PubsSPs.html">NIST
|
||||
//! SP 800-90B or SP 800-90C</A> requirements.
|
||||
virtual void IncorporateEntropy(const byte *entropy, size_t entropyLength, const byte* additional, size_t additionaLength)=0;
|
||||
|
||||
//! \brief Generate random array of bytes
|
||||
//! \param output the byte buffer
|
||||
//! \param size the length of the buffer, in bytes
|
||||
//! \throws NIST_DRBG::Err if a reseed is required
|
||||
//! \throws NIST_DRBG::Err if the size exceeds <tt>MAXIMUM_BYTES_PER_REQUEST</tt>
|
||||
virtual void GenerateBlock(byte *output, size_t size)=0;
|
||||
//! \brief Generate random array of bytes
|
||||
//! \param output the byte buffer
|
||||
//! \param size the length of the buffer, in bytes
|
||||
//! \throws NIST_DRBG::Err if a reseed is required
|
||||
//! \throws NIST_DRBG::Err if the size exceeds <tt>MAXIMUM_BYTES_PER_REQUEST</tt>
|
||||
virtual void GenerateBlock(byte *output, size_t size)=0;
|
||||
|
||||
//! \brief Generate random array of bytes
|
||||
//! \param additional additional input to add to the generator
|
||||
//! \param additionaLength the size of the additional input buffer
|
||||
//! \param output the byte buffer
|
||||
//! \param size the length of the buffer, in bytes
|
||||
//! \throws NIST_DRBG::Err if a reseed is required
|
||||
//! \throws NIST_DRBG::Err if the size exceeds <tt>MAXIMUM_BYTES_PER_REQUEST</tt>
|
||||
//! \details GenerateBlock() is an overload provided to match NIST requirements. The byte array for <tt>additional</tt>
|
||||
//! input 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;
|
||||
//! \brief Generate random array of bytes
|
||||
//! \param additional additional input to add to the generator
|
||||
//! \param additionaLength the size of the additional input buffer
|
||||
//! \param output the byte buffer
|
||||
//! \param size the length of the buffer, in bytes
|
||||
//! \throws NIST_DRBG::Err if a reseed is required
|
||||
//! \throws NIST_DRBG::Err if the size exceeds <tt>MAXIMUM_BYTES_PER_REQUEST</tt>
|
||||
//! \details GenerateBlock() is an overload provided to match NIST requirements. The byte array for <tt>additional</tt>
|
||||
//! input 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;
|
||||
|
||||
//! \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;
|
||||
//! \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;
|
||||
|
||||
//! \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;
|
||||
//! \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;
|
||||
|
||||
//! \brief Provides the minimum entropy size
|
||||
//! \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 or SP 800-90C</A> requirements.
|
||||
virtual unsigned int GetMinEntropy() const=0;
|
||||
//! \brief Provides the minimum entropy size
|
||||
//! \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 or SP 800-90C</A> requirements.
|
||||
virtual unsigned int GetMinEntropy() const=0;
|
||||
|
||||
//! \brief Provides the maximum entropy size
|
||||
//! \returns The maximum entropy size that can be consumed by the generator, in bytes
|
||||
//! \details The equivalent class constant is <tt>MAXIMUM_ENTROPY</tt>. The bytes must meet <A
|
||||
//! HREF="http://csrc.nist.gov/publications/PubsSPs.html">NIST SP 800-90B or SP 800-90C</A> requirements.
|
||||
//! <tt>MAXIMUM_ENTROPY</tt> has been reduced from 2<sup>35</sup> to <tt>INT_MAX</tt> to fit the underlying C++ datatype.
|
||||
virtual unsigned int GetMaxEntropy() const=0;
|
||||
//! \brief Provides the maximum entropy size
|
||||
//! \returns The maximum entropy size that can be consumed by the generator, in bytes
|
||||
//! \details The equivalent class constant is <tt>MAXIMUM_ENTROPY</tt>. The bytes must meet <A
|
||||
//! HREF="http://csrc.nist.gov/publications/PubsSPs.html">NIST SP 800-90B or SP 800-90C</A> requirements.
|
||||
//! <tt>MAXIMUM_ENTROPY</tt> has been reduced from 2<sup>35</sup> to <tt>INT_MAX</tt> to fit the underlying C++ datatype.
|
||||
virtual unsigned int GetMaxEntropy() const=0;
|
||||
|
||||
//! \brief Provides the minimum nonce size
|
||||
//! \returns The minimum nonce size recommended for the generator, in bytes
|
||||
//! \details The equivalent class constant is <tt>MINIMUM_NONCE</tt>. If a nonce is not required then
|
||||
//! <tt>MINIMUM_NONCE</tt> is 0. <tt>Hash_DRBG</tt> does not require a nonce, while <tt>HMAC_DRBG</tt>
|
||||
//! and <tt>CTR_DRBG</tt> require a nonce.
|
||||
virtual unsigned int GetMinNonce() const=0;
|
||||
//! \brief Provides the minimum nonce size
|
||||
//! \returns The minimum nonce size recommended for the generator, in bytes
|
||||
//! \details The equivalent class constant is <tt>MINIMUM_NONCE</tt>. If a nonce is not required then
|
||||
//! <tt>MINIMUM_NONCE</tt> is 0. <tt>Hash_DRBG</tt> does not require a nonce, while <tt>HMAC_DRBG</tt>
|
||||
//! and <tt>CTR_DRBG</tt> require a nonce.
|
||||
virtual unsigned int GetMinNonce() const=0;
|
||||
|
||||
//! \brief Provides the maximum nonce size
|
||||
//! \returns The maximum nonce that can be consumed by the generator, in bytes
|
||||
//! \details The equivalent class constant is <tt>MAXIMUM_NONCE</tt>. <tt>MAXIMUM_NONCE</tt> has been reduced from
|
||||
//! 2<sup>35</sup> to <tt>INT_MAX</tt> to fit the underlying C++ datatype. If a nonce is not required then
|
||||
//! <tt>MINIMUM_NONCE</tt> is 0. <tt>Hash_DRBG</tt> does not require a nonce, while <tt>HMAC_DRBG</tt>
|
||||
//! and <tt>CTR_DRBG</tt> require a nonce.
|
||||
virtual unsigned int GetMaxNonce() const=0;
|
||||
//! \brief Provides the maximum nonce size
|
||||
//! \returns The maximum nonce that can be consumed by the generator, in bytes
|
||||
//! \details The equivalent class constant is <tt>MAXIMUM_NONCE</tt>. <tt>MAXIMUM_NONCE</tt> has been reduced from
|
||||
//! 2<sup>35</sup> to <tt>INT_MAX</tt> to fit the underlying C++ datatype. If a nonce is not required then
|
||||
//! <tt>MINIMUM_NONCE</tt> is 0. <tt>Hash_DRBG</tt> does not require a nonce, while <tt>HMAC_DRBG</tt>
|
||||
//! and <tt>CTR_DRBG</tt> require a nonce.
|
||||
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 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>.
|
||||
//! <tt>MAXIMUM_REQUESTS_BEFORE_RESEED</tt> has been reduced from 2<sup>48</sup> to <tt>INT_MAX</tt>
|
||||
//! to fit the underlying C++ datatype.
|
||||
virtual unsigned int GetMaxRequestBeforeReseed() 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>.
|
||||
//! <tt>MAXIMUM_REQUESTS_BEFORE_RESEED</tt> has been reduced from 2<sup>48</sup> to <tt>INT_MAX</tt>
|
||||
//! to fit the underlying C++ datatype.
|
||||
virtual unsigned int GetMaxRequestBeforeReseed() const=0;
|
||||
|
||||
protected:
|
||||
virtual void DRBG_Instantiate(const byte* entropy, size_t entropyLength,
|
||||
const byte* nonce, size_t nonceLength, const byte* personalization, size_t personalizationLength)=0;
|
||||
virtual void DRBG_Instantiate(const byte* entropy, size_t entropyLength,
|
||||
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;
|
||||
};
|
||||
|
||||
// *************************************************************
|
||||
|
||||
//! \class Hash_DRBG
|
||||
//! \tparam HASH NIST approved hash derived from HashTransformation
|
||||
//! \tparam STRENGTH security strength, in bytes
|
||||
@ -153,257 +155,533 @@ protected:
|
||||
//! for Random Number Generation Using Deterministic Random Bit Generators, Rev 1 (June 2015)</A>
|
||||
//! \since Crypto++ 5.7
|
||||
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, public NotCopyable
|
||||
{
|
||||
public:
|
||||
CRYPTOPP_CONSTANT(SECURITY_STRENGTH=STRENGTH)
|
||||
CRYPTOPP_CONSTANT(SEED_LENGTH=SEEDLENGTH)
|
||||
CRYPTOPP_CONSTANT(MINIMUM_ENTROPY=STRENGTH)
|
||||
CRYPTOPP_CONSTANT(MINIMUM_NONCE=0)
|
||||
CRYPTOPP_CONSTANT(MINIMUM_ADDITIONAL=0)
|
||||
CRYPTOPP_CONSTANT(MINIMUM_PERSONALIZATION=0)
|
||||
CRYPTOPP_CONSTANT(MAXIMUM_ENTROPY=INT_MAX)
|
||||
CRYPTOPP_CONSTANT(MAXIMUM_NONCE=INT_MAX)
|
||||
CRYPTOPP_CONSTANT(MAXIMUM_ADDITIONAL=INT_MAX)
|
||||
CRYPTOPP_CONSTANT(MAXIMUM_PERSONALIZATION=INT_MAX)
|
||||
CRYPTOPP_CONSTANT(MAXIMUM_BYTES_PER_REQUEST=65536)
|
||||
CRYPTOPP_CONSTANT(MAXIMUM_REQUESTS_BEFORE_RESEED=INT_MAX)
|
||||
CRYPTOPP_CONSTANT(SECURITY_STRENGTH=STRENGTH)
|
||||
CRYPTOPP_CONSTANT(SEED_LENGTH=SEEDLENGTH)
|
||||
CRYPTOPP_CONSTANT(MINIMUM_ENTROPY=STRENGTH)
|
||||
CRYPTOPP_CONSTANT(MINIMUM_NONCE=0)
|
||||
CRYPTOPP_CONSTANT(MINIMUM_ADDITIONAL=0)
|
||||
CRYPTOPP_CONSTANT(MINIMUM_PERSONALIZATION=0)
|
||||
CRYPTOPP_CONSTANT(MAXIMUM_ENTROPY=INT_MAX)
|
||||
CRYPTOPP_CONSTANT(MAXIMUM_NONCE=INT_MAX)
|
||||
CRYPTOPP_CONSTANT(MAXIMUM_ADDITIONAL=INT_MAX)
|
||||
CRYPTOPP_CONSTANT(MAXIMUM_PERSONALIZATION=INT_MAX)
|
||||
CRYPTOPP_CONSTANT(MAXIMUM_BYTES_PER_REQUEST=65536)
|
||||
CRYPTOPP_CONSTANT(MAXIMUM_REQUESTS_BEFORE_RESEED=INT_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 input to instantiate the generator
|
||||
//! \param nonceLength the size of the nonce buffer
|
||||
//! \param personalization additional input to instantiate the generator
|
||||
//! \param personalizationLength the size of the personalization buffer
|
||||
//! \throws NIST_DRBG::Err if the generator is instantiated with insufficient entropy
|
||||
//! \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 or SP 800-90C</A> requirements.
|
||||
//! \details The <tt>nonce</tt> and <tt>personalization</tt> are optional byte arrays. If <tt>nonce</tt> is supplied,
|
||||
//! then it should be at least <tt>MINIMUM_NONCE</tt> bytes of entropy.
|
||||
//! \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 or SP 800-90C</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, 128/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,
|
||||
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, personalization, personalizationLength);
|
||||
}
|
||||
//! \brief Construct a Hash DRBG
|
||||
//! \param entropy the entropy to instantiate the generator
|
||||
//! \param entropyLength the size of the entropy buffer
|
||||
//! \param nonce additional input to instantiate the generator
|
||||
//! \param nonceLength the size of the nonce buffer
|
||||
//! \param personalization additional input to instantiate the generator
|
||||
//! \param personalizationLength the size of the personalization buffer
|
||||
//! \throws NIST_DRBG::Err if the generator is instantiated with insufficient entropy
|
||||
//! \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 or SP 800-90C</A> requirements.
|
||||
//! \details The <tt>nonce</tt> and <tt>personalization</tt> are optional byte arrays. If <tt>nonce</tt> is supplied,
|
||||
//! then it should be at least <tt>MINIMUM_NONCE</tt> bytes of entropy.
|
||||
//! \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 or SP 800-90C</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, 128/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,
|
||||
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, personalization, personalizationLength);
|
||||
}
|
||||
|
||||
unsigned int GetSecurityStrength() const {return SECURITY_STRENGTH;}
|
||||
unsigned int GetSeedLength() const {return SEED_LENGTH;}
|
||||
unsigned int GetMinEntropy() const {return MINIMUM_ENTROPY;}
|
||||
unsigned int GetMaxEntropy() const {return MAXIMUM_ENTROPY;}
|
||||
unsigned int GetMinNonce() const {return MINIMUM_NONCE;}
|
||||
unsigned int GetMaxNonce() const {return MAXIMUM_NONCE;}
|
||||
unsigned int GetMaxBytesPerRequest() const {return MAXIMUM_BYTES_PER_REQUEST;}
|
||||
unsigned int GetMaxRequestBeforeReseed() const {return MAXIMUM_REQUESTS_BEFORE_RESEED;}
|
||||
unsigned int GetSecurityStrength() const {return SECURITY_STRENGTH;}
|
||||
unsigned int GetSeedLength() const {return SEED_LENGTH;}
|
||||
unsigned int GetMinEntropy() const {return MINIMUM_ENTROPY;}
|
||||
unsigned int GetMaxEntropy() const {return MAXIMUM_ENTROPY;}
|
||||
unsigned int GetMinNonce() const {return MINIMUM_NONCE;}
|
||||
unsigned int GetMaxNonce() const {return MAXIMUM_NONCE;}
|
||||
unsigned int GetMaxBytesPerRequest() const {return MAXIMUM_BYTES_PER_REQUEST;}
|
||||
unsigned int GetMaxRequestBeforeReseed() const {return MAXIMUM_REQUESTS_BEFORE_RESEED;}
|
||||
|
||||
void IncorporateEntropy(const byte *input, size_t length)
|
||||
{return DRBG_Reseed(input, length, NULL, 0);}
|
||||
void IncorporateEntropy(const byte *input, size_t length)
|
||||
{return DRBG_Reseed(input, length, NULL, 0);}
|
||||
|
||||
void IncorporateEntropy(const byte *entropy, size_t entropyLength, const byte* additional, size_t additionaLength)
|
||||
{return DRBG_Reseed(entropy, entropyLength, additional, additionaLength);}
|
||||
void IncorporateEntropy(const byte *entropy, size_t entropyLength, const byte* additional, size_t additionaLength)
|
||||
{return DRBG_Reseed(entropy, entropyLength, additional, additionaLength);}
|
||||
|
||||
void GenerateBlock(byte *output, size_t size)
|
||||
{return Hash_Generate(NULL, 0, output, size);}
|
||||
void GenerateBlock(byte *output, size_t size)
|
||||
{return Hash_Generate(NULL, 0, output, size);}
|
||||
|
||||
void GenerateBlock(const byte* additional, size_t additionaLength, byte *output, size_t size)
|
||||
{return Hash_Generate(additional, additionaLength, output, size);}
|
||||
void GenerateBlock(const byte* additional, size_t additionaLength, byte *output, size_t size)
|
||||
{return Hash_Generate(additional, additionaLength, output, size);}
|
||||
|
||||
protected:
|
||||
// 10.3.1 Derivation Function Using a Hash Function (Hash_df) (p.58)
|
||||
void Hash_df(const byte* input1, size_t inlen1, const byte* input2, size_t inlen2,
|
||||
const byte* input3, size_t inlen3, const byte* input4, size_t inlen4, byte* output, size_t outlen)
|
||||
{
|
||||
HASH hash;
|
||||
byte counter = 1;
|
||||
word32 bits = ConditionalByteReverse(BIG_ENDIAN_ORDER, static_cast<word32>(outlen*8));
|
||||
// 10.1.1.2 Instantiation of Hash_DRBG (p.39)
|
||||
void DRBG_Instantiate(const byte* entropy, size_t entropyLength, const byte* nonce, size_t nonceLength,
|
||||
const byte* personalization, size_t personalizationLength);
|
||||
|
||||
size_t count;
|
||||
for (count=0; outlen; outlen -= count, output += count, counter++)
|
||||
{
|
||||
hash.Update(&counter, 1);
|
||||
hash.Update(reinterpret_cast<const byte*>(&bits), 4);
|
||||
// 10.1.1.3 Reseeding a Hash_DRBG Instantiation (p.40)
|
||||
void DRBG_Reseed(const byte* entropy, size_t entropyLength, const byte* additional, size_t additionaLength);
|
||||
|
||||
if (input1 && inlen1)
|
||||
hash.Update(input1, inlen1);
|
||||
if (input2 && inlen2)
|
||||
hash.Update(input2, inlen2);
|
||||
if (input3 && inlen3)
|
||||
hash.Update(input3, inlen3);
|
||||
if (input4 && inlen4)
|
||||
hash.Update(input4, inlen4);
|
||||
// 10.1.1.4 Generating Pseudorandom Bits Using Hash_DRBG (p.41)
|
||||
void Hash_Generate(const byte* additional, size_t additionaLength, byte *output, size_t size);
|
||||
|
||||
count = STDMIN(outlen, (size_t)HASH::DIGESTSIZE);
|
||||
hash.TruncatedFinal(output, count);
|
||||
}
|
||||
}
|
||||
|
||||
// 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* personalization, size_t personalizationLength)
|
||||
{
|
||||
// SP 800-90A, 8.6.3: The entropy input shall have entropy that is equal to or greater than the security
|
||||
// strength of the instantiation. Additional entropy may be provided in the nonce or the optional
|
||||
// personalization string during instantiation, or in the additional input during reseeding and generation,
|
||||
// but this is not required and does not increase the "official" security strength of the DRBG
|
||||
// instantiation that is recorded in the internal state.
|
||||
CRYPTOPP_ASSERT(entropyLength >= MINIMUM_ENTROPY);
|
||||
if (entropyLength < MINIMUM_ENTROPY)
|
||||
throw NIST_DRBG::Err("Hash_DRBG", "Insufficient entropy during instantiate");
|
||||
|
||||
// SP 800-90A, Section 9, says we should throw if we have too much entropy, too large a nonce,
|
||||
// or too large a persoanlization string. We warn in Debug builds, but do nothing in Release builds.
|
||||
CRYPTOPP_ASSERT(entropyLength <= MAXIMUM_ENTROPY);
|
||||
CRYPTOPP_ASSERT(nonceLength <= MAXIMUM_NONCE);
|
||||
CRYPTOPP_ASSERT(personalizationLength <= MAXIMUM_PERSONALIZATION);
|
||||
|
||||
const byte zero = 0;
|
||||
SecByteBlock t1(SEEDLENGTH), t2(SEEDLENGTH);
|
||||
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);
|
||||
m_reseed = 1;
|
||||
}
|
||||
|
||||
// 10.1.1.3 Reseeding a Hash_DRBG Instantiation (p.49)
|
||||
void DRBG_Reseed(const byte* entropy, size_t entropyLength, const byte* additional, size_t additionaLength)
|
||||
{
|
||||
// SP 800-90A, 8.6.3: The entropy input shall have entropy that is equal to or greater than the security
|
||||
// strength of the instantiation. Additional entropy may be provided in the nonce or the optional
|
||||
// personalization string during instantiation, or in the additional input during reseeding and generation,
|
||||
// but this is not required and does not increase the "official" security strength of the DRBG
|
||||
// instantiation that is recorded in the internal state..
|
||||
CRYPTOPP_ASSERT(entropyLength >= MINIMUM_ENTROPY);
|
||||
if (entropyLength < MINIMUM_ENTROPY)
|
||||
throw NIST_DRBG::Err("Hash_DRBG", "Insufficient entropy during reseed");
|
||||
|
||||
// SP 800-90A, Section 9, says we should throw if we have too much entropy, too large a nonce,
|
||||
// or too large a persoanlization string. We warn in Debug builds, but do nothing in Release builds.
|
||||
CRYPTOPP_ASSERT(entropyLength <= MAXIMUM_ENTROPY);
|
||||
CRYPTOPP_ASSERT(additionaLength <= MAXIMUM_ADDITIONAL);
|
||||
|
||||
const byte zero = 0, one = 1;
|
||||
SecByteBlock t1(SEEDLENGTH), t2(SEEDLENGTH);
|
||||
Hash_df(&one, 1, m_v, m_v.size(), entropy, entropyLength, additional, additionaLength, 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);
|
||||
m_reseed = 1;
|
||||
}
|
||||
|
||||
// 10.1.1.4 Generating Pseudorandom Bits Using Hash_DRBG (p.50)
|
||||
void Hash_Generate(const byte* additional, size_t additionaLength, byte *output, size_t size)
|
||||
{
|
||||
// Step 1
|
||||
if (static_cast<word64>(m_reseed) >= static_cast<word64>(GetMaxRequestBeforeReseed()))
|
||||
throw NIST_DRBG::Err("Hash_DRBG", "Reseed required");
|
||||
|
||||
if (size > GetMaxBytesPerRequest())
|
||||
throw NIST_DRBG::Err("Hash_DRBG", "Request size exceeds limit");
|
||||
|
||||
// SP 800-90A, Section 9, says we should throw if we have too much entropy, too large a nonce,
|
||||
// or too large a persoanlization string. We warn in Debug builds, but do nothing in Release builds.
|
||||
CRYPTOPP_ASSERT(additionaLength <= MAXIMUM_ADDITIONAL);
|
||||
|
||||
// Step 2
|
||||
if (additional && additionaLength)
|
||||
{
|
||||
HASH hash;
|
||||
const byte two = 2;
|
||||
SecByteBlock w(HASH::DIGESTSIZE);
|
||||
|
||||
hash.Update(&two, 1);
|
||||
hash.Update(m_v, m_v.size());
|
||||
hash.Update(additional, additionaLength);
|
||||
hash.Final(w);
|
||||
|
||||
CRYPTOPP_ASSERT(SEEDLENGTH >= HASH::DIGESTSIZE);
|
||||
int carry=0, i=SEEDLENGTH-1, j=HASH::DIGESTSIZE-1;
|
||||
while(i>=0 && j>=0)
|
||||
{
|
||||
carry = m_v[i] + w[j] + carry;
|
||||
m_v[i] = static_cast<byte>(carry);
|
||||
carry >>= 8; i--; j--;
|
||||
}
|
||||
while (carry && i>=0)
|
||||
{
|
||||
carry = m_v[i] + carry;
|
||||
m_v[i] = static_cast<byte>(carry);
|
||||
carry >>= 8; i--;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3
|
||||
{
|
||||
HASH hash;
|
||||
SecByteBlock data(m_v);
|
||||
|
||||
size_t count;
|
||||
for (count = 0; size; size -= count, output += count)
|
||||
{
|
||||
hash.Update(data, data.size());
|
||||
count = STDMIN(size, (size_t)HASH::DIGESTSIZE);
|
||||
hash.TruncatedFinal(output, count);
|
||||
|
||||
IncrementCounterByOne(data, static_cast<unsigned int>(data.size()));
|
||||
}
|
||||
}
|
||||
|
||||
// Steps 4-7
|
||||
{
|
||||
HASH hash;
|
||||
const byte three = 3;
|
||||
SecByteBlock h(HASH::DIGESTSIZE);
|
||||
|
||||
hash.Update(&three, 1);
|
||||
hash.Update(m_v, m_v.size());
|
||||
hash.Final(h);
|
||||
|
||||
CRYPTOPP_ASSERT(SEEDLENGTH >= HASH::DIGESTSIZE);
|
||||
CRYPTOPP_ASSERT(HASH::DIGESTSIZE >= sizeof(m_reseed));
|
||||
int carry=0, i=SEEDLENGTH-1, j=HASH::DIGESTSIZE-1, k=sizeof(m_reseed)-1;
|
||||
while(i>=0 && j>=0 && k>=0)
|
||||
{
|
||||
carry = m_v[i] + m_c[i] + h[j] + GetByte<word64>(BIG_ENDIAN_ORDER, m_reseed, k) + carry;
|
||||
m_v[i] = static_cast<byte>(carry);
|
||||
carry >>= 8; i--; j--; k--;
|
||||
}
|
||||
while(i>=0 && j>=0)
|
||||
{
|
||||
carry = m_v[i] + m_c[i] + h[j] + carry;
|
||||
m_v[i] = static_cast<byte>(carry);
|
||||
carry >>= 8; i--; j--;
|
||||
}
|
||||
while (i>=0)
|
||||
{
|
||||
carry = m_v[i] + m_c[i] + carry;
|
||||
m_v[i] = static_cast<byte>(carry);
|
||||
carry >>= 8; i--;
|
||||
}
|
||||
}
|
||||
|
||||
m_reseed++;
|
||||
}
|
||||
// 10.3.1 Derivation Function Using a Hash Function (Hash_df) (p.49)
|
||||
void Hash_Update(const byte* input1, size_t inlen1, const byte* input2, size_t inlen2,
|
||||
const byte* input3, size_t inlen3, const byte* input4, size_t inlen4, byte* output, size_t outlen);
|
||||
|
||||
private:
|
||||
SecByteBlock m_c, m_v;
|
||||
word64 m_reseed;
|
||||
SecByteBlock m_c, m_v;
|
||||
word64 m_reseed;
|
||||
};
|
||||
|
||||
// typedef Hash_DRBG<SHA1, 128/8, 440/8> Hash_SHA1_DRBG;
|
||||
// typedef Hash_DRBG<SHA256, 128/8, 440/8> Hash_SHA256_DRBG;
|
||||
// typedef Hash_DRBG<SHA384, 256/8, 888/8> Hash_SHA384_DRBG;
|
||||
// typedef Hash_DRBG<SHA512, 256/8, 888/8> Hash_SHA512_DRBG;
|
||||
|
||||
// *************************************************************
|
||||
|
||||
//! \class HMAC_DRBG
|
||||
//! \tparam HASH NIST approved hash derived from HashTransformation
|
||||
//! \tparam STRENGTH security strength, in bytes
|
||||
//! \tparam SEEDLENGTH seed length, in bytes
|
||||
//! \brief HMAC_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,
|
||||
//! 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
|
||||
//! 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, HMAC_DRBG limits it to <tt>INT_MAX</tt> due to the limited data range of an int.
|
||||
//! \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
|
||||
template <typename HASH=SHA256, unsigned int STRENGTH=128/8, unsigned int SEEDLENGTH=440/8>
|
||||
class HMAC_DRBG : public NIST_DRBG, public NotCopyable
|
||||
{
|
||||
public:
|
||||
CRYPTOPP_CONSTANT(SECURITY_STRENGTH=STRENGTH)
|
||||
CRYPTOPP_CONSTANT(SEED_LENGTH=SEEDLENGTH)
|
||||
CRYPTOPP_CONSTANT(MINIMUM_ENTROPY=STRENGTH)
|
||||
CRYPTOPP_CONSTANT(MINIMUM_NONCE=0)
|
||||
CRYPTOPP_CONSTANT(MINIMUM_ADDITIONAL=0)
|
||||
CRYPTOPP_CONSTANT(MINIMUM_PERSONALIZATION=0)
|
||||
CRYPTOPP_CONSTANT(MAXIMUM_ENTROPY=INT_MAX)
|
||||
CRYPTOPP_CONSTANT(MAXIMUM_NONCE=INT_MAX)
|
||||
CRYPTOPP_CONSTANT(MAXIMUM_ADDITIONAL=INT_MAX)
|
||||
CRYPTOPP_CONSTANT(MAXIMUM_PERSONALIZATION=INT_MAX)
|
||||
CRYPTOPP_CONSTANT(MAXIMUM_BYTES_PER_REQUEST=65536)
|
||||
CRYPTOPP_CONSTANT(MAXIMUM_REQUESTS_BEFORE_RESEED=INT_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 input to instantiate the generator
|
||||
//! \param nonceLength the size of the nonce buffer
|
||||
//! \param personalization additional input to instantiate the generator
|
||||
//! \param personalizationLength the size of the personalization buffer
|
||||
//! \throws NIST_DRBG::Err if the generator is instantiated with insufficient entropy
|
||||
//! \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 or SP 800-90C</A> requirements.
|
||||
//! \details The <tt>nonce</tt> and <tt>personalization</tt> are optional byte arrays. If <tt>nonce</tt> is supplied,
|
||||
//! then it should be at least <tt>MINIMUM_NONCE</tt> bytes of entropy.
|
||||
//! \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 or SP 800-90C</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()));
|
||||
//!
|
||||
//! HMAC_DRBG<SHA256, 128/8, 440/8> drbg(entropy, 32, entropy+32, 16);
|
||||
//! drbg.GenerateBlock(result, result.size());
|
||||
//! </pre>
|
||||
HMAC_DRBG(const byte* entropy, size_t entropyLength=STRENGTH, const byte* nonce=NULL,
|
||||
size_t nonceLength=0, const byte* personalization=NULL, size_t personalizationLength=0)
|
||||
: NIST_DRBG(), m_k(HASH::DIGESTSIZE), m_v(HASH::DIGESTSIZE)
|
||||
{
|
||||
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 MINIMUM_ENTROPY;}
|
||||
unsigned int GetMaxEntropy() const {return MAXIMUM_ENTROPY;}
|
||||
unsigned int GetMinNonce() const {return MINIMUM_NONCE;}
|
||||
unsigned int GetMaxNonce() const {return MAXIMUM_NONCE;}
|
||||
unsigned int GetMaxBytesPerRequest() const {return MAXIMUM_BYTES_PER_REQUEST;}
|
||||
unsigned int GetMaxRequestBeforeReseed() const {return MAXIMUM_REQUESTS_BEFORE_RESEED;}
|
||||
|
||||
void IncorporateEntropy(const byte *input, size_t length)
|
||||
{return DRBG_Reseed(input, length, NULL, 0);}
|
||||
|
||||
void IncorporateEntropy(const byte *entropy, size_t entropyLength, const byte* additional, size_t additionaLength)
|
||||
{return DRBG_Reseed(entropy, entropyLength, additional, additionaLength);}
|
||||
|
||||
void GenerateBlock(byte *output, size_t size)
|
||||
{return HMAC_Generate(NULL, 0, output, size);}
|
||||
|
||||
void GenerateBlock(const byte* additional, size_t additionaLength, byte *output, size_t size)
|
||||
{return HMAC_Generate(additional, additionaLength, output, size);}
|
||||
|
||||
protected:
|
||||
// 10.1.2.3 Instantiation of HMAC_DRBG (p.45)
|
||||
void DRBG_Instantiate(const byte* entropy, size_t entropyLength, const byte* nonce, size_t nonceLength,
|
||||
const byte* personalization, size_t personalizationLength);
|
||||
|
||||
// 10.1.2.4 Reseeding a HMAC_DRBG Instantiation (p.46)
|
||||
void DRBG_Reseed(const byte* entropy, size_t entropyLength, const byte* additional, size_t additionaLength);
|
||||
|
||||
// 10.1.2.5 Generating Pseudorandom Bits Using HMAC_DRBG (p.46)
|
||||
void HMAC_Generate(const byte* additional, size_t additionaLength, byte *output, size_t size);
|
||||
|
||||
// 10.1.2.2 Derivation Function Using a HMAC Function (HMAC_Update) (p.44)
|
||||
void HMAC_Update(const byte* input1, size_t inlen1, const byte* input2, size_t inlen2, const byte* input3, size_t inlen3);
|
||||
|
||||
private:
|
||||
SecByteBlock m_k, m_v;
|
||||
word64 m_reseed;
|
||||
};
|
||||
|
||||
// typedef HMAC_DRBG<SHA1, 128/8, 440/8> HMAC_SHA1_DRBG;
|
||||
// typedef HMAC_DRBG<SHA256, 128/8, 440/8> HMAC_SHA256_DRBG;
|
||||
// typedef HMAC_DRBG<SHA384, 256/8, 888/8> HMAC_SHA384_DRBG;
|
||||
// typedef HMAC_DRBG<SHA512, 256/8, 888/8> HMAC_SHA512_DRBG;
|
||||
|
||||
// *************************************************************
|
||||
|
||||
// 10.1.1.2 Instantiation of Hash_DRBG (p.39)
|
||||
template <typename HASH, unsigned int STRENGTH, unsigned int SEEDLENGTH>
|
||||
void Hash_DRBG<HASH, STRENGTH, SEEDLENGTH>::DRBG_Instantiate(const byte* entropy, size_t entropyLength, const byte* nonce, size_t nonceLength,
|
||||
const byte* personalization, size_t personalizationLength)
|
||||
{
|
||||
// SP 800-90A, 8.6.3: The entropy input shall have entropy that is equal to or greater than the security
|
||||
// strength of the instantiation. Additional entropy may be provided in the nonce or the optional
|
||||
// personalization string during instantiation, or in the additional input during reseeding and generation,
|
||||
// but this is not required and does not increase the "official" security strength of the DRBG
|
||||
// instantiation that is recorded in the internal state.
|
||||
CRYPTOPP_ASSERT(entropyLength >= MINIMUM_ENTROPY);
|
||||
if (entropyLength < MINIMUM_ENTROPY)
|
||||
throw NIST_DRBG::Err("Hash_DRBG", "Insufficient entropy during instantiate");
|
||||
|
||||
// SP 800-90A, Section 9, says we should throw if we have too much entropy, too large a nonce,
|
||||
// or too large a persoanlization string. We warn in Debug builds, but do nothing in Release builds.
|
||||
CRYPTOPP_ASSERT(entropyLength <= MAXIMUM_ENTROPY);
|
||||
CRYPTOPP_ASSERT(nonceLength <= MAXIMUM_NONCE);
|
||||
CRYPTOPP_ASSERT(personalizationLength <= MAXIMUM_PERSONALIZATION);
|
||||
|
||||
const byte zero = 0;
|
||||
SecByteBlock t1(SEEDLENGTH), t2(SEEDLENGTH);
|
||||
Hash_Update(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength, NULL, 0, t1, t1.size());
|
||||
Hash_Update(&zero, 1, t1, t1.size(), NULL, 0, NULL, 0, t2, t2.size());
|
||||
|
||||
m_v.swap(t1); m_c.swap(t2);
|
||||
m_reseed = 1;
|
||||
}
|
||||
|
||||
// 10.1.1.3 Reseeding a Hash_DRBG Instantiation (p.40)
|
||||
template <typename HASH, unsigned int STRENGTH, unsigned int SEEDLENGTH>
|
||||
void Hash_DRBG<HASH, STRENGTH, SEEDLENGTH>::DRBG_Reseed(const byte* entropy, size_t entropyLength, const byte* additional, size_t additionaLength)
|
||||
{
|
||||
// SP 800-90A, 8.6.3: The entropy input shall have entropy that is equal to or greater than the security
|
||||
// strength of the instantiation. Additional entropy may be provided in the nonce or the optional
|
||||
// personalization string during instantiation, or in the additional input during reseeding and generation,
|
||||
// but this is not required and does not increase the "official" security strength of the DRBG
|
||||
// instantiation that is recorded in the internal state..
|
||||
CRYPTOPP_ASSERT(entropyLength >= MINIMUM_ENTROPY);
|
||||
if (entropyLength < MINIMUM_ENTROPY)
|
||||
throw NIST_DRBG::Err("Hash_DRBG", "Insufficient entropy during reseed");
|
||||
|
||||
// SP 800-90A, Section 9, says we should throw if we have too much entropy, too large a nonce,
|
||||
// or too large a persoanlization string. We warn in Debug builds, but do nothing in Release builds.
|
||||
CRYPTOPP_ASSERT(entropyLength <= MAXIMUM_ENTROPY);
|
||||
CRYPTOPP_ASSERT(additionaLength <= MAXIMUM_ADDITIONAL);
|
||||
|
||||
const byte zero = 0, one = 1;
|
||||
SecByteBlock t1(SEEDLENGTH), t2(SEEDLENGTH);
|
||||
Hash_Update(&one, 1, m_v, m_v.size(), entropy, entropyLength, additional, additionaLength, t1, t1.size());
|
||||
Hash_Update(&zero, 1, t1, t1.size(), NULL, 0, NULL, 0, t2, t2.size());
|
||||
|
||||
m_v.swap(t1); m_c.swap(t2);
|
||||
m_reseed = 1;
|
||||
}
|
||||
|
||||
// 10.1.1.4 Generating Pseudorandom Bits Using Hash_DRBG (p.41)
|
||||
template <typename HASH, unsigned int STRENGTH, unsigned int SEEDLENGTH>
|
||||
void Hash_DRBG<HASH, STRENGTH, SEEDLENGTH>::Hash_Generate(const byte* additional, size_t additionaLength, byte *output, size_t size)
|
||||
{
|
||||
// Step 1
|
||||
if (static_cast<word64>(m_reseed) >= static_cast<word64>(GetMaxRequestBeforeReseed()))
|
||||
throw NIST_DRBG::Err("Hash_DRBG", "Reseed required");
|
||||
|
||||
if (size > GetMaxBytesPerRequest())
|
||||
throw NIST_DRBG::Err("Hash_DRBG", "Request size exceeds limit");
|
||||
|
||||
// SP 800-90A, Section 9, says we should throw if we have too much entropy, too large a nonce,
|
||||
// or too large a persoanlization string. We warn in Debug builds, but do nothing in Release builds.
|
||||
CRYPTOPP_ASSERT(additionaLength <= MAXIMUM_ADDITIONAL);
|
||||
|
||||
// Step 2
|
||||
if (additional && additionaLength)
|
||||
{
|
||||
HASH hash;
|
||||
const byte two = 2;
|
||||
SecByteBlock w(HASH::DIGESTSIZE);
|
||||
|
||||
hash.Update(&two, 1);
|
||||
hash.Update(m_v, m_v.size());
|
||||
hash.Update(additional, additionaLength);
|
||||
hash.Final(w);
|
||||
|
||||
CRYPTOPP_ASSERT(SEEDLENGTH >= HASH::DIGESTSIZE);
|
||||
int carry=0, i=SEEDLENGTH-1, j=HASH::DIGESTSIZE-1;
|
||||
while(i>=0 && j>=0)
|
||||
{
|
||||
carry = m_v[i] + w[j] + carry;
|
||||
m_v[i] = static_cast<byte>(carry);
|
||||
carry >>= 8; i--; j--;
|
||||
}
|
||||
while (carry && i>=0)
|
||||
{
|
||||
carry = m_v[i] + carry;
|
||||
m_v[i] = static_cast<byte>(carry);
|
||||
carry >>= 8; i--;
|
||||
}
|
||||
}
|
||||
|
||||
// Step 3
|
||||
{
|
||||
HASH hash;
|
||||
SecByteBlock data(m_v);
|
||||
|
||||
while (size)
|
||||
{
|
||||
hash.Update(data, data.size());
|
||||
size_t count = STDMIN(size, (size_t)HASH::DIGESTSIZE);
|
||||
hash.TruncatedFinal(output, count);
|
||||
|
||||
IncrementCounterByOne(data, static_cast<unsigned int>(data.size()));
|
||||
output += count; size -= count;
|
||||
}
|
||||
}
|
||||
|
||||
// Steps 4-7
|
||||
{
|
||||
HASH hash;
|
||||
const byte three = 3;
|
||||
SecByteBlock h(HASH::DIGESTSIZE);
|
||||
|
||||
hash.Update(&three, 1);
|
||||
hash.Update(m_v, m_v.size());
|
||||
hash.Final(h);
|
||||
|
||||
CRYPTOPP_ASSERT(SEEDLENGTH >= HASH::DIGESTSIZE);
|
||||
CRYPTOPP_ASSERT(HASH::DIGESTSIZE >= sizeof(m_reseed));
|
||||
int carry=0, i=SEEDLENGTH-1, j=HASH::DIGESTSIZE-1, k=sizeof(m_reseed)-1;
|
||||
while(i>=0 && j>=0 && k>=0)
|
||||
{
|
||||
carry = m_v[i] + m_c[i] + h[j] + GetByte<word64>(BIG_ENDIAN_ORDER, m_reseed, k) + carry;
|
||||
m_v[i] = static_cast<byte>(carry);
|
||||
carry >>= 8; i--; j--; k--;
|
||||
}
|
||||
while(i>=0 && j>=0)
|
||||
{
|
||||
carry = m_v[i] + m_c[i] + h[j] + carry;
|
||||
m_v[i] = static_cast<byte>(carry);
|
||||
carry >>= 8; i--; j--;
|
||||
}
|
||||
while (i>=0)
|
||||
{
|
||||
carry = m_v[i] + m_c[i] + carry;
|
||||
m_v[i] = static_cast<byte>(carry);
|
||||
carry >>= 8; i--;
|
||||
}
|
||||
}
|
||||
|
||||
m_reseed++;
|
||||
}
|
||||
|
||||
// 10.3.1 Derivation Function Using a Hash Function (Hash_df) (p.49)
|
||||
template <typename HASH, unsigned int STRENGTH, unsigned int SEEDLENGTH>
|
||||
void Hash_DRBG<HASH, STRENGTH, SEEDLENGTH>::Hash_Update(const byte* input1, size_t inlen1, const byte* input2, size_t inlen2,
|
||||
const byte* input3, size_t inlen3, const byte* input4, size_t inlen4, byte* output, size_t outlen)
|
||||
{
|
||||
HASH hash;
|
||||
byte counter = 1;
|
||||
word32 bits = ConditionalByteReverse(BIG_ENDIAN_ORDER, static_cast<word32>(outlen*8));
|
||||
|
||||
size_t count;
|
||||
for (count=0; outlen; outlen -= count, output += count, counter++)
|
||||
{
|
||||
hash.Update(&counter, 1);
|
||||
hash.Update(reinterpret_cast<const byte*>(&bits), 4);
|
||||
|
||||
if (input1 && inlen1)
|
||||
hash.Update(input1, inlen1);
|
||||
if (input2 && inlen2)
|
||||
hash.Update(input2, inlen2);
|
||||
if (input3 && inlen3)
|
||||
hash.Update(input3, inlen3);
|
||||
if (input4 && inlen4)
|
||||
hash.Update(input4, inlen4);
|
||||
|
||||
count = STDMIN(outlen, (size_t)HASH::DIGESTSIZE);
|
||||
hash.TruncatedFinal(output, count);
|
||||
}
|
||||
}
|
||||
|
||||
// *************************************************************
|
||||
|
||||
// 10.1.2.3 Instantiation of HMAC_DRBG (p.45)
|
||||
template <typename HASH, unsigned int STRENGTH, unsigned int SEEDLENGTH>
|
||||
void HMAC_DRBG<HASH, STRENGTH, SEEDLENGTH>::DRBG_Instantiate(const byte* entropy, size_t entropyLength, const byte* nonce, size_t nonceLength,
|
||||
const byte* personalization, size_t personalizationLength)
|
||||
{
|
||||
// SP 800-90A, 8.6.3: The entropy input shall have entropy that is equal to or greater than the security
|
||||
// strength of the instantiation. Additional entropy may be provided in the nonce or the optional
|
||||
// personalization string during instantiation, or in the additional input during reseeding and generation,
|
||||
// but this is not required and does not increase the "official" security strength of the DRBG
|
||||
// instantiation that is recorded in the internal state.
|
||||
CRYPTOPP_ASSERT(entropyLength >= MINIMUM_ENTROPY);
|
||||
if (entropyLength < MINIMUM_ENTROPY)
|
||||
throw NIST_DRBG::Err("HMAC_DRBG", "Insufficient entropy during instantiate");
|
||||
|
||||
// SP 800-90A, Section 9, says we should throw if we have too much entropy, too large a nonce,
|
||||
// or too large a persoanlization string. We warn in Debug builds, but do nothing in Release builds.
|
||||
CRYPTOPP_ASSERT(entropyLength <= MAXIMUM_ENTROPY);
|
||||
CRYPTOPP_ASSERT(nonceLength <= MAXIMUM_NONCE);
|
||||
CRYPTOPP_ASSERT(personalizationLength <= MAXIMUM_PERSONALIZATION);
|
||||
|
||||
std::fill(m_k.begin(), m_k.begin()+m_k.size(), byte(0));
|
||||
std::fill(m_v.begin(), m_v.begin()+m_v.size(), byte(1));
|
||||
|
||||
HMAC_Update(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength);
|
||||
m_reseed = 1;
|
||||
}
|
||||
|
||||
// 10.1.2.4 Reseeding a HMAC_DRBG Instantiation (p.46)
|
||||
template <typename HASH, unsigned int STRENGTH, unsigned int SEEDLENGTH>
|
||||
void HMAC_DRBG<HASH, STRENGTH, SEEDLENGTH>::DRBG_Reseed(const byte* entropy, size_t entropyLength, const byte* additional, size_t additionaLength)
|
||||
{
|
||||
// SP 800-90A, 8.6.3: The entropy input shall have entropy that is equal to or greater than the security
|
||||
// strength of the instantiation. Additional entropy may be provided in the nonce or the optional
|
||||
// personalization string during instantiation, or in the additional input during reseeding and generation,
|
||||
// but this is not required and does not increase the "official" security strength of the DRBG
|
||||
// instantiation that is recorded in the internal state..
|
||||
CRYPTOPP_ASSERT(entropyLength >= MINIMUM_ENTROPY);
|
||||
if (entropyLength < MINIMUM_ENTROPY)
|
||||
throw NIST_DRBG::Err("HMAC_DRBG", "Insufficient entropy during reseed");
|
||||
|
||||
// SP 800-90A, Section 9, says we should throw if we have too much entropy, too large a nonce,
|
||||
// or too large a persoanlization string. We warn in Debug builds, but do nothing in Release builds.
|
||||
CRYPTOPP_ASSERT(entropyLength <= MAXIMUM_ENTROPY);
|
||||
CRYPTOPP_ASSERT(additionaLength <= MAXIMUM_ADDITIONAL);
|
||||
|
||||
HMAC_Update(entropy, entropyLength, additional, additionaLength, NULL, 0);
|
||||
m_reseed = 1;
|
||||
}
|
||||
|
||||
// 10.1.2.5 Generating Pseudorandom Bits Using HMAC_DRBG (p.46)
|
||||
template <typename HASH, unsigned int STRENGTH, unsigned int SEEDLENGTH>
|
||||
void HMAC_DRBG<HASH, STRENGTH, SEEDLENGTH>::HMAC_Generate(const byte* additional, size_t additionaLength, byte *output, size_t size)
|
||||
{
|
||||
// Step 1
|
||||
if (static_cast<word64>(m_reseed) >= static_cast<word64>(GetMaxRequestBeforeReseed()))
|
||||
throw NIST_DRBG::Err("HMAC_DRBG", "Reseed required");
|
||||
|
||||
if (size > GetMaxBytesPerRequest())
|
||||
throw NIST_DRBG::Err("HMAC_DRBG", "Request size exceeds limit");
|
||||
|
||||
// SP 800-90A, Section 9, says we should throw if we have too much entropy, too large a nonce,
|
||||
// or too large a persoanlization string. We warn in Debug builds, but do nothing in Release builds.
|
||||
CRYPTOPP_ASSERT(additionaLength <= MAXIMUM_ADDITIONAL);
|
||||
|
||||
// Step 2
|
||||
if (additional && additionaLength)
|
||||
HMAC_Update(additional, additionaLength, NULL, 0, NULL, 0);
|
||||
|
||||
// Step 3
|
||||
HMAC<HASH> hmac;
|
||||
hmac.SetKey(m_k, m_k.size());
|
||||
|
||||
while (size)
|
||||
{
|
||||
hmac.Update(m_v, m_v.size());
|
||||
hmac.TruncatedFinal(m_v, m_v.size());
|
||||
|
||||
size_t count = STDMIN(size, (size_t)HASH::DIGESTSIZE);
|
||||
memcpy(output, m_v, count);
|
||||
|
||||
size -= count; output += count;
|
||||
}
|
||||
|
||||
HMAC_Update(additional, additionaLength, NULL, 0, NULL, 0);
|
||||
m_reseed++;
|
||||
}
|
||||
|
||||
// 10.1.2.2 Derivation Function Using a HMAC Function (HMAC_Update) (p.44)
|
||||
template <typename HASH, unsigned int STRENGTH, unsigned int SEEDLENGTH>
|
||||
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)
|
||||
{
|
||||
const byte zero = 0, one = 1;
|
||||
HMAC<HASH> hmac;
|
||||
|
||||
// Step 1
|
||||
hmac.SetKey(m_k, m_k.size());
|
||||
hmac.Update(m_v, m_v.size());
|
||||
hmac.Update(&zero, 1);
|
||||
|
||||
if (input1 && inlen1)
|
||||
hmac.Update(input1, inlen1);
|
||||
if (input2 && inlen2)
|
||||
hmac.Update(input2, inlen2);
|
||||
if (input3 && inlen3)
|
||||
hmac.Update(input3, inlen3);
|
||||
|
||||
hmac.TruncatedFinal(m_k, m_k.size());
|
||||
|
||||
// Step 2
|
||||
hmac.SetKey(m_k, m_k.size());
|
||||
hmac.Update(m_v, m_v.size());
|
||||
|
||||
hmac.TruncatedFinal(m_v, m_v.size());
|
||||
|
||||
// Step 3
|
||||
if ((inlen1 | inlen2 | inlen3) == 0)
|
||||
return;
|
||||
|
||||
// Step 4
|
||||
hmac.SetKey(m_k, m_k.size());
|
||||
hmac.Update(m_v, m_v.size());
|
||||
hmac.Update(&one, 1);
|
||||
|
||||
if (input1 && inlen1)
|
||||
hmac.Update(input1, inlen1);
|
||||
if (input2 && inlen2)
|
||||
hmac.Update(input2, inlen2);
|
||||
if (input3 && inlen3)
|
||||
hmac.Update(input3, inlen3);
|
||||
|
||||
hmac.TruncatedFinal(m_k, m_k.size());
|
||||
|
||||
// Step 5
|
||||
hmac.SetKey(m_k, m_k.size());
|
||||
hmac.Update(m_v, m_v.size());
|
||||
|
||||
hmac.TruncatedFinal(m_v, m_v.size());
|
||||
}
|
||||
|
||||
NAMESPACE_END
|
||||
|
||||
#endif // CRYPTOPP_NIST_DRBG_H
|
||||
|
10
secblock.h
10
secblock.h
@ -498,13 +498,13 @@ public:
|
||||
//! \details The elements are not initialized.
|
||||
//! \note size is the count of elements, and not the number of bytes
|
||||
explicit SecBlock(size_type size=0)
|
||||
: m_size(size), m_mark(SIZE_MAX/sizeof(T)), m_ptr(m_alloc.allocate(size, NULL)) { }
|
||||
: m_mark(SIZE_MAX/sizeof(T)), m_size(size), m_ptr(m_alloc.allocate(size, NULL)) { }
|
||||
|
||||
//! \brief Copy construct a SecBlock from another SecBlock
|
||||
//! \param t the other SecBlock
|
||||
//! \throws std::bad_alloc
|
||||
SecBlock(const SecBlock<T, A> &t)
|
||||
: m_size(t.m_size), m_mark(t.m_mark), m_ptr(m_alloc.allocate(t.m_size, NULL)) {
|
||||
: m_mark(t.m_mark), m_size(t.m_size), m_ptr(m_alloc.allocate(t.m_size, NULL)) {
|
||||
CRYPTOPP_ASSERT((!t.m_ptr && !m_size) || (t.m_ptr && m_size));
|
||||
if (t.m_ptr) {memcpy_s(m_ptr, m_size*sizeof(T), t.m_ptr, t.m_size*sizeof(T));}
|
||||
}
|
||||
@ -518,7 +518,7 @@ public:
|
||||
//! Otherwise, the block is empty and not initialized.
|
||||
//! \note size is the count of elements, and not the number of bytes
|
||||
SecBlock(const T *ptr, size_type len)
|
||||
: m_size(len), m_mark(SIZE_MAX/sizeof(T)), m_ptr(m_alloc.allocate(len, NULL)) {
|
||||
: m_mark(SIZE_MAX/sizeof(T)), m_size(len), m_ptr(m_alloc.allocate(len, NULL)) {
|
||||
CRYPTOPP_ASSERT((!m_ptr && !m_size) || (m_ptr && m_size));
|
||||
if (ptr && m_ptr)
|
||||
memcpy_s(m_ptr, m_size*sizeof(T), ptr, len*sizeof(T));
|
||||
@ -797,14 +797,14 @@ public:
|
||||
{
|
||||
// Swap must occur on the allocator in case its FixedSize that spilled into the heap.
|
||||
std::swap(m_alloc, b.m_alloc);
|
||||
std::swap(m_size, b.m_size);
|
||||
std::swap(m_mark, b.m_mark);
|
||||
std::swap(m_size, b.m_size);
|
||||
std::swap(m_ptr, b.m_ptr);
|
||||
}
|
||||
|
||||
// protected:
|
||||
A m_alloc;
|
||||
size_type m_size, m_mark;
|
||||
size_type m_mark, m_size;
|
||||
T *m_ptr;
|
||||
};
|
||||
|
||||
|
4
test.cpp
4
test.cpp
@ -900,7 +900,7 @@ bool Validate(int alg, bool thorough, const char *seedInput)
|
||||
case 0: result = ValidateAll(thorough); break;
|
||||
case 1: result = TestSettings(); break;
|
||||
case 2: result = TestOS_RNG(); break;
|
||||
case 3: result = TestNIST_DRBG(); break;
|
||||
// case 3: result = TestSecRandom(); break;
|
||||
case 4: result = ValidateMD5(); break;
|
||||
case 5: result = ValidateSHA(); break;
|
||||
case 6: result = ValidateDES(); break;
|
||||
@ -974,6 +974,8 @@ bool Validate(int alg, bool thorough, const char *seedInput)
|
||||
case 74: result = ValidateBLAKE2b(); break;
|
||||
case 75: result = ValidatePoly1305(); break;
|
||||
case 76: result = ValidateSipHash(); break;
|
||||
case 77: result = ValidateHashDRBG(); break;
|
||||
case 78: result = ValidateHmacDRBG(); break;
|
||||
|
||||
#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_IMPORTS)
|
||||
// http://github.com/weidai11/cryptopp/issues/92
|
||||
|
153
validat1.cpp
153
validat1.cpp
@ -73,7 +73,7 @@ bool ValidateAll(bool thorough)
|
||||
pass=TestOS_RNG() && pass;
|
||||
pass=TestAutoSeeded() && pass;
|
||||
pass=TestAutoSeededX917() && pass;
|
||||
pass=TestNIST_DRBG() && pass;
|
||||
// pass=TestSecRandom() && pass;
|
||||
|
||||
#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
|
||||
pass=TestRDRAND() && pass;
|
||||
@ -105,6 +105,9 @@ bool ValidateAll(bool thorough)
|
||||
pass=RunTestDataFile(CRYPTOPP_DATA_DIR "TestVectors/keccak.txt") && pass;
|
||||
pass=RunTestDataFile(CRYPTOPP_DATA_DIR "TestVectors/sha3_fips_202.txt") && pass;
|
||||
|
||||
pass=ValidateHashDRBG() && pass;
|
||||
pass=ValidateHmacDRBG() && pass;
|
||||
|
||||
pass=ValidateTiger() && pass;
|
||||
pass=ValidateRIPEMD() && pass;
|
||||
pass=ValidatePanama() && pass;
|
||||
@ -764,9 +767,9 @@ bool TestRDSEED()
|
||||
}
|
||||
#endif
|
||||
|
||||
bool TestNIST_DRBG()
|
||||
bool ValidateHashDRBG()
|
||||
{
|
||||
cout << "\nTesting NIST DRBG generators...\n\n";
|
||||
cout << "\nTesting NIST Hash DRBGs...\n\n";
|
||||
bool pass=true, fail;
|
||||
|
||||
// # CAVS 14.3
|
||||
@ -795,7 +798,7 @@ bool TestNIST_DRBG()
|
||||
fail = !!memcmp(result, expected, 640/8);
|
||||
pass = !fail && pass;
|
||||
|
||||
cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA1/128/440 (COUNT=0, E=16, N=8)" << endl;
|
||||
cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA1/128/440 (COUNT=0, E=16, N=8)\n";
|
||||
}
|
||||
|
||||
{
|
||||
@ -820,7 +823,7 @@ bool TestNIST_DRBG()
|
||||
fail = !!memcmp(result, expected, 640/8);
|
||||
pass = !fail && pass;
|
||||
|
||||
cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA1/128/440 (COUNT=1, E=16, N=8)" << endl;
|
||||
cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA1/128/440 (COUNT=1, E=16, N=8)\n";
|
||||
}
|
||||
|
||||
{
|
||||
@ -848,7 +851,7 @@ bool TestNIST_DRBG()
|
||||
fail = !!memcmp(result, expected, 640/8);
|
||||
pass = !fail && pass;
|
||||
|
||||
cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA1/128/440 (C0UNT=0, E=16, N=8, A=16)" << endl;
|
||||
cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA1/128/440 (C0UNT=0, E=16, N=8, A=16)\n";
|
||||
}
|
||||
|
||||
{
|
||||
@ -876,7 +879,7 @@ bool TestNIST_DRBG()
|
||||
fail = !!memcmp(result, expected, 640/8);
|
||||
pass = !fail && pass;
|
||||
|
||||
cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA1/128/440 (C0UNT=1, E=16, N=8, A=16)" << endl;
|
||||
cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA1/128/440 (C0UNT=1, E=16, N=8, A=16)\n";
|
||||
}
|
||||
|
||||
{
|
||||
@ -902,7 +905,7 @@ bool TestNIST_DRBG()
|
||||
fail = !!memcmp(result, expected, 640/8);
|
||||
pass = !fail && pass;
|
||||
|
||||
cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA1/128/440 (C0UNT=0, E=16, N=8, A=0, P=16)" << endl;
|
||||
cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA1/128/440 (C0UNT=0, E=16, N=8, A=0, P=16)\n";
|
||||
}
|
||||
|
||||
{
|
||||
@ -928,7 +931,7 @@ bool TestNIST_DRBG()
|
||||
fail = !!memcmp(result, expected, 640/8);
|
||||
pass = !fail && pass;
|
||||
|
||||
cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA1/128/440 (C0UNT=1, E=16, N=8, A=0, P=16)" << endl;
|
||||
cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA1/128/440 (C0UNT=1, E=16, N=8, A=0, P=16)\n";
|
||||
}
|
||||
|
||||
{
|
||||
@ -957,7 +960,7 @@ bool TestNIST_DRBG()
|
||||
fail = !!memcmp(result, expected, 640/8);
|
||||
pass = !fail && pass;
|
||||
|
||||
cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA1/128/440 (C0UNT=0, E=16, N=8, A=16, P=16)" << endl;
|
||||
cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA1/128/440 (C0UNT=0, E=16, N=8, A=16, P=16)\n";
|
||||
}
|
||||
|
||||
{
|
||||
@ -986,7 +989,7 @@ bool TestNIST_DRBG()
|
||||
fail = !!memcmp(result, expected, 640/8);
|
||||
pass = !fail && pass;
|
||||
|
||||
cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA1/128/440 (C0UNT=1, E=16, N=8, A=16, P=16)" << endl;
|
||||
cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA1/128/440 (C0UNT=1, E=16, N=8, A=16, P=16)\n";
|
||||
}
|
||||
|
||||
{
|
||||
@ -1018,7 +1021,7 @@ bool TestNIST_DRBG()
|
||||
fail = !!memcmp(result, expected, 1024/8);
|
||||
pass = !fail && pass;
|
||||
|
||||
cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA256/128/440 (C0UNT=0, E=32, N=16, A=32, P=32)" << endl;
|
||||
cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA256/128/440 (C0UNT=0, E=32, N=16, A=32, P=32)\n";
|
||||
}
|
||||
|
||||
{
|
||||
@ -1050,7 +1053,7 @@ bool TestNIST_DRBG()
|
||||
fail = !!memcmp(result, expected, 1024/8);
|
||||
pass = !fail && pass;
|
||||
|
||||
cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA256/128/440 (C0UNT=1, E=32, N=16, A=32, P=32)" << endl;
|
||||
cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA256/128/440 (C0UNT=1, E=32, N=16, A=32, P=32)\n";
|
||||
}
|
||||
|
||||
{
|
||||
@ -1088,7 +1091,7 @@ bool TestNIST_DRBG()
|
||||
fail = !!memcmp(result, expected, 2048/8);
|
||||
pass = !fail && pass;
|
||||
|
||||
cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA512/256/888 (C0UNT=0, E=32, N=16, A=32, P=32)" << endl;
|
||||
cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA512/256/888 (C0UNT=0, E=32, N=16, A=32, P=32)\n";
|
||||
}
|
||||
|
||||
{
|
||||
@ -1126,7 +1129,127 @@ bool TestNIST_DRBG()
|
||||
fail = !!memcmp(result, expected, 2048/8);
|
||||
pass = !fail && pass;
|
||||
|
||||
cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA512/256/888 (C0UNT=1, E=32, N=16, A=32, P=32)" << endl;
|
||||
cout << (fail ? "FAILED " : "passed ") << "Hash_DRBG SHA512/256/888 (C0UNT=1, E=32, N=16, A=32, P=32)\n";
|
||||
}
|
||||
|
||||
return pass;
|
||||
}
|
||||
|
||||
bool ValidateHmacDRBG()
|
||||
{
|
||||
cout << "\nTesting NIST HMAC DRBGs...\n\n";
|
||||
bool pass=true, fail;
|
||||
|
||||
// # CAVS 14.3
|
||||
// # DRBG800-90A information for "drbg_pr"
|
||||
// # Generated on Tue Apr 02 15:32:12 2013
|
||||
|
||||
{
|
||||
// [SHA-1], [PredictionResistance = False], [EntropyInputLen = 128], [NonceLen = 64]
|
||||
// [PersonalizationStringLen = 0], [AdditionalInputLen = 0], [ReturnedBitsLen = 640]
|
||||
const byte entropy1[] = "\x79\x34\x9b\xbf\x7c\xdd\xa5\x79\x95\x57\x86\x66\x21\xc9\x13\x83";
|
||||
const byte entropy2[] = "\xc7\x21\x5b\x5b\x96\xc4\x8e\x9b\x33\x8c\x74\xe3\xe9\x9d\xfe\xdf";
|
||||
const byte nonce[] = "\x11\x46\x73\x3a\xbf\x8c\x35\xc8";
|
||||
|
||||
HMAC_DRBG<SHA1, 128/8, 440/8> drbg(entropy1, 16, nonce, 8);
|
||||
drbg.IncorporateEntropy(entropy2, 16);
|
||||
|
||||
SecByteBlock result(80);
|
||||
drbg.GenerateBlock(result, result.size());
|
||||
drbg.GenerateBlock(result, result.size());
|
||||
|
||||
const byte expected[] = "\xc6\xa1\x6a\xb8\xd4\x20\x70\x6f\x0f\x34\xab\x7f\xec\x5a\xdc\xa9\xd8\xca\x3a\x13"
|
||||
"\x3e\x15\x9c\xa6\xac\x43\xc6\xf8\xa2\xbe\x22\x83\x4a\x4c\x0a\x0a\xff\xb1\x0d\x71"
|
||||
"\x94\xf1\xc1\xa5\xcf\x73\x22\xec\x1a\xe0\x96\x4e\xd4\xbf\x12\x27\x46\xe0\x87\xfd"
|
||||
"\xb5\xb3\xe9\x1b\x34\x93\xd5\xbb\x98\xfa\xed\x49\xe8\x5f\x13\x0f\xc8\xa4\x59\xb7";
|
||||
|
||||
fail = !!memcmp(result, expected, 640/8);
|
||||
pass = !fail && pass;
|
||||
|
||||
cout << (fail ? "FAILED " : "passed ") << "HMAC_DRBG SHA1/128/440 (COUNT=0, E=16, N=8)\n";
|
||||
}
|
||||
|
||||
{
|
||||
// [SHA-1], [PredictionResistance = False], [EntropyInputLen = 128], [NonceLen = 64]
|
||||
// [PersonalizationStringLen = 0], [AdditionalInputLen = 0], [ReturnedBitsLen = 640]
|
||||
const byte entropy1[] = "\xee\x57\xfc\x23\x60\x0f\xb9\x02\x9a\x9e\xc6\xc8\x2e\x7b\x51\xe4";
|
||||
const byte entropy2[] = "\x84\x1d\x27\x6c\xa9\x51\x90\x61\xd9\x2d\x7d\xdf\xa6\x62\x8c\xa3";
|
||||
const byte nonce[] = "\x3e\x97\x21\xe4\x39\x3e\xf9\xad";
|
||||
|
||||
HMAC_DRBG<SHA1, 128/8, 440/8> drbg(entropy1, 16, nonce, 8);
|
||||
drbg.IncorporateEntropy(entropy2, 16);
|
||||
|
||||
SecByteBlock result(80);
|
||||
drbg.GenerateBlock(result, result.size());
|
||||
drbg.GenerateBlock(result, result.size());
|
||||
|
||||
const byte expected[] = "\xee\x26\xa5\xc8\xef\x08\xa1\xca\x8f\x14\x15\x4d\x67\xc8\x8f\x5e\x7e\xd8\x21\x9d"
|
||||
"\x93\x1b\x98\x42\xac\x00\x39\xf2\x14\x55\x39\xf2\x14\x2b\x44\x11\x7a\x99\x8c\x22"
|
||||
"\xf5\x90\xf6\xc9\xb3\x8b\x46\x5b\x78\x3e\xcf\xf1\x3a\x77\x50\x20\x1f\x7e\xcf\x1b"
|
||||
"\x8a\xb3\x93\x60\x4c\x73\xb2\x38\x93\x36\x60\x9a\xf3\x44\x0c\xde\x43\x29\x8b\x84";
|
||||
|
||||
fail = !!memcmp(result, expected, 640/8);
|
||||
pass = !fail && pass;
|
||||
|
||||
cout << (fail ? "FAILED " : "passed ") << "HMAC_DRBG SHA1/128/440 (COUNT=1, E=16, N=8)\n";
|
||||
}
|
||||
|
||||
// *****************************************************
|
||||
|
||||
{
|
||||
// [SHA-1], [PredictionResistance = False], [EntropyInputLen = 128], [NonceLen = 64]
|
||||
// [PersonalizationStringLen = 0], [AdditionalInputLen = 16], [ReturnedBitsLen = 640]
|
||||
const byte entropy1[] = "\x7d\x70\x52\xa7\x76\xfd\x2f\xb3\xd7\x19\x1f\x73\x33\x04\xee\x8b";
|
||||
const byte entropy2[] = "\x49\x04\x7e\x87\x9d\x61\x09\x55\xee\xd9\x16\xe4\x06\x0e\x00\xc9";
|
||||
const byte nonce[] = "\xbe\x4a\x0c\xee\xdc\xa8\x02\x07";
|
||||
const byte additional1[] = "\xfd\x8b\xb3\x3a\xab\x2f\x6c\xdf\xbc\x54\x18\x11\x86\x1d\x51\x8d";
|
||||
const byte additional2[] = "\x99\xaf\xe3\x47\x54\x04\x61\xdd\xf6\xab\xeb\x49\x1e\x07\x15\xb4";
|
||||
const byte additional3[] = "\x02\xf7\x73\x48\x2d\xd7\xae\x66\xf7\x6e\x38\x15\x98\xa6\x4e\xf0";
|
||||
|
||||
HMAC_DRBG<SHA1, 128/8, 440/8> drbg(entropy1, 16, nonce, 8);
|
||||
drbg.IncorporateEntropy(entropy2, 16, additional1, 16);
|
||||
|
||||
SecByteBlock result(80);
|
||||
drbg.GenerateBlock(additional2, 16, result, result.size());
|
||||
drbg.GenerateBlock(additional3, 16, result, result.size());
|
||||
|
||||
const byte expected[] = "\xa7\x36\x34\x38\x44\xfc\x92\x51\x13\x91\xdb\x0a\xdd\xd9\x06\x4d\xbe\xe2\x4c\x89"
|
||||
"\x76\xaa\x25\x9a\x9e\x3b\x63\x68\xaa\x6d\xe4\xc9\xbf\x3a\x0e\xff\xcd\xa9\xcb\x0e"
|
||||
"\x9d\xc3\x36\x52\xab\x58\xec\xb7\x65\x0e\xd8\x04\x67\xf7\x6a\x84\x9f\xb1\xcf\xc1"
|
||||
"\xed\x0a\x09\xf7\x15\x50\x86\x06\x4d\xb3\x24\xb1\xe1\x24\xf3\xfc\x9e\x61\x4f\xcb";
|
||||
|
||||
fail = !!memcmp(result, expected, 640/8);
|
||||
pass = !fail && pass;
|
||||
|
||||
cout << (fail ? "FAILED " : "passed ") << "HMAC_DRBG SHA1/128/440 (COUNT=0, E=16, N=8, A=16)\n";
|
||||
}
|
||||
|
||||
{
|
||||
// [SHA-1], [PredictionResistance = False], [EntropyInputLen = 128], [NonceLen = 64]
|
||||
// [PersonalizationStringLen = 0], [AdditionalInputLen = 16], [ReturnedBitsLen = 640]
|
||||
const byte entropy1[] = "\x29\xc6\x2a\xfa\x3c\x52\x20\x8a\x3f\xde\xcb\x43\xfa\x61\x3f\x15";
|
||||
const byte entropy2[] = "\xbd\x87\xbe\x99\xd1\x84\x16\x54\x12\x31\x41\x40\xd4\x02\x71\x41";
|
||||
const byte nonce[] = "\x6c\x9e\xb5\x9a\xc3\xc2\xd4\x8b";
|
||||
const byte additional1[] = "\x43\x3d\xda\xf2\x59\xd1\x4b\xcf\x89\x76\x30\xcc\xaa\x27\x33\x8c";
|
||||
const byte additional2[] = "\x14\x11\x46\xd4\x04\xf2\x84\xc2\xd0\x2b\x6a\x10\x15\x6e\x33\x82";
|
||||
const byte additional3[] = "\xed\xc3\x43\xdb\xff\xe7\x1a\xb4\x11\x4a\xc3\x63\x9d\x44\x5b\x65";
|
||||
|
||||
HMAC_DRBG<SHA1, 128/8, 440/8> drbg(entropy1, 16, nonce, 8);
|
||||
drbg.IncorporateEntropy(entropy2, 16, additional1, 16);
|
||||
|
||||
SecByteBlock result(80);
|
||||
drbg.GenerateBlock(additional2, 16, result, result.size());
|
||||
drbg.GenerateBlock(additional3, 16, result, result.size());
|
||||
|
||||
const byte expected[] = "\x8c\x73\x0f\x05\x26\x69\x4d\x5a\x9a\x45\xdb\xab\x05\x7a\x19\x75\x35\x7d\x65\xaf"
|
||||
"\xd3\xef\xf3\x03\x32\x0b\xd1\x40\x61\xf9\xad\x38\x75\x91\x02\xb6\xc6\x01\x16\xf6"
|
||||
"\xdb\x7a\x6e\x8e\x7a\xb9\x4c\x05\x50\x0b\x4d\x1e\x35\x7d\xf8\xe9\x57\xac\x89\x37"
|
||||
"\xb0\x5f\xb3\xd0\x80\xa0\xf9\x06\x74\xd4\x4d\xe1\xbd\x6f\x94\xd2\x95\xc4\x51\x9d";
|
||||
|
||||
fail = !!memcmp(result, expected, 640/8);
|
||||
pass = !fail && pass;
|
||||
|
||||
cout << (fail ? "FAILED " : "passed ") << "HMAC_DRBG SHA1/128/440 (COUNT=1, E=16, N=8, A=16)\n";
|
||||
}
|
||||
|
||||
return pass;
|
||||
|
@ -8,7 +8,7 @@
|
||||
bool ValidateAll(bool thorough);
|
||||
bool TestSettings();
|
||||
bool TestOS_RNG();
|
||||
bool TestNIST_DRBG();
|
||||
// bool TestSecRandom();
|
||||
bool TestAutoSeeded();
|
||||
bool TestAutoSeededX917();
|
||||
|
||||
@ -94,6 +94,9 @@ bool ValidateECDSA();
|
||||
bool ValidateECGDSA();
|
||||
bool ValidateESIGN();
|
||||
|
||||
bool ValidateHashDRBG();
|
||||
bool ValidateHmacDRBG();
|
||||
|
||||
#if defined(CRYPTOPP_DEBUG) && !defined(CRYPTOPP_IMPORTS)
|
||||
// http://github.com/weidai11/cryptopp/issues/92
|
||||
bool TestSecBlock();
|
||||
|
Loading…
Reference in New Issue
Block a user