Coverage Report

Created: 2024-11-21 07:03

/src/cryptopp/cryptlib.cpp
Line
Count
Source (jump to first uncovered line)
1
// cryptlib.cpp - originally written and placed in the public domain by Wei Dai
2
3
#include "pch.h"
4
#include "config.h"
5
6
#if CRYPTOPP_MSC_VERSION
7
# pragma warning(disable: 4127 4189 4459)
8
#endif
9
10
#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
11
# pragma GCC diagnostic ignored "-Wunused-value"
12
# pragma GCC diagnostic ignored "-Wunused-variable"
13
# pragma GCC diagnostic ignored "-Wunused-parameter"
14
#endif
15
16
#ifndef CRYPTOPP_IMPORTS
17
18
#include "cryptlib.h"
19
#include "filters.h"
20
#include "algparam.h"
21
#include "fips140.h"
22
#include "argnames.h"
23
#include "fltrimpl.h"
24
#include "osrng.h"
25
#include "secblock.h"
26
#include "smartptr.h"
27
#include "stdcpp.h"
28
#include "misc.h"
29
30
NAMESPACE_BEGIN(CryptoPP)
31
32
CRYPTOPP_COMPILE_ASSERT(sizeof(byte) == 1);
33
CRYPTOPP_COMPILE_ASSERT(sizeof(word16) == 2);
34
CRYPTOPP_COMPILE_ASSERT(sizeof(word32) == 4);
35
CRYPTOPP_COMPILE_ASSERT(sizeof(word64) == 8);
36
#ifdef CRYPTOPP_NATIVE_DWORD_AVAILABLE
37
CRYPTOPP_COMPILE_ASSERT(sizeof(dword) == 2*sizeof(word));
38
#endif
39
40
BufferedTransformation & TheBitBucket()
41
5.65M
{
42
5.65M
  static BitBucket bitBucket;
43
5.65M
  return bitBucket;
44
5.65M
}
45
46
Algorithm::Algorithm(bool checkSelfTestStatus)
47
305M
{
48
305M
  if (checkSelfTestStatus && FIPS_140_2_ComplianceEnabled())
49
0
  {
50
0
    if (GetPowerUpSelfTestStatus() == POWER_UP_SELF_TEST_NOT_DONE && !PowerUpSelfTestInProgressOnThisThread())
51
0
      throw SelfTestFailure("Cryptographic algorithms are disabled before the power-up self tests are performed.");
52
53
0
    if (GetPowerUpSelfTestStatus() == POWER_UP_SELF_TEST_FAILED)
54
0
      throw SelfTestFailure("Cryptographic algorithms are disabled after a power-up self test failed.");
55
0
  }
56
305M
}
57
58
void SimpleKeyingInterface::SetKey(const byte *key, size_t length, const NameValuePairs &params)
59
6.96k
{
60
6.96k
  this->ThrowIfInvalidKeyLength(length);
61
6.96k
  this->UncheckedSetKey(key, static_cast<unsigned int>(length), params);
62
6.96k
}
63
64
void SimpleKeyingInterface::SetKeyWithRounds(const byte *key, size_t length, int rounds)
65
0
{
66
0
  SetKey(key, length, MakeParameters(Name::Rounds(), rounds));
67
0
}
68
69
void SimpleKeyingInterface::SetKeyWithIV(const byte *key, size_t length, const byte *iv, size_t ivLength)
70
142
{
71
142
  SetKey(key, length, MakeParameters(Name::IV(), ConstByteArrayParameter(iv, ivLength)));
72
142
}
73
74
void SimpleKeyingInterface::ThrowIfInvalidKeyLength(size_t length)
75
6.99k
{
76
6.99k
  if (!IsValidKeyLength(length))
77
397
    throw InvalidKeyLength(GetAlgorithm().AlgorithmName(), length);
78
6.99k
}
79
80
void SimpleKeyingInterface::ThrowIfResynchronizable()
81
53
{
82
53
  if (IsResynchronizable())
83
53
    throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": this object requires an IV");
84
53
}
85
86
void SimpleKeyingInterface::ThrowIfInvalidIV(const byte *iv)
87
805
{
88
805
  if (!iv && IVRequirement() == UNPREDICTABLE_RANDOM_IV)
89
0
    throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": this object cannot use a null IV");
90
805
}
91
92
size_t SimpleKeyingInterface::ThrowIfInvalidIVLength(int length)
93
1.10k
{
94
1.10k
  size_t size = 0;
95
1.10k
  if (length < 0)
96
228
    size = static_cast<size_t>(IVSize());
97
877
  else if ((size_t)length < MinIVLength())
98
17
    throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": IV length " + IntToString(length) + " is less than the minimum of " + IntToString(MinIVLength()));
99
860
  else if ((size_t)length > MaxIVLength())
100
8
    throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": IV length " + IntToString(length) + " exceeds the maximum of " + IntToString(MaxIVLength()));
101
852
  else
102
852
    size = static_cast<size_t>(length);
103
104
1.08k
  return size;
105
1.10k
}
106
107
const byte * SimpleKeyingInterface::GetIVAndThrowIfInvalid(const NameValuePairs &params, size_t &size)
108
630
{
109
630
  ConstByteArrayParameter ivWithLength;
110
630
  const byte *iv = NULLPTR;
111
630
  bool found = false;
112
113
630
  try {found = params.GetValue(Name::IV(), ivWithLength);}
114
630
  catch (const NameValuePairs::ValueTypeMismatch &) {}
115
116
630
  if (found)
117
577
  {
118
577
    iv = ivWithLength.begin();
119
577
    ThrowIfInvalidIV(iv);
120
577
    size = ThrowIfInvalidIVLength(static_cast<int>(ivWithLength.size()));
121
577
  }
122
53
  else if (params.GetValue(Name::IV(), iv))
123
0
  {
124
0
    ThrowIfInvalidIV(iv);
125
0
    size = static_cast<size_t>(IVSize());
126
0
  }
127
53
  else
128
53
  {
129
53
    ThrowIfResynchronizable();
130
53
    size = 0;
131
53
  }
132
133
630
  return iv;
134
630
}
135
136
void SimpleKeyingInterface::GetNextIV(RandomNumberGenerator &rng, byte *iv)
137
0
{
138
0
  rng.GenerateBlock(iv, IVSize());
139
0
}
140
141
size_t BlockTransformation::AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const
142
865
{
143
865
  CRYPTOPP_ASSERT(inBlocks);
144
865
  CRYPTOPP_ASSERT(outBlocks);
145
865
  CRYPTOPP_ASSERT(length);
146
147
865
  const unsigned int blockSize = BlockSize();
148
865
  size_t inIncrement = (flags & (BT_InBlockIsCounter|BT_DontIncrementInOutPointers)) ? 0 : blockSize;
149
865
  size_t xorIncrement = xorBlocks ? blockSize : 0;
150
865
  size_t outIncrement = (flags & BT_DontIncrementInOutPointers) ? 0 : blockSize;
151
152
865
  if (flags & BT_ReverseDirection)
153
19
  {
154
19
    inBlocks = PtrAdd(inBlocks, length - blockSize);
155
19
    xorBlocks = PtrAdd(xorBlocks, length - blockSize);
156
19
    outBlocks = PtrAdd(outBlocks, length - blockSize);
157
19
    inIncrement = 0-inIncrement;
158
19
    xorIncrement = 0-xorIncrement;
159
19
    outIncrement = 0-outIncrement;
160
19
  }
161
162
  // Coverity finding.
163
865
  const bool xorFlag = xorBlocks && (flags & BT_XorInput);
164
30.1k
  while (length >= blockSize)
165
29.2k
  {
166
29.2k
    if (xorFlag)
167
427
    {
168
      // xorBlocks non-NULL and with BT_XorInput.
169
427
      xorbuf(outBlocks, xorBlocks, inBlocks, blockSize);
170
427
      ProcessBlock(outBlocks);
171
427
    }
172
28.8k
    else
173
28.8k
    {
174
      // xorBlocks may be non-NULL and without BT_XorInput.
175
28.8k
      ProcessAndXorBlock(inBlocks, xorBlocks, outBlocks);
176
28.8k
    }
177
178
29.2k
    if (flags & BT_InBlockIsCounter)
179
0
      const_cast<byte *>(inBlocks)[blockSize-1]++;
180
181
29.2k
    inBlocks = PtrAdd(inBlocks, inIncrement);
182
29.2k
    outBlocks = PtrAdd(outBlocks, outIncrement);
183
29.2k
    xorBlocks = PtrAdd(xorBlocks, xorIncrement);
184
29.2k
    length -= blockSize;
185
29.2k
  }
186
187
865
  return length;
188
865
}
189
190
unsigned int BlockTransformation::OptimalDataAlignment() const
191
305
{
192
305
  return GetAlignmentOf<word32>();
193
305
}
194
195
unsigned int StreamTransformation::OptimalDataAlignment() const
196
0
{
197
0
  return GetAlignmentOf<word32>();
198
0
}
199
200
unsigned int HashTransformation::OptimalDataAlignment() const
201
0
{
202
0
  return GetAlignmentOf<word32>();
203
0
}
204
205
#if 0
206
void StreamTransformation::ProcessLastBlock(byte *outString, const byte *inString, size_t length)
207
{
208
  CRYPTOPP_ASSERT(MinLastBlockSize() == 0); // this function should be overridden otherwise
209
210
  if (length == MandatoryBlockSize())
211
    ProcessData(outString, inString, length);
212
  else if (length != 0)
213
    throw NotImplemented(AlgorithmName() + ": this object doesn't support a special last block");
214
}
215
#endif
216
217
size_t StreamTransformation::ProcessLastBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength)
218
0
{
219
  // this function should be overridden otherwise
220
0
  CRYPTOPP_ASSERT(MinLastBlockSize() == 0);
221
222
0
  if (inLength == MandatoryBlockSize())
223
0
  {
224
0
    outLength = inLength; // squash unused warning
225
0
    ProcessData(outString, inString, inLength);
226
0
  }
227
0
  else if (inLength != 0)
228
0
    throw NotImplemented(AlgorithmName() + ": this object doesn't support a special last block");
229
230
0
  return outLength;
231
0
}
232
233
void AuthenticatedSymmetricCipher::SpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength)
234
0
{
235
0
  if (headerLength > MaxHeaderLength())
236
0
    throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": header length " + IntToString(headerLength) + " exceeds the maximum of " + IntToString(MaxHeaderLength()));
237
238
0
  if (messageLength > MaxMessageLength())
239
0
    throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": message length " + IntToString(messageLength) + " exceeds the maximum of " + IntToString(MaxMessageLength()));
240
241
0
  if (footerLength > MaxFooterLength())
242
0
    throw InvalidArgument(GetAlgorithm().AlgorithmName() + ": footer length " + IntToString(footerLength) + " exceeds the maximum of " + IntToString(MaxFooterLength()));
243
244
0
  UncheckedSpecifyDataLengths(headerLength, messageLength, footerLength);
245
0
}
246
247
void AuthenticatedSymmetricCipher::EncryptAndAuthenticate(byte *ciphertext, byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *header, size_t headerLength, const byte *message, size_t messageLength)
248
0
{
249
0
  Resynchronize(iv, ivLength);
250
0
  SpecifyDataLengths(headerLength, messageLength);
251
0
  Update(header, headerLength);
252
0
  ProcessString(ciphertext, message, messageLength);
253
0
  TruncatedFinal(mac, macSize);
254
0
}
255
256
bool AuthenticatedSymmetricCipher::DecryptAndVerify(byte *message, const byte *mac, size_t macLength, const byte *iv, int ivLength, const byte *header, size_t headerLength, const byte *ciphertext, size_t ciphertextLength)
257
0
{
258
0
  Resynchronize(iv, ivLength);
259
0
  SpecifyDataLengths(headerLength, ciphertextLength);
260
0
  Update(header, headerLength);
261
0
  ProcessString(message, ciphertext, ciphertextLength);
262
0
  return TruncatedVerify(mac, macLength);
263
0
}
264
265
std::string AuthenticatedSymmetricCipher::AlgorithmName() const
266
0
{
267
  // Squash C4505 on Visual Studio 2008 and friends
268
0
  return "Unknown";
269
0
}
270
271
unsigned int RandomNumberGenerator::GenerateBit()
272
0
{
273
0
  return GenerateByte() & 1;
274
0
}
275
276
byte RandomNumberGenerator::GenerateByte()
277
0
{
278
0
  byte b;
279
0
  GenerateBlock(&b, 1);
280
0
  return b;
281
0
}
282
283
word32 RandomNumberGenerator::GenerateWord32(word32 min, word32 max)
284
0
{
285
0
  const word32 range = max-min;
286
0
  const unsigned int maxBits = BitPrecision(range);
287
288
0
  word32 value;
289
290
0
  do
291
0
  {
292
0
    GenerateBlock((byte *)&value, sizeof(value));
293
0
    value = Crop(value, maxBits);
294
0
  } while (value > range);
295
296
0
  return value+min;
297
0
}
298
299
// Stack recursion below... GenerateIntoBufferedTransformation calls GenerateBlock,
300
// and GenerateBlock calls GenerateIntoBufferedTransformation. Ad infinitum. Also
301
// see http://github.com/weidai11/cryptopp/issues/38.
302
//
303
// According to Wei, RandomNumberGenerator is an interface, and it should not
304
// be instantiable. Its now spilt milk, and we are going to CRYPTOPP_ASSERT it in Debug
305
// builds to alert the programmer and throw in Release builds. Developers have
306
// a reference implementation in case its needed. If a programmer
307
// unintentionally lands here, then they should ensure use of a
308
// RandomNumberGenerator pointer or reference so polymorphism can provide the
309
// proper runtime dispatching.
310
311
void RandomNumberGenerator::GenerateBlock(byte *output, size_t size)
312
0
{
313
0
  CRYPTOPP_UNUSED(output), CRYPTOPP_UNUSED(size);
314
315
0
  ArraySink s(output, size);
316
0
  GenerateIntoBufferedTransformation(s, DEFAULT_CHANNEL, size);
317
0
}
318
319
void RandomNumberGenerator::DiscardBytes(size_t n)
320
0
{
321
0
  GenerateIntoBufferedTransformation(TheBitBucket(), DEFAULT_CHANNEL, n);
322
0
}
323
324
void RandomNumberGenerator::GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length)
325
0
{
326
0
  FixedSizeSecBlock<byte, 256> buffer;
327
0
  while (length)
328
0
  {
329
0
    size_t len = UnsignedMin(buffer.size(), length);
330
0
    GenerateBlock(buffer, len);
331
0
    (void)target.ChannelPut(channel, buffer, len);
332
0
    length -= len;
333
0
  }
334
0
}
335
336
size_t KeyDerivationFunction::MinDerivedKeyLength() const
337
0
{
338
0
  return 0;
339
0
}
340
341
size_t KeyDerivationFunction::MaxDerivedKeyLength() const
342
0
{
343
0
  return static_cast<size_t>(-1);
344
0
}
345
346
void KeyDerivationFunction::ThrowIfInvalidDerivedKeyLength(size_t length) const
347
5.55k
{
348
5.55k
  if (!IsValidDerivedLength(length))
349
205
    throw InvalidDerivedKeyLength(GetAlgorithm().AlgorithmName(), length);
350
5.55k
}
351
352
0
void KeyDerivationFunction::SetParameters(const NameValuePairs& params) {
353
0
  CRYPTOPP_UNUSED(params);
354
0
}
355
356
/// \brief Random Number Generator that does not produce random numbers
357
/// \details ClassNullRNG can be used for functions that require a RandomNumberGenerator
358
///   but don't actually use it. The class throws NotImplemented when a generation function is called.
359
/// \sa NullRNG()
360
class ClassNullRNG : public RandomNumberGenerator
361
{
362
public:
363
  /// \brief The name of the generator
364
  /// \returns the string \a NullRNGs
365
0
  std::string AlgorithmName() const {return "NullRNG";}
366
367
#if defined(CRYPTOPP_DOXYGEN_PROCESSING)
368
  /// \brief An implementation that throws NotImplemented
369
  byte GenerateByte () {}
370
  /// \brief An implementation that throws NotImplemented
371
  unsigned int GenerateBit () {}
372
  /// \brief An implementation that throws NotImplemented
373
  word32 GenerateWord32 (word32 min, word32 max) {}
374
#endif
375
376
  /// \brief An implementation that throws NotImplemented
377
  void GenerateBlock(byte *output, size_t size)
378
0
  {
379
0
    CRYPTOPP_UNUSED(output); CRYPTOPP_UNUSED(size);
380
0
    throw NotImplemented("NullRNG: NullRNG should only be passed to functions that don't need to generate random bytes");
381
0
  }
382
383
#if defined(CRYPTOPP_DOXYGEN_PROCESSING)
384
  /// \brief An implementation that throws NotImplemented
385
  void GenerateIntoBufferedTransformation (BufferedTransformation &target, const std::string &channel, lword length) {}
386
  /// \brief An implementation that throws NotImplemented
387
  void IncorporateEntropy (const byte *input, size_t length) {}
388
  /// \brief An implementation that returns \p false
389
  bool CanIncorporateEntropy () const {}
390
  /// \brief An implementation that does nothing
391
  void DiscardBytes (size_t n) {}
392
  /// \brief An implementation that does nothing
393
  void Shuffle (IT begin, IT end) {}
394
395
private:
396
  Clonable* Clone () const { return NULLPTR; }
397
#endif
398
};
399
400
RandomNumberGenerator & NullRNG()
401
0
{
402
0
  static ClassNullRNG s_nullRNG;
403
0
  return s_nullRNG;
404
0
}
405
406
bool HashTransformation::TruncatedVerify(const byte *digest, size_t digestLength)
407
38
{
408
  // Allocate at least 1 for calculated to avoid triggering diagnostics
409
38
  ThrowIfInvalidTruncatedSize(digestLength);
410
38
  SecByteBlock calculated(digestLength ? digestLength : 1);
411
38
  TruncatedFinal(calculated, digestLength);
412
38
  return VerifyBufsEqual(calculated, digest, digestLength);
413
38
}
414
415
void HashTransformation::ThrowIfInvalidTruncatedSize(size_t size) const
416
553k
{
417
553k
  if (size > DigestSize())
418
41
    throw InvalidArgument("HashTransformation: can't truncate a " + IntToString(DigestSize()) + " byte digest to " + IntToString(size) + " bytes");
419
553k
}
420
421
unsigned int BufferedTransformation::GetMaxWaitObjectCount() const
422
0
{
423
0
  const BufferedTransformation *t = AttachedTransformation();
424
0
  return t ? t->GetMaxWaitObjectCount() : 0;
425
0
}
426
427
void BufferedTransformation::GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
428
0
{
429
0
  BufferedTransformation *t = AttachedTransformation();
430
0
  if (t)
431
0
    t->GetWaitObjects(container, callStack);  // reduce clutter by not adding to stack here
432
0
}
433
434
void BufferedTransformation::Initialize(const NameValuePairs &parameters, int propagation)
435
412k
{
436
412k
  CRYPTOPP_UNUSED(propagation);
437
412k
  CRYPTOPP_ASSERT(!AttachedTransformation());
438
412k
  IsolatedInitialize(parameters);
439
412k
}
440
441
bool BufferedTransformation::Flush(bool hardFlush, int propagation, bool blocking)
442
0
{
443
0
  CRYPTOPP_UNUSED(propagation);
444
0
  CRYPTOPP_ASSERT(!AttachedTransformation());
445
0
  return IsolatedFlush(hardFlush, blocking);
446
0
}
447
448
bool BufferedTransformation::MessageSeriesEnd(int propagation, bool blocking)
449
0
{
450
0
  CRYPTOPP_UNUSED(propagation);
451
0
  CRYPTOPP_ASSERT(!AttachedTransformation());
452
0
  return IsolatedMessageSeriesEnd(blocking);
453
0
}
454
455
byte * BufferedTransformation::ChannelCreatePutSpace(const std::string &channel, size_t &size)
456
630
{
457
630
  byte* space = NULLPTR;
458
630
  if (channel.empty())
459
630
    space = CreatePutSpace(size);
460
0
  else
461
0
    throw NoChannelSupport(AlgorithmName());
462
630
  return space;
463
630
}
464
465
size_t BufferedTransformation::ChannelPut2(const std::string &channel, const byte *inString, size_t length, int messageEnd, bool blocking)
466
301M
{
467
301M
  size_t size = 0;
468
301M
  if (channel.empty())
469
301M
    size = Put2(inString, length, messageEnd, blocking);
470
0
  else
471
0
    throw NoChannelSupport(AlgorithmName());
472
301M
  return size;
473
301M
}
474
475
size_t BufferedTransformation::ChannelPutModifiable2(const std::string &channel, byte *inString, size_t length, int messageEnd, bool blocking)
476
4.91M
{
477
4.91M
  size_t size = 0;
478
4.91M
  if (channel.empty())
479
4.91M
    size = PutModifiable2(inString, length, messageEnd, blocking);
480
0
  else
481
0
    size = ChannelPut2(channel, inString, length, messageEnd, blocking);
482
4.91M
  return size;
483
4.91M
}
484
485
bool BufferedTransformation::ChannelFlush(const std::string &channel, bool hardFlush, int propagation, bool blocking)
486
0
{
487
0
  bool result = 0;
488
0
  if (channel.empty())
489
0
    result = Flush(hardFlush, propagation, blocking);
490
0
  else
491
0
    throw NoChannelSupport(AlgorithmName());
492
0
  return result;
493
0
}
494
495
bool BufferedTransformation::ChannelMessageSeriesEnd(const std::string &channel, int propagation, bool blocking)
496
0
{
497
0
  bool result = false;
498
0
  if (channel.empty())
499
0
    result = MessageSeriesEnd(propagation, blocking);
500
0
  else
501
0
    throw NoChannelSupport(AlgorithmName());
502
0
  return result;
503
0
}
504
505
lword BufferedTransformation::MaxRetrievable() const
506
5.55M
{
507
5.55M
  lword size = 0;
508
5.55M
  if (AttachedTransformation())
509
598k
    size = AttachedTransformation()->MaxRetrievable();
510
4.95M
  else
511
4.95M
    size = CopyTo(TheBitBucket());
512
5.55M
  return size;
513
5.55M
}
514
515
bool BufferedTransformation::AnyRetrievable() const
516
407k
{
517
407k
  bool result = false;
518
407k
  if (AttachedTransformation())
519
0
    result = AttachedTransformation()->AnyRetrievable();
520
407k
  else
521
407k
  {
522
407k
    byte b;
523
407k
    result = Peek(b) != 0;
524
407k
  }
525
407k
  return result;
526
407k
}
527
528
size_t BufferedTransformation::Get(byte &outByte)
529
298M
{
530
298M
  size_t size = 0;
531
298M
  if (AttachedTransformation())
532
9.31M
    size = AttachedTransformation()->Get(outByte);
533
289M
  else
534
289M
    size = Get(&outByte, 1);
535
298M
  return size;
536
298M
}
537
538
size_t BufferedTransformation::Get(byte *outString, size_t getMax)
539
289M
{
540
289M
  size_t size = 0;
541
289M
  if (AttachedTransformation())
542
479
    size = AttachedTransformation()->Get(outString, getMax);
543
289M
  else
544
289M
  {
545
289M
    ArraySink arraySink(outString, getMax);
546
289M
    size = (size_t)TransferTo(arraySink, getMax);
547
289M
  }
548
289M
  return size;
549
289M
}
550
551
size_t BufferedTransformation::Peek(byte &outByte) const
552
6.51M
{
553
6.51M
  size_t size = 0;
554
6.51M
  if (AttachedTransformation())
555
835k
    size = AttachedTransformation()->Peek(outByte);
556
5.67M
  else
557
5.67M
    size = Peek(&outByte, 1);
558
6.51M
  return size;
559
6.51M
}
560
561
size_t BufferedTransformation::Peek(byte *outString, size_t peekMax) const
562
5.67M
{
563
5.67M
  size_t size = 0;
564
5.67M
  if (AttachedTransformation())
565
0
    size = AttachedTransformation()->Peek(outString, peekMax);
566
5.67M
  else
567
5.67M
  {
568
5.67M
    ArraySink arraySink(outString, peekMax);
569
5.67M
    size = (size_t)CopyTo(arraySink, peekMax);
570
5.67M
  }
571
5.67M
  return size;
572
5.67M
}
573
574
lword BufferedTransformation::Skip(lword skipMax)
575
1.20M
{
576
1.20M
  lword size = 0;
577
1.20M
  if (AttachedTransformation())
578
509k
    size = AttachedTransformation()->Skip(skipMax);
579
695k
  else
580
695k
    size = TransferTo(TheBitBucket(), skipMax);
581
1.20M
  return size;
582
1.20M
}
583
584
lword BufferedTransformation::TotalBytesRetrievable() const
585
0
{
586
0
  lword size = 0;
587
0
  if (AttachedTransformation())
588
0
    size = AttachedTransformation()->TotalBytesRetrievable();
589
0
  else
590
0
    size = MaxRetrievable();
591
0
  return size;
592
0
}
593
594
unsigned int BufferedTransformation::NumberOfMessages() const
595
0
{
596
0
  unsigned int size = 0;
597
0
  if (AttachedTransformation())
598
0
    size = AttachedTransformation()->NumberOfMessages();
599
0
  else
600
0
    size = CopyMessagesTo(TheBitBucket());
601
0
  return size;
602
0
}
603
604
bool BufferedTransformation::AnyMessages() const
605
407k
{
606
407k
  bool result = false;
607
407k
  if (AttachedTransformation())
608
0
    result = AttachedTransformation()->AnyMessages();
609
407k
  else
610
407k
    result = NumberOfMessages() != 0;
611
407k
  return result;
612
407k
}
613
614
bool BufferedTransformation::GetNextMessage()
615
0
{
616
0
  bool result = false;
617
0
  if (AttachedTransformation())
618
0
    result = AttachedTransformation()->GetNextMessage();
619
0
  else
620
0
  {
621
0
    CRYPTOPP_ASSERT(!AnyMessages());
622
0
  }
623
0
  return result;
624
0
}
625
626
unsigned int BufferedTransformation::SkipMessages(unsigned int count)
627
0
{
628
0
  unsigned int size = 0;
629
0
  if (AttachedTransformation())
630
0
    size = AttachedTransformation()->SkipMessages(count);
631
0
  else
632
0
    size = TransferMessagesTo(TheBitBucket(), count);
633
0
  return size;
634
0
}
635
636
size_t BufferedTransformation::TransferMessagesTo2(BufferedTransformation &target, unsigned int &messageCount, const std::string &channel, bool blocking)
637
271k
{
638
271k
  if (AttachedTransformation())
639
0
    return AttachedTransformation()->TransferMessagesTo2(target, messageCount, channel, blocking);
640
271k
  else
641
271k
  {
642
271k
    unsigned int maxMessages = messageCount;
643
407k
    for (messageCount=0; messageCount < maxMessages && AnyMessages(); messageCount++)
644
135k
    {
645
135k
      size_t blockedBytes;
646
135k
      lword transferredBytes;
647
648
271k
      while (AnyRetrievable())
649
135k
      {
650
        // MaxRetrievable() instead of LWORD_MAX due to GH #962. If
651
        // the target calls CreatePutSpace(), then the allocation
652
        // size will be LWORD_MAX. That happens when target is a
653
        // ByteQueue. Maybe ByteQueue should check the size, and if
654
        // it is LWORD_MAX or -1, then use a default like 4096.
655
135k
        transferredBytes = MaxRetrievable();
656
135k
        blockedBytes = TransferTo2(target, transferredBytes, channel, blocking);
657
135k
        if (blockedBytes > 0)
658
0
          return blockedBytes;
659
135k
      }
660
661
135k
      if (target.ChannelMessageEnd(channel, GetAutoSignalPropagation(), blocking))
662
0
        return 1;
663
664
135k
      bool result = GetNextMessage();
665
135k
      CRYPTOPP_UNUSED(result); CRYPTOPP_ASSERT(result);
666
135k
    }
667
271k
    return 0;
668
271k
  }
669
271k
}
670
671
unsigned int BufferedTransformation::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const
672
0
{
673
0
  unsigned int size = 0;
674
0
  if (AttachedTransformation())
675
0
    size = AttachedTransformation()->CopyMessagesTo(target, count, channel);
676
0
  return size;
677
0
}
678
679
void BufferedTransformation::SkipAll()
680
0
{
681
0
  if (AttachedTransformation())
682
0
    AttachedTransformation()->SkipAll();
683
0
  else
684
0
  {
685
0
    while (SkipMessages()) {}
686
0
    while (Skip()) {}
687
0
  }
688
0
}
689
690
size_t BufferedTransformation::TransferAllTo2(BufferedTransformation &target, const std::string &channel, bool blocking)
691
135k
{
692
135k
  if (AttachedTransformation())
693
0
    return AttachedTransformation()->TransferAllTo2(target, channel, blocking);
694
135k
  else
695
135k
  {
696
135k
    CRYPTOPP_ASSERT(!NumberOfMessageSeries());
697
698
135k
    unsigned int messageCount;
699
135k
    do
700
271k
    {
701
271k
      messageCount = UINT_MAX;
702
271k
      size_t blockedBytes = TransferMessagesTo2(target, messageCount, channel, blocking);
703
271k
      if (blockedBytes)
704
0
        return blockedBytes;
705
271k
    }
706
271k
    while (messageCount != 0);
707
708
135k
    lword byteCount;
709
135k
    do
710
135k
    {
711
135k
      byteCount = ULONG_MAX;
712
135k
      size_t blockedBytes = TransferTo2(target, byteCount, channel, blocking);
713
135k
      if (blockedBytes)
714
0
        return blockedBytes;
715
135k
    }
716
135k
    while (byteCount != 0);
717
718
135k
    return 0;
719
135k
  }
720
135k
}
721
722
void BufferedTransformation::CopyAllTo(BufferedTransformation &target, const std::string &channel) const
723
0
{
724
0
  if (AttachedTransformation())
725
0
    AttachedTransformation()->CopyAllTo(target, channel);
726
0
  else
727
0
  {
728
0
    CRYPTOPP_ASSERT(!NumberOfMessageSeries());
729
0
    while (CopyMessagesTo(target, UINT_MAX, channel)) {}
730
0
  }
731
0
}
732
733
void BufferedTransformation::SetRetrievalChannel(const std::string &channel)
734
30
{
735
30
  if (AttachedTransformation())
736
15
    AttachedTransformation()->SetRetrievalChannel(channel);
737
30
}
738
739
size_t BufferedTransformation::ChannelPutWord16(const std::string &channel, word16 value, ByteOrder order, bool blocking)
740
0
{
741
0
  PutWord(false, order, m_buf, value);
742
0
  return ChannelPut(channel, m_buf, 2, blocking);
743
0
}
744
745
size_t BufferedTransformation::ChannelPutWord32(const std::string &channel, word32 value, ByteOrder order, bool blocking)
746
0
{
747
0
  PutWord(false, order, m_buf, value);
748
0
  return ChannelPut(channel, m_buf, 4, blocking);
749
0
}
750
751
size_t BufferedTransformation::ChannelPutWord64(const std::string &channel, word64 value, ByteOrder order, bool blocking)
752
0
{
753
0
  PutWord(false, order, m_buf, value);
754
0
  return ChannelPut(channel, m_buf, 8, blocking);
755
0
}
756
757
size_t BufferedTransformation::PutWord16(word16 value, ByteOrder order, bool blocking)
758
0
{
759
0
  return ChannelPutWord16(DEFAULT_CHANNEL, value, order, blocking);
760
0
}
761
762
size_t BufferedTransformation::PutWord32(word32 value, ByteOrder order, bool blocking)
763
0
{
764
0
  return ChannelPutWord32(DEFAULT_CHANNEL, value, order, blocking);
765
0
}
766
767
size_t BufferedTransformation::PutWord64(word64 value, ByteOrder order, bool blocking)
768
0
{
769
0
  return ChannelPutWord64(DEFAULT_CHANNEL, value, order, blocking);
770
0
}
771
772
size_t BufferedTransformation::PeekWord16(word16 &value, ByteOrder order) const
773
0
{
774
0
  byte buf[2] = {0, 0};
775
0
  size_t len = Peek(buf, 2);
776
777
0
  if (order == BIG_ENDIAN_ORDER)
778
0
    value = word16((buf[0] << 8) | buf[1]);
779
0
  else
780
0
    value = word16((buf[1] << 8) | buf[0]);
781
782
0
  return len;
783
0
}
784
785
size_t BufferedTransformation::PeekWord32(word32 &value, ByteOrder order) const
786
0
{
787
0
  byte buf[4] = {0, 0, 0, 0};
788
0
  size_t len = Peek(buf, 4);
789
790
0
  if (order == BIG_ENDIAN_ORDER)
791
0
    value = word32((buf[0] << 24) | (buf[1] << 16) |
792
0
                   (buf[2] << 8)  | (buf[3] << 0));
793
0
  else
794
0
    value = word32((buf[3] << 24) | (buf[2] << 16) |
795
0
                   (buf[1] << 8)  | (buf[0] << 0));
796
797
0
  return len;
798
0
}
799
800
size_t BufferedTransformation::PeekWord64(word64 &value, ByteOrder order) const
801
0
{
802
0
  byte buf[8] = {0, 0, 0, 0, 0, 0, 0, 0};
803
0
  size_t len = Peek(buf, 8);
804
805
0
  if (order == BIG_ENDIAN_ORDER)
806
0
    value = ((word64)buf[0] << 56) | ((word64)buf[1] << 48) | ((word64)buf[2] << 40) |
807
0
            ((word64)buf[3] << 32) | ((word64)buf[4] << 24) | ((word64)buf[5] << 16) |
808
0
            ((word64)buf[6] << 8)  |  (word64)buf[7];
809
0
  else
810
0
    value = ((word64)buf[7] << 56) | ((word64)buf[6] << 48) | ((word64)buf[5] << 40) |
811
0
            ((word64)buf[4] << 32) | ((word64)buf[3] << 24) | ((word64)buf[2] << 16) |
812
0
            ((word64)buf[1] << 8)  |  (word64)buf[0];
813
814
0
  return len;
815
0
}
816
817
size_t BufferedTransformation::GetWord16(word16 &value, ByteOrder order)
818
0
{
819
0
  return (size_t)Skip(PeekWord16(value, order));
820
0
}
821
822
size_t BufferedTransformation::GetWord32(word32 &value, ByteOrder order)
823
0
{
824
0
  return (size_t)Skip(PeekWord32(value, order));
825
0
}
826
827
size_t BufferedTransformation::GetWord64(word64 &value, ByteOrder order)
828
0
{
829
0
  return (size_t)Skip(PeekWord64(value, order));
830
0
}
831
832
void BufferedTransformation::Attach(BufferedTransformation *newAttachment)
833
0
{
834
0
  if (AttachedTransformation() && AttachedTransformation()->Attachable())
835
0
    AttachedTransformation()->Attach(newAttachment);
836
0
  else
837
0
    Detach(newAttachment);
838
0
}
839
840
void GeneratableCryptoMaterial::GenerateRandomWithKeySize(RandomNumberGenerator &rng, unsigned int keySize)
841
0
{
842
0
  GenerateRandom(rng, MakeParameters("KeySize", (int)keySize));
843
0
}
844
845
class PK_DefaultEncryptionFilter : public Unflushable<Filter>
846
{
847
public:
848
  PK_DefaultEncryptionFilter(RandomNumberGenerator &rng, const PK_Encryptor &encryptor, BufferedTransformation *attachment, const NameValuePairs &parameters)
849
    : m_rng(rng), m_encryptor(encryptor), m_parameters(parameters)
850
0
  {
851
0
    Detach(attachment);
852
0
  }
853
854
  size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
855
0
  {
856
0
    FILTER_BEGIN;
857
0
    m_plaintextQueue.Put(inString, length);
858
859
0
    if (messageEnd)
860
0
    {
861
0
      {
862
0
      size_t plaintextLength;
863
0
      if (!SafeConvert(m_plaintextQueue.CurrentSize(), plaintextLength))
864
0
        throw InvalidArgument("PK_DefaultEncryptionFilter: plaintext too long");
865
0
      size_t ciphertextLength = m_encryptor.CiphertextLength(plaintextLength);
866
867
0
      SecByteBlock plaintext(plaintextLength);
868
0
      m_plaintextQueue.Get(plaintext, plaintextLength);
869
0
      m_ciphertext.resize(ciphertextLength);
870
0
      m_encryptor.Encrypt(m_rng, plaintext, plaintextLength, m_ciphertext, m_parameters);
871
0
      }
872
873
0
      FILTER_OUTPUT(1, m_ciphertext, m_ciphertext.size(), messageEnd);
874
0
    }
875
0
    FILTER_END_NO_MESSAGE_END;
876
0
  }
877
878
  RandomNumberGenerator &m_rng;
879
  const PK_Encryptor &m_encryptor;
880
  const NameValuePairs &m_parameters;
881
  ByteQueue m_plaintextQueue;
882
  SecByteBlock m_ciphertext;
883
};
884
885
BufferedTransformation * PK_Encryptor::CreateEncryptionFilter(RandomNumberGenerator &rng, BufferedTransformation *attachment, const NameValuePairs &parameters) const
886
0
{
887
0
  return new PK_DefaultEncryptionFilter(rng, *this, attachment, parameters);
888
0
}
889
890
class PK_DefaultDecryptionFilter : public Unflushable<Filter>
891
{
892
public:
893
  PK_DefaultDecryptionFilter(RandomNumberGenerator &rng, const PK_Decryptor &decryptor, BufferedTransformation *attachment, const NameValuePairs &parameters)
894
    : m_rng(rng), m_decryptor(decryptor), m_parameters(parameters)
895
0
  {
896
0
    Detach(attachment);
897
0
  }
898
899
  size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
900
0
  {
901
0
    FILTER_BEGIN;
902
0
    m_ciphertextQueue.Put(inString, length);
903
904
0
    if (messageEnd)
905
0
    {
906
0
      {
907
0
      size_t ciphertextLength;
908
0
      if (!SafeConvert(m_ciphertextQueue.CurrentSize(), ciphertextLength))
909
0
        throw InvalidArgument("PK_DefaultDecryptionFilter: ciphertext too long");
910
0
      size_t maxPlaintextLength = m_decryptor.MaxPlaintextLength(ciphertextLength);
911
912
0
      SecByteBlock ciphertext(ciphertextLength);
913
0
      m_ciphertextQueue.Get(ciphertext, ciphertextLength);
914
0
      m_plaintext.resize(maxPlaintextLength);
915
0
      m_result = m_decryptor.Decrypt(m_rng, ciphertext, ciphertextLength, m_plaintext, m_parameters);
916
0
      if (!m_result.isValidCoding)
917
0
        throw InvalidCiphertext(m_decryptor.AlgorithmName() + ": invalid ciphertext");
918
0
      }
919
920
0
      FILTER_OUTPUT(1, m_plaintext, m_result.messageLength, messageEnd);
921
0
    }
922
0
    FILTER_END_NO_MESSAGE_END;
923
0
  }
924
925
  RandomNumberGenerator &m_rng;
926
  const PK_Decryptor &m_decryptor;
927
  const NameValuePairs &m_parameters;
928
  ByteQueue m_ciphertextQueue;
929
  SecByteBlock m_plaintext;
930
  DecodingResult m_result;
931
};
932
933
BufferedTransformation * PK_Decryptor::CreateDecryptionFilter(RandomNumberGenerator &rng, BufferedTransformation *attachment, const NameValuePairs &parameters) const
934
0
{
935
0
  return new PK_DefaultDecryptionFilter(rng, *this, attachment, parameters);
936
0
}
937
938
size_t PK_Signer::Sign(RandomNumberGenerator &rng, PK_MessageAccumulator *messageAccumulator, byte *signature) const
939
0
{
940
0
  member_ptr<PK_MessageAccumulator> m(messageAccumulator);
941
0
  return SignAndRestart(rng, *m, signature, false);
942
0
}
943
944
size_t PK_Signer::SignMessage(RandomNumberGenerator &rng, const byte *message, size_t messageLen, byte *signature) const
945
0
{
946
0
  member_ptr<PK_MessageAccumulator> m(NewSignatureAccumulator(rng));
947
0
  m->Update(message, messageLen);
948
0
  return SignAndRestart(rng, *m, signature, false);
949
0
}
950
951
size_t PK_Signer::SignMessageWithRecovery(RandomNumberGenerator &rng, const byte *recoverableMessage, size_t recoverableMessageLength,
952
  const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength, byte *signature) const
953
0
{
954
0
  member_ptr<PK_MessageAccumulator> m(NewSignatureAccumulator(rng));
955
0
  InputRecoverableMessage(*m, recoverableMessage, recoverableMessageLength);
956
0
  m->Update(nonrecoverableMessage, nonrecoverableMessageLength);
957
0
  return SignAndRestart(rng, *m, signature, false);
958
0
}
959
960
bool PK_Verifier::Verify(PK_MessageAccumulator *messageAccumulator) const
961
0
{
962
0
  member_ptr<PK_MessageAccumulator> m(messageAccumulator);
963
0
  return VerifyAndRestart(*m);
964
0
}
965
966
bool PK_Verifier::VerifyMessage(const byte *message, size_t messageLen, const byte *signature, size_t signatureLen) const
967
0
{
968
0
  member_ptr<PK_MessageAccumulator> m(NewVerificationAccumulator());
969
0
  InputSignature(*m, signature, signatureLen);
970
0
  m->Update(message, messageLen);
971
0
  return VerifyAndRestart(*m);
972
0
}
973
974
DecodingResult PK_Verifier::Recover(byte *recoveredMessage, PK_MessageAccumulator *messageAccumulator) const
975
0
{
976
0
  member_ptr<PK_MessageAccumulator> m(messageAccumulator);
977
0
  return RecoverAndRestart(recoveredMessage, *m);
978
0
}
979
980
DecodingResult PK_Verifier::RecoverMessage(byte *recoveredMessage,
981
  const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength,
982
  const byte *signature, size_t signatureLength) const
983
0
{
984
0
  member_ptr<PK_MessageAccumulator> m(NewVerificationAccumulator());
985
0
  InputSignature(*m, signature, signatureLength);
986
0
  m->Update(nonrecoverableMessage, nonrecoverableMessageLength);
987
0
  return RecoverAndRestart(recoveredMessage, *m);
988
0
}
989
990
void SimpleKeyAgreementDomain::GenerateKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const
991
0
{
992
0
  GeneratePrivateKey(rng, privateKey);
993
0
  GeneratePublicKey(rng, privateKey, publicKey);
994
0
}
995
996
void AuthenticatedKeyAgreementDomain::GenerateStaticKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const
997
0
{
998
0
  GenerateStaticPrivateKey(rng, privateKey);
999
0
  GenerateStaticPublicKey(rng, privateKey, publicKey);
1000
0
}
1001
1002
void AuthenticatedKeyAgreementDomain::GenerateEphemeralKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const
1003
0
{
1004
0
  GenerateEphemeralPrivateKey(rng, privateKey);
1005
0
  GenerateEphemeralPublicKey(rng, privateKey, publicKey);
1006
0
}
1007
1008
// Allow a distro or packager to override the build-time version
1009
//  http://github.com/weidai11/cryptopp/issues/371
1010
#ifndef CRYPTOPP_BUILD_VERSION
1011
0
# define CRYPTOPP_BUILD_VERSION CRYPTOPP_VERSION
1012
#endif
1013
int LibraryVersion(CRYPTOPP_NOINLINE_DOTDOTDOT)
1014
0
{
1015
0
  return CRYPTOPP_BUILD_VERSION;
1016
0
}
1017
1018
class NullNameValuePairs : public NameValuePairs
1019
{
1020
public:
1021
10
  NullNameValuePairs() {}    //  Clang complains a default ctor must be available
1022
  bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const
1023
326
    {CRYPTOPP_UNUSED(name); CRYPTOPP_UNUSED(valueType); CRYPTOPP_UNUSED(pValue); return false;}
1024
};
1025
1026
#if HAVE_GCC_INIT_PRIORITY
1027
  const std::string DEFAULT_CHANNEL __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 25))) = "";
1028
  const std::string AAD_CHANNEL __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 26))) = "AAD";
1029
  const NullNameValuePairs s_nullNameValuePairs __attribute__ ((init_priority (CRYPTOPP_INIT_PRIORITY + 27)));
1030
  const NameValuePairs& g_nullNameValuePairs = s_nullNameValuePairs;
1031
#elif HAVE_MSC_INIT_PRIORITY
1032
  #pragma warning(disable: 4073)
1033
  #pragma init_seg(lib)
1034
  const std::string DEFAULT_CHANNEL = "";
1035
  const std::string AAD_CHANNEL = "AAD";
1036
  const NullNameValuePairs s_nullNameValuePairs;
1037
  const NameValuePairs& g_nullNameValuePairs = s_nullNameValuePairs;
1038
  #pragma warning(default: 4073)
1039
#elif HAVE_XLC_INIT_PRIORITY
1040
  #pragma priority(260)
1041
  const std::string DEFAULT_CHANNEL = "";
1042
  const std::string AAD_CHANNEL = "AAD";
1043
  const NullNameValuePairs s_nullNameValuePairs;
1044
  const NameValuePairs& g_nullNameValuePairs = s_nullNameValuePairs;
1045
#else
1046
  const std::string DEFAULT_CHANNEL = "";
1047
  const std::string AAD_CHANNEL = "AAD";
1048
  const simple_ptr<NullNameValuePairs> s_pNullNameValuePairs(new NullNameValuePairs);
1049
  const NameValuePairs &g_nullNameValuePairs = *s_pNullNameValuePairs.m_p;
1050
#endif
1051
1052
NAMESPACE_END  // CryptoPP
1053
1054
#endif  // CRYPTOPP_IMPORTS