File indexing completed on 2025-01-18 09:55:01
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef CRYPTOPP_NIST_DRBG_H
0010 #define CRYPTOPP_NIST_DRBG_H
0011
0012 #include "cryptlib.h"
0013 #include "secblock.h"
0014 #include "hmac.h"
0015 #include "sha.h"
0016
0017 NAMESPACE_BEGIN(CryptoPP)
0018
0019
0020
0021
0022
0023
0024
0025
0026 class NIST_DRBG : public RandomNumberGenerator
0027 {
0028 public:
0029
0030 class Err : public Exception
0031 {
0032 public:
0033 explicit Err(const std::string &c, const std::string &m)
0034 : Exception(OTHER_ERROR, c + ": " + m) {}
0035 };
0036
0037 public:
0038 virtual ~NIST_DRBG() {}
0039
0040
0041
0042
0043 virtual bool CanIncorporateEntropy() const {return true;}
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053 virtual void IncorporateEntropy(const byte *input, size_t length)=0;
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066 virtual void IncorporateEntropy(const byte *entropy, size_t entropyLength, const byte* additional, size_t additionaLength)=0;
0067
0068
0069
0070
0071
0072
0073 virtual void GenerateBlock(byte *output, size_t size)=0;
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085 virtual void GenerateBlock(const byte* additional, size_t additionaLength, byte *output, size_t size)=0;
0086
0087
0088
0089
0090 virtual unsigned int SecurityStrength() const=0;
0091
0092
0093
0094
0095
0096 virtual unsigned int SeedLength() const=0;
0097
0098
0099
0100
0101
0102
0103
0104 virtual unsigned int MinEntropyLength() const=0;
0105
0106
0107
0108
0109
0110
0111
0112 virtual unsigned int MaxEntropyLength() const=0;
0113
0114
0115
0116
0117
0118
0119 virtual unsigned int MinNonceLength() const=0;
0120
0121
0122
0123
0124
0125
0126
0127 virtual unsigned int MaxNonceLength() const=0;
0128
0129
0130
0131
0132 virtual unsigned int MaxBytesPerRequest() const=0;
0133
0134
0135
0136
0137
0138
0139 virtual unsigned int MaxRequestBeforeReseed() const=0;
0140
0141 protected:
0142 virtual void DRBG_Instantiate(const byte* entropy, size_t entropyLength,
0143 const byte* nonce, size_t nonceLength, const byte* personalization, size_t personalizationLength)=0;
0144
0145 virtual void DRBG_Reseed(const byte* entropy, size_t entropyLength, const byte* additional, size_t additionaLength)=0;
0146 };
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166 template <typename HASH=SHA256, unsigned int STRENGTH=128/8, unsigned int SEEDLENGTH=440/8>
0167 class Hash_DRBG : public NIST_DRBG, public NotCopyable
0168 {
0169 public:
0170 CRYPTOPP_CONSTANT(SECURITY_STRENGTH=STRENGTH);
0171 CRYPTOPP_CONSTANT(SEED_LENGTH=SEEDLENGTH);
0172 CRYPTOPP_CONSTANT(MINIMUM_ENTROPY=STRENGTH);
0173 CRYPTOPP_CONSTANT(MINIMUM_NONCE=0);
0174 CRYPTOPP_CONSTANT(MINIMUM_ADDITIONAL=0);
0175 CRYPTOPP_CONSTANT(MINIMUM_PERSONALIZATION=0);
0176 CRYPTOPP_CONSTANT(MAXIMUM_ENTROPY=INT_MAX);
0177 CRYPTOPP_CONSTANT(MAXIMUM_NONCE=INT_MAX);
0178 CRYPTOPP_CONSTANT(MAXIMUM_ADDITIONAL=INT_MAX);
0179 CRYPTOPP_CONSTANT(MAXIMUM_PERSONALIZATION=INT_MAX);
0180 CRYPTOPP_CONSTANT(MAXIMUM_BYTES_PER_REQUEST=65536);
0181 CRYPTOPP_CONSTANT(MAXIMUM_REQUESTS_BEFORE_RESEED=INT_MAX);
0182
0183 static std::string StaticAlgorithmName() { return std::string("Hash_DRBG(") + HASH::StaticAlgorithmName() + std::string(")"); }
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210 Hash_DRBG(const byte* entropy=NULLPTR, size_t entropyLength=STRENGTH, const byte* nonce=NULLPTR,
0211 size_t nonceLength=0, const byte* personalization=NULLPTR, size_t personalizationLength=0)
0212 : NIST_DRBG(), m_c(SEEDLENGTH), m_v(SEEDLENGTH), m_reseed(0)
0213 {
0214 if (m_c.data())
0215 std::memset(m_c.data(), 0x00, m_c.size());
0216 if (m_v.data())
0217 std::memset(m_v.data(), 0x00, m_v.size());
0218
0219 if (entropy != NULLPTR && entropyLength != 0)
0220 DRBG_Instantiate(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength);
0221 }
0222
0223 unsigned int SecurityStrength() const {return SECURITY_STRENGTH;}
0224 unsigned int SeedLength() const {return SEED_LENGTH;}
0225 unsigned int MinEntropyLength() const {return MINIMUM_ENTROPY;}
0226 unsigned int MaxEntropyLength() const {return MAXIMUM_ENTROPY;}
0227 unsigned int MinNonceLength() const {return MINIMUM_NONCE;}
0228 unsigned int MaxNonceLength() const {return MAXIMUM_NONCE;}
0229 unsigned int MaxBytesPerRequest() const {return MAXIMUM_BYTES_PER_REQUEST;}
0230 unsigned int MaxRequestBeforeReseed() const {return MAXIMUM_REQUESTS_BEFORE_RESEED;}
0231
0232 void IncorporateEntropy(const byte *input, size_t length)
0233 {return DRBG_Reseed(input, length, NULLPTR, 0);}
0234
0235 void IncorporateEntropy(const byte *entropy, size_t entropyLength, const byte* additional, size_t additionaLength)
0236 {return DRBG_Reseed(entropy, entropyLength, additional, additionaLength);}
0237
0238 void GenerateBlock(byte *output, size_t size)
0239 {return Hash_Generate(NULLPTR, 0, output, size);}
0240
0241 void GenerateBlock(const byte* additional, size_t additionaLength, byte *output, size_t size)
0242 {return Hash_Generate(additional, additionaLength, output, size);}
0243
0244 std::string AlgorithmProvider() const
0245 {HASH hash; return hash.AlgorithmProvider();}
0246
0247 protected:
0248
0249 void DRBG_Instantiate(const byte* entropy, size_t entropyLength, const byte* nonce, size_t nonceLength,
0250 const byte* personalization, size_t personalizationLength);
0251
0252
0253 void DRBG_Reseed(const byte* entropy, size_t entropyLength, const byte* additional, size_t additionaLength);
0254
0255
0256 void Hash_Generate(const byte* additional, size_t additionaLength, byte *output, size_t size);
0257
0258
0259 void Hash_Update(const byte* input1, size_t inlen1, const byte* input2, size_t inlen2,
0260 const byte* input3, size_t inlen3, const byte* input4, size_t inlen4, byte* output, size_t outlen);
0261
0262 private:
0263 HASH m_hash;
0264 SecByteBlock m_c, m_v, m_temp;
0265 word64 m_reseed;
0266 };
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290 template <typename HASH=SHA256, unsigned int STRENGTH=128/8, unsigned int SEEDLENGTH=440/8>
0291 class HMAC_DRBG : public NIST_DRBG, public NotCopyable
0292 {
0293 public:
0294 CRYPTOPP_CONSTANT(SECURITY_STRENGTH=STRENGTH);
0295 CRYPTOPP_CONSTANT(SEED_LENGTH=SEEDLENGTH);
0296 CRYPTOPP_CONSTANT(MINIMUM_ENTROPY=STRENGTH);
0297 CRYPTOPP_CONSTANT(MINIMUM_NONCE=0);
0298 CRYPTOPP_CONSTANT(MINIMUM_ADDITIONAL=0);
0299 CRYPTOPP_CONSTANT(MINIMUM_PERSONALIZATION=0);
0300 CRYPTOPP_CONSTANT(MAXIMUM_ENTROPY=INT_MAX);
0301 CRYPTOPP_CONSTANT(MAXIMUM_NONCE=INT_MAX);
0302 CRYPTOPP_CONSTANT(MAXIMUM_ADDITIONAL=INT_MAX);
0303 CRYPTOPP_CONSTANT(MAXIMUM_PERSONALIZATION=INT_MAX);
0304 CRYPTOPP_CONSTANT(MAXIMUM_BYTES_PER_REQUEST=65536);
0305 CRYPTOPP_CONSTANT(MAXIMUM_REQUESTS_BEFORE_RESEED=INT_MAX);
0306
0307 static std::string StaticAlgorithmName() { return std::string("HMAC_DRBG(") + HASH::StaticAlgorithmName() + std::string(")"); }
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334 HMAC_DRBG(const byte* entropy=NULLPTR, size_t entropyLength=STRENGTH, const byte* nonce=NULLPTR,
0335 size_t nonceLength=0, const byte* personalization=NULLPTR, size_t personalizationLength=0)
0336 : NIST_DRBG(), m_k(HASH::DIGESTSIZE), m_v(HASH::DIGESTSIZE), m_reseed(0)
0337 {
0338 if (m_k.data())
0339 std::memset(m_k, 0x00, m_k.size());
0340 if (m_v.data())
0341 std::memset(m_v, 0x00, m_v.size());
0342
0343 if (entropy != NULLPTR && entropyLength != 0)
0344 DRBG_Instantiate(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength);
0345 }
0346
0347 unsigned int SecurityStrength() const {return SECURITY_STRENGTH;}
0348 unsigned int SeedLength() const {return SEED_LENGTH;}
0349 unsigned int MinEntropyLength() const {return MINIMUM_ENTROPY;}
0350 unsigned int MaxEntropyLength() const {return MAXIMUM_ENTROPY;}
0351 unsigned int MinNonceLength() const {return MINIMUM_NONCE;}
0352 unsigned int MaxNonceLength() const {return MAXIMUM_NONCE;}
0353 unsigned int MaxBytesPerRequest() const {return MAXIMUM_BYTES_PER_REQUEST;}
0354 unsigned int MaxRequestBeforeReseed() const {return MAXIMUM_REQUESTS_BEFORE_RESEED;}
0355
0356 void IncorporateEntropy(const byte *input, size_t length)
0357 {return DRBG_Reseed(input, length, NULLPTR, 0);}
0358
0359 void IncorporateEntropy(const byte *entropy, size_t entropyLength, const byte* additional, size_t additionaLength)
0360 {return DRBG_Reseed(entropy, entropyLength, additional, additionaLength);}
0361
0362 void GenerateBlock(byte *output, size_t size)
0363 {return HMAC_Generate(NULLPTR, 0, output, size);}
0364
0365 void GenerateBlock(const byte* additional, size_t additionaLength, byte *output, size_t size)
0366 {return HMAC_Generate(additional, additionaLength, output, size);}
0367
0368 std::string AlgorithmProvider() const
0369 {HASH hash; return hash.AlgorithmProvider();}
0370
0371 protected:
0372
0373 void DRBG_Instantiate(const byte* entropy, size_t entropyLength, const byte* nonce, size_t nonceLength,
0374 const byte* personalization, size_t personalizationLength);
0375
0376
0377 void DRBG_Reseed(const byte* entropy, size_t entropyLength, const byte* additional, size_t additionaLength);
0378
0379
0380 void HMAC_Generate(const byte* additional, size_t additionaLength, byte *output, size_t size);
0381
0382
0383 void HMAC_Update(const byte* input1, size_t inlen1, const byte* input2, size_t inlen2, const byte* input3, size_t inlen3);
0384
0385 private:
0386 HMAC<HASH> m_hmac;
0387 SecByteBlock m_k, m_v;
0388 word64 m_reseed;
0389 };
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399 template <typename HASH, unsigned int STRENGTH, unsigned int SEEDLENGTH>
0400 void Hash_DRBG<HASH, STRENGTH, SEEDLENGTH>::DRBG_Instantiate(const byte* entropy, size_t entropyLength, const byte* nonce, size_t nonceLength,
0401 const byte* personalization, size_t personalizationLength)
0402 {
0403
0404
0405
0406
0407
0408 CRYPTOPP_ASSERT(entropyLength >= MINIMUM_ENTROPY);
0409 if (entropyLength < MINIMUM_ENTROPY)
0410 throw NIST_DRBG::Err("Hash_DRBG", "Insufficient entropy during instantiate");
0411
0412
0413
0414 CRYPTOPP_ASSERT(entropyLength <= MAXIMUM_ENTROPY);
0415 CRYPTOPP_ASSERT(nonceLength <= MAXIMUM_NONCE);
0416 CRYPTOPP_ASSERT(personalizationLength <= MAXIMUM_PERSONALIZATION);
0417
0418 const byte zero = 0;
0419 SecByteBlock t1(SEEDLENGTH), t2(SEEDLENGTH);
0420 Hash_Update(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength, NULLPTR, 0, t1, t1.size());
0421 Hash_Update(&zero, 1, t1, t1.size(), NULLPTR, 0, NULLPTR, 0, t2, t2.size());
0422
0423 m_v.swap(t1); m_c.swap(t2);
0424 m_reseed = 1;
0425 }
0426
0427
0428 template <typename HASH, unsigned int STRENGTH, unsigned int SEEDLENGTH>
0429 void Hash_DRBG<HASH, STRENGTH, SEEDLENGTH>::DRBG_Reseed(const byte* entropy, size_t entropyLength, const byte* additional, size_t additionaLength)
0430 {
0431
0432
0433
0434
0435
0436 CRYPTOPP_ASSERT(entropyLength >= MINIMUM_ENTROPY);
0437 if (entropyLength < MINIMUM_ENTROPY)
0438 throw NIST_DRBG::Err("Hash_DRBG", "Insufficient entropy during reseed");
0439
0440
0441
0442 CRYPTOPP_ASSERT(entropyLength <= MAXIMUM_ENTROPY);
0443 CRYPTOPP_ASSERT(additionaLength <= MAXIMUM_ADDITIONAL);
0444
0445 const byte zero = 0, one = 1;
0446 SecByteBlock t1(SEEDLENGTH), t2(SEEDLENGTH);
0447 Hash_Update(&one, 1, m_v, m_v.size(), entropy, entropyLength, additional, additionaLength, t1, t1.size());
0448 Hash_Update(&zero, 1, t1, t1.size(), NULLPTR, 0, NULLPTR, 0, t2, t2.size());
0449
0450 m_v.swap(t1); m_c.swap(t2);
0451 m_reseed = 1;
0452 }
0453
0454
0455 template <typename HASH, unsigned int STRENGTH, unsigned int SEEDLENGTH>
0456 void Hash_DRBG<HASH, STRENGTH, SEEDLENGTH>::Hash_Generate(const byte* additional, size_t additionaLength, byte *output, size_t size)
0457 {
0458
0459 if (static_cast<word64>(m_reseed) >= static_cast<word64>(MaxRequestBeforeReseed()))
0460 throw NIST_DRBG::Err("Hash_DRBG", "Reseed required");
0461
0462 if (size > MaxBytesPerRequest())
0463 throw NIST_DRBG::Err("Hash_DRBG", "Request size exceeds limit");
0464
0465
0466
0467 CRYPTOPP_ASSERT(additionaLength <= MAXIMUM_ADDITIONAL);
0468
0469
0470 if (additional && additionaLength)
0471 {
0472 const byte two = 2;
0473 m_temp.New(HASH::DIGESTSIZE);
0474
0475 m_hash.Update(&two, 1);
0476 m_hash.Update(m_v, m_v.size());
0477 m_hash.Update(additional, additionaLength);
0478 m_hash.Final(m_temp);
0479
0480 CRYPTOPP_ASSERT(SEEDLENGTH >= HASH::DIGESTSIZE);
0481 int carry=0, j=HASH::DIGESTSIZE-1, i=SEEDLENGTH-1;
0482 while (j>=0)
0483 {
0484 carry = m_v[i] + m_temp[j] + carry;
0485 m_v[i] = static_cast<byte>(carry);
0486 i--; j--; carry >>= 8;
0487 }
0488 while (i>=0)
0489 {
0490 carry = m_v[i] + carry;
0491 m_v[i] = static_cast<byte>(carry);
0492 i--; carry >>= 8;
0493 }
0494 }
0495
0496
0497 {
0498 m_temp.Assign(m_v);
0499 while (size)
0500 {
0501 m_hash.Update(m_temp, m_temp.size());
0502 size_t count = STDMIN(size, (size_t)HASH::DIGESTSIZE);
0503 m_hash.TruncatedFinal(output, count);
0504
0505 IncrementCounterByOne(m_temp, static_cast<unsigned int>(m_temp.size()));
0506 size -= count; output += count;
0507 }
0508 }
0509
0510
0511 {
0512 const byte three = 3;
0513 m_temp.New(HASH::DIGESTSIZE);
0514
0515 m_hash.Update(&three, 1);
0516 m_hash.Update(m_v, m_v.size());
0517 m_hash.Final(m_temp);
0518
0519 CRYPTOPP_ASSERT(SEEDLENGTH >= HASH::DIGESTSIZE);
0520 CRYPTOPP_ASSERT(HASH::DIGESTSIZE >= sizeof(m_reseed));
0521 int carry=0, k=sizeof(m_reseed)-1, j=HASH::DIGESTSIZE-1, i=SEEDLENGTH-1;
0522
0523 while (k>=0)
0524 {
0525 carry = m_v[i] + m_c[i] + m_temp[j] + GetByte<word64>(BIG_ENDIAN_ORDER, m_reseed, k) + carry;
0526 m_v[i] = static_cast<byte>(carry);
0527 i--; j--; k--; carry >>= 8;
0528 }
0529
0530 while (j>=0)
0531 {
0532 carry = m_v[i] + m_c[i] + m_temp[j] + carry;
0533 m_v[i] = static_cast<byte>(carry);
0534 i--; j--; carry >>= 8;
0535 }
0536
0537 while (i>=0)
0538 {
0539 carry = m_v[i] + m_c[i] + carry;
0540 m_v[i] = static_cast<byte>(carry);
0541 i--; carry >>= 8;
0542 }
0543 }
0544
0545 m_reseed++;
0546 }
0547
0548
0549 template <typename HASH, unsigned int STRENGTH, unsigned int SEEDLENGTH>
0550 void Hash_DRBG<HASH, STRENGTH, SEEDLENGTH>::Hash_Update(const byte* input1, size_t inlen1, const byte* input2, size_t inlen2,
0551 const byte* input3, size_t inlen3, const byte* input4, size_t inlen4, byte* output, size_t outlen)
0552 {
0553 byte counter = 1;
0554 word32 bits = ConditionalByteReverse(BIG_ENDIAN_ORDER, static_cast<word32>(outlen*8));
0555
0556 while (outlen)
0557 {
0558 m_hash.Update(&counter, 1);
0559 m_hash.Update(reinterpret_cast<const byte*>(&bits), 4);
0560
0561 if (input1 && inlen1)
0562 m_hash.Update(input1, inlen1);
0563 if (input2 && inlen2)
0564 m_hash.Update(input2, inlen2);
0565 if (input3 && inlen3)
0566 m_hash.Update(input3, inlen3);
0567 if (input4 && inlen4)
0568 m_hash.Update(input4, inlen4);
0569
0570 size_t count = STDMIN(outlen, (size_t)HASH::DIGESTSIZE);
0571 m_hash.TruncatedFinal(output, count);
0572
0573 output += count; outlen -= count;
0574 counter++;
0575 }
0576 }
0577
0578
0579
0580
0581 template <typename HASH, unsigned int STRENGTH, unsigned int SEEDLENGTH>
0582 void HMAC_DRBG<HASH, STRENGTH, SEEDLENGTH>::DRBG_Instantiate(const byte* entropy, size_t entropyLength, const byte* nonce, size_t nonceLength,
0583 const byte* personalization, size_t personalizationLength)
0584 {
0585
0586
0587
0588
0589
0590 CRYPTOPP_ASSERT(entropyLength >= MINIMUM_ENTROPY);
0591 if (entropyLength < MINIMUM_ENTROPY)
0592 throw NIST_DRBG::Err("HMAC_DRBG", "Insufficient entropy during instantiate");
0593
0594
0595
0596 CRYPTOPP_ASSERT(entropyLength <= MAXIMUM_ENTROPY);
0597 CRYPTOPP_ASSERT(nonceLength <= MAXIMUM_NONCE);
0598 CRYPTOPP_ASSERT(personalizationLength <= MAXIMUM_PERSONALIZATION);
0599
0600 std::fill(m_k.begin(), m_k.begin()+m_k.size(), byte(0));
0601 std::fill(m_v.begin(), m_v.begin()+m_v.size(), byte(1));
0602
0603 HMAC_Update(entropy, entropyLength, nonce, nonceLength, personalization, personalizationLength);
0604 m_reseed = 1;
0605 }
0606
0607
0608 template <typename HASH, unsigned int STRENGTH, unsigned int SEEDLENGTH>
0609 void HMAC_DRBG<HASH, STRENGTH, SEEDLENGTH>::DRBG_Reseed(const byte* entropy, size_t entropyLength, const byte* additional, size_t additionaLength)
0610 {
0611
0612
0613
0614
0615
0616 CRYPTOPP_ASSERT(entropyLength >= MINIMUM_ENTROPY);
0617 if (entropyLength < MINIMUM_ENTROPY)
0618 throw NIST_DRBG::Err("HMAC_DRBG", "Insufficient entropy during reseed");
0619
0620
0621
0622 CRYPTOPP_ASSERT(entropyLength <= MAXIMUM_ENTROPY);
0623 CRYPTOPP_ASSERT(additionaLength <= MAXIMUM_ADDITIONAL);
0624
0625 HMAC_Update(entropy, entropyLength, additional, additionaLength, NULLPTR, 0);
0626 m_reseed = 1;
0627 }
0628
0629
0630 template <typename HASH, unsigned int STRENGTH, unsigned int SEEDLENGTH>
0631 void HMAC_DRBG<HASH, STRENGTH, SEEDLENGTH>::HMAC_Generate(const byte* additional, size_t additionaLength, byte *output, size_t size)
0632 {
0633
0634 if (static_cast<word64>(m_reseed) >= static_cast<word64>(MaxRequestBeforeReseed()))
0635 throw NIST_DRBG::Err("HMAC_DRBG", "Reseed required");
0636
0637 if (size > MaxBytesPerRequest())
0638 throw NIST_DRBG::Err("HMAC_DRBG", "Request size exceeds limit");
0639
0640
0641
0642 CRYPTOPP_ASSERT(additionaLength <= MAXIMUM_ADDITIONAL);
0643
0644
0645 if (additional && additionaLength)
0646 HMAC_Update(additional, additionaLength, NULLPTR, 0, NULLPTR, 0);
0647
0648
0649 m_hmac.SetKey(m_k, m_k.size());
0650
0651 while (size)
0652 {
0653 m_hmac.Update(m_v, m_v.size());
0654 m_hmac.TruncatedFinal(m_v, m_v.size());
0655
0656 size_t count = STDMIN(size, (size_t)HASH::DIGESTSIZE);
0657 std::memcpy(output, m_v, count);
0658 size -= count; output += count;
0659 }
0660
0661 HMAC_Update(additional, additionaLength, NULLPTR, 0, NULLPTR, 0);
0662 m_reseed++;
0663 }
0664
0665
0666 template <typename HASH, unsigned int STRENGTH, unsigned int SEEDLENGTH>
0667 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)
0668 {
0669 const byte zero = 0, one = 1;
0670
0671
0672 m_hmac.SetKey(m_k, m_k.size());
0673 m_hmac.Update(m_v, m_v.size());
0674 m_hmac.Update(&zero, 1);
0675
0676 if (input1 && inlen1)
0677 m_hmac.Update(input1, inlen1);
0678 if (input2 && inlen2)
0679 m_hmac.Update(input2, inlen2);
0680 if (input3 && inlen3)
0681 m_hmac.Update(input3, inlen3);
0682
0683 m_hmac.TruncatedFinal(m_k, m_k.size());
0684
0685
0686 m_hmac.SetKey(m_k, m_k.size());
0687 m_hmac.Update(m_v, m_v.size());
0688
0689 m_hmac.TruncatedFinal(m_v, m_v.size());
0690
0691
0692 if ((inlen1 | inlen2 | inlen3) == 0)
0693 return;
0694
0695
0696 m_hmac.SetKey(m_k, m_k.size());
0697 m_hmac.Update(m_v, m_v.size());
0698 m_hmac.Update(&one, 1);
0699
0700 if (input1 && inlen1)
0701 m_hmac.Update(input1, inlen1);
0702 if (input2 && inlen2)
0703 m_hmac.Update(input2, inlen2);
0704 if (input3 && inlen3)
0705 m_hmac.Update(input3, inlen3);
0706
0707 m_hmac.TruncatedFinal(m_k, m_k.size());
0708
0709
0710 m_hmac.SetKey(m_k, m_k.size());
0711 m_hmac.Update(m_v, m_v.size());
0712
0713 m_hmac.TruncatedFinal(m_v, m_v.size());
0714 }
0715
0716 NAMESPACE_END
0717
0718 #endif