Crypto++ 8.7
Free C++ class library of cryptographic schemes
filters.cpp
1// filters.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: 4100 4189 4355)
8#endif
9
10#if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
11# pragma GCC diagnostic ignored "-Wunused-value"
12#endif
13
14#ifndef CRYPTOPP_IMPORTS
15
16#include "filters.h"
17#include "mqueue.h"
18#include "fltrimpl.h"
19#include "argnames.h"
20#include "smartptr.h"
21#include "stdcpp.h"
22#include "misc.h"
23
24NAMESPACE_BEGIN(CryptoPP)
25
27 : m_attachment(attachment), m_inputPosition(0), m_continueAt(0)
28{
29}
30
31BufferedTransformation * Filter::NewDefaultAttachment() const
32{
33 return new MessageQueue;
34}
35
37{
38 if (m_attachment.get() == NULLPTR)
39 m_attachment.reset(NewDefaultAttachment());
40 return m_attachment.get();
41}
42
44{
45 if (m_attachment.get() == NULLPTR)
46 const_cast<Filter *>(this)->m_attachment.reset(NewDefaultAttachment());
47 return m_attachment.get();
48}
49
51{
52 m_attachment.reset(newOut);
53}
54
55void Filter::Insert(Filter *filter)
56{
57 filter->m_attachment.reset(m_attachment.release());
58 m_attachment.reset(filter);
59}
60
61size_t Filter::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
62{
63 return AttachedTransformation()->CopyRangeTo2(target, begin, end, channel, blocking);
64}
65
66size_t Filter::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
67{
68 return AttachedTransformation()->TransferTo2(target, transferBytes, channel, blocking);
69}
70
71void Filter::Initialize(const NameValuePairs &parameters, int propagation)
72{
73 m_inputPosition = m_continueAt = 0;
74 IsolatedInitialize(parameters);
75 PropagateInitialize(parameters, propagation);
76}
77
78bool Filter::Flush(bool hardFlush, int propagation, bool blocking)
79{
80 switch (m_continueAt)
81 {
82 case 0:
83 if (IsolatedFlush(hardFlush, blocking))
84 return true;
85 // fall through
86 case 1:
87 if (OutputFlush(1, hardFlush, propagation, blocking))
88 return true;
89 // fall through
90 default: ;
91 }
92 return false;
93}
94
95bool Filter::MessageSeriesEnd(int propagation, bool blocking)
96{
97 switch (m_continueAt)
98 {
99 case 0:
100 if (IsolatedMessageSeriesEnd(blocking))
101 return true;
102 // fall through
103 case 1:
104 if (ShouldPropagateMessageSeriesEnd() && OutputMessageSeriesEnd(1, propagation, blocking))
105 return true;
106 // fall through
107 default: ;
108 }
109 return false;
110}
111
112void Filter::PropagateInitialize(const NameValuePairs &parameters, int propagation)
113{
114 if (propagation)
115 AttachedTransformation()->Initialize(parameters, propagation-1);
116}
117
118size_t Filter::OutputModifiable(int outputSite, byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel)
119{
120 if (messageEnd)
121 messageEnd--;
122 size_t result = AttachedTransformation()->ChannelPutModifiable2(channel, inString, length, messageEnd, blocking);
123 m_continueAt = result ? outputSite : 0;
124 return result;
125}
126
127size_t Filter::Output(int outputSite, const byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel)
128{
129 if (messageEnd)
130 messageEnd--;
131 size_t result = AttachedTransformation()->ChannelPut2(channel, inString, length, messageEnd, blocking);
132 m_continueAt = result ? outputSite : 0;
133 return result;
134}
135
136bool Filter::OutputFlush(int outputSite, bool hardFlush, int propagation, bool blocking, const std::string &channel)
137{
138 if (propagation && AttachedTransformation()->ChannelFlush(channel, hardFlush, propagation-1, blocking))
139 {
140 m_continueAt = outputSite;
141 return true;
142 }
143 m_continueAt = 0;
144 return false;
145}
146
147bool Filter::OutputMessageSeriesEnd(int outputSite, int propagation, bool blocking, const std::string &channel)
148{
149 if (propagation && AttachedTransformation()->ChannelMessageSeriesEnd(channel, propagation-1, blocking))
150 {
151 m_continueAt = outputSite;
152 return true;
153 }
154 m_continueAt = 0;
155 return false;
156}
157
158// *************************************************************
159
161{
162 m_currentMessageBytes = m_totalBytes = m_currentSeriesMessages = m_totalMessages = m_totalMessageSeries = 0;
163 m_rangesToSkip.clear();
164}
165
166void MeterFilter::AddRangeToSkip(unsigned int message, lword position, lword size, bool sortNow)
167{
168 MessageRange r = {message, position, size};
169 m_rangesToSkip.push_back(r);
170 if (sortNow)
171 std::sort(m_rangesToSkip.begin(), m_rangesToSkip.end());
172}
173
174size_t MeterFilter::PutMaybeModifiable(byte *begin, size_t length, int messageEnd, bool blocking, bool modifiable)
175{
176 if (!m_transparent)
177 return 0;
178
179 size_t t;
180 FILTER_BEGIN;
181
182 m_begin = begin;
183 m_length = length;
184
185 while (m_length > 0 || messageEnd)
186 {
187 if (m_length > 0 && !m_rangesToSkip.empty() && m_rangesToSkip.front().message == m_totalMessages && m_currentMessageBytes + m_length > m_rangesToSkip.front().position)
188 {
189 FILTER_OUTPUT_MAYBE_MODIFIABLE(1, m_begin, t = (size_t)SaturatingSubtract(m_rangesToSkip.front().position, m_currentMessageBytes), false, modifiable);
190
191 CRYPTOPP_ASSERT(t < m_length);
192 m_begin = PtrAdd(m_begin, t);
193 m_length -= t;
194 m_currentMessageBytes += t;
195 m_totalBytes += t;
196
197 if (m_currentMessageBytes + m_length < m_rangesToSkip.front().position + m_rangesToSkip.front().size)
198 t = m_length;
199 else
200 {
201 t = (size_t)SaturatingSubtract(m_rangesToSkip.front().position + m_rangesToSkip.front().size, m_currentMessageBytes);
202 CRYPTOPP_ASSERT(t <= m_length);
203 m_rangesToSkip.pop_front();
204 }
205
206 m_begin = PtrAdd(m_begin, t);
207 m_length -= t;
208 m_currentMessageBytes += t;
209 m_totalBytes += t;
210 }
211 else
212 {
213 FILTER_OUTPUT_MAYBE_MODIFIABLE(2, m_begin, m_length, messageEnd, modifiable);
214
215 m_currentMessageBytes += m_length;
216 m_totalBytes += m_length;
217 m_length = 0;
218
219 if (messageEnd)
220 {
221 m_currentMessageBytes = 0;
222 m_currentSeriesMessages++;
223 m_totalMessages++;
224 messageEnd = false;
225 }
226 }
227 }
228
229 FILTER_END_NO_MESSAGE_END;
230}
231
232size_t MeterFilter::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
233{
234 return PutMaybeModifiable(const_cast<byte *>(begin), length, messageEnd, blocking, false);
235}
236
237size_t MeterFilter::PutModifiable2(byte *begin, size_t length, int messageEnd, bool blocking)
238{
239 return PutMaybeModifiable(begin, length, messageEnd, blocking, true);
240}
241
243{
244 CRYPTOPP_UNUSED(blocking);
245 m_currentMessageBytes = 0;
246 m_currentSeriesMessages = 0;
247 m_totalMessageSeries++;
248 return false;
249}
250
251// *************************************************************
252
253void FilterWithBufferedInput::BlockQueue::ResetQueue(size_t blockSize, size_t maxBlocks)
254{
255 m_buffer.New(blockSize * maxBlocks);
256 m_blockSize = blockSize;
257 m_maxBlocks = maxBlocks;
258 m_size = 0;
259 m_begin = m_buffer;
260}
261
262byte *FilterWithBufferedInput::BlockQueue::GetBlock()
263{
264 if (m_size >= m_blockSize)
265 {
266 byte *ptr = m_begin;
267 if ((m_begin = PtrAdd(m_begin, m_blockSize)) == m_buffer.end())
268 m_begin = m_buffer;
269 m_size -= m_blockSize;
270 return ptr;
271 }
272 else
273 return NULLPTR;
274}
275
276byte *FilterWithBufferedInput::BlockQueue::GetContigousBlocks(size_t &numberOfBytes)
277{
278 numberOfBytes = STDMIN(numberOfBytes, STDMIN<size_t>(PtrDiff(m_buffer.end(), m_begin), m_size));
279 byte *ptr = m_begin;
280 m_begin = PtrAdd(m_begin, numberOfBytes);
281 m_size -= numberOfBytes;
282 if (m_size == 0 || m_begin == m_buffer.end())
283 m_begin = m_buffer;
284 return ptr;
285}
286
287size_t FilterWithBufferedInput::BlockQueue::GetAll(byte *outString)
288{
289 // Avoid passing NULL pointer to memcpy
290 if (!outString) return 0;
291
292 size_t size = m_size;
293 size_t numberOfBytes = m_maxBlocks*m_blockSize;
294 const byte *ptr = GetContigousBlocks(numberOfBytes);
295 memcpy(outString, ptr, numberOfBytes);
296 memcpy(PtrAdd(outString, numberOfBytes), m_begin, m_size);
297 m_size = 0;
298 return size;
299}
300
301void FilterWithBufferedInput::BlockQueue::Put(const byte *inString, size_t length)
302{
303 // Avoid passing NULL pointer to memcpy
304 if (!inString || !length) return;
305
306 CRYPTOPP_ASSERT(m_size + length <= m_buffer.size());
307 byte *end = (m_size < static_cast<size_t>(PtrDiff(m_buffer.end(), m_begin)) ?
308 PtrAdd(m_begin, m_size) : PtrAdd(m_begin, m_size - m_buffer.size()));
309 size_t len = STDMIN(length, size_t(m_buffer.end()-end));
310 memcpy(end, inString, len);
311 if (len < length)
312 memcpy(m_buffer, PtrAdd(inString, len), length-len);
313 m_size += length;
314}
315
317 : Filter(attachment), m_firstSize(SIZE_MAX), m_blockSize(0), m_lastSize(SIZE_MAX), m_firstInputDone(false)
318{
319}
320
321FilterWithBufferedInput::FilterWithBufferedInput(size_t firstSize, size_t blockSize, size_t lastSize, BufferedTransformation *attachment)
322 : Filter(attachment), m_firstSize(firstSize), m_blockSize(blockSize), m_lastSize(lastSize), m_firstInputDone(false)
323{
324 if (m_firstSize == SIZE_MAX || m_blockSize < 1 || m_lastSize == SIZE_MAX)
325 throw InvalidArgument("FilterWithBufferedInput: invalid buffer size");
326
327 m_queue.ResetQueue(1, m_firstSize);
328}
329
331{
332 InitializeDerivedAndReturnNewSizes(parameters, m_firstSize, m_blockSize, m_lastSize);
333 if (m_firstSize == SIZE_MAX || m_blockSize < 1 || m_lastSize == SIZE_MAX)
334 throw InvalidArgument("FilterWithBufferedInput: invalid buffer size");
335 m_queue.ResetQueue(1, m_firstSize);
336 m_firstInputDone = false;
337}
338
339bool FilterWithBufferedInput::IsolatedFlush(bool hardFlush, bool blocking)
340{
341 if (!blocking)
342 throw BlockingInputOnly("FilterWithBufferedInput");
343
344 if (hardFlush)
345 ForceNextPut();
346 FlushDerived();
347
348 return false;
349}
350
351size_t FilterWithBufferedInput::PutMaybeModifiable(byte *inString, size_t length, int messageEnd, bool blocking, bool modifiable)
352{
353 if (!blocking)
354 throw BlockingInputOnly("FilterWithBufferedInput");
355
356 if (length != 0)
357 {
358 size_t newLength = m_queue.CurrentSize() + length;
359
360 if (!m_firstInputDone && newLength >= m_firstSize)
361 {
362 size_t len = m_firstSize - m_queue.CurrentSize();
363 m_queue.Put(inString, len);
364 FirstPut(m_queue.GetContigousBlocks(m_firstSize));
365 CRYPTOPP_ASSERT(m_queue.CurrentSize() == 0);
366 m_queue.ResetQueue(m_blockSize, (2*m_blockSize+m_lastSize-2)/m_blockSize);
367
368 inString = PtrAdd(inString, len);
369 newLength -= m_firstSize;
370 m_firstInputDone = true;
371 }
372
373 if (m_firstInputDone)
374 {
375 if (m_blockSize == 1)
376 {
377 while (newLength > m_lastSize && m_queue.CurrentSize() > 0)
378 {
379 size_t len = newLength - m_lastSize;
380 byte *ptr = m_queue.GetContigousBlocks(len);
381 NextPutModifiable(ptr, len);
382 newLength -= len;
383 }
384
385 if (newLength > m_lastSize)
386 {
387 size_t len = newLength - m_lastSize;
388 NextPutMaybeModifiable(inString, len, modifiable);
389 inString = PtrAdd(inString, len);
390 newLength -= len;
391 }
392 }
393 else
394 {
395 while (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() >= m_blockSize)
396 {
397 NextPutModifiable(m_queue.GetBlock(), m_blockSize);
398 newLength -= m_blockSize;
399 }
400
401 if (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() > 0)
402 {
403 CRYPTOPP_ASSERT(m_queue.CurrentSize() < m_blockSize);
404 size_t len = m_blockSize - m_queue.CurrentSize();
405 m_queue.Put(inString, len);
406 inString = PtrAdd(inString, len);
407 NextPutModifiable(m_queue.GetBlock(), m_blockSize);
408 newLength -= m_blockSize;
409 }
410
411 if (newLength >= m_blockSize + m_lastSize)
412 {
413 size_t len = RoundDownToMultipleOf(newLength - m_lastSize, m_blockSize);
414 NextPutMaybeModifiable(inString, len, modifiable);
415 inString = PtrAdd(inString, len);
416 newLength -= len;
417 }
418 }
419 }
420
421 m_queue.Put(inString, newLength - m_queue.CurrentSize());
422 }
423
424 if (messageEnd)
425 {
426 if (!m_firstInputDone && m_firstSize==0)
427 FirstPut(NULLPTR);
428
429 SecByteBlock temp(m_queue.CurrentSize());
430 m_queue.GetAll(temp);
431 LastPut(temp, temp.size());
432
433 m_firstInputDone = false;
434 m_queue.ResetQueue(1, m_firstSize);
435
436 // Cast to void to suppress Coverity finding
437 (void)Output(1, NULLPTR, 0, messageEnd, blocking);
438 }
439 return 0;
440}
441
443{
444 if (!m_firstInputDone)
445 return;
446
447 if (m_blockSize > 1)
448 {
449 while (m_queue.CurrentSize() >= m_blockSize)
450 NextPutModifiable(m_queue.GetBlock(), m_blockSize);
451 }
452 else
453 {
454 size_t len;
455 while ((len = m_queue.CurrentSize()) > 0)
456 NextPutModifiable(m_queue.GetContigousBlocks(len), len);
457 }
458}
459
460void FilterWithBufferedInput::NextPutMultiple(const byte *inString, size_t length)
461{
462 CRYPTOPP_ASSERT(m_blockSize > 1); // m_blockSize = 1 should always override this function
463 while (length > 0)
464 {
465 CRYPTOPP_ASSERT(length >= m_blockSize);
466 NextPutSingle(inString);
467 inString = PtrAdd(inString, m_blockSize);
468 length -= m_blockSize;
469 }
470}
471
472// *************************************************************
473
474void Redirector::Initialize(const NameValuePairs &parameters, int propagation)
475{
476 m_target = parameters.GetValueWithDefault("RedirectionTargetPointer", (BufferedTransformation*)NULLPTR);
477 m_behavior = parameters.GetIntValueWithDefault("RedirectionBehavior", PASS_EVERYTHING);
478
479 if (m_target && GetPassSignals())
480 m_target->Initialize(parameters, propagation);
481}
482
483// *************************************************************
484
485ProxyFilter::ProxyFilter(BufferedTransformation *filter, size_t firstSize, size_t lastSize, BufferedTransformation *attachment)
486 : FilterWithBufferedInput(firstSize, 1, lastSize, attachment), m_filter(filter)
487{
488 if (m_filter.get())
489 m_filter->Attach(new OutputProxy(*this, false));
490}
491
492bool ProxyFilter::IsolatedFlush(bool hardFlush, bool blocking)
493{
494 return m_filter.get() ? m_filter->Flush(hardFlush, -1, blocking) : false;
495}
496
497void ProxyFilter::SetFilter(Filter *filter)
498{
499 m_filter.reset(filter);
500 if (filter)
501 {
502 OutputProxy *proxy;
503 member_ptr<OutputProxy> temp(proxy = new OutputProxy(*this, false));
504 m_filter->TransferAllTo(*proxy);
505 m_filter->Attach(temp.release());
506 }
507}
508
509void ProxyFilter::NextPutMultiple(const byte *s, size_t len)
510{
511 if (m_filter.get())
512 m_filter->Put(s, len);
513}
514
515void ProxyFilter::NextPutModifiable(byte *s, size_t len)
516{
517 if (m_filter.get())
518 m_filter->PutModifiable(s, len);
519}
520
521// *************************************************************
522
524{
525 parameters.GetRequiredParameter("RandomNumberSink", "RandomNumberGeneratorPointer", m_rng);
526}
527
528size_t RandomNumberSink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
529{
530 CRYPTOPP_UNUSED(messageEnd); CRYPTOPP_UNUSED(blocking);
531 m_rng->IncorporateEntropy(begin, length);
532 return 0;
533}
534
535size_t ArraySink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
536{
537 CRYPTOPP_UNUSED(messageEnd); CRYPTOPP_UNUSED(blocking);
538
539 // Avoid passing NULL pointer to memcpy. Using memmove due to
540 // Valgrind finding on overlapping buffers.
541 size_t copied = 0;
542 if (m_buf && begin)
543 {
544 copied = STDMIN(length, SaturatingSubtract(m_size, m_total));
545 memmove(PtrAdd(m_buf, m_total), begin, copied);
546 }
547 m_total += copied;
548 return length - copied;
549}
550
551byte * ArraySink::CreatePutSpace(size_t &size)
552{
553 size = SaturatingSubtract(m_size, m_total);
554 return PtrAdd(m_buf, m_total);
555}
556
557void ArraySink::IsolatedInitialize(const NameValuePairs &parameters)
558{
559 ByteArrayParameter array;
560 if (!parameters.GetValue(Name::OutputBuffer(), array))
561 throw InvalidArgument("ArraySink: missing OutputBuffer argument");
562 m_buf = array.begin();
563 m_size = array.size();
564}
565
566size_t ArrayXorSink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
567{
568 CRYPTOPP_UNUSED(messageEnd); CRYPTOPP_UNUSED(blocking);
569
570 // Avoid passing NULL pointer to xorbuf
571 size_t copied = 0;
572 if (m_buf && begin)
573 {
574 copied = STDMIN(length, SaturatingSubtract(m_size, m_total));
575 xorbuf(PtrAdd(m_buf, m_total), begin, copied);
576 }
577 m_total += copied;
578 return length - copied;
579}
580
581// *************************************************************
582
584 : FilterWithBufferedInput(attachment), m_cipher(c), m_padding(DEFAULT_PADDING)
585{
586 CRYPTOPP_ASSERT(c.MinLastBlockSize() == 0 || c.MinLastBlockSize() > c.MandatoryBlockSize());
587
588 const bool authenticatedFilter = dynamic_cast<AuthenticatedSymmetricCipher *>(&c) != NULLPTR;
589 if (authenticatedFilter)
590 throw InvalidArgument("StreamTransformationFilter: please use AuthenticatedEncryptionFilter and AuthenticatedDecryptionFilter for AuthenticatedSymmetricCipher");
591
592 // InitializeDerivedAndReturnNewSizes may override some of these
593 m_mandatoryBlockSize = m_cipher.MandatoryBlockSize();
594 m_optimalBufferSize = m_cipher.OptimalBlockSize();
595 m_isSpecial = m_cipher.IsLastBlockSpecial() && m_mandatoryBlockSize > 1;
596 m_reservedBufferSize = STDMAX(2*m_mandatoryBlockSize, m_optimalBufferSize);
597
600 (Name::BlockPaddingScheme(), padding));
601}
602
604 : FilterWithBufferedInput(attachment), m_cipher(c), m_padding(DEFAULT_PADDING)
605{
606 const bool authenticatedFilter = dynamic_cast<AuthenticatedSymmetricCipher *>(&c) != NULLPTR;
607 if (!authenticatedFilter)
608 {
609 CRYPTOPP_ASSERT(c.MinLastBlockSize() == 0 || c.MinLastBlockSize() > c.MandatoryBlockSize());
610 }
611
612 if (authenticatedFilter && !authenticated)
613 throw InvalidArgument("StreamTransformationFilter: please use AuthenticatedEncryptionFilter and AuthenticatedDecryptionFilter for AuthenticatedSymmetricCipher");
614
615 // InitializeDerivedAndReturnNewSizes may override some of these
616 m_mandatoryBlockSize = m_cipher.MandatoryBlockSize();
617 m_optimalBufferSize = m_cipher.OptimalBlockSize();
618 m_isSpecial = m_cipher.IsLastBlockSpecial() && m_mandatoryBlockSize > 1;
619 m_reservedBufferSize = STDMAX(2*m_mandatoryBlockSize, m_optimalBufferSize);
620
623 (Name::BlockPaddingScheme(), padding));
624}
625
626size_t StreamTransformationFilter::LastBlockSize(StreamTransformation &c, BlockPaddingScheme padding)
627{
628 if (c.MinLastBlockSize() > 0)
629 return c.MinLastBlockSize();
630 else if (c.MandatoryBlockSize() > 1 && !c.IsForwardTransformation() && padding != NO_PADDING && padding != ZEROS_PADDING)
631 return c.MandatoryBlockSize();
632
633 return 0;
634}
635
636void StreamTransformationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
637{
639 bool isBlockCipher = (m_mandatoryBlockSize > 1 && m_cipher.MinLastBlockSize() == 0);
640
641 if (padding == DEFAULT_PADDING)
642 m_padding = isBlockCipher ? PKCS_PADDING : NO_PADDING;
643 else
644 m_padding = padding;
645
646 if (!isBlockCipher)
647 {
648 if (m_padding == PKCS_PADDING)
649 throw InvalidArgument("StreamTransformationFilter: PKCS_PADDING cannot be used with " + m_cipher.AlgorithmName());
650 else if (m_padding == W3C_PADDING)
651 throw InvalidArgument("StreamTransformationFilter: W3C_PADDING cannot be used with " + m_cipher.AlgorithmName());
652 else if (m_padding == ONE_AND_ZEROS_PADDING)
653 throw InvalidArgument("StreamTransformationFilter: ONE_AND_ZEROS_PADDING cannot be used with " + m_cipher.AlgorithmName());
654 }
655
656 firstSize = 0;
657 blockSize = m_mandatoryBlockSize;
658 lastSize = LastBlockSize(m_cipher, m_padding);
659}
660
661void StreamTransformationFilter::FirstPut(const byte* inString)
662{
663 CRYPTOPP_UNUSED(inString);
664 m_optimalBufferSize = STDMAX<unsigned int>(m_optimalBufferSize, RoundDownToMultipleOf(4096U, m_optimalBufferSize));
665}
666
667void StreamTransformationFilter::NextPutMultiple(const byte *inString, size_t length)
668{
669 if (!length)
670 {return;}
671
672 const size_t s = m_cipher.MandatoryBlockSize();
673 do
674 {
675 size_t len = m_optimalBufferSize;
676 byte *space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, s, length, len);
677 if (len < length)
678 {
679 if (len == m_optimalBufferSize)
680 len -= m_cipher.GetOptimalBlockSizeUsed();
681 len = RoundDownToMultipleOf(len, s);
682 }
683 else
684 len = length;
685 m_cipher.ProcessString(space, inString, len);
687 inString = PtrAdd(inString, len);
688 length -= len;
689 }
690 while (length > 0);
691}
692
693void StreamTransformationFilter::NextPutModifiable(byte *inString, size_t length)
694{
695 m_cipher.ProcessString(inString, length);
696 AttachedTransformation()->PutModifiable(inString, length);
697}
698
699void StreamTransformationFilter::LastPut(const byte *inString, size_t length)
700{
701 // This block is new to StreamTransformationFilter. It is somewhat of a hack and was
702 // added for OCB mode; see GitHub Issue 515. The rub with OCB is, its a block cipher
703 // and the last block size can be 0. However, "last block = 0" is not the 0 predicated
704 // in the original code. In the original code 0 means "nothing special" so
705 // DEFAULT_PADDING is applied. OCB's 0 literally means a final block size can be 0 or
706 // non-0; and no padding is needed in either case because OCB has its own scheme (see
707 // handling of P_* and A_*).
708 // Stream ciphers have policy objects to convey how to operate the cipher. The Crypto++
709 // framework operates well when MinLastBlockSize() is 1. However, it did not appear to
710 // cover the OCB case either because we can't stream OCB. It needs full block sizes. In
711 // response we hacked a IsLastBlockSpecial(). When true StreamTransformationFilter
712 // defers to the mode for processing of the last block.
713 // The behavior supplied when IsLastBlockSpecial() will likely have to evolve to capture
714 // more complex cases from different authenc modes. I suspect it will have to change
715 // from a simple bool to something that conveys more information, like "last block
716 // no padding" or "custom padding applied by cipher".
717 // In some respect we have already hit the need for more information. For example, OCB
718 // calculates the checksum on the cipher text at the same time, so we don't need the
719 // disjoint behavior of calling "EncryptBlock" followed by a separate "AuthenticateBlock".
720 // Additional information may allow us to avoid the two separate calls.
721 if (m_isSpecial)
722 {
723 const size_t leftOver = length % m_mandatoryBlockSize;
724 byte* space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, m_reservedBufferSize);
725 length -= leftOver;
726
727 if (length)
728 {
729 // Process full blocks
730 m_cipher.ProcessData(space, inString, length);
731 AttachedTransformation()->Put(space, length);
732 inString = PtrAdd(inString, length);
733 }
734
735 if (leftOver)
736 {
737 // Process final partial block
738 length = m_cipher.ProcessLastBlock(space, m_reservedBufferSize, inString, leftOver);
739 AttachedTransformation()->Put(space, length);
740 }
741 else
742 {
743 // Process final empty block
744 length = m_cipher.ProcessLastBlock(space, m_reservedBufferSize, NULLPTR, 0);
745 AttachedTransformation()->Put(space, length);
746 }
747
748 return;
749 }
750
751 switch (m_padding)
752 {
753 case NO_PADDING:
754 case ZEROS_PADDING:
755 if (length > 0)
756 {
757 const size_t minLastBlockSize = m_cipher.MinLastBlockSize();
758 const bool isForwardTransformation = m_cipher.IsForwardTransformation();
759
760 if (isForwardTransformation && m_padding == ZEROS_PADDING && (minLastBlockSize == 0 || length < minLastBlockSize))
761 {
762 // do padding
763 size_t blockSize = STDMAX(minLastBlockSize, (size_t)m_mandatoryBlockSize);
764 byte* space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, blockSize);
765 if (inString) {memcpy(space, inString, length);}
766 memset(PtrAdd(space, length), 0, blockSize - length);
767 size_t used = m_cipher.ProcessLastBlock(space, blockSize, space, blockSize);
768 AttachedTransformation()->Put(space, used);
769 }
770 else
771 {
772 if (minLastBlockSize == 0)
773 {
774 if (isForwardTransformation)
775 throw InvalidDataFormat("StreamTransformationFilter: plaintext length is not a multiple of block size and NO_PADDING is specified");
776 else
777 throw InvalidCiphertext("StreamTransformationFilter: ciphertext length is not a multiple of block size");
778 }
779
780 byte* space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, length, m_optimalBufferSize);
781 size_t used = m_cipher.ProcessLastBlock(space, length, inString, length);
782 AttachedTransformation()->Put(space, used);
783 }
784 }
785 break;
786
787 case PKCS_PADDING:
788 case W3C_PADDING:
790 unsigned int s;
791 byte* space;
792 s = m_mandatoryBlockSize;
793 CRYPTOPP_ASSERT(s > 1);
794 space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, s, m_optimalBufferSize);
795 if (m_cipher.IsForwardTransformation())
796 {
797 CRYPTOPP_ASSERT(length < s);
798 if (inString) {memcpy(space, inString, length);}
799 if (m_padding == PKCS_PADDING)
800 {
801 CRYPTOPP_ASSERT(s < 256);
802 byte pad = static_cast<byte>(s-length);
803 memset(PtrAdd(space, length), pad, s-length);
804 }
805 else if (m_padding == W3C_PADDING)
806 {
807 CRYPTOPP_ASSERT(s < 256);
808 memset(PtrAdd(space, length), 0, s-length-1);
809 space[s-1] = static_cast<byte>(s-length);
810 }
811 else
812 {
813 space[length] = 0x80;
814 memset(PtrAdd(space, length+1), 0, s-length-1);
815 }
816 m_cipher.ProcessData(space, space, s);
817 AttachedTransformation()->Put(space, s);
818 }
819 else
820 {
821 if (length != s)
822 throw InvalidCiphertext("StreamTransformationFilter: ciphertext length is not a multiple of block size");
823 m_cipher.ProcessData(space, inString, s);
824 if (m_padding == PKCS_PADDING)
825 {
826 byte pad = space[s-1];
827 if (pad < 1 || pad > s || FindIfNot(PtrAdd(space, s-pad), PtrAdd(space, s), pad) != PtrAdd(space, s))
828 throw InvalidCiphertext("StreamTransformationFilter: invalid PKCS #7 block padding found");
829 length = s-pad;
830 }
831 else if (m_padding == W3C_PADDING)
832 {
833 byte pad = space[s - 1];
834 if (pad < 1 || pad > s)
835 throw InvalidCiphertext("StreamTransformationFilter: invalid W3C block padding found");
836 length = s - pad;
837 }
838 else
839 {
840 while (length > 1 && space[length-1] == 0)
841 --length;
842 if (space[--length] != 0x80)
843 throw InvalidCiphertext("StreamTransformationFilter: invalid ones-and-zeros padding found");
844 }
845 AttachedTransformation()->Put(space, length);
846 }
847 break;
848
849 default:
850 CRYPTOPP_ASSERT(false);
851 }
852}
853
854// *************************************************************
855
856HashFilter::HashFilter(HashTransformation &hm, BufferedTransformation *attachment, bool putMessage, int truncatedDigestSize, const std::string &messagePutChannel, const std::string &hashPutChannel)
857 : m_hashModule(hm), m_putMessage(putMessage), m_digestSize(0), m_space(NULLPTR)
858 , m_messagePutChannel(messagePutChannel), m_hashPutChannel(hashPutChannel)
859{
860 m_digestSize = truncatedDigestSize < 0 ? m_hashModule.DigestSize() : truncatedDigestSize;
861 Detach(attachment);
862}
863
865{
866 m_putMessage = parameters.GetValueWithDefault(Name::PutMessage(), false);
867 int s = parameters.GetIntValueWithDefault(Name::TruncatedDigestSize(), -1);
868 m_digestSize = s < 0 ? m_hashModule.DigestSize() : s;
869}
870
871size_t HashFilter::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
872{
873 FILTER_BEGIN;
874 if (m_putMessage)
875 FILTER_OUTPUT3(1, 0, inString, length, 0, m_messagePutChannel);
876 if (inString && length)
877 m_hashModule.Update(inString, length);
878 if (messageEnd)
879 {
880 {
881 size_t size;
882 m_space = HelpCreatePutSpace(*AttachedTransformation(), m_hashPutChannel, m_digestSize, m_digestSize, size = m_digestSize);
883 m_hashModule.TruncatedFinal(m_space, m_digestSize);
884 }
885 FILTER_OUTPUT3(2, 0, m_space, m_digestSize, messageEnd, m_hashPutChannel);
886 }
887 FILTER_END_NO_MESSAGE_END;
888}
889
890// *************************************************************
891
893 : FilterWithBufferedInput(attachment)
894 , m_hashModule(hm), m_flags(0), m_digestSize(0), m_verified(false)
895{
899 (Name::TruncatedDigestSize(), truncatedDigestSize));
900}
901
902void HashVerificationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
903{
905 int s = parameters.GetIntValueWithDefault(Name::TruncatedDigestSize(), -1);
906 m_digestSize = s < 0 ? m_hashModule.DigestSize() : s;
907 m_verified = false;
908 firstSize = m_flags & HASH_AT_BEGIN ? m_digestSize : 0;
909 blockSize = 1;
910 lastSize = m_flags & HASH_AT_BEGIN ? 0 : m_digestSize;
911}
912
913void HashVerificationFilter::FirstPut(const byte *inString)
914{
915 if (m_flags & HASH_AT_BEGIN)
916 {
917 m_expectedHash.New(m_digestSize);
918 if (inString) {memcpy(m_expectedHash, inString, m_expectedHash.size());}
919 if (m_flags & PUT_HASH)
920 AttachedTransformation()->Put(inString, m_expectedHash.size());
921 }
922}
923
924void HashVerificationFilter::NextPutMultiple(const byte *inString, size_t length)
925{
926 m_hashModule.Update(inString, length);
927 if (m_flags & PUT_MESSAGE)
928 AttachedTransformation()->Put(inString, length);
929}
930
931void HashVerificationFilter::LastPut(const byte *inString, size_t length)
932{
933 if (m_flags & HASH_AT_BEGIN)
934 {
935 CRYPTOPP_ASSERT(length == 0);
936 m_verified = m_hashModule.TruncatedVerify(m_expectedHash, m_digestSize);
937 }
938 else
939 {
940 m_verified = (length==m_digestSize && m_hashModule.TruncatedVerify(inString, length));
941 if (m_flags & PUT_HASH)
942 AttachedTransformation()->Put(inString, length);
943 }
944
945 if (m_flags & PUT_RESULT)
946 AttachedTransformation()->Put(m_verified);
947
948 if ((m_flags & THROW_EXCEPTION) && !m_verified)
949 throw HashVerificationFailed();
950}
951
952// *************************************************************
953
955 bool putAAD, int truncatedDigestSize, const std::string &macChannel, BlockPaddingScheme padding)
956 : StreamTransformationFilter(c, attachment, padding, true)
957 , m_hf(c, new OutputProxy(*this, false), putAAD, truncatedDigestSize, AAD_CHANNEL, macChannel)
958{
959 CRYPTOPP_ASSERT(c.IsForwardTransformation());
960}
961
963{
964 m_hf.IsolatedInitialize(parameters);
966}
967
968byte * AuthenticatedEncryptionFilter::ChannelCreatePutSpace(const std::string &channel, size_t &size)
969{
970 if (channel.empty())
972
973 if (channel == AAD_CHANNEL)
974 return m_hf.CreatePutSpace(size);
975
976 throw InvalidChannelName("AuthenticatedEncryptionFilter", channel);
977}
978
979size_t AuthenticatedEncryptionFilter::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
980{
981 if (channel.empty())
982 return StreamTransformationFilter::Put2(begin, length, messageEnd, blocking);
983
984 if (channel == AAD_CHANNEL)
985 return m_hf.Put2(begin, length, 0, blocking);
986
987 throw InvalidChannelName("AuthenticatedEncryptionFilter", channel);
988}
989
990void AuthenticatedEncryptionFilter::LastPut(const byte *inString, size_t length)
991{
992 StreamTransformationFilter::LastPut(inString, length);
993 m_hf.MessageEnd();
994}
995
996// *************************************************************
997
999 : FilterWithBufferedInput(attachment)
1000 , m_hashVerifier(c, new OutputProxy(*this, false))
1001 , m_streamFilter(c, new OutputProxy(*this, false), padding, true)
1002{
1003 CRYPTOPP_ASSERT(!c.IsForwardTransformation() || c.IsSelfInverting());
1006 (Name::BlockPaddingScheme(), padding)
1008 (Name::TruncatedDigestSize(), truncatedDigestSize));
1009}
1010
1011void AuthenticatedDecryptionFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
1012{
1014
1016 m_streamFilter.Initialize(parameters);
1017
1018 firstSize = m_hashVerifier.m_firstSize;
1019 blockSize = 1;
1020 lastSize = m_hashVerifier.m_lastSize;
1021}
1022
1023byte * AuthenticatedDecryptionFilter::ChannelCreatePutSpace(const std::string &channel, size_t &size)
1024{
1025 if (channel.empty())
1026 return m_streamFilter.CreatePutSpace(size);
1027
1028 if (channel == AAD_CHANNEL)
1029 return m_hashVerifier.CreatePutSpace(size);
1030
1031 throw InvalidChannelName("AuthenticatedDecryptionFilter", channel);
1032}
1033
1034size_t AuthenticatedDecryptionFilter::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
1035{
1036 if (channel.empty())
1037 {
1038 if (m_lastSize > 0)
1039 m_hashVerifier.ForceNextPut();
1040 return FilterWithBufferedInput::Put2(begin, length, messageEnd, blocking);
1041 }
1042
1043 if (channel == AAD_CHANNEL)
1044 return m_hashVerifier.Put2(begin, length, 0, blocking);
1045
1046 throw InvalidChannelName("AuthenticatedDecryptionFilter", channel);
1047}
1048
1049void AuthenticatedDecryptionFilter::FirstPut(const byte *inString)
1050{
1051 m_hashVerifier.Put(inString, m_firstSize);
1052}
1053
1054void AuthenticatedDecryptionFilter::NextPutMultiple(const byte *inString, size_t length)
1055{
1056 m_streamFilter.Put(inString, length);
1057}
1058
1059void AuthenticatedDecryptionFilter::LastPut(const byte *inString, size_t length)
1060{
1061 m_streamFilter.MessageEnd();
1062 m_hashVerifier.PutMessageEnd(inString, length);
1063}
1064
1065// *************************************************************
1066
1068{
1069 m_putMessage = parameters.GetValueWithDefault(Name::PutMessage(), false);
1070 m_messageAccumulator.reset(m_signer.NewSignatureAccumulator(m_rng));
1071}
1072
1073size_t SignerFilter::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
1074{
1075 FILTER_BEGIN;
1076 m_messageAccumulator->Update(inString, length);
1077 if (m_putMessage)
1078 FILTER_OUTPUT(1, inString, length, 0);
1079 if (messageEnd)
1080 {
1081 m_buf.New(m_signer.SignatureLength());
1082 m_signer.Sign(m_rng, m_messageAccumulator.release(), m_buf);
1083 FILTER_OUTPUT(2, m_buf, m_buf.size(), messageEnd);
1084 m_messageAccumulator.reset(m_signer.NewSignatureAccumulator(m_rng));
1085 }
1086 FILTER_END_NO_MESSAGE_END;
1087}
1088
1090 : FilterWithBufferedInput(attachment)
1091 , m_verifier(verifier), m_flags(0), m_verified(0)
1092{
1096}
1097
1098void SignatureVerificationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
1099{
1101 m_messageAccumulator.reset(m_verifier.NewVerificationAccumulator());
1102 size_t size = m_verifier.SignatureLength();
1103 CRYPTOPP_ASSERT(size != 0); // TODO: handle recoverable signature scheme
1104 m_verified = false;
1105 firstSize = m_flags & SIGNATURE_AT_BEGIN ? size : 0;
1106 blockSize = 1;
1107 lastSize = m_flags & SIGNATURE_AT_BEGIN ? 0 : size;
1108}
1109
1110void SignatureVerificationFilter::FirstPut(const byte *inString)
1111{
1112 if (m_flags & SIGNATURE_AT_BEGIN)
1113 {
1114 if (m_verifier.SignatureUpfront())
1115 m_verifier.InputSignature(*m_messageAccumulator, inString, m_verifier.SignatureLength());
1116 else
1117 {
1118 m_signature.New(m_verifier.SignatureLength());
1119 if (inString) {memcpy(m_signature, inString, m_signature.size());}
1120 }
1121
1122 if (m_flags & PUT_SIGNATURE)
1123 AttachedTransformation()->Put(inString, m_signature.size());
1124 }
1125 else
1126 {
1127 CRYPTOPP_ASSERT(!m_verifier.SignatureUpfront());
1128 }
1129}
1130
1131void SignatureVerificationFilter::NextPutMultiple(const byte *inString, size_t length)
1132{
1133 m_messageAccumulator->Update(inString, length);
1134 if (m_flags & PUT_MESSAGE)
1135 AttachedTransformation()->Put(inString, length);
1136}
1137
1138void SignatureVerificationFilter::LastPut(const byte *inString, size_t length)
1139{
1140 if (m_flags & SIGNATURE_AT_BEGIN)
1141 {
1142 CRYPTOPP_ASSERT(length == 0);
1143 m_verifier.InputSignature(*m_messageAccumulator, m_signature, m_signature.size());
1144 m_verified = m_verifier.VerifyAndRestart(*m_messageAccumulator);
1145 }
1146 else
1147 {
1148 m_verifier.InputSignature(*m_messageAccumulator, inString, length);
1149 m_verified = m_verifier.VerifyAndRestart(*m_messageAccumulator);
1150 if (m_flags & PUT_SIGNATURE)
1151 AttachedTransformation()->Put(inString, length);
1152 }
1153
1154 if (m_flags & PUT_RESULT)
1155 AttachedTransformation()->Put(m_verified);
1156
1157 if ((m_flags & THROW_EXCEPTION) && !m_verified)
1158 throw SignatureVerificationFailed();
1159}
1160
1161// *************************************************************
1162
1163size_t Source::PumpAll2(bool blocking)
1164{
1165 unsigned int messageCount = UINT_MAX;
1166 do {
1167 RETURN_IF_NONZERO(PumpMessages2(messageCount, blocking));
1168 } while(messageCount == UINT_MAX);
1169
1170 return 0;
1171}
1172
1174{
1175 if (!m_messageEnd && !AnyRetrievable())
1176 {
1177 m_messageEnd=true;
1178 return true;
1179 }
1180 else
1181 return false;
1182}
1183
1184unsigned int Store::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const
1185{
1186 if (m_messageEnd || count == 0)
1187 return 0;
1188 else
1189 {
1190 CopyTo(target, ULONG_MAX, channel);
1192 target.ChannelMessageEnd(channel, GetAutoSignalPropagation()-1);
1193 return 1;
1194 }
1195}
1196
1197void StringStore::StoreInitialize(const NameValuePairs &parameters)
1198{
1200 if (!parameters.GetValue(Name::InputBuffer(), array))
1201 throw InvalidArgument("StringStore: missing InputBuffer argument");
1202 m_store = array.begin();
1203 m_length = array.size();
1204 m_count = 0;
1205}
1206
1207size_t StringStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
1208{
1209 lword position = 0;
1210 size_t blockedBytes = CopyRangeTo2(target, position, transferBytes, channel, blocking);
1211 m_count += static_cast<size_t>(position);
1212 transferBytes = position;
1213 return blockedBytes;
1214}
1215
1216size_t StringStore::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
1217{
1218 size_t i = UnsignedMin(m_length, m_count+begin);
1219 size_t len = UnsignedMin(m_length-i, end-begin);
1220 size_t blockedBytes = target.ChannelPut2(channel, PtrAdd(m_store, i), len, 0, blocking);
1221 if (!blockedBytes)
1222 begin = PtrAdd(begin, len);
1223 return blockedBytes;
1224}
1225
1226void RandomNumberStore::StoreInitialize(const NameValuePairs &parameters)
1227{
1228 parameters.GetRequiredParameter("RandomNumberStore", "RandomNumberGeneratorPointer", m_rng);
1229 int length;
1230 parameters.GetRequiredIntParameter("RandomNumberStore", "RandomNumberStoreSize", length);
1231 m_length = length;
1232}
1233
1234size_t RandomNumberStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
1235{
1236 if (!blocking)
1237 throw NotImplemented("RandomNumberStore: nonblocking transfer is not implemented by this object");
1238
1239 transferBytes = UnsignedMin(transferBytes, m_length - m_count);
1240 m_rng->GenerateIntoBufferedTransformation(target, channel, transferBytes);
1241 m_count += transferBytes;
1242
1243 return 0;
1244}
1245
1246size_t NullStore::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
1247{
1248 static const byte nullBytes[128] = {0};
1249 while (begin < end)
1250 {
1251 size_t len = (size_t)STDMIN(end-begin, lword(128));
1252 size_t blockedBytes = target.ChannelPut2(channel, nullBytes, len, 0, blocking);
1253 if (blockedBytes)
1254 return blockedBytes;
1255 begin = PtrAdd(begin, len);
1256 }
1257 return 0;
1258}
1259
1260size_t NullStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
1261{
1262 lword begin = 0;
1263 size_t blockedBytes = NullStore::CopyRangeTo2(target, begin, transferBytes, channel, blocking);
1264 transferBytes = begin; m_size -= begin;
1265 return blockedBytes;
1266}
1267
1268NAMESPACE_END
1269
1270#endif
AlgorithmParameters MakeParameters(const char *name, const T &value, bool throwIfNotUsed=true)
Create an object that implements NameValuePairs.
Definition: algparam.h:508
Standard names for retrieving values by name when working with NameValuePairs.
virtual std::string AlgorithmName() const
Provides the name of this algorithm.
Definition: cryptlib.h:619
void IsolatedInitialize(const NameValuePairs &parameters)
Initialize or reinitialize this object, without signal propagation.
byte * CreatePutSpace(size_t &size)
Request space which can be written into by the caller.
size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
Input multiple bytes for processing.
size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
Input multiple bytes for processing.
@ DEFAULT_FLAGS
Default flags using THROW_EXCEPTION.
Definition: filters.h:745
AuthenticatedDecryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment=NULL, word32 flags=DEFAULT_FLAGS, int truncatedDigestSize=-1, BlockPaddingScheme padding=DEFAULT_PADDING)
Construct a AuthenticatedDecryptionFilter.
size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
Input multiple bytes for processing on a channel.
byte * ChannelCreatePutSpace(const std::string &channel, size_t &size)
Request space which can be written into by the caller.
size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
Input multiple bytes for processing on a channel.
void LastPut(const byte *inString, size_t length)
Input the last block of data.
byte * ChannelCreatePutSpace(const std::string &channel, size_t &size)
Request space which can be written into by the caller.
void IsolatedInitialize(const NameValuePairs &parameters)
Initialize or reinitialize this object, without signal propagation.
AuthenticatedEncryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment=NULL, bool putAAD=false, int truncatedDigestSize=-1, const std::string &macChannel=DEFAULT_CHANNEL, BlockPaddingScheme padding=DEFAULT_PADDING)
Construct a AuthenticatedEncryptionFilter.
Interface for authenticated encryption modes of operation.
Definition: cryptlib.h:1321
int GetAutoSignalPropagation() const
Retrieve automatic signal propagation value.
Definition: simple.h:439
Interface for buffered transformations.
Definition: cryptlib.h:1652
virtual bool AnyRetrievable() const
Determines whether bytes are ready for retrieval.
virtual void Initialize(const NameValuePairs &parameters=g_nullNameValuePairs, int propagation=-1)
Initialize or reinitialize this object, with signal propagation.
bool MessageEnd(int propagation=-1, bool blocking=true)
Signals the end of messages to the object.
Definition: cryptlib.h:1743
virtual size_t TransferTo2(BufferedTransformation &target, lword &byteCount, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true)=0
Transfer bytes from this object to another BufferedTransformation.
virtual bool ChannelFlush(const std::string &channel, bool hardFlush, int propagation=-1, bool blocking=true)
Flush buffered input and/or output on a channel.
virtual void Attach(BufferedTransformation *newAttachment)
Add newAttachment to the end of attachment chain.
virtual size_t ChannelPutModifiable2(const std::string &channel, byte *inString, size_t length, int messageEnd, bool blocking)
Input multiple bytes that may be modified by callee on a channel.
virtual bool IsolatedFlush(bool hardFlush, bool blocking)=0
Flushes data buffered by this object, without signal propagation.
lword CopyTo(BufferedTransformation &target, lword copyMax=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL) const
Copy bytes from this object to another BufferedTransformation.
Definition: cryptlib.h:2013
virtual void IsolatedInitialize(const NameValuePairs &parameters)
Initialize or reinitialize this object, without signal propagation.
Definition: cryptlib.h:1816
virtual size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const =0
Copy bytes from this object to another BufferedTransformation.
void TransferAllTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL)
Transfer all bytes from this object to another BufferedTransformation.
Definition: cryptlib.h:2093
virtual size_t ChannelPut2(const std::string &channel, const byte *inString, size_t length, int messageEnd, bool blocking)
Input multiple bytes for processing on a channel.
virtual byte * CreatePutSpace(size_t &size)
Request space which can be written into by the caller.
Definition: cryptlib.h:1720
size_t PutMessageEnd(const byte *inString, size_t length, int propagation=-1, bool blocking=true)
Input multiple bytes for processing and signal the end of a message.
Definition: cryptlib.h:1757
virtual bool IsolatedMessageSeriesEnd(bool blocking)
Marks the end of a series of messages, without signal propagation.
Definition: cryptlib.h:1832
virtual bool Flush(bool hardFlush, int propagation=-1, bool blocking=true)
Flush buffered input and/or output, with signal propagation.
virtual bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true)
Marks the end of a series of messages on a channel.
bool ChannelMessageEnd(const std::string &channel, int propagation=-1, bool blocking=true)
Signal the end of a message.
Definition: cryptlib.h:2252
size_t PutModifiable(byte *inString, size_t length, bool blocking=true)
Input multiple bytes that may be modified by callee.
Definition: cryptlib.h:1735
size_t Put(byte inByte, bool blocking=true)
Input a byte for processing.
Definition: cryptlib.h:1673
Used to pass byte array input as part of a NameValuePairs object.
Definition: algparam.h:99
byte * begin() const
Pointer to the first byte in the memory block.
Definition: algparam.h:113
size_t size() const
Length of the memory block.
Definition: algparam.h:117
Combines two sets of NameValuePairs.
Definition: algparam.h:129
Used to pass byte array input as part of a NameValuePairs object.
Definition: algparam.h:25
const byte * begin() const
Pointer to the first byte in the memory block.
Definition: algparam.h:84
size_t size() const
Length of the memory block.
Definition: algparam.h:88
Implementation of BufferedTransformation's attachment interface.
Definition: filters.h:36
void Initialize(const NameValuePairs &parameters=g_nullNameValuePairs, int propagation=-1)
Initialize or reinitialize this object, with signal propagation.
Filter(BufferedTransformation *attachment=NULL)
Construct a Filter.
void Detach(BufferedTransformation *newAttachment=NULL)
Replace an attached transformation.
size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const
Copy bytes from this object to another BufferedTransformation.
bool MessageSeriesEnd(int propagation=-1, bool blocking=true)
Marks the end of a series of messages, with signal propagation.
size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true)
Transfer bytes from this object to another BufferedTransformation.
BufferedTransformation * AttachedTransformation()
Retrieve attached transformation.
bool Flush(bool hardFlush, int propagation=-1, bool blocking=true)
Flush buffered input and/or output, with signal propagation.
Divides an input stream into discrete blocks.
Definition: filters.h:342
bool IsolatedFlush(bool hardFlush, bool blocking)
Flushes data buffered by this object, without signal propagation.
FilterWithBufferedInput(BufferedTransformation *attachment)
Construct a FilterWithBufferedInput with an attached transformation.
size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
Input multiple bytes for processing.
Definition: filters.h:359
void IsolatedInitialize(const NameValuePairs &parameters)
Initialize or reinitialize this object, without signal propagation.
void ForceNextPut()
Flushes data buffered by this object.
byte * CreatePutSpace(size_t &size)
Request space which can be written into by the caller.
Definition: filters.h:598
HashFilter(HashTransformation &hm, BufferedTransformation *attachment=NULL, bool putMessage=false, int truncatedDigestSize=-1, const std::string &messagePutChannel=DEFAULT_CHANNEL, const std::string &hashPutChannel=DEFAULT_CHANNEL)
Construct a HashFilter.
size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
Input multiple bytes for processing.
void IsolatedInitialize(const NameValuePairs &parameters)
Initialize or reinitialize this object, without signal propagation.
Interface for hash functions and data processing part of MACs.
Definition: cryptlib.h:1113
virtual void TruncatedFinal(byte *digest, size_t digestSize)=0
Computes the hash of the current message.
virtual unsigned int DigestSize() const =0
Provides the digest size of the hash.
virtual void Update(const byte *input, size_t length)=0
Updates a hash with additional input.
virtual bool TruncatedVerify(const byte *digest, size_t digestLength)
Verifies the hash of the current message.
HashVerificationFilter(HashTransformation &hm, BufferedTransformation *attachment=NULL, word32 flags=DEFAULT_FLAGS, int truncatedDigestSize=-1)
Construct a HashVerificationFilter.
@ DEFAULT_FLAGS
Default flags using HASH_AT_BEGIN and PUT_RESULT.
Definition: filters.h:640
@ HASH_AT_BEGIN
The hash is at the beginning of the message (i.e., concatenation of hash+message)
Definition: filters.h:630
@ THROW_EXCEPTION
The filter should throw a HashVerificationFailed if a failure is encountered.
Definition: filters.h:638
@ PUT_HASH
The hash should be passed to an attached transformation.
Definition: filters.h:634
@ PUT_MESSAGE
The message should be passed to an attached transformation.
Definition: filters.h:632
@ PUT_RESULT
The result of the verification should be passed to an attached transformation.
Definition: filters.h:636
An invalid argument was detected.
Definition: cryptlib.h:203
A decryption filter encountered invalid ciphertext.
Definition: cryptlib.h:223
Input data was received that did not conform to expected format.
Definition: cryptlib.h:213
Data structure used to store messages.
Definition: mqueue.h:24
size_t PutModifiable2(byte *inString, size_t length, int messageEnd, bool blocking)
Input multiple bytes that may be modified by callee.
void AddRangeToSkip(unsigned int message, lword position, lword size, bool sortNow=true)
Adds a range to skip during processing.
void ResetMeter()
Resets the meter.
size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
Input multiple bytes for processing.
bool IsolatedMessageSeriesEnd(bool blocking)
Marks the end of a series of messages, without signal propagation.
Interface for retrieving values given their names.
Definition: cryptlib.h:322
T GetValueWithDefault(const char *name, T defaultValue) const
Get a named value.
Definition: cryptlib.h:392
bool GetValue(const char *name, T &value) const
Get a named value.
Definition: cryptlib.h:379
CRYPTOPP_DLL int GetIntValueWithDefault(const char *name, int defaultValue) const
Get a named value with type int, with default.
Definition: cryptlib.h:424
CRYPTOPP_DLL void GetRequiredIntParameter(const char *className, const char *name, int &value) const
Retrieves a required name/value pair.
Definition: cryptlib.h:483
void GetRequiredParameter(const char *className, const char *name, T &value) const
Retrieves a required name/value pair.
Definition: cryptlib.h:468
A method was called which was not implemented.
Definition: cryptlib.h:233
size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const
Copy bytes from this object to another BufferedTransformation.
size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true)
Transfer bytes from this object to another BufferedTransformation.
Filter class that is a proxy for a sink.
Definition: filters.h:991
virtual bool SignatureUpfront() const
Determines whether the signature must be input before the message.
Definition: cryptlib.h:2848
virtual size_t SignatureLength() const =0
Provides the signature length if it only depends on the key.
virtual size_t Sign(RandomNumberGenerator &rng, PK_MessageAccumulator *messageAccumulator, byte *signature) const
Sign and delete the messageAccumulator.
virtual PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator &rng) const =0
Create a new HashTransformation to accumulate the message to be signed.
Interface for public-key signature verifiers.
Definition: cryptlib.h:2941
virtual PK_MessageAccumulator * NewVerificationAccumulator() const =0
Create a new HashTransformation to accumulate the message to be verified.
virtual bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const =0
Check whether messageAccumulator contains a valid signature and message, and restart messageAccumulat...
virtual void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const =0
Input signature into a message accumulator.
ProxyFilter(BufferedTransformation *filter, size_t firstSize, size_t lastSize, BufferedTransformation *attachment)
Construct a ProxyFilter.
void SetFilter(Filter *filter)
Sets the OutputProxy filter.
bool IsolatedFlush(bool hardFlush, bool blocking)
Flushes data buffered by this object, without signal propagation.
virtual void IncorporateEntropy(const byte *input, size_t length)
Update RNG state with additional unpredictable values.
Definition: cryptlib.h:1447
virtual void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length)
Generate random bytes into a BufferedTransformation.
void IsolatedInitialize(const NameValuePairs &parameters)
Initialize or reinitialize this object, without signal propagation.
size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
Input multiple bytes for processing.
size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true)
Transfer bytes from this object to another BufferedTransformation.
@ PASS_EVERYTHING
Pass everything.
Definition: filters.h:898
bool GetPassSignals() const
Retrieve signal propagation behavior.
Definition: filters.h:926
void Initialize(const NameValuePairs &parameters, int propagation)
Initialize or reinitialize this object, with signal propagation.
void New(size_type newSize)
Change size without preserving contents.
Definition: secblock.h:1126
size_type size() const
Provides the count of elements in the SecBlock.
Definition: secblock.h:867
SecBlock<byte> typedef.
Definition: secblock.h:1226
@ SIGNATURE_AT_BEGIN
The signature is at the beginning of the message (i.e., concatenation of signature+message)
Definition: filters.h:840
@ THROW_EXCEPTION
The filter should throw a HashVerificationFailed if a failure is encountered.
Definition: filters.h:848
@ DEFAULT_FLAGS
Default flags using SIGNATURE_AT_BEGIN and PUT_RESULT.
Definition: filters.h:850
@ PUT_MESSAGE
The message should be passed to an attached transformation.
Definition: filters.h:842
@ PUT_RESULT
The result of the verification should be passed to an attached transformation.
Definition: filters.h:846
@ PUT_SIGNATURE
The signature should be passed to an attached transformation.
Definition: filters.h:844
SignatureVerificationFilter(const PK_Verifier &verifier, BufferedTransformation *attachment=NULL, word32 flags=DEFAULT_FLAGS)
Construct a SignatureVerificationFilter.
size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
Input multiple bytes for processing.
void IsolatedInitialize(const NameValuePairs &parameters)
Initialize or reinitialize this object, without signal propagation.
virtual size_t PumpMessages2(unsigned int &messageCount, bool blocking=true)=0
Pump messages to attached transformation.
virtual size_t PumpAll2(bool blocking=true)
Pump all data to attached transformation.
bool GetNextMessage()
Start retrieving the next message.
Filter wrapper for StreamTransformation.
Definition: filters.h:532
StreamTransformationFilter(StreamTransformation &c, BufferedTransformation *attachment=NULL, BlockPaddingScheme padding=DEFAULT_PADDING)
Construct a StreamTransformationFilter.
Interface for the data processing portion of stream ciphers.
Definition: cryptlib.h:946
virtual unsigned int MinLastBlockSize() const
Provides the size of the last block.
Definition: cryptlib.h:1021
virtual void ProcessData(byte *outString, const byte *inString, size_t length)=0
Encrypt or decrypt an array of bytes.
virtual bool IsForwardTransformation() const =0
Determines if the cipher is being operated in its forward direction.
virtual size_t ProcessLastBlock(byte *outString, size_t outLength, const byte *inString, size_t inLength)
Encrypt or decrypt the last block of data.
virtual unsigned int GetOptimalBlockSizeUsed() const
Provides the number of bytes used in the current block when processing at optimal block size.
Definition: cryptlib.h:976
void ProcessString(byte *inoutString, size_t length)
Encrypt or decrypt a string of bytes.
Definition: cryptlib.h:1060
virtual unsigned int MandatoryBlockSize() const
Provides the mandatory block size of the cipher.
Definition: cryptlib.h:965
CRYPTOPP_DLL size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const
Copy bytes from this object to another BufferedTransformation.
CRYPTOPP_DLL size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true)
Transfer bytes from this object to another BufferedTransformation.
Pointer that overloads operator ->
Definition: smartptr.h:38
Library configuration file.
unsigned int word32
32-bit unsigned datatype
Definition: config_int.h:62
word64 lword
Large word type.
Definition: config_int.h:158
const std::string DEFAULT_CHANNEL
Default channel for BufferedTransformation.
Definition: cryptlib.h:511
const std::string AAD_CHANNEL
Channel for additional authenticated data.
Definition: cryptlib.h:520
Implementation of BufferedTransformation's attachment interface.
Utility functions for the Crypto++ library.
T1 SaturatingSubtract(const T1 &a, const T2 &b)
Performs a saturating subtract clamped at 0.
Definition: misc.h:1093
const T & STDMAX(const T &a, const T &b)
Replacement function for std::max.
Definition: misc.h:666
#define SIZE_MAX
The maximum value of a machine word.
Definition: misc.h:118
const T & STDMIN(const T &a, const T &b)
Replacement function for std::min.
Definition: misc.h:655
ptrdiff_t PtrDiff(const PTR pointer1, const PTR pointer2)
Determine pointer difference.
Definition: misc.h:414
T1 RoundDownToMultipleOf(const T1 &n, const T2 &m)
Rounds a value down to a multiple of a second value.
Definition: misc.h:1145
InputIt FindIfNot(InputIt first, InputIt last, const T &value)
Finds first element not in a range.
Definition: misc.h:2981
PTR PtrAdd(PTR pointer, OFF offset)
Create a pointer with an offset.
Definition: misc.h:386
const T1 UnsignedMin(const T1 &a, const T2 &b)
Safe comparison of values that could be negative and incorrectly promoted.
Definition: misc.h:694
CRYPTOPP_DLL void xorbuf(byte *buf, const byte *mask, size_t count)
Performs an XOR of a buffer with a mask.
Classes for an unlimited queue to store messages.
Crypto++ library namespace.
const char * InputBuffer()
ConstByteArrayParameter.
Definition: argnames.h:56
const char * TruncatedDigestSize()
int
Definition: argnames.h:51
const char * AuthenticatedDecryptionFilterFlags()
word32
Definition: argnames.h:54
const char * PutMessage()
bool
Definition: argnames.h:50
const char * OutputBuffer()
ByteArrayParameter.
Definition: argnames.h:57
const char * HashVerificationFilterFlags()
word32
Definition: argnames.h:53
const char * BlockPaddingScheme()
StreamTransformationFilter::BlockPaddingScheme.
Definition: argnames.h:52
const char * SignatureVerificationFilterFlags()
word32
Definition: argnames.h:55
Precompiled header file.
Classes for automatic resource management.
Common C++ header files.
BlockPaddingScheme
Padding schemes used for block ciphers.
Definition: filters.h:501
@ DEFAULT_PADDING
Default padding scheme.
Definition: filters.h:521
@ W3C_PADDING
W3C padding added to a block.
Definition: filters.h:518
@ PKCS_PADDING
PKCS padding added to a block.
Definition: filters.h:510
@ ONE_AND_ZEROS_PADDING
1 and 0's padding added to a block
Definition: filters.h:513
@ NO_PADDING
No padding added to a block.
Definition: filters.h:504
@ ZEROS_PADDING
0's padding added to a block
Definition: filters.h:507
byte * HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, size_t minSize, size_t desiredSize, size_t &bufferSize)
Create a working space in a BufferedTransformation.
Definition: filters.h:187
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:68