Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members

filters.cpp

00001 // filters.cpp - written and placed in the public domain by Wei Dai
00002 
00003 #include "pch.h"
00004 #include "filters.h"
00005 #include "mqueue.h"
00006 #include "fltrimpl.h"
00007 #include "argnames.h"
00008 #include <memory>
00009 #include <functional>
00010 
00011 NAMESPACE_BEGIN(CryptoPP)
00012 
00013 Filter::Filter(BufferedTransformation *attachment)
00014         : m_attachment(attachment), m_continueAt(0)
00015 {
00016 }
00017 
00018 BufferedTransformation * Filter::NewDefaultAttachment() const
00019 {
00020         return new MessageQueue;
00021 }
00022 
00023 BufferedTransformation * Filter::AttachedTransformation()
00024 {
00025         if (m_attachment.get() == NULL)
00026                 m_attachment.reset(NewDefaultAttachment());
00027         return m_attachment.get();
00028 }
00029 
00030 const BufferedTransformation *Filter::AttachedTransformation() const
00031 {
00032         if (m_attachment.get() == NULL)
00033                 const_cast<Filter *>(this)->m_attachment.reset(NewDefaultAttachment());
00034         return m_attachment.get();
00035 }
00036 
00037 void Filter::Detach(BufferedTransformation *newOut)
00038 {
00039         m_attachment.reset(newOut);
00040         NotifyAttachmentChange();
00041 }
00042 
00043 void Filter::Insert(Filter *filter)
00044 {
00045         filter->m_attachment.reset(m_attachment.release());
00046         m_attachment.reset(filter);
00047         NotifyAttachmentChange();
00048 }
00049 
00050 unsigned int Filter::CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end, const std::string &channel, bool blocking) const
00051 {
00052         return AttachedTransformation()->CopyRangeTo2(target, begin, end, channel, blocking);
00053 }
00054 
00055 unsigned int Filter::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking)
00056 {
00057         return AttachedTransformation()->TransferTo2(target, transferBytes, channel, blocking);
00058 }
00059 
00060 void Filter::Initialize(const NameValuePairs &parameters, int propagation)
00061 {
00062         m_continueAt = 0;
00063         IsolatedInitialize(parameters);
00064         PropagateInitialize(parameters, propagation);
00065 }
00066 
00067 bool Filter::Flush(bool hardFlush, int propagation, bool blocking)
00068 {
00069         switch (m_continueAt)
00070         {
00071         case 0:
00072                 if (IsolatedFlush(hardFlush, blocking))
00073                         return true;
00074         case 1:
00075                 if (OutputFlush(1, hardFlush, propagation, blocking))
00076                         return true;
00077         }
00078         return false;
00079 }
00080 
00081 bool Filter::MessageSeriesEnd(int propagation, bool blocking)
00082 {
00083         switch (m_continueAt)
00084         {
00085         case 0:
00086                 if (IsolatedMessageSeriesEnd(blocking))
00087                         return true;
00088         case 1:
00089                 if (ShouldPropagateMessageSeriesEnd() && OutputMessageSeriesEnd(1, propagation, blocking))
00090                         return true;
00091         }
00092         return false;
00093 }
00094 
00095 void Filter::PropagateInitialize(const NameValuePairs &parameters, int propagation, const std::string &channel)
00096 {
00097         if (propagation)
00098                 AttachedTransformation()->ChannelInitialize(channel, parameters, propagation-1);
00099 }
00100 
00101 unsigned int Filter::Output(int outputSite, const byte *inString, unsigned int length, int messageEnd, bool blocking, const std::string &channel)
00102 {
00103         if (messageEnd)
00104                 messageEnd--;
00105         unsigned int result = AttachedTransformation()->Put2(inString, length, messageEnd, blocking);
00106         m_continueAt = result ? outputSite : 0;
00107         return result;
00108 }
00109 
00110 bool Filter::OutputFlush(int outputSite, bool hardFlush, int propagation, bool blocking, const std::string &channel)
00111 {
00112         if (propagation && AttachedTransformation()->ChannelFlush(channel, hardFlush, propagation-1, blocking))
00113         {
00114                 m_continueAt = outputSite;
00115                 return true;
00116         }
00117         m_continueAt = 0;
00118         return false;
00119 }
00120 
00121 bool Filter::OutputMessageSeriesEnd(int outputSite, int propagation, bool blocking, const std::string &channel)
00122 {
00123         if (propagation && AttachedTransformation()->ChannelMessageSeriesEnd(channel, propagation-1, blocking))
00124         {
00125                 m_continueAt = outputSite;
00126                 return true;
00127         }
00128         m_continueAt = 0;
00129         return false;
00130 }
00131 
00132 // *************************************************************
00133 
00134 unsigned int MeterFilter::Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
00135 {
00136         if (m_transparent)
00137         {
00138                 FILTER_BEGIN;
00139                 m_currentMessageBytes += length;
00140                 m_totalBytes += length;
00141 
00142                 if (messageEnd)
00143                 {
00144                         m_currentMessageBytes = 0;
00145                         m_currentSeriesMessages++;
00146                         m_totalMessages++;
00147                 }
00148                 
00149                 FILTER_OUTPUT(1, begin, length, messageEnd);
00150                 FILTER_END_NO_MESSAGE_END;
00151         }
00152         return 0;
00153 }
00154 
00155 bool MeterFilter::IsolatedMessageSeriesEnd(bool blocking)
00156 {
00157         m_currentMessageBytes = 0;
00158         m_currentSeriesMessages = 0;
00159         m_totalMessageSeries++;
00160         return false;
00161 }
00162 
00163 // *************************************************************
00164 
00165 void FilterWithBufferedInput::BlockQueue::ResetQueue(unsigned int blockSize, unsigned int maxBlocks)
00166 {
00167         m_buffer.New(blockSize * maxBlocks);
00168         m_blockSize = blockSize;
00169         m_maxBlocks = maxBlocks;
00170         m_size = 0;
00171         m_begin = m_buffer;
00172 }
00173 
00174 byte *FilterWithBufferedInput::BlockQueue::GetBlock()
00175 {
00176         if (m_size >= m_blockSize)
00177         {
00178                 byte *ptr = m_begin;
00179                 if ((m_begin+=m_blockSize) == m_buffer.end())
00180                         m_begin = m_buffer;
00181                 m_size -= m_blockSize;
00182                 return ptr;
00183         }
00184         else
00185                 return NULL;
00186 }
00187 
00188 byte *FilterWithBufferedInput::BlockQueue::GetContigousBlocks(unsigned int &numberOfBytes)
00189 {
00190         numberOfBytes = STDMIN(numberOfBytes, STDMIN((unsigned int)(m_buffer.end()-m_begin), m_size));
00191         byte *ptr = m_begin;
00192         m_begin += numberOfBytes;
00193         m_size -= numberOfBytes;
00194         if (m_size == 0 || m_begin == m_buffer.end())
00195                 m_begin = m_buffer;
00196         return ptr;
00197 }
00198 
00199 unsigned int FilterWithBufferedInput::BlockQueue::GetAll(byte *outString)
00200 {
00201         unsigned int size = m_size;
00202         unsigned int numberOfBytes = m_maxBlocks*m_blockSize;
00203         const byte *ptr = GetContigousBlocks(numberOfBytes);
00204         memcpy(outString, ptr, numberOfBytes);
00205         memcpy(outString+numberOfBytes, m_begin, m_size);
00206         m_size = 0;
00207         return size;
00208 }
00209 
00210 void FilterWithBufferedInput::BlockQueue::Put(const byte *inString, unsigned int length)
00211 {
00212         assert(m_size + length <= m_buffer.size());
00213         byte *end = (m_size < (unsigned int)(m_buffer.end()-m_begin)) ? m_begin + m_size : m_begin + m_size - m_buffer.size();
00214         unsigned int len = STDMIN(length, (unsigned int)(m_buffer.end()-end));
00215         memcpy(end, inString, len);
00216         if (len < length)
00217                 memcpy(m_buffer, inString+len, length-len);
00218         m_size += length;
00219 }
00220 
00221 FilterWithBufferedInput::FilterWithBufferedInput(BufferedTransformation *attachment)
00222         : Filter(attachment)
00223 {
00224 }
00225 
00226 FilterWithBufferedInput::FilterWithBufferedInput(unsigned int firstSize, unsigned int blockSize, unsigned int lastSize, BufferedTransformation *attachment)
00227         : Filter(attachment), m_firstSize(firstSize), m_blockSize(blockSize), m_lastSize(lastSize)
00228         , m_firstInputDone(false)
00229 {
00230         if (m_firstSize < 0 || m_blockSize < 1 || m_lastSize < 0)
00231                 throw InvalidArgument("FilterWithBufferedInput: invalid buffer size");
00232 
00233         m_queue.ResetQueue(1, m_firstSize);
00234 }
00235 
00236 void FilterWithBufferedInput::IsolatedInitialize(const NameValuePairs &parameters)
00237 {
00238         InitializeDerivedAndReturnNewSizes(parameters, m_firstSize, m_blockSize, m_lastSize);
00239         if (m_firstSize < 0 || m_blockSize < 1 || m_lastSize < 0)
00240                 throw InvalidArgument("FilterWithBufferedInput: invalid buffer size");
00241         m_queue.ResetQueue(1, m_firstSize);
00242         m_firstInputDone = false;
00243 }
00244 
00245 bool FilterWithBufferedInput::IsolatedFlush(bool hardFlush, bool blocking)
00246 {
00247         if (!blocking)
00248                 throw BlockingInputOnly("FilterWithBufferedInput");
00249         
00250         if (hardFlush)
00251                 ForceNextPut();
00252         FlushDerived();
00253         
00254         return false;
00255 }
00256 
00257 unsigned int FilterWithBufferedInput::PutMaybeModifiable(byte *inString, unsigned int length, int messageEnd, bool blocking, bool modifiable)
00258 {
00259         if (!blocking)
00260                 throw BlockingInputOnly("FilterWithBufferedInput");
00261 
00262         if (length != 0)
00263         {
00264                 unsigned int newLength = m_queue.CurrentSize() + length;
00265 
00266                 if (!m_firstInputDone && newLength >= m_firstSize)
00267                 {
00268                         unsigned int len = m_firstSize - m_queue.CurrentSize();
00269                         m_queue.Put(inString, len);
00270                         FirstPut(m_queue.GetContigousBlocks(m_firstSize));
00271                         assert(m_queue.CurrentSize() == 0);
00272                         m_queue.ResetQueue(m_blockSize, (2*m_blockSize+m_lastSize-2)/m_blockSize);
00273 
00274                         inString += len;
00275                         newLength -= m_firstSize;
00276                         m_firstInputDone = true;
00277                 }
00278 
00279                 if (m_firstInputDone)
00280                 {
00281                         if (m_blockSize == 1)
00282                         {
00283                                 while (newLength > m_lastSize && m_queue.CurrentSize() > 0)
00284                                 {
00285                                         unsigned int len = newLength - m_lastSize;
00286                                         byte *ptr = m_queue.GetContigousBlocks(len);
00287                                         NextPutModifiable(ptr, len);
00288                                         newLength -= len;
00289                                 }
00290 
00291                                 if (newLength > m_lastSize)
00292                                 {
00293                                         unsigned int len = newLength - m_lastSize;
00294                                         NextPutMaybeModifiable(inString, len, modifiable);
00295                                         inString += len;
00296                                         newLength -= len;
00297                                 }
00298                         }
00299                         else
00300                         {
00301                                 while (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() >= m_blockSize)
00302                                 {
00303                                         NextPutModifiable(m_queue.GetBlock(), m_blockSize);
00304                                         newLength -= m_blockSize;
00305                                 }
00306 
00307                                 if (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() > 0)
00308                                 {
00309                                         assert(m_queue.CurrentSize() < m_blockSize);
00310                                         unsigned int len = m_blockSize - m_queue.CurrentSize();
00311                                         m_queue.Put(inString, len);
00312                                         inString += len;
00313                                         NextPutModifiable(m_queue.GetBlock(), m_blockSize);
00314                                         newLength -= m_blockSize;
00315                                 }
00316 
00317                                 if (newLength >= m_blockSize + m_lastSize)
00318                                 {
00319                                         unsigned int len = RoundDownToMultipleOf(newLength - m_lastSize, m_blockSize);
00320                                         NextPutMaybeModifiable(inString, len, modifiable);
00321                                         inString += len;
00322                                         newLength -= len;
00323                                 }
00324                         }
00325                 }
00326 
00327                 m_queue.Put(inString, newLength - m_queue.CurrentSize());
00328         }
00329 
00330         if (messageEnd)
00331         {
00332                 if (!m_firstInputDone && m_firstSize==0)
00333                         FirstPut(NULL);
00334 
00335                 SecByteBlock temp(m_queue.CurrentSize());
00336                 m_queue.GetAll(temp);
00337                 LastPut(temp, temp.size());
00338 
00339                 m_firstInputDone = false;
00340                 m_queue.ResetQueue(1, m_firstSize);
00341 
00342                 Output(1, NULL, 0, messageEnd, blocking);
00343         }
00344         return 0;
00345 }
00346 
00347 void FilterWithBufferedInput::ForceNextPut()
00348 {
00349         if (!m_firstInputDone)
00350                 return;
00351         
00352         if (m_blockSize > 1)
00353         {
00354                 while (m_queue.CurrentSize() >= m_blockSize)
00355                         NextPutModifiable(m_queue.GetBlock(), m_blockSize);
00356         }
00357         else
00358         {
00359                 unsigned int len;
00360                 while ((len = m_queue.CurrentSize()) > 0)
00361                         NextPutModifiable(m_queue.GetContigousBlocks(len), len);
00362         }
00363 }
00364 
00365 void FilterWithBufferedInput::NextPutMultiple(const byte *inString, unsigned int length)
00366 {
00367         assert(m_blockSize > 1);        // m_blockSize = 1 should always override this function
00368         while (length > 0)
00369         {
00370                 assert(length >= m_blockSize);
00371                 NextPutSingle(inString);
00372                 inString += m_blockSize;
00373                 length -= m_blockSize;
00374         }
00375 }
00376 
00377 // *************************************************************
00378 
00379 void Redirector::ChannelInitialize(const std::string &channel, const NameValuePairs &parameters, int propagation)
00380 {
00381         if (channel.empty())
00382         {
00383                 m_target = parameters.GetValueWithDefault("RedirectionTargetPointer", (BufferedTransformation*)NULL);
00384                 m_passSignal = parameters.GetValueWithDefault("PassSignal", true);
00385         }
00386 
00387         if (m_target && m_passSignal)
00388                 m_target->ChannelInitialize(channel, parameters, propagation);
00389 }
00390 
00391 // *************************************************************
00392 
00393 ProxyFilter::ProxyFilter(BufferedTransformation *filter, unsigned int firstSize, unsigned int lastSize, BufferedTransformation *attachment)
00394         : FilterWithBufferedInput(firstSize, 1, lastSize, attachment), m_filter(filter)
00395 {
00396         if (m_filter.get())
00397                 m_filter->Attach(new OutputProxy(*this, false));
00398 }
00399 
00400 bool ProxyFilter::IsolatedFlush(bool hardFlush, bool blocking)
00401 {
00402         return m_filter.get() ? m_filter->Flush(hardFlush, -1, blocking) : false;
00403 }
00404 
00405 void ProxyFilter::SetFilter(Filter *filter)
00406 {
00407         m_filter.reset(filter);
00408         if (filter)
00409         {
00410                 OutputProxy *proxy;
00411                 std::auto_ptr<OutputProxy> temp(proxy = new OutputProxy(*this, false));
00412                 m_filter->TransferAllTo(*proxy);
00413                 m_filter->Attach(temp.release());
00414         }
00415 }
00416 
00417 void ProxyFilter::NextPutMultiple(const byte *s, unsigned int len) 
00418 {
00419         if (m_filter.get())
00420                 m_filter->Put(s, len);
00421 }
00422 
00423 // *************************************************************
00424 
00425 unsigned int ArraySink::Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
00426 {
00427         memcpy(m_buf+m_total, begin, STDMIN(length, SaturatingSubtract(m_size, m_total)));
00428         m_total += length;
00429         return 0;
00430 }
00431 
00432 byte * ArraySink::CreatePutSpace(unsigned int &size)
00433 {
00434         size = m_size - m_total;
00435         return m_buf + m_total;
00436 }
00437 
00438 void ArraySink::IsolatedInitialize(const NameValuePairs &parameters)
00439 {
00440         ByteArrayParameter array;
00441         if (!parameters.GetValue(Name::OutputBuffer(), array))
00442                 throw InvalidArgument("ArraySink: missing OutputBuffer argument");
00443         m_buf = array.begin();
00444         m_size = array.size();
00445         m_total = 0;
00446 }
00447 
00448 unsigned int ArrayXorSink::Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking)
00449 {
00450         xorbuf(m_buf+m_total, begin, STDMIN(length, SaturatingSubtract(m_size, m_total)));
00451         m_total += length;
00452         return 0;
00453 }
00454 
00455 // *************************************************************
00456 
00457 unsigned int StreamTransformationFilter::LastBlockSize(StreamTransformation &c, BlockPaddingScheme padding)
00458 {
00459         if (c.MinLastBlockSize() > 0)
00460                 return c.MinLastBlockSize();
00461         else if (c.MandatoryBlockSize() > 1 && !c.IsForwardTransformation() && padding != NO_PADDING && padding != ZEROS_PADDING)
00462                 return c.MandatoryBlockSize();
00463         else
00464                 return 0;
00465 }
00466 
00467 StreamTransformationFilter::StreamTransformationFilter(StreamTransformation &c, BufferedTransformation *attachment, BlockPaddingScheme padding)
00468    : FilterWithBufferedInput(0, c.MandatoryBlockSize(), LastBlockSize(c, padding), attachment)
00469         , m_cipher(c)
00470 {
00471         assert(c.MinLastBlockSize() == 0 || c.MinLastBlockSize() > c.MandatoryBlockSize());
00472 
00473         bool isBlockCipher = (c.MandatoryBlockSize() > 1 && c.MinLastBlockSize() == 0);
00474 
00475         if (padding == DEFAULT_PADDING)
00476         {
00477                 if (isBlockCipher)
00478                         m_padding = PKCS_PADDING;
00479                 else
00480                         m_padding = NO_PADDING;
00481         }
00482         else
00483                 m_padding = padding;
00484 
00485         if (!isBlockCipher && (m_padding == PKCS_PADDING || m_padding == ONE_AND_ZEROS_PADDING))
00486                 throw InvalidArgument("StreamTransformationFilter: PKCS_PADDING and ONE_AND_ZEROS_PADDING cannot be used with " + c.AlgorithmName());
00487 }
00488 
00489 void StreamTransformationFilter::FirstPut(const byte *inString)
00490 {
00491         m_optimalBufferSize = m_cipher.OptimalBlockSize();
00492         m_optimalBufferSize = STDMAX(m_optimalBufferSize, RoundDownToMultipleOf(4096U, m_optimalBufferSize));
00493 }
00494 
00495 void StreamTransformationFilter::NextPutMultiple(const byte *inString, unsigned int length)
00496 {
00497         if (!length)
00498                 return;
00499 
00500         unsigned int s = m_cipher.MandatoryBlockSize();
00501 
00502         do
00503         {
00504                 unsigned int len = m_optimalBufferSize;
00505                 byte *space = HelpCreatePutSpace(*AttachedTransformation(), NULL_CHANNEL, s, length, len);
00506                 if (len < length)
00507                 {
00508                         if (len == m_optimalBufferSize)
00509                                 len -= m_cipher.GetOptimalBlockSizeUsed();
00510                         len = RoundDownToMultipleOf(len, s);
00511                 }
00512                 else
00513                         len = length;
00514                 m_cipher.ProcessString(space, inString, len);
00515                 AttachedTransformation()->PutModifiable(space, len);
00516                 inString += len;
00517                 length -= len;
00518         }
00519         while (length > 0);
00520 }
00521 
00522 void StreamTransformationFilter::NextPutModifiable(byte *inString, unsigned int length)
00523 {
00524         m_cipher.ProcessString(inString, length);
00525         AttachedTransformation()->PutModifiable(inString, length);
00526 }
00527 
00528 void StreamTransformationFilter::LastPut(const byte *inString, unsigned int length)
00529 {
00530         byte *space = NULL;
00531         
00532         switch (m_padding)
00533         {
00534         case NO_PADDING:
00535         case ZEROS_PADDING:
00536                 if (length > 0)
00537                 {
00538                         unsigned int minLastBlockSize = m_cipher.MinLastBlockSize();
00539                         bool isForwardTransformation = m_cipher.IsForwardTransformation();
00540 
00541                         if (isForwardTransformation && m_padding == ZEROS_PADDING && (minLastBlockSize == 0 || length < minLastBlockSize))
00542                         {
00543                                 // do padding
00544                                 unsigned int blockSize = STDMAX(minLastBlockSize, m_cipher.MandatoryBlockSize());
00545                                 space = HelpCreatePutSpace(*AttachedTransformation(), NULL_CHANNEL, blockSize);
00546                                 memcpy(space, inString, length);
00547                                 memset(space + length, 0, blockSize - length);
00548                                 m_cipher.ProcessLastBlock(space, space, blockSize);
00549                                 AttachedTransformation()->Put(space, blockSize);
00550                         }
00551                         else
00552                         {
00553                                 if (minLastBlockSize == 0)
00554                                 {
00555                                         if (isForwardTransformation)
00556                                                 throw InvalidDataFormat("StreamTransformationFilter: plaintext length is not a multiple of block size and NO_PADDING is specified");
00557                                         else
00558                                                 throw InvalidCiphertext("StreamTransformationFilter: ciphertext length is not a multiple of block size");
00559                                 }
00560 
00561                                 space = HelpCreatePutSpace(*AttachedTransformation(), NULL_CHANNEL, length, m_optimalBufferSize);
00562                                 m_cipher.ProcessLastBlock(space, inString, length);
00563                                 AttachedTransformation()->Put(space, length);
00564                         }
00565                 }
00566                 break;
00567 
00568         case PKCS_PADDING:
00569         case ONE_AND_ZEROS_PADDING:
00570                 unsigned int s;
00571                 s = m_cipher.MandatoryBlockSize();
00572                 assert(s > 1);
00573                 space = HelpCreatePutSpace(*AttachedTransformation(), NULL_CHANNEL, s, m_optimalBufferSize);
00574                 if (m_cipher.IsForwardTransformation())
00575                 {
00576                         assert(length < s);
00577                         memcpy(space, inString, length);
00578                         if (m_padding == PKCS_PADDING)
00579                         {
00580                                 assert(s < 256);
00581                                 byte pad = s-length;
00582                                 memset(space+length, pad, s-length);
00583                         }
00584                         else
00585                         {
00586                                 space[length] = 1;
00587                                 memset(space+length+1, 0, s-length-1);
00588                         }
00589                         m_cipher.ProcessData(space, space, s);
00590                         AttachedTransformation()->Put(space, s);
00591                 }
00592                 else
00593                 {
00594                         if (length != s)
00595                                 throw InvalidCiphertext("StreamTransformationFilter: ciphertext length is not a multiple of block size");
00596                         m_cipher.ProcessData(space, inString, s);
00597                         if (m_padding == PKCS_PADDING)
00598                         {
00599                                 byte pad = space[s-1];
00600                                 if (pad < 1 || pad > s || std::find_if(space+s-pad, space+s, std::bind2nd(std::not_equal_to<byte>(), pad)) != space+s)
00601                                         throw InvalidCiphertext("StreamTransformationFilter: invalid PKCS #7 block padding found");
00602                                 length = s-pad;
00603                         }
00604                         else
00605                         {
00606                                 while (length > 1 && space[length-1] == '\0')
00607                                         --length;
00608                                 if (space[--length] != '\1')
00609                                         throw InvalidCiphertext("StreamTransformationFilter: invalid ones-and-zeros padding found");
00610                         }
00611                         AttachedTransformation()->Put(space, length);
00612                 }
00613                 break;
00614 
00615         default:
00616                 assert(false);
00617         }
00618 }
00619 
00620 // *************************************************************
00621 
00622 void HashFilter::IsolatedInitialize(const NameValuePairs &parameters)
00623 {
00624         m_putMessage = parameters.GetValueWithDefault(Name::PutMessage(), false);
00625         m_hashModule.Restart();
00626 }
00627 
00628 unsigned int HashFilter::Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking)
00629 {
00630         FILTER_BEGIN;
00631         m_hashModule.Update(inString, length);
00632         if (m_putMessage)
00633                 FILTER_OUTPUT(1, inString, length, 0);
00634         if (messageEnd)
00635         {
00636                 {
00637                         unsigned int size, digestSize = m_hashModule.DigestSize();
00638                         m_space = HelpCreatePutSpace(*AttachedTransformation(), NULL_CHANNEL, digestSize, digestSize, size = digestSize);
00639                         m_hashModule.Final(m_space);
00640                 }
00641                 FILTER_OUTPUT(2, m_space, m_hashModule.DigestSize(), messageEnd);
00642         }
00643         FILTER_END_NO_MESSAGE_END;
00644 }
00645 
00646 // *************************************************************
00647 
00648 HashVerificationFilter::HashVerificationFilter(HashTransformation &hm, BufferedTransformation *attachment, word32 flags)
00649         : FilterWithBufferedInput(attachment)
00650         , m_hashModule(hm)
00651 {
00652         IsolatedInitialize(MakeParameters(Name::HashVerificationFilterFlags(), flags));
00653 }
00654 
00655 void HashVerificationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, unsigned int &firstSize, unsigned int &blockSize, unsigned int &lastSize)
00656 {
00657         m_flags = parameters.GetValueWithDefault(Name::HashVerificationFilterFlags(), (word32)DEFAULT_FLAGS);
00658         m_hashModule.Restart();
00659         unsigned int size = m_hashModule.DigestSize();
00660         m_verified = false;
00661         firstSize = m_flags & HASH_AT_BEGIN ? size : 0;
00662         blockSize = 1;
00663         lastSize = m_flags & HASH_AT_BEGIN ? 0 : size;
00664 }
00665 
00666 void HashVerificationFilter::FirstPut(const byte *inString)
00667 {
00668         if (m_flags & HASH_AT_BEGIN)
00669         {
00670                 m_expectedHash.New(m_hashModule.DigestSize());
00671                 memcpy(m_expectedHash, inString, m_expectedHash.size());
00672                 if (m_flags & PUT_HASH)
00673                         AttachedTransformation()->Put(inString, m_expectedHash.size());
00674         }
00675 }
00676 
00677 void HashVerificationFilter::NextPutMultiple(const byte *inString, unsigned int length)
00678 {
00679         m_hashModule.Update(inString, length);
00680         if (m_flags & PUT_MESSAGE)
00681                 AttachedTransformation()->Put(inString, length);
00682 }
00683 
00684 void HashVerificationFilter::LastPut(const byte *inString, unsigned int length)
00685 {
00686         if (m_flags & HASH_AT_BEGIN)
00687         {
00688                 assert(length == 0);
00689                 m_verified = m_hashModule.Verify(m_expectedHash);
00690         }
00691         else
00692         {
00693                 m_verified = (length==m_hashModule.DigestSize() && m_hashModule.Verify(inString));
00694                 if (m_flags & PUT_HASH)
00695                         AttachedTransformation()->Put(inString, length);
00696         }
00697 
00698         if (m_flags & PUT_RESULT)
00699                 AttachedTransformation()->Put(m_verified);
00700 
00701         if ((m_flags & THROW_EXCEPTION) && !m_verified)
00702                 throw HashVerificationFailed();
00703 }
00704 
00705 // *************************************************************
00706 
00707 void SignerFilter::IsolatedInitialize(const NameValuePairs &parameters)
00708 {
00709         m_putMessage = parameters.GetValueWithDefault(Name::PutMessage(), false);
00710         m_messageAccumulator.reset(m_signer.NewSignatureAccumulator());
00711 }
00712 
00713 unsigned int SignerFilter::Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking)
00714 {
00715         FILTER_BEGIN;
00716         m_messageAccumulator->Update(inString, length);
00717         if (m_putMessage)
00718                 FILTER_OUTPUT(1, inString, length, 0);
00719         if (messageEnd)
00720         {
00721                 m_buf.New(m_signer.SignatureLength());
00722                 m_signer.Sign(m_rng, m_messageAccumulator.release(), m_buf);
00723                 FILTER_OUTPUT(2, m_buf, m_buf.size(), messageEnd);
00724                 m_messageAccumulator.reset(m_signer.NewSignatureAccumulator());
00725         }
00726         FILTER_END_NO_MESSAGE_END;
00727 }
00728 
00729 SignatureVerificationFilter::SignatureVerificationFilter(const PK_Verifier &verifier, BufferedTransformation *attachment, word32 flags)
00730         : FilterWithBufferedInput(attachment)
00731         , m_verifier(verifier)
00732 {
00733         IsolatedInitialize(MakeParameters(Name::SignatureVerificationFilterFlags(), flags));
00734 }
00735 
00736 void SignatureVerificationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, unsigned int &firstSize, unsigned int &blockSize, unsigned int &lastSize)
00737 {
00738         m_flags = parameters.GetValueWithDefault(Name::SignatureVerificationFilterFlags(), (word32)DEFAULT_FLAGS);
00739         m_messageAccumulator.reset(m_verifier.NewVerificationAccumulator());
00740         unsigned int size =     m_verifier.SignatureLength();
00741         assert(size != 0);      // TODO: handle recoverable signature scheme
00742         m_verified = false;
00743         firstSize = m_flags & SIGNATURE_AT_BEGIN ? size : 0;
00744         blockSize = 1;
00745         lastSize = m_flags & SIGNATURE_AT_BEGIN ? 0 : size;
00746 }
00747 
00748 void SignatureVerificationFilter::FirstPut(const byte *inString)
00749 {
00750         if (m_flags & SIGNATURE_AT_BEGIN)
00751         {
00752                 if (m_verifier.SignatureUpfront())
00753                         m_verifier.InputSignature(*m_messageAccumulator, inString, m_verifier.SignatureLength());
00754                 else
00755                 {
00756                         m_signature.New(m_verifier.SignatureLength());
00757                         memcpy(m_signature, inString, m_signature.size());
00758                 }
00759 
00760                 if (m_flags & PUT_SIGNATURE)
00761                         AttachedTransformation()->Put(inString, m_signature.size());
00762         }
00763         else
00764         {
00765                 assert(!m_verifier.SignatureUpfront());
00766         }
00767 }
00768 
00769 void SignatureVerificationFilter::NextPutMultiple(const byte *inString, unsigned int length)
00770 {
00771         m_messageAccumulator->Update(inString, length);
00772         if (m_flags & PUT_MESSAGE)
00773                 AttachedTransformation()->Put(inString, length);
00774 }
00775 
00776 void SignatureVerificationFilter::LastPut(const byte *inString, unsigned int length)
00777 {
00778         if (m_flags & SIGNATURE_AT_BEGIN)
00779         {
00780                 assert(length == 0);
00781                 m_verifier.InputSignature(*m_messageAccumulator, m_signature, m_signature.size());
00782                 m_verified = m_verifier.VerifyAndRestart(*m_messageAccumulator);
00783         }
00784         else
00785         {
00786                 m_verifier.InputSignature(*m_messageAccumulator, inString, length);
00787                 m_verified = m_verifier.VerifyAndRestart(*m_messageAccumulator);
00788                 if (m_flags & PUT_SIGNATURE)
00789                         AttachedTransformation()->Put(inString, length);
00790         }
00791 
00792         if (m_flags & PUT_RESULT)
00793                 AttachedTransformation()->Put(m_verified);
00794 
00795         if ((m_flags & THROW_EXCEPTION) && !m_verified)
00796                 throw SignatureVerificationFailed();
00797 }
00798 
00799 // *************************************************************
00800 
00801 unsigned int Source::PumpAll2(bool blocking)
00802 {
00803         // TODO: switch length type
00804         unsigned long i = UINT_MAX;
00805         RETURN_IF_NONZERO(Pump2(i, blocking));
00806         unsigned int j = UINT_MAX;
00807         return PumpMessages2(j, blocking);
00808 }
00809 
00810 bool Store::GetNextMessage()
00811 {
00812         if (!m_messageEnd && !AnyRetrievable())
00813         {
00814                 m_messageEnd=true;
00815                 return true;
00816         }
00817         else
00818                 return false;
00819 }
00820 
00821 unsigned int Store::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const
00822 {
00823         if (m_messageEnd || count == 0)
00824                 return 0;
00825         else
00826         {
00827                 CopyTo(target, ULONG_MAX, channel);
00828                 if (GetAutoSignalPropagation())
00829                         target.ChannelMessageEnd(channel, GetAutoSignalPropagation()-1);
00830                 return 1;
00831         }
00832 }
00833 
00834 void StringStore::StoreInitialize(const NameValuePairs &parameters)
00835 {
00836         ConstByteArrayParameter array;
00837         if (!parameters.GetValue(Name::InputBuffer(), array))
00838                 throw InvalidArgument("StringStore: missing InputBuffer argument");
00839         m_store = array.begin();
00840         m_length = array.size();
00841         m_count = 0;
00842 }
00843 
00844 unsigned int StringStore::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking)
00845 {
00846         unsigned long position = 0;
00847         unsigned int blockedBytes = CopyRangeTo2(target, position, transferBytes, channel, blocking);
00848         m_count += position;
00849         transferBytes = position;
00850         return blockedBytes;
00851 }
00852 
00853 unsigned int StringStore::CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end, const std::string &channel, bool blocking) const
00854 {
00855         unsigned int i = (unsigned int)STDMIN((unsigned long)m_count+begin, (unsigned long)m_length);
00856         unsigned int len = (unsigned int)STDMIN((unsigned long)m_length-i, end-begin);
00857         unsigned int blockedBytes = target.ChannelPut2(channel, m_store+i, len, 0, blocking);
00858         if (!blockedBytes)
00859                 begin += len;
00860         return blockedBytes;
00861 }
00862 
00863 unsigned int RandomNumberStore::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking)
00864 {
00865         if (!blocking)
00866                 throw NotImplemented("RandomNumberStore: nonblocking transfer is not implemented by this object");
00867 
00868         unsigned long transferMax = transferBytes;
00869         for (transferBytes = 0; transferBytes<transferMax && m_count < m_length; ++transferBytes, ++m_count)
00870                 target.ChannelPut(channel, m_rng.GenerateByte());
00871         return 0;
00872 }
00873 
00874 unsigned int NullStore::CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end, const std::string &channel, bool blocking) const
00875 {
00876         static const byte nullBytes[128] = {0};
00877         while (begin < end)
00878         {
00879                 unsigned int len = STDMIN(end-begin, 128UL);
00880                 unsigned int blockedBytes = target.ChannelPut2(channel, nullBytes, len, 0, blocking);
00881                 if (blockedBytes)
00882                         return blockedBytes;
00883                 begin += len;
00884         }
00885         return 0;
00886 }
00887 
00888 unsigned int NullStore::TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel, bool blocking)
00889 {
00890         unsigned long begin = 0;
00891         unsigned int blockedBytes = NullStore::CopyRangeTo2(target, begin, transferBytes, channel, blocking);
00892         transferBytes = begin;
00893         m_size -= begin;
00894         return blockedBytes;
00895 }
00896 
00897 NAMESPACE_END

Generated on Sun Mar 14 20:44:25 2004 for Crypto++ by doxygen 1.3.6-20040222