source: git/src-cryptopp/filters.cpp

Last change on this file was e230cb0, checked in by David Stainton <dstainton415@…>, at 2016-10-12T13:27:29Z

Add cryptopp from tag CRYPTOPP_5_6_5

  • Property mode set to 100644
File size: 36.1 KB
Line 
1// filters.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: 4100 4189)
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
26Filter::Filter(BufferedTransformation *attachment)
27        : m_attachment(attachment), m_inputPosition(0), m_continueAt(0)
28{
29}
30
31BufferedTransformation * Filter::NewDefaultAttachment() const
32{
33        return new MessageQueue;
34}
35
36BufferedTransformation * Filter::AttachedTransformation()
37{
38        if (m_attachment.get() == NULL)
39                m_attachment.reset(NewDefaultAttachment());
40        return m_attachment.get();
41}
42
43const BufferedTransformation *Filter::AttachedTransformation() const
44{
45        if (m_attachment.get() == NULL)
46                const_cast<Filter *>(this)->m_attachment.reset(NewDefaultAttachment());
47        return m_attachment.get();
48}
49
50void Filter::Detach(BufferedTransformation *newOut)
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
160void MeterFilter::ResetMeter()
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 += 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 += 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
242bool MeterFilter::IsolatedMessageSeriesEnd(bool blocking)
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+=m_blockSize) == m_buffer.end())
268                        m_begin = m_buffer;
269                m_size -= m_blockSize;
270                return ptr;
271        }
272        else
273                return NULL;
274}
275
276byte *FilterWithBufferedInput::BlockQueue::GetContigousBlocks(size_t &numberOfBytes)
277{
278        numberOfBytes = STDMIN(numberOfBytes, STDMIN(size_t(m_buffer.end()-m_begin), m_size));
279        byte *ptr = m_begin;
280        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(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 < size_t(m_buffer.end()-m_begin)) ? m_begin + m_size : m_begin + m_size - m_buffer.size();
308        size_t len = STDMIN(length, size_t(m_buffer.end()-end));
309        memcpy(end, inString, len);
310        if (len < length)
311                memcpy(m_buffer, inString+len, length-len);
312        m_size += length;
313}
314
315#if !defined(CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562)
316FilterWithBufferedInput::FilterWithBufferedInput()
317        : Filter(), m_firstSize(SIZE_MAX), m_blockSize(0), m_lastSize(SIZE_MAX), m_firstInputDone(false)
318{
319}
320#endif
321
322FilterWithBufferedInput::FilterWithBufferedInput(BufferedTransformation *attachment)
323        : Filter(attachment), m_firstSize(SIZE_MAX), m_blockSize(0), m_lastSize(SIZE_MAX), m_firstInputDone(false)
324{
325}
326
327FilterWithBufferedInput::FilterWithBufferedInput(size_t firstSize, size_t blockSize, size_t lastSize, BufferedTransformation *attachment)
328        : Filter(attachment), m_firstSize(firstSize), m_blockSize(blockSize), m_lastSize(lastSize), m_firstInputDone(false)
329{
330        if (m_firstSize == SIZE_MAX || m_blockSize < 1 || m_lastSize == SIZE_MAX)
331                throw InvalidArgument("FilterWithBufferedInput: invalid buffer size");
332
333        m_queue.ResetQueue(1, m_firstSize);
334}
335
336void FilterWithBufferedInput::IsolatedInitialize(const NameValuePairs &parameters)
337{
338        InitializeDerivedAndReturnNewSizes(parameters, m_firstSize, m_blockSize, m_lastSize);
339        if (m_firstSize == SIZE_MAX || m_blockSize < 1 || m_lastSize == SIZE_MAX)
340                throw InvalidArgument("FilterWithBufferedInput: invalid buffer size");
341        m_queue.ResetQueue(1, m_firstSize);
342        m_firstInputDone = false;
343}
344
345bool FilterWithBufferedInput::IsolatedFlush(bool hardFlush, bool blocking)
346{
347        if (!blocking)
348                throw BlockingInputOnly("FilterWithBufferedInput");
349
350        if (hardFlush)
351                ForceNextPut();
352        FlushDerived();
353
354        return false;
355}
356
357size_t FilterWithBufferedInput::PutMaybeModifiable(byte *inString, size_t length, int messageEnd, bool blocking, bool modifiable)
358{
359        if (!blocking)
360                throw BlockingInputOnly("FilterWithBufferedInput");
361
362        if (length != 0)
363        {
364                size_t newLength = m_queue.CurrentSize() + length;
365
366                if (!m_firstInputDone && newLength >= m_firstSize)
367                {
368                        size_t len = m_firstSize - m_queue.CurrentSize();
369                        m_queue.Put(inString, len);
370                        FirstPut(m_queue.GetContigousBlocks(m_firstSize));
371                        CRYPTOPP_ASSERT(m_queue.CurrentSize() == 0);
372                        m_queue.ResetQueue(m_blockSize, (2*m_blockSize+m_lastSize-2)/m_blockSize);
373
374                        inString += len;
375                        newLength -= m_firstSize;
376                        m_firstInputDone = true;
377                }
378
379                if (m_firstInputDone)
380                {
381                        if (m_blockSize == 1)
382                        {
383                                while (newLength > m_lastSize && m_queue.CurrentSize() > 0)
384                                {
385                                        size_t len = newLength - m_lastSize;
386                                        byte *ptr = m_queue.GetContigousBlocks(len);
387                                        NextPutModifiable(ptr, len);
388                                        newLength -= len;
389                                }
390
391                                if (newLength > m_lastSize)
392                                {
393                                        size_t len = newLength - m_lastSize;
394                                        NextPutMaybeModifiable(inString, len, modifiable);
395                                        inString += len;
396                                        newLength -= len;
397                                }
398                        }
399                        else
400                        {
401                                while (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() >= m_blockSize)
402                                {
403                                        NextPutModifiable(m_queue.GetBlock(), m_blockSize);
404                                        newLength -= m_blockSize;
405                                }
406
407                                if (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() > 0)
408                                {
409                                        CRYPTOPP_ASSERT(m_queue.CurrentSize() < m_blockSize);
410                                        size_t len = m_blockSize - m_queue.CurrentSize();
411                                        m_queue.Put(inString, len);
412                                        inString += len;
413                                        NextPutModifiable(m_queue.GetBlock(), m_blockSize);
414                                        newLength -= m_blockSize;
415                                }
416
417                                if (newLength >= m_blockSize + m_lastSize)
418                                {
419                                        size_t len = RoundDownToMultipleOf(newLength - m_lastSize, m_blockSize);
420                                        NextPutMaybeModifiable(inString, len, modifiable);
421                                        inString += len;
422                                        newLength -= len;
423                                }
424                        }
425                }
426
427                m_queue.Put(inString, newLength - m_queue.CurrentSize());
428        }
429
430        if (messageEnd)
431        {
432                if (!m_firstInputDone && m_firstSize==0)
433                        FirstPut(NULL);
434
435                SecByteBlock temp(m_queue.CurrentSize());
436                m_queue.GetAll(temp);
437                LastPut(temp, temp.size());
438
439                m_firstInputDone = false;
440                m_queue.ResetQueue(1, m_firstSize);
441
442                // Cast to void to supress Coverity finding
443                (void)Output(1, NULL, 0, messageEnd, blocking);
444        }
445        return 0;
446}
447
448void FilterWithBufferedInput::ForceNextPut()
449{
450        if (!m_firstInputDone)
451                return;
452
453        if (m_blockSize > 1)
454        {
455                while (m_queue.CurrentSize() >= m_blockSize)
456                        NextPutModifiable(m_queue.GetBlock(), m_blockSize);
457        }
458        else
459        {
460                size_t len;
461                while ((len = m_queue.CurrentSize()) > 0)
462                        NextPutModifiable(m_queue.GetContigousBlocks(len), len);
463        }
464}
465
466void FilterWithBufferedInput::NextPutMultiple(const byte *inString, size_t length)
467{
468        CRYPTOPP_ASSERT(m_blockSize > 1);       // m_blockSize = 1 should always override this function
469        while (length > 0)
470        {
471                CRYPTOPP_ASSERT(length >= m_blockSize);
472                NextPutSingle(inString);
473                inString += m_blockSize;
474                length -= m_blockSize;
475        }
476}
477
478// *************************************************************
479
480void Redirector::Initialize(const NameValuePairs &parameters, int propagation)
481{
482        m_target = parameters.GetValueWithDefault("RedirectionTargetPointer", (BufferedTransformation*)NULL);
483        m_behavior = parameters.GetIntValueWithDefault("RedirectionBehavior", PASS_EVERYTHING);
484
485        if (m_target && GetPassSignals())
486                m_target->Initialize(parameters, propagation);
487}
488
489// *************************************************************
490
491ProxyFilter::ProxyFilter(BufferedTransformation *filter, size_t firstSize, size_t lastSize, BufferedTransformation *attachment)
492        : FilterWithBufferedInput(firstSize, 1, lastSize, attachment), m_filter(filter)
493{
494        if (m_filter.get())
495                m_filter->Attach(new OutputProxy(*this, false));
496}
497
498bool ProxyFilter::IsolatedFlush(bool hardFlush, bool blocking)
499{
500        return m_filter.get() ? m_filter->Flush(hardFlush, -1, blocking) : false;
501}
502
503void ProxyFilter::SetFilter(Filter *filter)
504{
505        m_filter.reset(filter);
506        if (filter)
507        {
508                OutputProxy *proxy;
509                member_ptr<OutputProxy> temp(proxy = new OutputProxy(*this, false));
510                m_filter->TransferAllTo(*proxy);
511                m_filter->Attach(temp.release());
512        }
513}
514
515void ProxyFilter::NextPutMultiple(const byte *s, size_t len)
516{
517        if (m_filter.get())
518                m_filter->Put(s, len);
519}
520
521void ProxyFilter::NextPutModifiable(byte *s, size_t len)
522{
523        if (m_filter.get())
524                m_filter->PutModifiable(s, len);
525}
526
527// *************************************************************
528
529void RandomNumberSink::IsolatedInitialize(const NameValuePairs &parameters)
530{
531        parameters.GetRequiredParameter("RandomNumberSink", "RandomNumberGeneratorPointer", m_rng);
532}
533
534size_t RandomNumberSink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
535{
536        CRYPTOPP_UNUSED(messageEnd); CRYPTOPP_UNUSED(blocking);
537        m_rng->IncorporateEntropy(begin, length);
538        return 0;
539}
540
541size_t ArraySink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
542{
543        CRYPTOPP_UNUSED(messageEnd); CRYPTOPP_UNUSED(blocking);
544
545        // Avoid passing NULL pointer to memcpy. Using memmove due to
546        //  Valgrind finding on overlapping buffers.
547        size_t copied = 0;
548        if (m_buf && begin)
549        {
550                copied = STDMIN(length, SaturatingSubtract(m_size, m_total));
551                memmove(m_buf+m_total, begin, copied);
552        }
553        m_total += copied;
554        return length - copied;
555}
556
557byte * ArraySink::CreatePutSpace(size_t &size)
558{
559        size = SaturatingSubtract(m_size, m_total);
560        return m_buf + m_total;
561}
562
563void ArraySink::IsolatedInitialize(const NameValuePairs &parameters)
564{
565        ByteArrayParameter array;
566        if (!parameters.GetValue(Name::OutputBuffer(), array))
567                throw InvalidArgument("ArraySink: missing OutputBuffer argument");
568        m_buf = array.begin();
569        m_size = array.size();
570}
571
572size_t ArrayXorSink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
573{
574        CRYPTOPP_UNUSED(messageEnd); CRYPTOPP_UNUSED(blocking);
575
576        // Avoid passing NULL pointer to xorbuf
577        size_t copied = 0;
578        if (m_buf && begin)
579        {
580                copied = STDMIN(length, SaturatingSubtract(m_size, m_total));
581                xorbuf(m_buf+m_total, begin, copied);
582        }
583        m_total += copied;
584        return length - copied;
585}
586
587// *************************************************************
588
589StreamTransformationFilter::StreamTransformationFilter(StreamTransformation &c, BufferedTransformation *attachment, BlockPaddingScheme padding, bool allowAuthenticatedSymmetricCipher)
590        : FilterWithBufferedInput(attachment)
591        , m_cipher(c), m_padding(DEFAULT_PADDING), m_optimalBufferSize(0)
592{
593        CRYPTOPP_ASSERT(c.MinLastBlockSize() == 0 || c.MinLastBlockSize() > c.MandatoryBlockSize());
594
595        if (!allowAuthenticatedSymmetricCipher && dynamic_cast<AuthenticatedSymmetricCipher *>(&c) != 0)
596                throw InvalidArgument("StreamTransformationFilter: please use AuthenticatedEncryptionFilter and AuthenticatedDecryptionFilter for AuthenticatedSymmetricCipher");
597
598        IsolatedInitialize(MakeParameters(Name::BlockPaddingScheme(), padding));
599}
600
601size_t StreamTransformationFilter::LastBlockSize(StreamTransformation &c, BlockPaddingScheme padding)
602{
603        if (c.MinLastBlockSize() > 0)
604                return c.MinLastBlockSize();
605        else if (c.MandatoryBlockSize() > 1 && !c.IsForwardTransformation() && padding != NO_PADDING && padding != ZEROS_PADDING)
606                return c.MandatoryBlockSize();
607        else
608                return 0;
609}
610
611void StreamTransformationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
612{
613        BlockPaddingScheme padding = parameters.GetValueWithDefault(Name::BlockPaddingScheme(), DEFAULT_PADDING);
614        bool isBlockCipher = (m_cipher.MandatoryBlockSize() > 1 && m_cipher.MinLastBlockSize() == 0);
615
616        if (padding == DEFAULT_PADDING)
617                m_padding = isBlockCipher ? PKCS_PADDING : NO_PADDING;
618        else
619                m_padding = padding;
620
621        if (!isBlockCipher && (m_padding == PKCS_PADDING || m_padding == ONE_AND_ZEROS_PADDING))
622                throw InvalidArgument("StreamTransformationFilter: PKCS_PADDING and ONE_AND_ZEROS_PADDING cannot be used with " + m_cipher.AlgorithmName());
623
624        firstSize = 0;
625        blockSize = m_cipher.MandatoryBlockSize();
626        lastSize = LastBlockSize(m_cipher, m_padding);
627}
628
629void StreamTransformationFilter::FirstPut(const byte* inString)
630{
631        CRYPTOPP_UNUSED(inString);
632        m_optimalBufferSize = m_cipher.OptimalBlockSize();
633        m_optimalBufferSize = (unsigned int)STDMAX(m_optimalBufferSize, RoundDownToMultipleOf(4096U, m_optimalBufferSize));
634}
635
636void StreamTransformationFilter::NextPutMultiple(const byte *inString, size_t length)
637{
638        if (!length)
639                return;
640
641        size_t s = m_cipher.MandatoryBlockSize();
642
643        do
644        {
645                size_t len = m_optimalBufferSize;
646                byte *space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, s, length, len);
647                if (len < length)
648                {
649                        if (len == m_optimalBufferSize)
650                                len -= m_cipher.GetOptimalBlockSizeUsed();
651                        len = RoundDownToMultipleOf(len, s);
652                }
653                else
654                        len = length;
655                m_cipher.ProcessString(space, inString, len);
656                AttachedTransformation()->PutModifiable(space, len);
657                inString += len;
658                length -= len;
659        }
660        while (length > 0);
661}
662
663void StreamTransformationFilter::NextPutModifiable(byte *inString, size_t length)
664{
665        m_cipher.ProcessString(inString, length);
666        AttachedTransformation()->PutModifiable(inString, length);
667}
668
669void StreamTransformationFilter::LastPut(const byte *inString, size_t length)
670{
671        byte *space = NULL;
672
673        switch (m_padding)
674        {
675        case NO_PADDING:
676        case ZEROS_PADDING:
677                if (length > 0)
678                {
679                        size_t minLastBlockSize = m_cipher.MinLastBlockSize();
680                        bool isForwardTransformation = m_cipher.IsForwardTransformation();
681
682                        if (isForwardTransformation && m_padding == ZEROS_PADDING && (minLastBlockSize == 0 || length < minLastBlockSize))
683                        {
684                                // do padding
685                                size_t blockSize = STDMAX(minLastBlockSize, (size_t)m_cipher.MandatoryBlockSize());
686                                space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, blockSize);
687                                if (inString) {memcpy(space, inString, length);}
688                                memset(space + length, 0, blockSize - length);
689                                m_cipher.ProcessLastBlock(space, space, blockSize);
690                                AttachedTransformation()->Put(space, blockSize);
691                        }
692                        else
693                        {
694                                if (minLastBlockSize == 0)
695                                {
696                                        if (isForwardTransformation)
697                                                throw InvalidDataFormat("StreamTransformationFilter: plaintext length is not a multiple of block size and NO_PADDING is specified");
698                                        else
699                                                throw InvalidCiphertext("StreamTransformationFilter: ciphertext length is not a multiple of block size");
700                                }
701
702                                space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, length, m_optimalBufferSize);
703                                m_cipher.ProcessLastBlock(space, inString, length);
704                                AttachedTransformation()->Put(space, length);
705                        }
706                }
707                break;
708
709        case PKCS_PADDING:
710        case ONE_AND_ZEROS_PADDING:
711                unsigned int s;
712                s = m_cipher.MandatoryBlockSize();
713                CRYPTOPP_ASSERT(s > 1);
714                space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, s, m_optimalBufferSize);
715                if (m_cipher.IsForwardTransformation())
716                {
717                        CRYPTOPP_ASSERT(length < s);
718                        if (inString) {memcpy(space, inString, length);}
719                        if (m_padding == PKCS_PADDING)
720                        {
721                                CRYPTOPP_ASSERT(s < 256);
722                                byte pad = byte(s-length);
723                                memset(space+length, pad, s-length);
724                        }
725                        else
726                        {
727                                space[length] = 0x80;
728                                memset(space+length+1, 0, s-length-1);
729                        }
730                        m_cipher.ProcessData(space, space, s);
731                        AttachedTransformation()->Put(space, s);
732                }
733                else
734                {
735                        if (length != s)
736                                throw InvalidCiphertext("StreamTransformationFilter: ciphertext length is not a multiple of block size");
737                        m_cipher.ProcessData(space, inString, s);
738                        if (m_padding == PKCS_PADDING)
739                        {
740                                byte pad = space[s-1];
741                                if (pad < 1 || pad > s || std::find_if(space+s-pad, space+s, std::bind2nd(std::not_equal_to<byte>(), pad)) != space+s)
742                                        throw InvalidCiphertext("StreamTransformationFilter: invalid PKCS #7 block padding found");
743                                length = s-pad;
744                        }
745                        else
746                        {
747                                while (length > 1 && space[length-1] == 0)
748                                        --length;
749                                if (space[--length] != 0x80)
750                                        throw InvalidCiphertext("StreamTransformationFilter: invalid ones-and-zeros padding found");
751                        }
752                        AttachedTransformation()->Put(space, length);
753                }
754                break;
755
756        default:
757                CRYPTOPP_ASSERT(false);
758        }
759}
760
761// *************************************************************
762
763HashFilter::HashFilter(HashTransformation &hm, BufferedTransformation *attachment, bool putMessage, int truncatedDigestSize, const std::string &messagePutChannel, const std::string &hashPutChannel)
764        : m_hashModule(hm), m_putMessage(putMessage), m_digestSize(0), m_space(NULL)
765        , m_messagePutChannel(messagePutChannel), m_hashPutChannel(hashPutChannel)
766{
767        m_digestSize = truncatedDigestSize < 0 ? m_hashModule.DigestSize() : truncatedDigestSize;
768        Detach(attachment);
769}
770
771void HashFilter::IsolatedInitialize(const NameValuePairs &parameters)
772{
773        m_putMessage = parameters.GetValueWithDefault(Name::PutMessage(), false);
774        int s = parameters.GetIntValueWithDefault(Name::TruncatedDigestSize(), -1);
775        m_digestSize = s < 0 ? m_hashModule.DigestSize() : s;
776}
777
778size_t HashFilter::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
779{
780        FILTER_BEGIN;
781        if (m_putMessage)
782                FILTER_OUTPUT3(1, 0, inString, length, 0, m_messagePutChannel);
783        if (inString && length)
784                m_hashModule.Update(inString, length);
785        if (messageEnd)
786        {
787                {
788                        size_t size;
789                        m_space = HelpCreatePutSpace(*AttachedTransformation(), m_hashPutChannel, m_digestSize, m_digestSize, size = m_digestSize);
790                        m_hashModule.TruncatedFinal(m_space, m_digestSize);
791                }
792                FILTER_OUTPUT3(2, 0, m_space, m_digestSize, messageEnd, m_hashPutChannel);
793        }
794        FILTER_END_NO_MESSAGE_END;
795}
796
797// *************************************************************
798
799HashVerificationFilter::HashVerificationFilter(HashTransformation &hm, BufferedTransformation *attachment, word32 flags, int truncatedDigestSize)
800        : FilterWithBufferedInput(attachment)
801        , m_hashModule(hm), m_flags(0), m_digestSize(0), m_verified(false)
802{
803        IsolatedInitialize(MakeParameters(Name::HashVerificationFilterFlags(), flags)(Name::TruncatedDigestSize(), truncatedDigestSize));
804}
805
806void HashVerificationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
807{
808        m_flags = parameters.GetValueWithDefault(Name::HashVerificationFilterFlags(), (word32)DEFAULT_FLAGS);
809        int s = parameters.GetIntValueWithDefault(Name::TruncatedDigestSize(), -1);
810        m_digestSize = s < 0 ? m_hashModule.DigestSize() : s;
811        m_verified = false;
812        firstSize = m_flags & HASH_AT_BEGIN ? m_digestSize : 0;
813        blockSize = 1;
814        lastSize = m_flags & HASH_AT_BEGIN ? 0 : m_digestSize;
815}
816
817void HashVerificationFilter::FirstPut(const byte *inString)
818{
819        if (m_flags & HASH_AT_BEGIN)
820        {
821                m_expectedHash.New(m_digestSize);
822                if (inString) {memcpy(m_expectedHash, inString, m_expectedHash.size());}
823                if (m_flags & PUT_HASH)
824                        AttachedTransformation()->Put(inString, m_expectedHash.size());
825        }
826}
827
828void HashVerificationFilter::NextPutMultiple(const byte *inString, size_t length)
829{
830        m_hashModule.Update(inString, length);
831        if (m_flags & PUT_MESSAGE)
832                AttachedTransformation()->Put(inString, length);
833}
834
835void HashVerificationFilter::LastPut(const byte *inString, size_t length)
836{
837        if (m_flags & HASH_AT_BEGIN)
838        {
839                CRYPTOPP_ASSERT(length == 0);
840                m_verified = m_hashModule.TruncatedVerify(m_expectedHash, m_digestSize);
841        }
842        else
843        {
844                m_verified = (length==m_digestSize && m_hashModule.TruncatedVerify(inString, length));
845                if (m_flags & PUT_HASH)
846                        AttachedTransformation()->Put(inString, length);
847        }
848
849        if (m_flags & PUT_RESULT)
850                AttachedTransformation()->Put(m_verified);
851
852        if ((m_flags & THROW_EXCEPTION) && !m_verified)
853                throw HashVerificationFailed();
854}
855
856// *************************************************************
857
858AuthenticatedEncryptionFilter::AuthenticatedEncryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment,
859                                                                bool putAAD, int truncatedDigestSize, const std::string &macChannel, BlockPaddingScheme padding)
860        : StreamTransformationFilter(c, attachment, padding, true)
861        , m_hf(c, new OutputProxy(*this, false), putAAD, truncatedDigestSize, AAD_CHANNEL, macChannel)
862{
863        CRYPTOPP_ASSERT(c.IsForwardTransformation());
864}
865
866void AuthenticatedEncryptionFilter::IsolatedInitialize(const NameValuePairs &parameters)
867{
868        m_hf.IsolatedInitialize(parameters);
869        StreamTransformationFilter::IsolatedInitialize(parameters);
870}
871
872byte * AuthenticatedEncryptionFilter::ChannelCreatePutSpace(const std::string &channel, size_t &size)
873{
874        if (channel.empty())
875                return StreamTransformationFilter::CreatePutSpace(size);
876
877        if (channel == AAD_CHANNEL)
878                return m_hf.CreatePutSpace(size);
879
880        throw InvalidChannelName("AuthenticatedEncryptionFilter", channel);
881}
882
883size_t AuthenticatedEncryptionFilter::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
884{
885        if (channel.empty())
886                return StreamTransformationFilter::Put2(begin, length, messageEnd, blocking);
887
888        if (channel == AAD_CHANNEL)
889                return m_hf.Put2(begin, length, 0, blocking);
890
891        throw InvalidChannelName("AuthenticatedEncryptionFilter", channel);
892}
893
894void AuthenticatedEncryptionFilter::LastPut(const byte *inString, size_t length)
895{
896        StreamTransformationFilter::LastPut(inString, length);
897        m_hf.MessageEnd();
898}
899
900// *************************************************************
901
902AuthenticatedDecryptionFilter::AuthenticatedDecryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment, word32 flags, int truncatedDigestSize, BlockPaddingScheme padding)
903        : FilterWithBufferedInput(attachment)
904        , m_hashVerifier(c, new OutputProxy(*this, false))
905        , m_streamFilter(c, new OutputProxy(*this, false), padding, true)
906{
907        CRYPTOPP_ASSERT(!c.IsForwardTransformation() || c.IsSelfInverting());
908        IsolatedInitialize(MakeParameters(Name::BlockPaddingScheme(), padding)(Name::AuthenticatedDecryptionFilterFlags(), flags)(Name::TruncatedDigestSize(), truncatedDigestSize));
909}
910
911void AuthenticatedDecryptionFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
912{
913        word32 flags = parameters.GetValueWithDefault(Name::AuthenticatedDecryptionFilterFlags(), (word32)DEFAULT_FLAGS);
914
915        m_hashVerifier.Initialize(CombinedNameValuePairs(parameters, MakeParameters(Name::HashVerificationFilterFlags(), flags)));
916        m_streamFilter.Initialize(parameters);
917
918        firstSize = m_hashVerifier.m_firstSize;
919        blockSize = 1;
920        lastSize = m_hashVerifier.m_lastSize;
921}
922
923byte * AuthenticatedDecryptionFilter::ChannelCreatePutSpace(const std::string &channel, size_t &size)
924{
925        if (channel.empty())
926                return m_streamFilter.CreatePutSpace(size);
927
928        if (channel == AAD_CHANNEL)
929                return m_hashVerifier.CreatePutSpace(size);
930
931        throw InvalidChannelName("AuthenticatedDecryptionFilter", channel);
932}
933
934size_t AuthenticatedDecryptionFilter::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
935{
936        if (channel.empty())
937        {
938                if (m_lastSize > 0)
939                        m_hashVerifier.ForceNextPut();
940                return FilterWithBufferedInput::Put2(begin, length, messageEnd, blocking);
941        }
942
943        if (channel == AAD_CHANNEL)
944                return m_hashVerifier.Put2(begin, length, 0, blocking);
945
946        throw InvalidChannelName("AuthenticatedDecryptionFilter", channel);
947}
948
949void AuthenticatedDecryptionFilter::FirstPut(const byte *inString)
950{
951        m_hashVerifier.Put(inString, m_firstSize);
952}
953
954void AuthenticatedDecryptionFilter::NextPutMultiple(const byte *inString, size_t length)
955{
956        m_streamFilter.Put(inString, length);
957}
958
959void AuthenticatedDecryptionFilter::LastPut(const byte *inString, size_t length)
960{
961        m_streamFilter.MessageEnd();
962        m_hashVerifier.PutMessageEnd(inString, length);
963}
964
965// *************************************************************
966
967void SignerFilter::IsolatedInitialize(const NameValuePairs &parameters)
968{
969        m_putMessage = parameters.GetValueWithDefault(Name::PutMessage(), false);
970        m_messageAccumulator.reset(m_signer.NewSignatureAccumulator(m_rng));
971}
972
973size_t SignerFilter::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
974{
975        FILTER_BEGIN;
976        m_messageAccumulator->Update(inString, length);
977        if (m_putMessage)
978                FILTER_OUTPUT(1, inString, length, 0);
979        if (messageEnd)
980        {
981                m_buf.New(m_signer.SignatureLength());
982                m_signer.Sign(m_rng, m_messageAccumulator.release(), m_buf);
983                FILTER_OUTPUT(2, m_buf, m_buf.size(), messageEnd);
984                m_messageAccumulator.reset(m_signer.NewSignatureAccumulator(m_rng));
985        }
986        FILTER_END_NO_MESSAGE_END;
987}
988
989SignatureVerificationFilter::SignatureVerificationFilter(const PK_Verifier &verifier, BufferedTransformation *attachment, word32 flags)
990        : FilterWithBufferedInput(attachment)
991        , m_verifier(verifier), m_flags(0), m_verified(0)
992{
993        IsolatedInitialize(MakeParameters(Name::SignatureVerificationFilterFlags(), flags));
994}
995
996void SignatureVerificationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
997{
998        m_flags = parameters.GetValueWithDefault(Name::SignatureVerificationFilterFlags(), (word32)DEFAULT_FLAGS);
999        m_messageAccumulator.reset(m_verifier.NewVerificationAccumulator());
1000        size_t size = m_verifier.SignatureLength();
1001        CRYPTOPP_ASSERT(size != 0);     // TODO: handle recoverable signature scheme
1002        m_verified = false;
1003        firstSize = m_flags & SIGNATURE_AT_BEGIN ? size : 0;
1004        blockSize = 1;
1005        lastSize = m_flags & SIGNATURE_AT_BEGIN ? 0 : size;
1006}
1007
1008void SignatureVerificationFilter::FirstPut(const byte *inString)
1009{
1010        if (m_flags & SIGNATURE_AT_BEGIN)
1011        {
1012                if (m_verifier.SignatureUpfront())
1013                        m_verifier.InputSignature(*m_messageAccumulator, inString, m_verifier.SignatureLength());
1014                else
1015                {
1016                        m_signature.New(m_verifier.SignatureLength());
1017                        if (inString) {memcpy(m_signature, inString, m_signature.size());}
1018                }
1019
1020                if (m_flags & PUT_SIGNATURE)
1021                        AttachedTransformation()->Put(inString, m_signature.size());
1022        }
1023        else
1024        {
1025                CRYPTOPP_ASSERT(!m_verifier.SignatureUpfront());
1026        }
1027}
1028
1029void SignatureVerificationFilter::NextPutMultiple(const byte *inString, size_t length)
1030{
1031        m_messageAccumulator->Update(inString, length);
1032        if (m_flags & PUT_MESSAGE)
1033                AttachedTransformation()->Put(inString, length);
1034}
1035
1036void SignatureVerificationFilter::LastPut(const byte *inString, size_t length)
1037{
1038        if (m_flags & SIGNATURE_AT_BEGIN)
1039        {
1040                CRYPTOPP_ASSERT(length == 0);
1041                m_verifier.InputSignature(*m_messageAccumulator, m_signature, m_signature.size());
1042                m_verified = m_verifier.VerifyAndRestart(*m_messageAccumulator);
1043        }
1044        else
1045        {
1046                m_verifier.InputSignature(*m_messageAccumulator, inString, length);
1047                m_verified = m_verifier.VerifyAndRestart(*m_messageAccumulator);
1048                if (m_flags & PUT_SIGNATURE)
1049                        AttachedTransformation()->Put(inString, length);
1050        }
1051
1052        if (m_flags & PUT_RESULT)
1053                AttachedTransformation()->Put(m_verified);
1054
1055        if ((m_flags & THROW_EXCEPTION) && !m_verified)
1056                throw SignatureVerificationFailed();
1057}
1058
1059// *************************************************************
1060
1061size_t Source::PumpAll2(bool blocking)
1062{
1063        unsigned int messageCount = UINT_MAX;
1064        do {
1065                RETURN_IF_NONZERO(PumpMessages2(messageCount, blocking));
1066        } while(messageCount == UINT_MAX);
1067
1068        return 0;
1069}
1070
1071bool Store::GetNextMessage()
1072{
1073        if (!m_messageEnd && !AnyRetrievable())
1074        {
1075                m_messageEnd=true;
1076                return true;
1077        }
1078        else
1079                return false;
1080}
1081
1082unsigned int Store::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const
1083{
1084        if (m_messageEnd || count == 0)
1085                return 0;
1086        else
1087        {
1088                CopyTo(target, ULONG_MAX, channel);
1089                if (GetAutoSignalPropagation())
1090                        target.ChannelMessageEnd(channel, GetAutoSignalPropagation()-1);
1091                return 1;
1092        }
1093}
1094
1095void StringStore::StoreInitialize(const NameValuePairs &parameters)
1096{
1097        ConstByteArrayParameter array;
1098        if (!parameters.GetValue(Name::InputBuffer(), array))
1099                throw InvalidArgument("StringStore: missing InputBuffer argument");
1100        m_store = array.begin();
1101        m_length = array.size();
1102        m_count = 0;
1103}
1104
1105size_t StringStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
1106{
1107        lword position = 0;
1108        size_t blockedBytes = CopyRangeTo2(target, position, transferBytes, channel, blocking);
1109        m_count += (size_t)position;
1110        transferBytes = position;
1111        return blockedBytes;
1112}
1113
1114size_t StringStore::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
1115{
1116        size_t i = UnsignedMin(m_length, m_count+begin);
1117        size_t len = UnsignedMin(m_length-i, end-begin);
1118        size_t blockedBytes = target.ChannelPut2(channel, m_store+i, len, 0, blocking);
1119        if (!blockedBytes)
1120                begin += len;
1121        return blockedBytes;
1122}
1123
1124void RandomNumberStore::StoreInitialize(const NameValuePairs &parameters)
1125{
1126        parameters.GetRequiredParameter("RandomNumberStore", "RandomNumberGeneratorPointer", m_rng);
1127        int length;
1128        parameters.GetRequiredIntParameter("RandomNumberStore", "RandomNumberStoreSize", length);
1129        m_length = length;
1130}
1131
1132size_t RandomNumberStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
1133{
1134        if (!blocking)
1135                throw NotImplemented("RandomNumberStore: nonblocking transfer is not implemented by this object");
1136
1137        transferBytes = UnsignedMin(transferBytes, m_length - m_count);
1138        m_rng->GenerateIntoBufferedTransformation(target, channel, transferBytes);
1139        m_count += transferBytes;
1140
1141        return 0;
1142}
1143
1144size_t NullStore::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
1145{
1146        static const byte nullBytes[128] = {0};
1147        while (begin < end)
1148        {
1149                size_t len = (size_t)STDMIN(end-begin, lword(128));
1150                size_t blockedBytes = target.ChannelPut2(channel, nullBytes, len, 0, blocking);
1151                if (blockedBytes)
1152                        return blockedBytes;
1153                begin += len;
1154        }
1155        return 0;
1156}
1157
1158size_t NullStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
1159{
1160        lword begin = 0;
1161        size_t blockedBytes = NullStore::CopyRangeTo2(target, begin, transferBytes, channel, blocking);
1162        transferBytes = begin;
1163        m_size -= begin;
1164        return blockedBytes;
1165}
1166
1167NAMESPACE_END
1168
1169#endif
Note: See TracBrowser for help on using the repository browser.