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());
702 #endif // CRYPTOPP_NIST_DRBG_H