9#ifndef CRYPTOPP_NIST_DRBG_H
10#define CRYPTOPP_NIST_DRBG_H
33 explicit Err(
const std::string &c,
const std::string &m)
66 virtual void IncorporateEntropy(
const byte *entropy,
size_t entropyLength,
const byte* additional,
size_t additionaLength)=0;
85 virtual void GenerateBlock(
const byte* additional,
size_t additionaLength,
byte *output,
size_t size)=0;
142 virtual void DRBG_Instantiate(
const byte* entropy,
size_t entropyLength,
143 const byte* nonce,
size_t nonceLength,
const byte* personalization,
size_t personalizationLength)=0;
145 virtual void DRBG_Reseed(
const byte* entropy,
size_t entropyLength,
const byte* additional,
size_t additionaLength)=0;
166template <
typename HASH=
SHA256,
unsigned int STRENGTH=128/8,
unsigned int SEEDLENGTH=440/8>
170 CRYPTOPP_CONSTANT(SECURITY_STRENGTH=STRENGTH);
171 CRYPTOPP_CONSTANT(SEED_LENGTH=SEEDLENGTH);
172 CRYPTOPP_CONSTANT(MINIMUM_ENTROPY=STRENGTH);
173 CRYPTOPP_CONSTANT(MINIMUM_NONCE=0);
174 CRYPTOPP_CONSTANT(MINIMUM_ADDITIONAL=0);
175 CRYPTOPP_CONSTANT(MINIMUM_PERSONALIZATION=0);
176 CRYPTOPP_CONSTANT(MAXIMUM_ENTROPY=INT_MAX);
177 CRYPTOPP_CONSTANT(MAXIMUM_NONCE=INT_MAX);
178 CRYPTOPP_CONSTANT(MAXIMUM_ADDITIONAL=INT_MAX);
179 CRYPTOPP_CONSTANT(MAXIMUM_PERSONALIZATION=INT_MAX);
180 CRYPTOPP_CONSTANT(MAXIMUM_BYTES_PER_REQUEST=65536);
181 CRYPTOPP_CONSTANT(MAXIMUM_REQUESTS_BEFORE_RESEED=INT_MAX);
183 static std::string StaticAlgorithmName() {
return std::string(
"Hash_DRBG(") + HASH::StaticAlgorithmName() + std::string(
")"); }
210 Hash_DRBG(
const byte* entropy=NULLPTR,
size_t entropyLength=STRENGTH,
const byte* nonce=NULLPTR,
211 size_t nonceLength=0,
const byte* personalization=NULLPTR,
size_t personalizationLength=0)
212 :
NIST_DRBG(), m_c(SEEDLENGTH), m_v(SEEDLENGTH), m_reseed(0)
215 std::memset(m_c.
data(), 0x00, m_c.
size());
217 std::memset(m_v.
data(), 0x00, m_v.
size());
219 if (entropy != NULLPTR && entropyLength != 0)
220 DRBG_Instantiate(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength);
233 {
return DRBG_Reseed(input, length, NULLPTR, 0);}
235 void IncorporateEntropy(
const byte *entropy,
size_t entropyLength,
const byte* additional,
size_t additionaLength)
236 {
return DRBG_Reseed(entropy, entropyLength, additional, additionaLength);}
239 {
return Hash_Generate(NULLPTR, 0, output, size);}
241 void GenerateBlock(
const byte* additional,
size_t additionaLength,
byte *output,
size_t size)
242 {
return Hash_Generate(additional, additionaLength, output, size);}
245 {HASH hash;
return hash.AlgorithmProvider();}
249 void DRBG_Instantiate(
const byte* entropy,
size_t entropyLength,
const byte* nonce,
size_t nonceLength,
250 const byte* personalization,
size_t personalizationLength);
253 void DRBG_Reseed(
const byte* entropy,
size_t entropyLength,
const byte* additional,
size_t additionaLength);
256 void Hash_Generate(
const byte* additional,
size_t additionaLength,
byte *output,
size_t size);
259 void Hash_Update(
const byte* input1,
size_t inlen1,
const byte* input2,
size_t inlen2,
260 const byte* input3,
size_t inlen3,
const byte* input4,
size_t inlen4,
byte* output,
size_t outlen);
290template <
typename HASH=
SHA256,
unsigned int STRENGTH=128/8,
unsigned int SEEDLENGTH=440/8>
294 CRYPTOPP_CONSTANT(SECURITY_STRENGTH=STRENGTH);
295 CRYPTOPP_CONSTANT(SEED_LENGTH=SEEDLENGTH);
296 CRYPTOPP_CONSTANT(MINIMUM_ENTROPY=STRENGTH);
297 CRYPTOPP_CONSTANT(MINIMUM_NONCE=0);
298 CRYPTOPP_CONSTANT(MINIMUM_ADDITIONAL=0);
299 CRYPTOPP_CONSTANT(MINIMUM_PERSONALIZATION=0);
300 CRYPTOPP_CONSTANT(MAXIMUM_ENTROPY=INT_MAX);
301 CRYPTOPP_CONSTANT(MAXIMUM_NONCE=INT_MAX);
302 CRYPTOPP_CONSTANT(MAXIMUM_ADDITIONAL=INT_MAX);
303 CRYPTOPP_CONSTANT(MAXIMUM_PERSONALIZATION=INT_MAX);
304 CRYPTOPP_CONSTANT(MAXIMUM_BYTES_PER_REQUEST=65536);
305 CRYPTOPP_CONSTANT(MAXIMUM_REQUESTS_BEFORE_RESEED=INT_MAX);
307 static std::string StaticAlgorithmName() {
return std::string(
"HMAC_DRBG(") + HASH::StaticAlgorithmName() + std::string(
")"); }
334 HMAC_DRBG(
const byte* entropy=NULLPTR,
size_t entropyLength=STRENGTH,
const byte* nonce=NULLPTR,
335 size_t nonceLength=0,
const byte* personalization=NULLPTR,
size_t personalizationLength=0)
336 :
NIST_DRBG(), m_k(HASH::DIGESTSIZE), m_v(HASH::DIGESTSIZE), m_reseed(0)
339 std::memset(m_k, 0x00, m_k.
size());
341 std::memset(m_v, 0x00, m_v.
size());
343 if (entropy != NULLPTR && entropyLength != 0)
344 DRBG_Instantiate(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength);
357 {
return DRBG_Reseed(input, length, NULLPTR, 0);}
359 void IncorporateEntropy(
const byte *entropy,
size_t entropyLength,
const byte* additional,
size_t additionaLength)
360 {
return DRBG_Reseed(entropy, entropyLength, additional, additionaLength);}
363 {
return HMAC_Generate(NULLPTR, 0, output, size);}
365 void GenerateBlock(
const byte* additional,
size_t additionaLength,
byte *output,
size_t size)
366 {
return HMAC_Generate(additional, additionaLength, output, size);}
369 {HASH hash;
return hash.AlgorithmProvider();}
373 void DRBG_Instantiate(
const byte* entropy,
size_t entropyLength,
const byte* nonce,
size_t nonceLength,
374 const byte* personalization,
size_t personalizationLength);
377 void DRBG_Reseed(
const byte* entropy,
size_t entropyLength,
const byte* additional,
size_t additionaLength);
380 void HMAC_Generate(
const byte* additional,
size_t additionaLength,
byte *output,
size_t size);
383 void HMAC_Update(
const byte* input1,
size_t inlen1,
const byte* input2,
size_t inlen2,
const byte* input3,
size_t inlen3);
399template <
typename HASH,
unsigned int STRENGTH,
unsigned int SEEDLENGTH>
401 const byte* personalization,
size_t personalizationLength)
409 if (entropyLength < MINIMUM_ENTROPY)
410 throw NIST_DRBG::Err(
"Hash_DRBG",
"Insufficient entropy during instantiate");
420 Hash_Update(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength, NULLPTR, 0, t1, t1.size());
421 Hash_Update(&zero, 1, t1, t1.size(), NULLPTR, 0, NULLPTR, 0, t2, t2.size());
423 m_v.swap(t1); m_c.swap(t2);
428template <
typename HASH,
unsigned int STRENGTH,
unsigned int SEEDLENGTH>
437 if (entropyLength < MINIMUM_ENTROPY)
438 throw NIST_DRBG::Err(
"Hash_DRBG",
"Insufficient entropy during reseed");
445 const byte zero = 0, one = 1;
447 Hash_Update(&one, 1, m_v, m_v.size(), entropy, entropyLength, additional, additionaLength, t1, t1.size());
448 Hash_Update(&zero, 1, t1, t1.size(), NULLPTR, 0, NULLPTR, 0, t2, t2.size());
450 m_v.swap(t1); m_c.swap(t2);
455template <
typename HASH,
unsigned int STRENGTH,
unsigned int SEEDLENGTH>
459 if (
static_cast<word64>(m_reseed) >=
static_cast<word64>(MaxRequestBeforeReseed()))
462 if (size > MaxBytesPerRequest())
470 if (additional && additionaLength)
473 m_temp.New(HASH::DIGESTSIZE);
475 m_hash.Update(&two, 1);
476 m_hash.Update(m_v, m_v.size());
477 m_hash.Update(additional, additionaLength);
478 m_hash.Final(m_temp);
481 int carry=0, j=HASH::DIGESTSIZE-1, i=SEEDLENGTH-1;
484 carry = m_v[i] + m_temp[j] + carry;
485 m_v[i] =
static_cast<byte>(carry);
486 i--; j--; carry >>= 8;
490 carry = m_v[i] + carry;
491 m_v[i] =
static_cast<byte>(carry);
501 m_hash.Update(m_temp, m_temp.size());
502 size_t count =
STDMIN(size, (
size_t)HASH::DIGESTSIZE);
503 m_hash.TruncatedFinal(output, count);
506 size -= count; output += count;
512 const byte three = 3;
513 m_temp.New(HASH::DIGESTSIZE);
515 m_hash.Update(&three, 1);
516 m_hash.Update(m_v, m_v.size());
517 m_hash.Final(m_temp);
521 int carry=0, k=
sizeof(m_reseed)-1, j=HASH::DIGESTSIZE-1, i=SEEDLENGTH-1;
525 carry = m_v[i] + m_c[i] + m_temp[j] + GetByte<word64>(
BIG_ENDIAN_ORDER, m_reseed, k) + carry;
526 m_v[i] =
static_cast<byte>(carry);
527 i--; j--; k--; carry >>= 8;
532 carry = m_v[i] + m_c[i] + m_temp[j] + carry;
533 m_v[i] =
static_cast<byte>(carry);
534 i--; j--; carry >>= 8;
539 carry = m_v[i] + m_c[i] + carry;
540 m_v[i] =
static_cast<byte>(carry);
549template <
typename HASH,
unsigned int STRENGTH,
unsigned int SEEDLENGTH>
551 const byte* input3,
size_t inlen3,
const byte* input4,
size_t inlen4,
byte* output,
size_t outlen)
558 m_hash.Update(&counter, 1);
559 m_hash.Update(
reinterpret_cast<const byte*
>(&bits), 4);
561 if (input1 && inlen1)
562 m_hash.Update(input1, inlen1);
563 if (input2 && inlen2)
564 m_hash.Update(input2, inlen2);
565 if (input3 && inlen3)
566 m_hash.Update(input3, inlen3);
567 if (input4 && inlen4)
568 m_hash.Update(input4, inlen4);
570 size_t count =
STDMIN(outlen, (
size_t)HASH::DIGESTSIZE);
571 m_hash.TruncatedFinal(output, count);
573 output += count; outlen -= count;
581template <
typename HASH,
unsigned int STRENGTH,
unsigned int SEEDLENGTH>
583 const byte* personalization,
size_t personalizationLength)
591 if (entropyLength < MINIMUM_ENTROPY)
592 throw NIST_DRBG::Err(
"HMAC_DRBG",
"Insufficient entropy during instantiate");
600 std::fill(m_k.begin(), m_k.begin()+m_k.size(),
byte(0));
601 std::fill(m_v.begin(), m_v.begin()+m_v.size(),
byte(1));
603 HMAC_Update(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength);
608template <
typename HASH,
unsigned int STRENGTH,
unsigned int SEEDLENGTH>
617 if (entropyLength < MINIMUM_ENTROPY)
618 throw NIST_DRBG::Err(
"HMAC_DRBG",
"Insufficient entropy during reseed");
625 HMAC_Update(entropy, entropyLength, additional, additionaLength, NULLPTR, 0);
630template <
typename HASH,
unsigned int STRENGTH,
unsigned int SEEDLENGTH>
634 if (
static_cast<word64>(m_reseed) >=
static_cast<word64>(MaxRequestBeforeReseed()))
637 if (size > MaxBytesPerRequest())
645 if (additional && additionaLength)
646 HMAC_Update(additional, additionaLength, NULLPTR, 0, NULLPTR, 0);
649 m_hmac.SetKey(m_k, m_k.size());
653 m_hmac.Update(m_v, m_v.size());
654 m_hmac.TruncatedFinal(m_v, m_v.size());
656 size_t count =
STDMIN(size, (
size_t)HASH::DIGESTSIZE);
657 memcpy(output, m_v, count);
658 size -= count; output += count;
661 HMAC_Update(additional, additionaLength, NULLPTR, 0, NULLPTR, 0);
666template <
typename HASH,
unsigned int STRENGTH,
unsigned int SEEDLENGTH>
669 const byte zero = 0, one = 1;
672 m_hmac.SetKey(m_k, m_k.size());
673 m_hmac.Update(m_v, m_v.size());
674 m_hmac.Update(&zero, 1);
676 if (input1 && inlen1)
677 m_hmac.Update(input1, inlen1);
678 if (input2 && inlen2)
679 m_hmac.Update(input2, inlen2);
680 if (input3 && inlen3)
681 m_hmac.Update(input3, inlen3);
683 m_hmac.TruncatedFinal(m_k, m_k.size());
686 m_hmac.SetKey(m_k, m_k.size());
687 m_hmac.Update(m_v, m_v.size());
689 m_hmac.TruncatedFinal(m_v, m_v.size());
692 if ((inlen1 | inlen2 | inlen3) == 0)
696 m_hmac.SetKey(m_k, m_k.size());
697 m_hmac.Update(m_v, m_v.size());
698 m_hmac.Update(&one, 1);
700 if (input1 && inlen1)
701 m_hmac.Update(input1, inlen1);
702 if (input2 && inlen2)
703 m_hmac.Update(input2, inlen2);
704 if (input3 && inlen3)
705 m_hmac.Update(input3, inlen3);
707 m_hmac.TruncatedFinal(m_k, m_k.size());
710 m_hmac.SetKey(m_k, m_k.size());
711 m_hmac.Update(m_v, m_v.size());
713 m_hmac.TruncatedFinal(m_v, m_v.size());
Base class for all exceptions thrown by the library.
HMAC_DRBG from SP 800-90A Rev 1 (June 2015)
void IncorporateEntropy(const byte *input, size_t length)
Update RNG state with additional unpredictable values.
unsigned int SeedLength() const
Provides the seed length.
unsigned int MaxRequestBeforeReseed() const
Provides the maximum number of requests before a reseed.
unsigned int MinEntropyLength() const
Provides the minimum entropy size.
void IncorporateEntropy(const byte *entropy, size_t entropyLength, const byte *additional, size_t additionaLength)
Update RNG state with additional unpredictable values.
void GenerateBlock(byte *output, size_t size)
Generate random array of bytes.
unsigned int SecurityStrength() const
Provides the security strength.
unsigned int MaxBytesPerRequest() const
Provides the maximum size of a request to GenerateBlock.
unsigned int MinNonceLength() const
Provides the minimum nonce size.
unsigned int MaxEntropyLength() const
Provides the maximum entropy size.
std::string AlgorithmProvider() const
Retrieve the provider of this algorithm.
void GenerateBlock(const byte *additional, size_t additionaLength, byte *output, size_t size)
Generate random array of bytes.
HMAC_DRBG(const byte *entropy=NULL, size_t entropyLength=STRENGTH, const byte *nonce=NULL, size_t nonceLength=0, const byte *personalization=NULL, size_t personalizationLength=0)
Construct a HMAC DRBG.
unsigned int MaxNonceLength() const
Provides the maximum nonce size.
Hash_DRBG from SP 800-90A Rev 1 (June 2015)
unsigned int MinNonceLength() const
Provides the minimum nonce size.
unsigned int MaxEntropyLength() const
Provides the maximum entropy size.
void IncorporateEntropy(const byte *input, size_t length)
Update RNG state with additional unpredictable values.
unsigned int SeedLength() const
Provides the seed length.
void GenerateBlock(const byte *additional, size_t additionaLength, byte *output, size_t size)
Generate random array of bytes.
unsigned int MaxRequestBeforeReseed() const
Provides the maximum number of requests before a reseed.
unsigned int MaxBytesPerRequest() const
Provides the maximum size of a request to GenerateBlock.
void IncorporateEntropy(const byte *entropy, size_t entropyLength, const byte *additional, size_t additionaLength)
Update RNG state with additional unpredictable values.
std::string AlgorithmProvider() const
Retrieve the provider of this algorithm.
Hash_DRBG(const byte *entropy=NULL, size_t entropyLength=STRENGTH, const byte *nonce=NULL, size_t nonceLength=0, const byte *personalization=NULL, size_t personalizationLength=0)
Construct a Hash DRBG.
void GenerateBlock(byte *output, size_t size)
Generate random array of bytes.
unsigned int SecurityStrength() const
Provides the security strength.
unsigned int MaxNonceLength() const
Provides the maximum nonce size.
unsigned int MinEntropyLength() const
Provides the minimum entropy size.
Exception thrown when a NIST DRBG encounters an error.
Interface for NIST DRBGs from SP 800-90A.
virtual void IncorporateEntropy(const byte *input, size_t length)=0
Update RNG state with additional unpredictable values.
virtual unsigned int SecurityStrength() const =0
Provides the security strength.
virtual void IncorporateEntropy(const byte *entropy, size_t entropyLength, const byte *additional, size_t additionaLength)=0
Update RNG state with additional unpredictable values.
virtual unsigned int MaxEntropyLength() const =0
Provides the maximum entropy size.
virtual void GenerateBlock(byte *output, size_t size)=0
Generate random array of bytes.
virtual unsigned int MinEntropyLength() const =0
Provides the minimum entropy size.
virtual void GenerateBlock(const byte *additional, size_t additionaLength, byte *output, size_t size)=0
Generate random array of bytes.
virtual unsigned int MaxBytesPerRequest() const =0
Provides the maximum size of a request to GenerateBlock.
virtual bool CanIncorporateEntropy() const
Determines if a generator can accept additional entropy.
virtual unsigned int MaxRequestBeforeReseed() const =0
Provides the maximum number of requests before a reseed.
virtual unsigned int MaxNonceLength() const =0
Provides the maximum nonce size.
virtual unsigned int MinNonceLength() const =0
Provides the minimum nonce size.
virtual unsigned int SeedLength() const =0
Provides the seed length.
Ensures an object is not copyable.
Interface for random number generators.
A::pointer data()
Provides a pointer to the first element in the memory block.
size_type size() const
Provides the count of elements in the SecBlock.
unsigned int word32
32-bit unsigned datatype
unsigned long long word64
64-bit unsigned datatype
Abstract base classes that provide a uniform interface to this library.
@ BIG_ENDIAN_ORDER
byte order is big-endian
Classes for HMAC message authentication codes.
void IncrementCounterByOne(byte *inout, unsigned int size)
Performs an addition with carry on a block of bytes.
const T & STDMIN(const T &a, const T &b)
Replacement function for std::min.
T ConditionalByteReverse(ByteOrder order, T value)
Reverses bytes in a value depending upon endianness.
Crypto++ library namespace.
Classes and functions for secure memory allocations.
Classes for SHA-1 and SHA-2 family of message digests.
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.