9 #ifndef CRYPTOPP_NIST_DRBG_H
10 #define CRYPTOPP_NIST_DRBG_H
31 explicit Err(
const std::string &c,
const std::string &m)
64 virtual void IncorporateEntropy(
const byte *entropy,
size_t entropyLength,
const byte* additional,
size_t additionaLength)=0;
83 virtual void GenerateBlock(
const byte* additional,
size_t additionaLength,
byte *output,
size_t size)=0;
140 virtual void DRBG_Instantiate(
const byte* entropy,
size_t entropyLength,
141 const byte* nonce,
size_t nonceLength,
const byte* personalization,
size_t personalizationLength)=0;
143 virtual void DRBG_Reseed(
const byte* entropy,
size_t entropyLength,
const byte* additional,
size_t additionaLength)=0;
162 template <
typename HASH=
SHA256,
unsigned int STRENGTH=128/8,
unsigned int SEEDLENGTH=440/8>
166 CRYPTOPP_CONSTANT(SECURITY_STRENGTH=STRENGTH)
167 CRYPTOPP_CONSTANT(SEED_LENGTH=SEEDLENGTH)
168 CRYPTOPP_CONSTANT(MINIMUM_ENTROPY=STRENGTH)
169 CRYPTOPP_CONSTANT(MINIMUM_NONCE=0)
170 CRYPTOPP_CONSTANT(MINIMUM_ADDITIONAL=0)
171 CRYPTOPP_CONSTANT(MINIMUM_PERSONALIZATION=0)
172 CRYPTOPP_CONSTANT(MAXIMUM_ENTROPY=INT_MAX)
173 CRYPTOPP_CONSTANT(MAXIMUM_NONCE=INT_MAX)
174 CRYPTOPP_CONSTANT(MAXIMUM_ADDITIONAL=INT_MAX)
175 CRYPTOPP_CONSTANT(MAXIMUM_PERSONALIZATION=INT_MAX)
176 CRYPTOPP_CONSTANT(MAXIMUM_BYTES_PER_REQUEST=65536)
177 CRYPTOPP_CONSTANT(MAXIMUM_REQUESTS_BEFORE_RESEED=INT_MAX)
179 static std::string StaticAlgorithmName() {
return std::string(
"Hash_DRBG(") + HASH::StaticAlgorithmName() + std::string(
")"); }
206 Hash_DRBG(
const byte* entropy=NULLPTR,
size_t entropyLength=STRENGTH,
const byte* nonce=NULLPTR,
207 size_t nonceLength=0,
const byte* personalization=NULLPTR,
size_t personalizationLength=0)
208 :
NIST_DRBG(), m_c(SEEDLENGTH), m_v(SEEDLENGTH), m_reseed(0)
210 if (entropy != NULLPTR && entropyLength != 0)
211 DRBG_Instantiate(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength);
224 {
return DRBG_Reseed(input, length, NULLPTR, 0);}
226 void IncorporateEntropy(
const byte *entropy,
size_t entropyLength,
const byte* additional,
size_t additionaLength)
227 {
return DRBG_Reseed(entropy, entropyLength, additional, additionaLength);}
230 {
return Hash_Generate(NULLPTR, 0, output, size);}
232 void GenerateBlock(
const byte* additional,
size_t additionaLength,
byte *output,
size_t size)
233 {
return Hash_Generate(additional, additionaLength, output, size);}
236 {HASH hash;
return hash.AlgorithmProvider();}
240 void DRBG_Instantiate(
const byte* entropy,
size_t entropyLength,
const byte* nonce,
size_t nonceLength,
241 const byte* personalization,
size_t personalizationLength);
244 void DRBG_Reseed(
const byte* entropy,
size_t entropyLength,
const byte* additional,
size_t additionaLength);
247 void Hash_Generate(
const byte* additional,
size_t additionaLength,
byte *output,
size_t size);
250 void Hash_Update(
const byte* input1,
size_t inlen1,
const byte* input2,
size_t inlen2,
251 const byte* input3,
size_t inlen3,
const byte* input4,
size_t inlen4,
byte* output,
size_t outlen);
279 template <
typename HASH=
SHA256,
unsigned int STRENGTH=128/8,
unsigned int SEEDLENGTH=440/8>
283 CRYPTOPP_CONSTANT(SECURITY_STRENGTH=STRENGTH)
284 CRYPTOPP_CONSTANT(SEED_LENGTH=SEEDLENGTH)
285 CRYPTOPP_CONSTANT(MINIMUM_ENTROPY=STRENGTH)
286 CRYPTOPP_CONSTANT(MINIMUM_NONCE=0)
287 CRYPTOPP_CONSTANT(MINIMUM_ADDITIONAL=0)
288 CRYPTOPP_CONSTANT(MINIMUM_PERSONALIZATION=0)
289 CRYPTOPP_CONSTANT(MAXIMUM_ENTROPY=INT_MAX)
290 CRYPTOPP_CONSTANT(MAXIMUM_NONCE=INT_MAX)
291 CRYPTOPP_CONSTANT(MAXIMUM_ADDITIONAL=INT_MAX)
292 CRYPTOPP_CONSTANT(MAXIMUM_PERSONALIZATION=INT_MAX)
293 CRYPTOPP_CONSTANT(MAXIMUM_BYTES_PER_REQUEST=65536)
294 CRYPTOPP_CONSTANT(MAXIMUM_REQUESTS_BEFORE_RESEED=INT_MAX)
296 static std::string StaticAlgorithmName() {
return std::string(
"HMAC_DRBG(") + HASH::StaticAlgorithmName() + std::string(
")"); }
323 HMAC_DRBG(
const byte* entropy=NULLPTR,
size_t entropyLength=STRENGTH,
const byte* nonce=NULLPTR,
324 size_t nonceLength=0,
const byte* personalization=NULLPTR,
size_t personalizationLength=0)
325 :
NIST_DRBG(), m_k(HASH::DIGESTSIZE), m_v(HASH::DIGESTSIZE), m_reseed(0)
327 if (entropy != NULLPTR && entropyLength != 0)
328 DRBG_Instantiate(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength);
341 {
return DRBG_Reseed(input, length, NULLPTR, 0);}
343 void IncorporateEntropy(
const byte *entropy,
size_t entropyLength,
const byte* additional,
size_t additionaLength)
344 {
return DRBG_Reseed(entropy, entropyLength, additional, additionaLength);}
347 {
return HMAC_Generate(NULLPTR, 0, output, size);}
349 void GenerateBlock(
const byte* additional,
size_t additionaLength,
byte *output,
size_t size)
350 {
return HMAC_Generate(additional, additionaLength, output, size);}
353 {HASH hash;
return hash.AlgorithmProvider();}
357 void DRBG_Instantiate(
const byte* entropy,
size_t entropyLength,
const byte* nonce,
size_t nonceLength,
358 const byte* personalization,
size_t personalizationLength);
361 void DRBG_Reseed(
const byte* entropy,
size_t entropyLength,
const byte* additional,
size_t additionaLength);
364 void HMAC_Generate(
const byte* additional,
size_t additionaLength,
byte *output,
size_t size);
367 void HMAC_Update(
const byte* input1,
size_t inlen1,
const byte* input2,
size_t inlen2,
const byte* input3,
size_t inlen3);
383 template <
typename HASH,
unsigned int STRENGTH,
unsigned int SEEDLENGTH>
385 const byte* personalization,
size_t personalizationLength)
393 if (entropyLength < MINIMUM_ENTROPY)
394 throw NIST_DRBG::Err(
"Hash_DRBG",
"Insufficient entropy during instantiate");
404 Hash_Update(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength, NULLPTR, 0, t1, t1.size());
405 Hash_Update(&zero, 1, t1, t1.size(), NULLPTR, 0, NULLPTR, 0, t2, t2.size());
407 m_v.swap(t1); m_c.swap(t2);
412 template <
typename HASH,
unsigned int STRENGTH,
unsigned int SEEDLENGTH>
421 if (entropyLength < MINIMUM_ENTROPY)
422 throw NIST_DRBG::Err(
"Hash_DRBG",
"Insufficient entropy during reseed");
429 const byte zero = 0, one = 1;
431 Hash_Update(&one, 1, m_v, m_v.size(), entropy, entropyLength, additional, additionaLength, t1, t1.size());
432 Hash_Update(&zero, 1, t1, t1.size(), NULLPTR, 0, NULLPTR, 0, t2, t2.size());
434 m_v.swap(t1); m_c.swap(t2);
439 template <
typename HASH,
unsigned int STRENGTH,
unsigned int SEEDLENGTH>
443 if (
static_cast<word64
>(m_reseed) >=
static_cast<word64
>(MaxRequestBeforeReseed()))
446 if (size > MaxBytesPerRequest())
454 if (additional && additionaLength)
457 m_temp.New(HASH::DIGESTSIZE);
459 m_hash.Update(&two, 1);
460 m_hash.Update(m_v, m_v.size());
461 m_hash.Update(additional, additionaLength);
462 m_hash.Final(m_temp);
465 int carry=0, j=HASH::DIGESTSIZE-1, i=SEEDLENGTH-1;
468 carry = m_v[i] + m_temp[j] + carry;
469 m_v[i] =
static_cast<byte>(carry);
470 i--; j--; carry >>= 8;
474 carry = m_v[i] + carry;
475 m_v[i] =
static_cast<byte>(carry);
485 m_hash.Update(m_temp, m_temp.size());
486 size_t count =
STDMIN(size, (
size_t)HASH::DIGESTSIZE);
487 m_hash.TruncatedFinal(output, count);
490 size -= count; output += count;
496 const byte three = 3;
497 m_temp.New(HASH::DIGESTSIZE);
499 m_hash.Update(&three, 1);
500 m_hash.Update(m_v, m_v.size());
501 m_hash.Final(m_temp);
505 int carry=0, k=
sizeof(m_reseed)-1, j=HASH::DIGESTSIZE-1, i=SEEDLENGTH-1;
509 carry = m_v[i] + m_c[i] + m_temp[j] + GetByte<word64>(
BIG_ENDIAN_ORDER, m_reseed, k) + carry;
510 m_v[i] =
static_cast<byte>(carry);
511 i--; j--; k--; carry >>= 8;
516 carry = m_v[i] + m_c[i] + m_temp[j] + carry;
517 m_v[i] =
static_cast<byte>(carry);
518 i--; j--; carry >>= 8;
523 carry = m_v[i] + m_c[i] + carry;
524 m_v[i] =
static_cast<byte>(carry);
533 template <
typename HASH,
unsigned int STRENGTH,
unsigned int SEEDLENGTH>
535 const byte* input3,
size_t inlen3,
const byte* input4,
size_t inlen4,
byte* output,
size_t outlen)
542 m_hash.Update(&counter, 1);
543 m_hash.Update(
reinterpret_cast<const byte*
>(&bits), 4);
545 if (input1 && inlen1)
546 m_hash.Update(input1, inlen1);
547 if (input2 && inlen2)
548 m_hash.Update(input2, inlen2);
549 if (input3 && inlen3)
550 m_hash.Update(input3, inlen3);
551 if (input4 && inlen4)
552 m_hash.Update(input4, inlen4);
554 size_t count =
STDMIN(outlen, (
size_t)HASH::DIGESTSIZE);
555 m_hash.TruncatedFinal(output, count);
557 output += count; outlen -= count;
565 template <
typename HASH,
unsigned int STRENGTH,
unsigned int SEEDLENGTH>
567 const byte* personalization,
size_t personalizationLength)
575 if (entropyLength < MINIMUM_ENTROPY)
576 throw NIST_DRBG::Err(
"HMAC_DRBG",
"Insufficient entropy during instantiate");
584 std::fill(m_k.begin(), m_k.begin()+m_k.size(),
byte(0));
585 std::fill(m_v.begin(), m_v.begin()+m_v.size(),
byte(1));
587 HMAC_Update(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength);
592 template <
typename HASH,
unsigned int STRENGTH,
unsigned int SEEDLENGTH>
601 if (entropyLength < MINIMUM_ENTROPY)
602 throw NIST_DRBG::Err(
"HMAC_DRBG",
"Insufficient entropy during reseed");
609 HMAC_Update(entropy, entropyLength, additional, additionaLength, NULLPTR, 0);
614 template <
typename HASH,
unsigned int STRENGTH,
unsigned int SEEDLENGTH>
618 if (
static_cast<word64
>(m_reseed) >=
static_cast<word64
>(MaxRequestBeforeReseed()))
621 if (size > MaxBytesPerRequest())
629 if (additional && additionaLength)
630 HMAC_Update(additional, additionaLength, NULLPTR, 0, NULLPTR, 0);
633 m_hmac.SetKey(m_k, m_k.size());
637 m_hmac.Update(m_v, m_v.size());
638 m_hmac.TruncatedFinal(m_v, m_v.size());
640 size_t count =
STDMIN(size, (
size_t)HASH::DIGESTSIZE);
641 memcpy(output, m_v, count);
642 size -= count; output += count;
645 HMAC_Update(additional, additionaLength, NULLPTR, 0, NULLPTR, 0);
650 template <
typename HASH,
unsigned int STRENGTH,
unsigned int SEEDLENGTH>
653 const byte zero = 0, one = 1;
656 m_hmac.SetKey(m_k, m_k.size());
657 m_hmac.Update(m_v, m_v.size());
658 m_hmac.Update(&zero, 1);
660 if (input1 && inlen1)
661 m_hmac.Update(input1, inlen1);
662 if (input2 && inlen2)
663 m_hmac.Update(input2, inlen2);
664 if (input3 && inlen3)
665 m_hmac.Update(input3, inlen3);
667 m_hmac.TruncatedFinal(m_k, m_k.size());
670 m_hmac.SetKey(m_k, m_k.size());
671 m_hmac.Update(m_v, m_v.size());
673 m_hmac.TruncatedFinal(m_v, m_v.size());
676 if ((inlen1 | inlen2 | inlen3) == 0)
680 m_hmac.SetKey(m_k, m_k.size());
681 m_hmac.Update(m_v, m_v.size());
682 m_hmac.Update(&one, 1);
684 if (input1 && inlen1)
685 m_hmac.Update(input1, inlen1);
686 if (input2 && inlen2)
687 m_hmac.Update(input2, inlen2);
688 if (input3 && inlen3)
689 m_hmac.Update(input3, inlen3);
691 m_hmac.TruncatedFinal(m_k, m_k.size());
694 m_hmac.SetKey(m_k, m_k.size());
695 m_hmac.Update(m_v, m_v.size());
697 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.
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.
T ConditionalByteReverse(ByteOrder order, T value)
Reverses bytes in a value depending upon endianness.
const T & STDMIN(const T &a, const T &b)
Replacement function for std::min.
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.