9 #ifndef CRYPTOPP_NIST_DRBG_H
10 #define CRYPTOPP_NIST_DRBG_H
33 explicit Err(
const std::string &c,
const std::string &m)
53 virtual void IncorporateEntropy(
const byte *input,
size_t length)=0;
66 virtual void IncorporateEntropy(
const byte *entropy,
size_t entropyLength,
const byte* additional,
size_t additionaLength)=0;
73 virtual void GenerateBlock(
byte *output,
size_t size)=0;
85 virtual void GenerateBlock(
const byte* additional,
size_t additionaLength,
byte *output,
size_t size)=0;
90 virtual unsigned int SecurityStrength()
const=0;
96 virtual unsigned int SeedLength()
const=0;
104 virtual unsigned int MinEntropyLength()
const=0;
112 virtual unsigned int MaxEntropyLength()
const=0;
119 virtual unsigned int MinNonceLength()
const=0;
127 virtual unsigned int MaxNonceLength()
const=0;
132 virtual unsigned int MaxBytesPerRequest()
const=0;
139 virtual unsigned int MaxRequestBeforeReseed()
const=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;
166 template <
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);
290 template <
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);
399 template <
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);
428 template <
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);
455 template <
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);
549 template <
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;
581 template <
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);
608 template <
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);
630 template <
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 std::memcpy(output, m_v, count);
658 size -= count; output += count;
661 HMAC_Update(additional, additionaLength, NULLPTR, 0, NULLPTR, 0);
666 template <
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());
718 #endif // CRYPTOPP_NIST_DRBG_H