00001
00002
00003 #include "pch.h"
00004 #include "config.h"
00005
00006 #if CRYPTOPP_MSC_VERSION
00007 # pragma warning(disable: 4100 4189)
00008 #endif
00009
00010 #if CRYPTOPP_GCC_DIAGNOSTIC_AVAILABLE
00011 # pragma GCC diagnostic ignored "-Wunused-value"
00012 #endif
00013
00014 #ifndef CRYPTOPP_IMPORTS
00015
00016 #include "filters.h"
00017 #include "mqueue.h"
00018 #include "fltrimpl.h"
00019 #include "argnames.h"
00020 #include "smartptr.h"
00021 #include "stdcpp.h"
00022 #include "misc.h"
00023
00024 NAMESPACE_BEGIN(CryptoPP)
00025
00026 Filter::Filter(BufferedTransformation *attachment)
00027 : m_attachment(attachment), m_inputPosition(0), m_continueAt(0)
00028 {
00029 }
00030
00031 BufferedTransformation * Filter::NewDefaultAttachment() const
00032 {
00033 return new MessageQueue;
00034 }
00035
00036 BufferedTransformation * Filter::AttachedTransformation()
00037 {
00038 if (m_attachment.get() == NULL)
00039 m_attachment.reset(NewDefaultAttachment());
00040 return m_attachment.get();
00041 }
00042
00043 const BufferedTransformation *Filter::AttachedTransformation() const
00044 {
00045 if (m_attachment.get() == NULL)
00046 const_cast<Filter *>(this)->m_attachment.reset(NewDefaultAttachment());
00047 return m_attachment.get();
00048 }
00049
00050 void Filter::Detach(BufferedTransformation *newOut)
00051 {
00052 m_attachment.reset(newOut);
00053 }
00054
00055 void Filter::Insert(Filter *filter)
00056 {
00057 filter->m_attachment.reset(m_attachment.release());
00058 m_attachment.reset(filter);
00059 }
00060
00061 size_t Filter::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
00062 {
00063 return AttachedTransformation()->CopyRangeTo2(target, begin, end, channel, blocking);
00064 }
00065
00066 size_t Filter::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
00067 {
00068 return AttachedTransformation()->TransferTo2(target, transferBytes, channel, blocking);
00069 }
00070
00071 void Filter::Initialize(const NameValuePairs ¶meters, int propagation)
00072 {
00073 m_inputPosition = m_continueAt = 0;
00074 IsolatedInitialize(parameters);
00075 PropagateInitialize(parameters, propagation);
00076 }
00077
00078 bool Filter::Flush(bool hardFlush, int propagation, bool blocking)
00079 {
00080 switch (m_continueAt)
00081 {
00082 case 0:
00083 if (IsolatedFlush(hardFlush, blocking))
00084 return true;
00085
00086 case 1:
00087 if (OutputFlush(1, hardFlush, propagation, blocking))
00088 return true;
00089
00090 default: ;;
00091 }
00092 return false;
00093 }
00094
00095 bool Filter::MessageSeriesEnd(int propagation, bool blocking)
00096 {
00097 switch (m_continueAt)
00098 {
00099 case 0:
00100 if (IsolatedMessageSeriesEnd(blocking))
00101 return true;
00102
00103 case 1:
00104 if (ShouldPropagateMessageSeriesEnd() && OutputMessageSeriesEnd(1, propagation, blocking))
00105 return true;
00106
00107 default: ;;
00108 }
00109 return false;
00110 }
00111
00112 void Filter::PropagateInitialize(const NameValuePairs ¶meters, int propagation)
00113 {
00114 if (propagation)
00115 AttachedTransformation()->Initialize(parameters, propagation-1);
00116 }
00117
00118 size_t Filter::OutputModifiable(int outputSite, byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel)
00119 {
00120 if (messageEnd)
00121 messageEnd--;
00122 size_t result = AttachedTransformation()->ChannelPutModifiable2(channel, inString, length, messageEnd, blocking);
00123 m_continueAt = result ? outputSite : 0;
00124 return result;
00125 }
00126
00127 size_t Filter::Output(int outputSite, const byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel)
00128 {
00129 if (messageEnd)
00130 messageEnd--;
00131 size_t result = AttachedTransformation()->ChannelPut2(channel, inString, length, messageEnd, blocking);
00132 m_continueAt = result ? outputSite : 0;
00133 return result;
00134 }
00135
00136 bool Filter::OutputFlush(int outputSite, bool hardFlush, int propagation, bool blocking, const std::string &channel)
00137 {
00138 if (propagation && AttachedTransformation()->ChannelFlush(channel, hardFlush, propagation-1, blocking))
00139 {
00140 m_continueAt = outputSite;
00141 return true;
00142 }
00143 m_continueAt = 0;
00144 return false;
00145 }
00146
00147 bool Filter::OutputMessageSeriesEnd(int outputSite, int propagation, bool blocking, const std::string &channel)
00148 {
00149 if (propagation && AttachedTransformation()->ChannelMessageSeriesEnd(channel, propagation-1, blocking))
00150 {
00151 m_continueAt = outputSite;
00152 return true;
00153 }
00154 m_continueAt = 0;
00155 return false;
00156 }
00157
00158
00159
00160 void MeterFilter::ResetMeter()
00161 {
00162 m_currentMessageBytes = m_totalBytes = m_currentSeriesMessages = m_totalMessages = m_totalMessageSeries = 0;
00163 m_rangesToSkip.clear();
00164 }
00165
00166 void MeterFilter::AddRangeToSkip(unsigned int message, lword position, lword size, bool sortNow)
00167 {
00168 MessageRange r = {message, position, size};
00169 m_rangesToSkip.push_back(r);
00170 if (sortNow)
00171 std::sort(m_rangesToSkip.begin(), m_rangesToSkip.end());
00172 }
00173
00174 size_t MeterFilter::PutMaybeModifiable(byte *begin, size_t length, int messageEnd, bool blocking, bool modifiable)
00175 {
00176 if (!m_transparent)
00177 return 0;
00178
00179 size_t t;
00180 FILTER_BEGIN;
00181
00182 m_begin = begin;
00183 m_length = length;
00184
00185 while (m_length > 0 || messageEnd)
00186 {
00187 if (m_length > 0 && !m_rangesToSkip.empty() && m_rangesToSkip.front().message == m_totalMessages && m_currentMessageBytes + m_length > m_rangesToSkip.front().position)
00188 {
00189 FILTER_OUTPUT_MAYBE_MODIFIABLE(1, m_begin, t = (size_t)SaturatingSubtract(m_rangesToSkip.front().position, m_currentMessageBytes), false, modifiable);
00190
00191 assert(t < m_length);
00192 m_begin += t;
00193 m_length -= t;
00194 m_currentMessageBytes += t;
00195 m_totalBytes += t;
00196
00197 if (m_currentMessageBytes + m_length < m_rangesToSkip.front().position + m_rangesToSkip.front().size)
00198 t = m_length;
00199 else
00200 {
00201 t = (size_t)SaturatingSubtract(m_rangesToSkip.front().position + m_rangesToSkip.front().size, m_currentMessageBytes);
00202 assert(t <= m_length);
00203 m_rangesToSkip.pop_front();
00204 }
00205
00206 m_begin += t;
00207 m_length -= t;
00208 m_currentMessageBytes += t;
00209 m_totalBytes += t;
00210 }
00211 else
00212 {
00213 FILTER_OUTPUT_MAYBE_MODIFIABLE(2, m_begin, m_length, messageEnd, modifiable);
00214
00215 m_currentMessageBytes += m_length;
00216 m_totalBytes += m_length;
00217 m_length = 0;
00218
00219 if (messageEnd)
00220 {
00221 m_currentMessageBytes = 0;
00222 m_currentSeriesMessages++;
00223 m_totalMessages++;
00224 messageEnd = false;
00225 }
00226 }
00227 }
00228
00229 FILTER_END_NO_MESSAGE_END;
00230 }
00231
00232 size_t MeterFilter::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
00233 {
00234 return PutMaybeModifiable(const_cast<byte *>(begin), length, messageEnd, blocking, false);
00235 }
00236
00237 size_t MeterFilter::PutModifiable2(byte *begin, size_t length, int messageEnd, bool blocking)
00238 {
00239 return PutMaybeModifiable(begin, length, messageEnd, blocking, true);
00240 }
00241
00242 bool MeterFilter::IsolatedMessageSeriesEnd(bool blocking)
00243 {
00244 CRYPTOPP_UNUSED(blocking);
00245 m_currentMessageBytes = 0;
00246 m_currentSeriesMessages = 0;
00247 m_totalMessageSeries++;
00248 return false;
00249 }
00250
00251
00252
00253 void FilterWithBufferedInput::BlockQueue::ResetQueue(size_t blockSize, size_t maxBlocks)
00254 {
00255 m_buffer.New(blockSize * maxBlocks);
00256 m_blockSize = blockSize;
00257 m_maxBlocks = maxBlocks;
00258 m_size = 0;
00259 m_begin = m_buffer;
00260 }
00261
00262 byte *FilterWithBufferedInput::BlockQueue::GetBlock()
00263 {
00264 if (m_size >= m_blockSize)
00265 {
00266 byte *ptr = m_begin;
00267 if ((m_begin+=m_blockSize) == m_buffer.end())
00268 m_begin = m_buffer;
00269 m_size -= m_blockSize;
00270 return ptr;
00271 }
00272 else
00273 return NULL;
00274 }
00275
00276 byte *FilterWithBufferedInput::BlockQueue::GetContigousBlocks(size_t &numberOfBytes)
00277 {
00278 numberOfBytes = STDMIN(numberOfBytes, STDMIN(size_t(m_buffer.end()-m_begin), m_size));
00279 byte *ptr = m_begin;
00280 m_begin += numberOfBytes;
00281 m_size -= numberOfBytes;
00282 if (m_size == 0 || m_begin == m_buffer.end())
00283 m_begin = m_buffer;
00284 return ptr;
00285 }
00286
00287 size_t FilterWithBufferedInput::BlockQueue::GetAll(byte *outString)
00288 {
00289
00290 if (!outString) return 0;
00291
00292 size_t size = m_size;
00293 size_t numberOfBytes = m_maxBlocks*m_blockSize;
00294 const byte *ptr = GetContigousBlocks(numberOfBytes);
00295 memcpy(outString, ptr, numberOfBytes);
00296 memcpy(outString+numberOfBytes, m_begin, m_size);
00297 m_size = 0;
00298 return size;
00299 }
00300
00301 void FilterWithBufferedInput::BlockQueue::Put(const byte *inString, size_t length)
00302 {
00303
00304 if (!inString || !length) return;
00305
00306 assert(m_size + length <= m_buffer.size());
00307 byte *end = (m_size < size_t(m_buffer.end()-m_begin)) ? m_begin + m_size : m_begin + m_size - m_buffer.size();
00308 size_t len = STDMIN(length, size_t(m_buffer.end()-end));
00309 memcpy(end, inString, len);
00310 if (len < length)
00311 memcpy(m_buffer, inString+len, length-len);
00312 m_size += length;
00313 }
00314
00315 #if !defined(CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY_562)
00316 FilterWithBufferedInput::FilterWithBufferedInput()
00317 : Filter(), m_firstSize(SIZE_MAX), m_blockSize(0), m_lastSize(SIZE_MAX), m_firstInputDone(false)
00318 {
00319 }
00320 #endif
00321
00322 FilterWithBufferedInput::FilterWithBufferedInput(BufferedTransformation *attachment)
00323 : Filter(attachment), m_firstSize(SIZE_MAX), m_blockSize(0), m_lastSize(SIZE_MAX), m_firstInputDone(false)
00324 {
00325 }
00326
00327 FilterWithBufferedInput::FilterWithBufferedInput(size_t firstSize, size_t blockSize, size_t lastSize, BufferedTransformation *attachment)
00328 : Filter(attachment), m_firstSize(firstSize), m_blockSize(blockSize), m_lastSize(lastSize), m_firstInputDone(false)
00329 {
00330 if (m_firstSize == SIZE_MAX || m_blockSize < 1 || m_lastSize == SIZE_MAX)
00331 throw InvalidArgument("FilterWithBufferedInput: invalid buffer size");
00332
00333 m_queue.ResetQueue(1, m_firstSize);
00334 }
00335
00336 void FilterWithBufferedInput::IsolatedInitialize(const NameValuePairs ¶meters)
00337 {
00338 InitializeDerivedAndReturnNewSizes(parameters, m_firstSize, m_blockSize, m_lastSize);
00339 if (m_firstSize == SIZE_MAX || m_blockSize < 1 || m_lastSize == SIZE_MAX)
00340 throw InvalidArgument("FilterWithBufferedInput: invalid buffer size");
00341 m_queue.ResetQueue(1, m_firstSize);
00342 m_firstInputDone = false;
00343 }
00344
00345 bool FilterWithBufferedInput::IsolatedFlush(bool hardFlush, bool blocking)
00346 {
00347 if (!blocking)
00348 throw BlockingInputOnly("FilterWithBufferedInput");
00349
00350 if (hardFlush)
00351 ForceNextPut();
00352 FlushDerived();
00353
00354 return false;
00355 }
00356
00357 size_t FilterWithBufferedInput::PutMaybeModifiable(byte *inString, size_t length, int messageEnd, bool blocking, bool modifiable)
00358 {
00359 if (!blocking)
00360 throw BlockingInputOnly("FilterWithBufferedInput");
00361
00362 if (length != 0)
00363 {
00364 size_t newLength = m_queue.CurrentSize() + length;
00365
00366 if (!m_firstInputDone && newLength >= m_firstSize)
00367 {
00368 size_t len = m_firstSize - m_queue.CurrentSize();
00369 m_queue.Put(inString, len);
00370 FirstPut(m_queue.GetContigousBlocks(m_firstSize));
00371 assert(m_queue.CurrentSize() == 0);
00372 m_queue.ResetQueue(m_blockSize, (2*m_blockSize+m_lastSize-2)/m_blockSize);
00373
00374 inString += len;
00375 newLength -= m_firstSize;
00376 m_firstInputDone = true;
00377 }
00378
00379 if (m_firstInputDone)
00380 {
00381 if (m_blockSize == 1)
00382 {
00383 while (newLength > m_lastSize && m_queue.CurrentSize() > 0)
00384 {
00385 size_t len = newLength - m_lastSize;
00386 byte *ptr = m_queue.GetContigousBlocks(len);
00387 NextPutModifiable(ptr, len);
00388 newLength -= len;
00389 }
00390
00391 if (newLength > m_lastSize)
00392 {
00393 size_t len = newLength - m_lastSize;
00394 NextPutMaybeModifiable(inString, len, modifiable);
00395 inString += len;
00396 newLength -= len;
00397 }
00398 }
00399 else
00400 {
00401 while (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() >= m_blockSize)
00402 {
00403 NextPutModifiable(m_queue.GetBlock(), m_blockSize);
00404 newLength -= m_blockSize;
00405 }
00406
00407 if (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() > 0)
00408 {
00409 assert(m_queue.CurrentSize() < m_blockSize);
00410 size_t len = m_blockSize - m_queue.CurrentSize();
00411 m_queue.Put(inString, len);
00412 inString += len;
00413 NextPutModifiable(m_queue.GetBlock(), m_blockSize);
00414 newLength -= m_blockSize;
00415 }
00416
00417 if (newLength >= m_blockSize + m_lastSize)
00418 {
00419 size_t len = RoundDownToMultipleOf(newLength - m_lastSize, m_blockSize);
00420 NextPutMaybeModifiable(inString, len, modifiable);
00421 inString += len;
00422 newLength -= len;
00423 }
00424 }
00425 }
00426
00427 m_queue.Put(inString, newLength - m_queue.CurrentSize());
00428 }
00429
00430 if (messageEnd)
00431 {
00432 if (!m_firstInputDone && m_firstSize==0)
00433 FirstPut(NULL);
00434
00435 SecByteBlock temp(m_queue.CurrentSize());
00436 m_queue.GetAll(temp);
00437 LastPut(temp, temp.size());
00438
00439 m_firstInputDone = false;
00440 m_queue.ResetQueue(1, m_firstSize);
00441
00442
00443 (void)Output(1, NULL, 0, messageEnd, blocking);
00444 }
00445 return 0;
00446 }
00447
00448 void FilterWithBufferedInput::ForceNextPut()
00449 {
00450 if (!m_firstInputDone)
00451 return;
00452
00453 if (m_blockSize > 1)
00454 {
00455 while (m_queue.CurrentSize() >= m_blockSize)
00456 NextPutModifiable(m_queue.GetBlock(), m_blockSize);
00457 }
00458 else
00459 {
00460 size_t len;
00461 while ((len = m_queue.CurrentSize()) > 0)
00462 NextPutModifiable(m_queue.GetContigousBlocks(len), len);
00463 }
00464 }
00465
00466 void FilterWithBufferedInput::NextPutMultiple(const byte *inString, size_t length)
00467 {
00468 assert(m_blockSize > 1);
00469 while (length > 0)
00470 {
00471 assert(length >= m_blockSize);
00472 NextPutSingle(inString);
00473 inString += m_blockSize;
00474 length -= m_blockSize;
00475 }
00476 }
00477
00478
00479
00480 void Redirector::Initialize(const NameValuePairs ¶meters, int propagation)
00481 {
00482 m_target = parameters.GetValueWithDefault("RedirectionTargetPointer", (BufferedTransformation*)NULL);
00483 m_behavior = parameters.GetIntValueWithDefault("RedirectionBehavior", PASS_EVERYTHING);
00484
00485 if (m_target && GetPassSignals())
00486 m_target->Initialize(parameters, propagation);
00487 }
00488
00489
00490
00491 ProxyFilter::ProxyFilter(BufferedTransformation *filter, size_t firstSize, size_t lastSize, BufferedTransformation *attachment)
00492 : FilterWithBufferedInput(firstSize, 1, lastSize, attachment), m_filter(filter)
00493 {
00494 if (m_filter.get())
00495 m_filter->Attach(new OutputProxy(*this, false));
00496 }
00497
00498 bool ProxyFilter::IsolatedFlush(bool hardFlush, bool blocking)
00499 {
00500 return m_filter.get() ? m_filter->Flush(hardFlush, -1, blocking) : false;
00501 }
00502
00503 void ProxyFilter::SetFilter(Filter *filter)
00504 {
00505 m_filter.reset(filter);
00506 if (filter)
00507 {
00508 OutputProxy *proxy;
00509 member_ptr<OutputProxy> temp(proxy = new OutputProxy(*this, false));
00510 m_filter->TransferAllTo(*proxy);
00511 m_filter->Attach(temp.release());
00512 }
00513 }
00514
00515 void ProxyFilter::NextPutMultiple(const byte *s, size_t len)
00516 {
00517 if (m_filter.get())
00518 m_filter->Put(s, len);
00519 }
00520
00521 void ProxyFilter::NextPutModifiable(byte *s, size_t len)
00522 {
00523 if (m_filter.get())
00524 m_filter->PutModifiable(s, len);
00525 }
00526
00527
00528
00529 void RandomNumberSink::IsolatedInitialize(const NameValuePairs ¶meters)
00530 {
00531 parameters.GetRequiredParameter("RandomNumberSink", "RandomNumberGeneratorPointer", m_rng);
00532 }
00533
00534 size_t RandomNumberSink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
00535 {
00536 CRYPTOPP_UNUSED(messageEnd); CRYPTOPP_UNUSED(blocking);
00537 m_rng->IncorporateEntropy(begin, length);
00538 return 0;
00539 }
00540
00541 size_t ArraySink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
00542 {
00543 CRYPTOPP_UNUSED(messageEnd); CRYPTOPP_UNUSED(blocking);
00544
00545
00546
00547 size_t copied = 0;
00548 if (m_buf && begin)
00549 {
00550 copied = STDMIN(length, SaturatingSubtract(m_size, m_total));
00551 memmove(m_buf+m_total, begin, copied);
00552 }
00553 m_total += copied;
00554 return length - copied;
00555 }
00556
00557 byte * ArraySink::CreatePutSpace(size_t &size)
00558 {
00559 size = SaturatingSubtract(m_size, m_total);
00560 return m_buf + m_total;
00561 }
00562
00563 void ArraySink::IsolatedInitialize(const NameValuePairs ¶meters)
00564 {
00565 ByteArrayParameter array;
00566 if (!parameters.GetValue(Name::OutputBuffer(), array))
00567 throw InvalidArgument("ArraySink: missing OutputBuffer argument");
00568 m_buf = array.begin();
00569 m_size = array.size();
00570 }
00571
00572 size_t ArrayXorSink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
00573 {
00574 CRYPTOPP_UNUSED(messageEnd); CRYPTOPP_UNUSED(blocking);
00575
00576
00577 size_t copied = 0;
00578 if (m_buf && begin)
00579 {
00580 copied = STDMIN(length, SaturatingSubtract(m_size, m_total));
00581 xorbuf(m_buf+m_total, begin, copied);
00582 }
00583 m_total += copied;
00584 return length - copied;
00585 }
00586
00587
00588
00589 StreamTransformationFilter::StreamTransformationFilter(StreamTransformation &c, BufferedTransformation *attachment, BlockPaddingScheme padding, bool allowAuthenticatedSymmetricCipher)
00590 : FilterWithBufferedInput(attachment)
00591 , m_cipher(c), m_padding(DEFAULT_PADDING), m_optimalBufferSize(0)
00592 {
00593 assert(c.MinLastBlockSize() == 0 || c.MinLastBlockSize() > c.MandatoryBlockSize());
00594
00595 if (!allowAuthenticatedSymmetricCipher && dynamic_cast<AuthenticatedSymmetricCipher *>(&c) != 0)
00596 throw InvalidArgument("StreamTransformationFilter: please use AuthenticatedEncryptionFilter and AuthenticatedDecryptionFilter for AuthenticatedSymmetricCipher");
00597
00598 IsolatedInitialize(MakeParameters(Name::BlockPaddingScheme(), padding));
00599 }
00600
00601 size_t StreamTransformationFilter::LastBlockSize(StreamTransformation &c, BlockPaddingScheme padding)
00602 {
00603 if (c.MinLastBlockSize() > 0)
00604 return c.MinLastBlockSize();
00605 else if (c.MandatoryBlockSize() > 1 && !c.IsForwardTransformation() && padding != NO_PADDING && padding != ZEROS_PADDING)
00606 return c.MandatoryBlockSize();
00607 else
00608 return 0;
00609 }
00610
00611 void StreamTransformationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
00612 {
00613 BlockPaddingScheme padding = parameters.GetValueWithDefault(Name::BlockPaddingScheme(), DEFAULT_PADDING);
00614 bool isBlockCipher = (m_cipher.MandatoryBlockSize() > 1 && m_cipher.MinLastBlockSize() == 0);
00615
00616 if (padding == DEFAULT_PADDING)
00617 m_padding = isBlockCipher ? PKCS_PADDING : NO_PADDING;
00618 else
00619 m_padding = padding;
00620
00621 if (!isBlockCipher && (m_padding == PKCS_PADDING || m_padding == ONE_AND_ZEROS_PADDING))
00622 throw InvalidArgument("StreamTransformationFilter: PKCS_PADDING and ONE_AND_ZEROS_PADDING cannot be used with " + m_cipher.AlgorithmName());
00623
00624 firstSize = 0;
00625 blockSize = m_cipher.MandatoryBlockSize();
00626 lastSize = LastBlockSize(m_cipher, m_padding);
00627 }
00628
00629 void StreamTransformationFilter::FirstPut(const byte* inString)
00630 {
00631 CRYPTOPP_UNUSED(inString);
00632 m_optimalBufferSize = m_cipher.OptimalBlockSize();
00633 m_optimalBufferSize = (unsigned int)STDMAX(m_optimalBufferSize, RoundDownToMultipleOf(4096U, m_optimalBufferSize));
00634 }
00635
00636 void StreamTransformationFilter::NextPutMultiple(const byte *inString, size_t length)
00637 {
00638 if (!length)
00639 return;
00640
00641 size_t s = m_cipher.MandatoryBlockSize();
00642
00643 do
00644 {
00645 size_t len = m_optimalBufferSize;
00646 byte *space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, s, length, len);
00647 if (len < length)
00648 {
00649 if (len == m_optimalBufferSize)
00650 len -= m_cipher.GetOptimalBlockSizeUsed();
00651 len = RoundDownToMultipleOf(len, s);
00652 }
00653 else
00654 len = length;
00655 m_cipher.ProcessString(space, inString, len);
00656 AttachedTransformation()->PutModifiable(space, len);
00657 inString += len;
00658 length -= len;
00659 }
00660 while (length > 0);
00661 }
00662
00663 void StreamTransformationFilter::NextPutModifiable(byte *inString, size_t length)
00664 {
00665 m_cipher.ProcessString(inString, length);
00666 AttachedTransformation()->PutModifiable(inString, length);
00667 }
00668
00669 void StreamTransformationFilter::LastPut(const byte *inString, size_t length)
00670 {
00671 byte *space = NULL;
00672
00673 switch (m_padding)
00674 {
00675 case NO_PADDING:
00676 case ZEROS_PADDING:
00677 if (length > 0)
00678 {
00679 size_t minLastBlockSize = m_cipher.MinLastBlockSize();
00680 bool isForwardTransformation = m_cipher.IsForwardTransformation();
00681
00682 if (isForwardTransformation && m_padding == ZEROS_PADDING && (minLastBlockSize == 0 || length < minLastBlockSize))
00683 {
00684
00685 size_t blockSize = STDMAX(minLastBlockSize, (size_t)m_cipher.MandatoryBlockSize());
00686 space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, blockSize);
00687 if (inString) {memcpy(space, inString, length);}
00688 memset(space + length, 0, blockSize - length);
00689 m_cipher.ProcessLastBlock(space, space, blockSize);
00690 AttachedTransformation()->Put(space, blockSize);
00691 }
00692 else
00693 {
00694 if (minLastBlockSize == 0)
00695 {
00696 if (isForwardTransformation)
00697 throw InvalidDataFormat("StreamTransformationFilter: plaintext length is not a multiple of block size and NO_PADDING is specified");
00698 else
00699 throw InvalidCiphertext("StreamTransformationFilter: ciphertext length is not a multiple of block size");
00700 }
00701
00702 space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, length, m_optimalBufferSize);
00703 m_cipher.ProcessLastBlock(space, inString, length);
00704 AttachedTransformation()->Put(space, length);
00705 }
00706 }
00707 break;
00708
00709 case PKCS_PADDING:
00710 case ONE_AND_ZEROS_PADDING:
00711 unsigned int s;
00712 s = m_cipher.MandatoryBlockSize();
00713 assert(s > 1);
00714 space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, s, m_optimalBufferSize);
00715 if (m_cipher.IsForwardTransformation())
00716 {
00717 assert(length < s);
00718 if (inString) {memcpy(space, inString, length);}
00719 if (m_padding == PKCS_PADDING)
00720 {
00721 assert(s < 256);
00722 byte pad = byte(s-length);
00723 memset(space+length, pad, s-length);
00724 }
00725 else
00726 {
00727 space[length] = 0x80;
00728 memset(space+length+1, 0, s-length-1);
00729 }
00730 m_cipher.ProcessData(space, space, s);
00731 AttachedTransformation()->Put(space, s);
00732 }
00733 else
00734 {
00735 if (length != s)
00736 throw InvalidCiphertext("StreamTransformationFilter: ciphertext length is not a multiple of block size");
00737 m_cipher.ProcessData(space, inString, s);
00738 if (m_padding == PKCS_PADDING)
00739 {
00740 byte pad = space[s-1];
00741 if (pad < 1 || pad > s || std::find_if(space+s-pad, space+s, std::bind2nd(std::not_equal_to<byte>(), pad)) != space+s)
00742 throw InvalidCiphertext("StreamTransformationFilter: invalid PKCS #7 block padding found");
00743 length = s-pad;
00744 }
00745 else
00746 {
00747 while (length > 1 && space[length-1] == 0)
00748 --length;
00749 if (space[--length] != 0x80)
00750 throw InvalidCiphertext("StreamTransformationFilter: invalid ones-and-zeros padding found");
00751 }
00752 AttachedTransformation()->Put(space, length);
00753 }
00754 break;
00755
00756 default:
00757 assert(false);
00758 }
00759 }
00760
00761
00762
00763 HashFilter::HashFilter(HashTransformation &hm, BufferedTransformation *attachment, bool putMessage, int truncatedDigestSize, const std::string &messagePutChannel, const std::string &hashPutChannel)
00764 : m_hashModule(hm), m_putMessage(putMessage), m_digestSize(0), m_space(NULL)
00765 , m_messagePutChannel(messagePutChannel), m_hashPutChannel(hashPutChannel)
00766 {
00767 m_digestSize = truncatedDigestSize < 0 ? m_hashModule.DigestSize() : truncatedDigestSize;
00768 Detach(attachment);
00769 }
00770
00771 void HashFilter::IsolatedInitialize(const NameValuePairs ¶meters)
00772 {
00773 m_putMessage = parameters.GetValueWithDefault(Name::PutMessage(), false);
00774 int s = parameters.GetIntValueWithDefault(Name::TruncatedDigestSize(), -1);
00775 m_digestSize = s < 0 ? m_hashModule.DigestSize() : s;
00776 }
00777
00778 size_t HashFilter::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
00779 {
00780 FILTER_BEGIN;
00781 if (m_putMessage)
00782 FILTER_OUTPUT3(1, 0, inString, length, 0, m_messagePutChannel);
00783 m_hashModule.Update(inString, length);
00784 if (messageEnd)
00785 {
00786 {
00787 size_t size;
00788 m_space = HelpCreatePutSpace(*AttachedTransformation(), m_hashPutChannel, m_digestSize, m_digestSize, size = m_digestSize);
00789 m_hashModule.TruncatedFinal(m_space, m_digestSize);
00790 }
00791 FILTER_OUTPUT3(2, 0, m_space, m_digestSize, messageEnd, m_hashPutChannel);
00792 }
00793 FILTER_END_NO_MESSAGE_END;
00794 }
00795
00796
00797
00798 HashVerificationFilter::HashVerificationFilter(HashTransformation &hm, BufferedTransformation *attachment, word32 flags, int truncatedDigestSize)
00799 : FilterWithBufferedInput(attachment)
00800 , m_hashModule(hm), m_flags(0), m_digestSize(0), m_verified(false)
00801 {
00802 IsolatedInitialize(MakeParameters(Name::HashVerificationFilterFlags(), flags)(Name::TruncatedDigestSize(), truncatedDigestSize));
00803 }
00804
00805 void HashVerificationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
00806 {
00807 m_flags = parameters.GetValueWithDefault(Name::HashVerificationFilterFlags(), (word32)DEFAULT_FLAGS);
00808 int s = parameters.GetIntValueWithDefault(Name::TruncatedDigestSize(), -1);
00809 m_digestSize = s < 0 ? m_hashModule.DigestSize() : s;
00810 m_verified = false;
00811 firstSize = m_flags & HASH_AT_BEGIN ? m_digestSize : 0;
00812 blockSize = 1;
00813 lastSize = m_flags & HASH_AT_BEGIN ? 0 : m_digestSize;
00814 }
00815
00816 void HashVerificationFilter::FirstPut(const byte *inString)
00817 {
00818 if (m_flags & HASH_AT_BEGIN)
00819 {
00820 m_expectedHash.New(m_digestSize);
00821 if (inString) {memcpy(m_expectedHash, inString, m_expectedHash.size());}
00822 if (m_flags & PUT_HASH)
00823 AttachedTransformation()->Put(inString, m_expectedHash.size());
00824 }
00825 }
00826
00827 void HashVerificationFilter::NextPutMultiple(const byte *inString, size_t length)
00828 {
00829 m_hashModule.Update(inString, length);
00830 if (m_flags & PUT_MESSAGE)
00831 AttachedTransformation()->Put(inString, length);
00832 }
00833
00834 void HashVerificationFilter::LastPut(const byte *inString, size_t length)
00835 {
00836 if (m_flags & HASH_AT_BEGIN)
00837 {
00838 assert(length == 0);
00839 m_verified = m_hashModule.TruncatedVerify(m_expectedHash, m_digestSize);
00840 }
00841 else
00842 {
00843 m_verified = (length==m_digestSize && m_hashModule.TruncatedVerify(inString, length));
00844 if (m_flags & PUT_HASH)
00845 AttachedTransformation()->Put(inString, length);
00846 }
00847
00848 if (m_flags & PUT_RESULT)
00849 AttachedTransformation()->Put(m_verified);
00850
00851 if ((m_flags & THROW_EXCEPTION) && !m_verified)
00852 throw HashVerificationFailed();
00853 }
00854
00855
00856
00857 AuthenticatedEncryptionFilter::AuthenticatedEncryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment,
00858 bool putAAD, int truncatedDigestSize, const std::string &macChannel, BlockPaddingScheme padding)
00859 : StreamTransformationFilter(c, attachment, padding, true)
00860 , m_hf(c, new OutputProxy(*this, false), putAAD, truncatedDigestSize, AAD_CHANNEL, macChannel)
00861 {
00862 assert(c.IsForwardTransformation());
00863 }
00864
00865 void AuthenticatedEncryptionFilter::IsolatedInitialize(const NameValuePairs ¶meters)
00866 {
00867 m_hf.IsolatedInitialize(parameters);
00868 StreamTransformationFilter::IsolatedInitialize(parameters);
00869 }
00870
00871 byte * AuthenticatedEncryptionFilter::ChannelCreatePutSpace(const std::string &channel, size_t &size)
00872 {
00873 if (channel.empty())
00874 return StreamTransformationFilter::CreatePutSpace(size);
00875
00876 if (channel == AAD_CHANNEL)
00877 return m_hf.CreatePutSpace(size);
00878
00879 throw InvalidChannelName("AuthenticatedEncryptionFilter", channel);
00880 }
00881
00882 size_t AuthenticatedEncryptionFilter::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
00883 {
00884 if (channel.empty())
00885 return StreamTransformationFilter::Put2(begin, length, messageEnd, blocking);
00886
00887 if (channel == AAD_CHANNEL)
00888 return m_hf.Put2(begin, length, 0, blocking);
00889
00890 throw InvalidChannelName("AuthenticatedEncryptionFilter", channel);
00891 }
00892
00893 void AuthenticatedEncryptionFilter::LastPut(const byte *inString, size_t length)
00894 {
00895 StreamTransformationFilter::LastPut(inString, length);
00896 m_hf.MessageEnd();
00897 }
00898
00899
00900
00901 AuthenticatedDecryptionFilter::AuthenticatedDecryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment, word32 flags, int truncatedDigestSize, BlockPaddingScheme padding)
00902 : FilterWithBufferedInput(attachment)
00903 , m_hashVerifier(c, new OutputProxy(*this, false))
00904 , m_streamFilter(c, new OutputProxy(*this, false), padding, true)
00905 {
00906 assert(!c.IsForwardTransformation() || c.IsSelfInverting());
00907 IsolatedInitialize(MakeParameters(Name::BlockPaddingScheme(), padding)(Name::AuthenticatedDecryptionFilterFlags(), flags)(Name::TruncatedDigestSize(), truncatedDigestSize));
00908 }
00909
00910 void AuthenticatedDecryptionFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
00911 {
00912 word32 flags = parameters.GetValueWithDefault(Name::AuthenticatedDecryptionFilterFlags(), (word32)DEFAULT_FLAGS);
00913
00914 m_hashVerifier.Initialize(CombinedNameValuePairs(parameters, MakeParameters(Name::HashVerificationFilterFlags(), flags)));
00915 m_streamFilter.Initialize(parameters);
00916
00917 firstSize = m_hashVerifier.m_firstSize;
00918 blockSize = 1;
00919 lastSize = m_hashVerifier.m_lastSize;
00920 }
00921
00922 byte * AuthenticatedDecryptionFilter::ChannelCreatePutSpace(const std::string &channel, size_t &size)
00923 {
00924 if (channel.empty())
00925 return m_streamFilter.CreatePutSpace(size);
00926
00927 if (channel == AAD_CHANNEL)
00928 return m_hashVerifier.CreatePutSpace(size);
00929
00930 throw InvalidChannelName("AuthenticatedDecryptionFilter", channel);
00931 }
00932
00933 size_t AuthenticatedDecryptionFilter::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
00934 {
00935 if (channel.empty())
00936 {
00937 if (m_lastSize > 0)
00938 m_hashVerifier.ForceNextPut();
00939 return FilterWithBufferedInput::Put2(begin, length, messageEnd, blocking);
00940 }
00941
00942 if (channel == AAD_CHANNEL)
00943 return m_hashVerifier.Put2(begin, length, 0, blocking);
00944
00945 throw InvalidChannelName("AuthenticatedDecryptionFilter", channel);
00946 }
00947
00948 void AuthenticatedDecryptionFilter::FirstPut(const byte *inString)
00949 {
00950 m_hashVerifier.Put(inString, m_firstSize);
00951 }
00952
00953 void AuthenticatedDecryptionFilter::NextPutMultiple(const byte *inString, size_t length)
00954 {
00955 m_streamFilter.Put(inString, length);
00956 }
00957
00958 void AuthenticatedDecryptionFilter::LastPut(const byte *inString, size_t length)
00959 {
00960 m_streamFilter.MessageEnd();
00961 m_hashVerifier.PutMessageEnd(inString, length);
00962 }
00963
00964
00965
00966 void SignerFilter::IsolatedInitialize(const NameValuePairs ¶meters)
00967 {
00968 m_putMessage = parameters.GetValueWithDefault(Name::PutMessage(), false);
00969 m_messageAccumulator.reset(m_signer.NewSignatureAccumulator(m_rng));
00970 }
00971
00972 size_t SignerFilter::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
00973 {
00974 FILTER_BEGIN;
00975 m_messageAccumulator->Update(inString, length);
00976 if (m_putMessage)
00977 FILTER_OUTPUT(1, inString, length, 0);
00978 if (messageEnd)
00979 {
00980 m_buf.New(m_signer.SignatureLength());
00981 m_signer.Sign(m_rng, m_messageAccumulator.release(), m_buf);
00982 FILTER_OUTPUT(2, m_buf, m_buf.size(), messageEnd);
00983 m_messageAccumulator.reset(m_signer.NewSignatureAccumulator(m_rng));
00984 }
00985 FILTER_END_NO_MESSAGE_END;
00986 }
00987
00988 SignatureVerificationFilter::SignatureVerificationFilter(const PK_Verifier &verifier, BufferedTransformation *attachment, word32 flags)
00989 : FilterWithBufferedInput(attachment)
00990 , m_verifier(verifier), m_flags(0), m_verified(0)
00991 {
00992 IsolatedInitialize(MakeParameters(Name::SignatureVerificationFilterFlags(), flags));
00993 }
00994
00995 void SignatureVerificationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
00996 {
00997 m_flags = parameters.GetValueWithDefault(Name::SignatureVerificationFilterFlags(), (word32)DEFAULT_FLAGS);
00998 m_messageAccumulator.reset(m_verifier.NewVerificationAccumulator());
00999 size_t size = m_verifier.SignatureLength();
01000 assert(size != 0);
01001 m_verified = false;
01002 firstSize = m_flags & SIGNATURE_AT_BEGIN ? size : 0;
01003 blockSize = 1;
01004 lastSize = m_flags & SIGNATURE_AT_BEGIN ? 0 : size;
01005 }
01006
01007 void SignatureVerificationFilter::FirstPut(const byte *inString)
01008 {
01009 if (m_flags & SIGNATURE_AT_BEGIN)
01010 {
01011 if (m_verifier.SignatureUpfront())
01012 m_verifier.InputSignature(*m_messageAccumulator, inString, m_verifier.SignatureLength());
01013 else
01014 {
01015 m_signature.New(m_verifier.SignatureLength());
01016 if (inString) {memcpy(m_signature, inString, m_signature.size());}
01017 }
01018
01019 if (m_flags & PUT_SIGNATURE)
01020 AttachedTransformation()->Put(inString, m_signature.size());
01021 }
01022 else
01023 {
01024 assert(!m_verifier.SignatureUpfront());
01025 }
01026 }
01027
01028 void SignatureVerificationFilter::NextPutMultiple(const byte *inString, size_t length)
01029 {
01030 m_messageAccumulator->Update(inString, length);
01031 if (m_flags & PUT_MESSAGE)
01032 AttachedTransformation()->Put(inString, length);
01033 }
01034
01035 void SignatureVerificationFilter::LastPut(const byte *inString, size_t length)
01036 {
01037 if (m_flags & SIGNATURE_AT_BEGIN)
01038 {
01039 assert(length == 0);
01040 m_verifier.InputSignature(*m_messageAccumulator, m_signature, m_signature.size());
01041 m_verified = m_verifier.VerifyAndRestart(*m_messageAccumulator);
01042 }
01043 else
01044 {
01045 m_verifier.InputSignature(*m_messageAccumulator, inString, length);
01046 m_verified = m_verifier.VerifyAndRestart(*m_messageAccumulator);
01047 if (m_flags & PUT_SIGNATURE)
01048 AttachedTransformation()->Put(inString, length);
01049 }
01050
01051 if (m_flags & PUT_RESULT)
01052 AttachedTransformation()->Put(m_verified);
01053
01054 if ((m_flags & THROW_EXCEPTION) && !m_verified)
01055 throw SignatureVerificationFailed();
01056 }
01057
01058
01059
01060 size_t Source::PumpAll2(bool blocking)
01061 {
01062 unsigned int messageCount = UINT_MAX;
01063 do {
01064 RETURN_IF_NONZERO(PumpMessages2(messageCount, blocking));
01065 } while(messageCount == UINT_MAX);
01066
01067 return 0;
01068 }
01069
01070 bool Store::GetNextMessage()
01071 {
01072 if (!m_messageEnd && !AnyRetrievable())
01073 {
01074 m_messageEnd=true;
01075 return true;
01076 }
01077 else
01078 return false;
01079 }
01080
01081 unsigned int Store::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const
01082 {
01083 if (m_messageEnd || count == 0)
01084 return 0;
01085 else
01086 {
01087 CopyTo(target, ULONG_MAX, channel);
01088 if (GetAutoSignalPropagation())
01089 target.ChannelMessageEnd(channel, GetAutoSignalPropagation()-1);
01090 return 1;
01091 }
01092 }
01093
01094 void StringStore::StoreInitialize(const NameValuePairs ¶meters)
01095 {
01096 ConstByteArrayParameter array;
01097 if (!parameters.GetValue(Name::InputBuffer(), array))
01098 throw InvalidArgument("StringStore: missing InputBuffer argument");
01099 m_store = array.begin();
01100 m_length = array.size();
01101 m_count = 0;
01102 }
01103
01104 size_t StringStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
01105 {
01106 lword position = 0;
01107 size_t blockedBytes = CopyRangeTo2(target, position, transferBytes, channel, blocking);
01108 m_count += (size_t)position;
01109 transferBytes = position;
01110 return blockedBytes;
01111 }
01112
01113 size_t StringStore::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
01114 {
01115 size_t i = UnsignedMin(m_length, m_count+begin);
01116 size_t len = UnsignedMin(m_length-i, end-begin);
01117 size_t blockedBytes = target.ChannelPut2(channel, m_store+i, len, 0, blocking);
01118 if (!blockedBytes)
01119 begin += len;
01120 return blockedBytes;
01121 }
01122
01123 void RandomNumberStore::StoreInitialize(const NameValuePairs ¶meters)
01124 {
01125 parameters.GetRequiredParameter("RandomNumberStore", "RandomNumberGeneratorPointer", m_rng);
01126 int length;
01127 parameters.GetRequiredIntParameter("RandomNumberStore", "RandomNumberStoreSize", length);
01128 m_length = length;
01129 }
01130
01131 size_t RandomNumberStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
01132 {
01133 if (!blocking)
01134 throw NotImplemented("RandomNumberStore: nonblocking transfer is not implemented by this object");
01135
01136 transferBytes = UnsignedMin(transferBytes, m_length - m_count);
01137 m_rng->GenerateIntoBufferedTransformation(target, channel, transferBytes);
01138 m_count += transferBytes;
01139
01140 return 0;
01141 }
01142
01143 size_t NullStore::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
01144 {
01145 static const byte nullBytes[128] = {0};
01146 while (begin < end)
01147 {
01148 size_t len = (size_t)STDMIN(end-begin, lword(128));
01149 size_t blockedBytes = target.ChannelPut2(channel, nullBytes, len, 0, blocking);
01150 if (blockedBytes)
01151 return blockedBytes;
01152 begin += len;
01153 }
01154 return 0;
01155 }
01156
01157 size_t NullStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
01158 {
01159 lword begin = 0;
01160 size_t blockedBytes = NullStore::CopyRangeTo2(target, begin, transferBytes, channel, blocking);
01161 transferBytes = begin;
01162 m_size -= begin;
01163 return blockedBytes;
01164 }
01165
01166 NAMESPACE_END
01167
01168 #endif