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