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