Crypto++
filters.h
Go to the documentation of this file.
00001 #ifndef CRYPTOPP_FILTERS_H
00002 #define CRYPTOPP_FILTERS_H
00003 
00004 //! \file
00005 
00006 #include "simple.h"
00007 #include "secblock.h"
00008 #include "misc.h"
00009 #include "smartptr.h"
00010 #include "queue.h"
00011 #include "algparam.h"
00012 #include <deque>
00013 
00014 NAMESPACE_BEGIN(CryptoPP)
00015 
00016 /// provides an implementation of BufferedTransformation's attachment interface
00017 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Filter : public BufferedTransformation, public NotCopyable
00018 {
00019 public:
00020     Filter(BufferedTransformation *attachment = NULL);
00021 
00022     bool Attachable() {return true;}
00023     BufferedTransformation *AttachedTransformation();
00024     const BufferedTransformation *AttachedTransformation() const;
00025     void Detach(BufferedTransformation *newAttachment = NULL);
00026 
00027     size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
00028     size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
00029 
00030     void Initialize(const NameValuePairs &parameters=g_nullNameValuePairs, int propagation=-1);
00031     bool Flush(bool hardFlush, int propagation=-1, bool blocking=true);
00032     bool MessageSeriesEnd(int propagation=-1, bool blocking=true);
00033 
00034 protected:
00035     virtual BufferedTransformation * NewDefaultAttachment() const;
00036     void Insert(Filter *nextFilter);    // insert filter after this one
00037 
00038     virtual bool ShouldPropagateMessageEnd() const {return true;}
00039     virtual bool ShouldPropagateMessageSeriesEnd() const {return true;}
00040 
00041     void PropagateInitialize(const NameValuePairs &parameters, int propagation);
00042 
00043     size_t Output(int outputSite, const byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel=DEFAULT_CHANNEL);
00044     size_t OutputModifiable(int outputSite, byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel=DEFAULT_CHANNEL);
00045     bool OutputMessageEnd(int outputSite, int propagation, bool blocking, const std::string &channel=DEFAULT_CHANNEL);
00046     bool OutputFlush(int outputSite, bool hardFlush, int propagation, bool blocking, const std::string &channel=DEFAULT_CHANNEL);
00047     bool OutputMessageSeriesEnd(int outputSite, int propagation, bool blocking, const std::string &channel=DEFAULT_CHANNEL);
00048 
00049 private:
00050     member_ptr<BufferedTransformation> m_attachment;
00051     
00052 protected:
00053     size_t m_inputPosition;
00054     int m_continueAt;
00055 };
00056 
00057 struct CRYPTOPP_DLL FilterPutSpaceHelper
00058 {
00059     // desiredSize is how much to ask target, bufferSize is how much to allocate in m_tempSpace
00060     byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, size_t minSize, size_t desiredSize, size_t &bufferSize)
00061     {
00062         assert(desiredSize >= minSize && bufferSize >= minSize);
00063         if (m_tempSpace.size() < minSize)
00064         {
00065             byte *result = target.ChannelCreatePutSpace(channel, desiredSize);
00066             if (desiredSize >= minSize)
00067             {
00068                 bufferSize = desiredSize;
00069                 return result;
00070             }
00071             m_tempSpace.New(bufferSize);
00072         }
00073 
00074         bufferSize = m_tempSpace.size();
00075         return m_tempSpace.begin();
00076     }
00077     byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, size_t minSize)
00078         {return HelpCreatePutSpace(target, channel, minSize, minSize, minSize);}
00079     byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, size_t minSize, size_t bufferSize)
00080         {return HelpCreatePutSpace(target, channel, minSize, minSize, bufferSize);}
00081     SecByteBlock m_tempSpace;
00082 };
00083 
00084 //! measure how many byte and messages pass through, also serves as valve
00085 class CRYPTOPP_DLL MeterFilter : public Bufferless<Filter>
00086 {
00087 public:
00088     MeterFilter(BufferedTransformation *attachment=NULL, bool transparent=true)
00089         : m_transparent(transparent) {Detach(attachment); ResetMeter();}
00090 
00091     void SetTransparent(bool transparent) {m_transparent = transparent;}
00092     void AddRangeToSkip(unsigned int message, lword position, lword size, bool sortNow = true);
00093     void ResetMeter();
00094     void IsolatedInitialize(const NameValuePairs &parameters) {ResetMeter();}
00095 
00096     lword GetCurrentMessageBytes() const {return m_currentMessageBytes;}
00097     lword GetTotalBytes() {return m_totalBytes;}
00098     unsigned int GetCurrentSeriesMessages() {return m_currentSeriesMessages;}
00099     unsigned int GetTotalMessages() {return m_totalMessages;}
00100     unsigned int GetTotalMessageSeries() {return m_totalMessageSeries;}
00101 
00102     byte * CreatePutSpace(size_t &size)
00103         {return AttachedTransformation()->CreatePutSpace(size);}
00104     size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
00105     size_t PutModifiable2(byte *inString, size_t length, int messageEnd, bool blocking);
00106     bool IsolatedMessageSeriesEnd(bool blocking);
00107 
00108 private:
00109     size_t PutMaybeModifiable(byte *inString, size_t length, int messageEnd, bool blocking, bool modifiable);
00110     bool ShouldPropagateMessageEnd() const {return m_transparent;}
00111     bool ShouldPropagateMessageSeriesEnd() const {return m_transparent;}
00112 
00113     struct MessageRange
00114     {
00115         inline bool operator<(const MessageRange &b) const  // BCB2006 workaround: this has to be a member function
00116             {return message < b.message || (message == b.message && position < b.position);}
00117         unsigned int message; lword position; lword size;
00118     };
00119 
00120     bool m_transparent;
00121     lword m_currentMessageBytes, m_totalBytes;
00122     unsigned int m_currentSeriesMessages, m_totalMessages, m_totalMessageSeries;
00123     std::deque<MessageRange> m_rangesToSkip;
00124     byte *m_begin;
00125     size_t m_length;
00126 };
00127 
00128 //! _
00129 class CRYPTOPP_DLL TransparentFilter : public MeterFilter
00130 {
00131 public:
00132     TransparentFilter(BufferedTransformation *attachment=NULL) : MeterFilter(attachment, true) {}
00133 };
00134 
00135 //! _
00136 class CRYPTOPP_DLL OpaqueFilter : public MeterFilter
00137 {
00138 public:
00139     OpaqueFilter(BufferedTransformation *attachment=NULL) : MeterFilter(attachment, false) {}
00140 };
00141 
00142 /*! FilterWithBufferedInput divides up the input stream into
00143     a first block, a number of middle blocks, and a last block.
00144     First and last blocks are optional, and middle blocks may
00145     be a stream instead (i.e. blockSize == 1).
00146 */
00147 class CRYPTOPP_DLL FilterWithBufferedInput : public Filter
00148 {
00149 public:
00150     FilterWithBufferedInput(BufferedTransformation *attachment);
00151     //! firstSize and lastSize may be 0, blockSize must be at least 1
00152     FilterWithBufferedInput(size_t firstSize, size_t blockSize, size_t lastSize, BufferedTransformation *attachment);
00153 
00154     void IsolatedInitialize(const NameValuePairs &parameters);
00155     size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
00156     {
00157         return PutMaybeModifiable(const_cast<byte *>(inString), length, messageEnd, blocking, false);
00158     }
00159     size_t PutModifiable2(byte *inString, size_t length, int messageEnd, bool blocking)
00160     {
00161         return PutMaybeModifiable(inString, length, messageEnd, blocking, true);
00162     }
00163     /*! calls ForceNextPut() if hardFlush is true */
00164     bool IsolatedFlush(bool hardFlush, bool blocking);
00165 
00166     /*! The input buffer may contain more than blockSize bytes if lastSize != 0.
00167         ForceNextPut() forces a call to NextPut() if this is the case.
00168     */
00169     void ForceNextPut();
00170 
00171 protected:
00172     bool DidFirstPut() {return m_firstInputDone;}
00173 
00174     virtual void InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
00175         {InitializeDerived(parameters);}
00176     virtual void InitializeDerived(const NameValuePairs &parameters) {}
00177     // FirstPut() is called if (firstSize != 0 and totalLength >= firstSize)
00178     // or (firstSize == 0 and (totalLength > 0 or a MessageEnd() is received))
00179     virtual void FirstPut(const byte *inString) =0;
00180     // NextPut() is called if totalLength >= firstSize+blockSize+lastSize
00181     virtual void NextPutSingle(const byte *inString) {assert(false);}
00182     // Same as NextPut() except length can be a multiple of blockSize
00183     // Either NextPut() or NextPutMultiple() must be overriden
00184     virtual void NextPutMultiple(const byte *inString, size_t length);
00185     // Same as NextPutMultiple(), but inString can be modified
00186     virtual void NextPutModifiable(byte *inString, size_t length)
00187         {NextPutMultiple(inString, length);}
00188     // LastPut() is always called
00189     // if totalLength < firstSize then length == totalLength
00190     // else if totalLength <= firstSize+lastSize then length == totalLength-firstSize
00191     // else lastSize <= length < lastSize+blockSize
00192     virtual void LastPut(const byte *inString, size_t length) =0;
00193     virtual void FlushDerived() {}
00194 
00195 protected:
00196     size_t PutMaybeModifiable(byte *begin, size_t length, int messageEnd, bool blocking, bool modifiable);
00197     void NextPutMaybeModifiable(byte *inString, size_t length, bool modifiable)
00198     {
00199         if (modifiable) NextPutModifiable(inString, length);
00200         else NextPutMultiple(inString, length);
00201     }
00202 
00203     // This function should no longer be used, put this here to cause a compiler error
00204     // if someone tries to override NextPut().
00205     virtual int NextPut(const byte *inString, size_t length) {assert(false); return 0;}
00206 
00207     class BlockQueue
00208     {
00209     public:
00210         void ResetQueue(size_t blockSize, size_t maxBlocks);
00211         byte *GetBlock();
00212         byte *GetContigousBlocks(size_t &numberOfBytes);
00213         size_t GetAll(byte *outString);
00214         void Put(const byte *inString, size_t length);
00215         size_t CurrentSize() const {return m_size;}
00216         size_t MaxSize() const {return m_buffer.size();}
00217 
00218     private:
00219         SecByteBlock m_buffer;
00220         size_t m_blockSize, m_maxBlocks, m_size;
00221         byte *m_begin;
00222     };
00223 
00224     size_t m_firstSize, m_blockSize, m_lastSize;
00225     bool m_firstInputDone;
00226     BlockQueue m_queue;
00227 };
00228 
00229 //! _
00230 class CRYPTOPP_DLL FilterWithInputQueue : public Filter
00231 {
00232 public:
00233     FilterWithInputQueue(BufferedTransformation *attachment=NULL) : Filter(attachment) {}
00234 
00235     size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
00236     {
00237         if (!blocking)
00238             throw BlockingInputOnly("FilterWithInputQueue");
00239         
00240         m_inQueue.Put(inString, length);
00241         if (messageEnd)
00242         {
00243             IsolatedMessageEnd(blocking);
00244             Output(0, NULL, 0, messageEnd, blocking);
00245         }
00246         return 0;
00247     }
00248 
00249 protected:
00250     virtual bool IsolatedMessageEnd(bool blocking) =0;
00251     void IsolatedInitialize(const NameValuePairs &parameters) {m_inQueue.Clear();}
00252 
00253     ByteQueue m_inQueue;
00254 };
00255 
00256 struct BlockPaddingSchemeDef
00257 {
00258     enum BlockPaddingScheme {NO_PADDING, ZEROS_PADDING, PKCS_PADDING, ONE_AND_ZEROS_PADDING, DEFAULT_PADDING};
00259 };
00260 
00261 //! Filter Wrapper for StreamTransformation, optionally handling padding/unpadding when needed
00262 class CRYPTOPP_DLL StreamTransformationFilter : public FilterWithBufferedInput, public BlockPaddingSchemeDef, private FilterPutSpaceHelper
00263 {
00264 public:
00265     /*! DEFAULT_PADDING means PKCS_PADDING if c.MandatoryBlockSize() > 1 && c.MinLastBlockSize() == 0 (e.g. ECB or CBC mode),
00266         otherwise NO_PADDING (OFB, CFB, CTR, CBC-CTS modes).
00267         See http://www.weidai.com/scan-mirror/csp.html for details of the padding schemes. */
00268     StreamTransformationFilter(StreamTransformation &c, BufferedTransformation *attachment = NULL, BlockPaddingScheme padding = DEFAULT_PADDING, bool allowAuthenticatedSymmetricCipher = false);
00269 
00270     std::string AlgorithmName() const {return m_cipher.AlgorithmName();}
00271 
00272 protected:
00273     void InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize);
00274     void FirstPut(const byte *inString);
00275     void NextPutMultiple(const byte *inString, size_t length);
00276     void NextPutModifiable(byte *inString, size_t length);
00277     void LastPut(const byte *inString, size_t length);
00278 
00279     static size_t LastBlockSize(StreamTransformation &c, BlockPaddingScheme padding);
00280 
00281     StreamTransformation &m_cipher;
00282     BlockPaddingScheme m_padding;
00283     unsigned int m_optimalBufferSize;
00284 };
00285 
00286 #ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
00287 typedef StreamTransformationFilter StreamCipherFilter;
00288 #endif
00289 
00290 //! Filter Wrapper for HashTransformation
00291 class CRYPTOPP_DLL HashFilter : public Bufferless<Filter>, private FilterPutSpaceHelper
00292 {
00293 public:
00294     HashFilter(HashTransformation &hm, BufferedTransformation *attachment = NULL, bool putMessage=false, int truncatedDigestSize=-1, const std::string &messagePutChannel=DEFAULT_CHANNEL, const std::string &hashPutChannel=DEFAULT_CHANNEL);
00295 
00296     std::string AlgorithmName() const {return m_hashModule.AlgorithmName();}
00297     void IsolatedInitialize(const NameValuePairs &parameters);
00298     size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
00299     byte * CreatePutSpace(size_t &size) {return m_hashModule.CreateUpdateSpace(size);}
00300 
00301 private:
00302     HashTransformation &m_hashModule;
00303     bool m_putMessage;
00304     unsigned int m_digestSize;
00305     byte *m_space;
00306     std::string m_messagePutChannel, m_hashPutChannel;
00307 };
00308 
00309 //! Filter Wrapper for HashTransformation
00310 class CRYPTOPP_DLL HashVerificationFilter : public FilterWithBufferedInput
00311 {
00312 public:
00313     class HashVerificationFailed : public Exception
00314     {
00315     public:
00316         HashVerificationFailed()
00317             : Exception(DATA_INTEGRITY_CHECK_FAILED, "HashVerificationFilter: message hash or MAC not valid") {}
00318     };
00319 
00320     enum Flags {HASH_AT_END=0, HASH_AT_BEGIN=1, PUT_MESSAGE=2, PUT_HASH=4, PUT_RESULT=8, THROW_EXCEPTION=16, DEFAULT_FLAGS = HASH_AT_BEGIN | PUT_RESULT};
00321     HashVerificationFilter(HashTransformation &hm, BufferedTransformation *attachment = NULL, word32 flags = DEFAULT_FLAGS, int truncatedDigestSize=-1);
00322 
00323     std::string AlgorithmName() const {return m_hashModule.AlgorithmName();}
00324     bool GetLastResult() const {return m_verified;}
00325 
00326 protected:
00327     void InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize);
00328     void FirstPut(const byte *inString);
00329     void NextPutMultiple(const byte *inString, size_t length);
00330     void LastPut(const byte *inString, size_t length);
00331 
00332 private:
00333     friend class AuthenticatedDecryptionFilter;
00334 
00335     HashTransformation &m_hashModule;
00336     word32 m_flags;
00337     unsigned int m_digestSize;
00338     bool m_verified;
00339     SecByteBlock m_expectedHash;
00340 };
00341 
00342 typedef HashVerificationFilter HashVerifier;    // for backwards compatibility
00343 
00344 //! Filter wrapper for encrypting with AuthenticatedSymmetricCipher, optionally handling padding/unpadding when needed
00345 /*! Additional authenticated data should be given in channel "AAD". If putAAD is true, AAD will be Put() to the attached BufferedTransformation in channel "AAD". */
00346 class CRYPTOPP_DLL AuthenticatedEncryptionFilter : public StreamTransformationFilter
00347 {
00348 public:
00349     /*! See StreamTransformationFilter for documentation on BlockPaddingScheme  */
00350     AuthenticatedEncryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment = NULL, bool putAAD=false, int truncatedDigestSize=-1, const std::string &macChannel=DEFAULT_CHANNEL, BlockPaddingScheme padding = DEFAULT_PADDING);
00351 
00352     void IsolatedInitialize(const NameValuePairs &parameters);
00353     byte * ChannelCreatePutSpace(const std::string &channel, size_t &size);
00354     size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking);
00355     void LastPut(const byte *inString, size_t length);
00356 
00357 protected:
00358     HashFilter m_hf;
00359 };
00360 
00361 //! Filter wrapper for decrypting with AuthenticatedSymmetricCipher, optionally handling padding/unpadding when needed
00362 /*! Additional authenticated data should be given in channel "AAD". */
00363 class CRYPTOPP_DLL AuthenticatedDecryptionFilter : public FilterWithBufferedInput, public BlockPaddingSchemeDef
00364 {
00365 public:
00366     enum Flags {MAC_AT_END=0, MAC_AT_BEGIN=1, THROW_EXCEPTION=16, DEFAULT_FLAGS = THROW_EXCEPTION};
00367 
00368     /*! See StreamTransformationFilter for documentation on BlockPaddingScheme  */
00369     AuthenticatedDecryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment = NULL, word32 flags = DEFAULT_FLAGS, int truncatedDigestSize=-1, BlockPaddingScheme padding = DEFAULT_PADDING);
00370 
00371     std::string AlgorithmName() const {return m_hashVerifier.AlgorithmName();}
00372     byte * ChannelCreatePutSpace(const std::string &channel, size_t &size);
00373     size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking);
00374     bool GetLastResult() const {return m_hashVerifier.GetLastResult();}
00375 
00376 protected:
00377     void InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize);
00378     void FirstPut(const byte *inString);
00379     void NextPutMultiple(const byte *inString, size_t length);
00380     void LastPut(const byte *inString, size_t length);
00381 
00382     HashVerificationFilter m_hashVerifier;
00383     StreamTransformationFilter m_streamFilter;
00384 };
00385 
00386 //! Filter Wrapper for PK_Signer
00387 class CRYPTOPP_DLL SignerFilter : public Unflushable<Filter>
00388 {
00389 public:
00390     SignerFilter(RandomNumberGenerator &rng, const PK_Signer &signer, BufferedTransformation *attachment = NULL, bool putMessage=false)
00391         : m_rng(rng), m_signer(signer), m_messageAccumulator(signer.NewSignatureAccumulator(rng)), m_putMessage(putMessage) {Detach(attachment);}
00392 
00393     std::string AlgorithmName() const {return m_signer.AlgorithmName();}
00394 
00395     void IsolatedInitialize(const NameValuePairs &parameters);
00396     size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
00397 
00398 private:
00399     RandomNumberGenerator &m_rng;
00400     const PK_Signer &m_signer;
00401     member_ptr<PK_MessageAccumulator> m_messageAccumulator;
00402     bool m_putMessage;
00403     SecByteBlock m_buf;
00404 };
00405 
00406 //! Filter Wrapper for PK_Verifier
00407 class CRYPTOPP_DLL SignatureVerificationFilter : public FilterWithBufferedInput
00408 {
00409 public:
00410     class SignatureVerificationFailed : public Exception
00411     {
00412     public:
00413         SignatureVerificationFailed()
00414             : Exception(DATA_INTEGRITY_CHECK_FAILED, "VerifierFilter: digital signature not valid") {}
00415     };
00416 
00417     enum Flags {SIGNATURE_AT_END=0, SIGNATURE_AT_BEGIN=1, PUT_MESSAGE=2, PUT_SIGNATURE=4, PUT_RESULT=8, THROW_EXCEPTION=16, DEFAULT_FLAGS = SIGNATURE_AT_BEGIN | PUT_RESULT};
00418     SignatureVerificationFilter(const PK_Verifier &verifier, BufferedTransformation *attachment = NULL, word32 flags = DEFAULT_FLAGS);
00419 
00420     std::string AlgorithmName() const {return m_verifier.AlgorithmName();}
00421 
00422     bool GetLastResult() const {return m_verified;}
00423 
00424 protected:
00425     void InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize);
00426     void FirstPut(const byte *inString);
00427     void NextPutMultiple(const byte *inString, size_t length);
00428     void LastPut(const byte *inString, size_t length);
00429 
00430 private:
00431     const PK_Verifier &m_verifier;
00432     member_ptr<PK_MessageAccumulator> m_messageAccumulator;
00433     word32 m_flags;
00434     SecByteBlock m_signature;
00435     bool m_verified;
00436 };
00437 
00438 typedef SignatureVerificationFilter VerifierFilter; // for backwards compatibility
00439 
00440 //! Redirect input to another BufferedTransformation without owning it
00441 class CRYPTOPP_DLL Redirector : public CustomSignalPropagation<Sink>
00442 {
00443 public:
00444     enum Behavior
00445     {
00446         DATA_ONLY = 0x00,
00447         PASS_SIGNALS = 0x01,
00448         PASS_WAIT_OBJECTS = 0x02,
00449         PASS_EVERYTHING = PASS_SIGNALS | PASS_WAIT_OBJECTS
00450     };
00451 
00452     Redirector() : m_target(NULL), m_behavior(PASS_EVERYTHING) {}
00453     Redirector(BufferedTransformation &target, Behavior behavior=PASS_EVERYTHING)
00454         : m_target(&target), m_behavior(behavior) {}
00455 
00456     void Redirect(BufferedTransformation &target) {m_target = &target;}
00457     void StopRedirection() {m_target = NULL;}
00458 
00459     Behavior GetBehavior() {return (Behavior) m_behavior;}
00460     void SetBehavior(Behavior behavior) {m_behavior=behavior;}
00461     bool GetPassSignals() const {return (m_behavior & PASS_SIGNALS) != 0;}
00462     void SetPassSignals(bool pass) { if (pass) m_behavior |= PASS_SIGNALS; else m_behavior &= ~(word32) PASS_SIGNALS; }
00463     bool GetPassWaitObjects() const {return (m_behavior & PASS_WAIT_OBJECTS) != 0;}
00464     void SetPassWaitObjects(bool pass) { if (pass) m_behavior |= PASS_WAIT_OBJECTS; else m_behavior &= ~(word32) PASS_WAIT_OBJECTS; }
00465 
00466     bool CanModifyInput() const
00467         {return m_target ? m_target->CanModifyInput() : false;}
00468 
00469     void Initialize(const NameValuePairs &parameters, int propagation);
00470     byte * CreatePutSpace(size_t &size)
00471         {return m_target ? m_target->CreatePutSpace(size) : (byte *)(size=0, NULL);}
00472     size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
00473         {return m_target ? m_target->Put2(begin, length, GetPassSignals() ? messageEnd : 0, blocking) : 0;}
00474     bool Flush(bool hardFlush, int propagation=-1, bool blocking=true)
00475         {return m_target && GetPassSignals() ? m_target->Flush(hardFlush, propagation, blocking) : false;}
00476     bool MessageSeriesEnd(int propagation=-1, bool blocking=true)
00477         {return m_target && GetPassSignals() ? m_target->MessageSeriesEnd(propagation, blocking) : false;}
00478 
00479     byte * ChannelCreatePutSpace(const std::string &channel, size_t &size)
00480         {return m_target ? m_target->ChannelCreatePutSpace(channel, size) : (byte *)(size=0, NULL);}
00481     size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
00482         {return m_target ? m_target->ChannelPut2(channel, begin, length, GetPassSignals() ? messageEnd : 0, blocking) : 0;}
00483     size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking)
00484         {return m_target ? m_target->ChannelPutModifiable2(channel, begin, length, GetPassSignals() ? messageEnd : 0, blocking) : 0;}
00485     bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true)
00486         {return m_target && GetPassSignals() ? m_target->ChannelFlush(channel, completeFlush, propagation, blocking) : false;}
00487     bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true)
00488         {return m_target && GetPassSignals() ? m_target->ChannelMessageSeriesEnd(channel, propagation, blocking) : false;}
00489 
00490     unsigned int GetMaxWaitObjectCount() const
00491         { return m_target && GetPassWaitObjects() ? m_target->GetMaxWaitObjectCount() : 0; }
00492     void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
00493         { if (m_target && GetPassWaitObjects()) m_target->GetWaitObjects(container, callStack); }
00494 
00495 private:
00496     BufferedTransformation *m_target;
00497     word32 m_behavior;
00498 };
00499 
00500 // Used By ProxyFilter
00501 class CRYPTOPP_DLL OutputProxy : public CustomSignalPropagation<Sink>
00502 {
00503 public:
00504     OutputProxy(BufferedTransformation &owner, bool passSignal) : m_owner(owner), m_passSignal(passSignal) {}
00505 
00506     bool GetPassSignal() const {return m_passSignal;}
00507     void SetPassSignal(bool passSignal) {m_passSignal = passSignal;}
00508 
00509     byte * CreatePutSpace(size_t &size)
00510         {return m_owner.AttachedTransformation()->CreatePutSpace(size);}
00511     size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
00512         {return m_owner.AttachedTransformation()->Put2(begin, length, m_passSignal ? messageEnd : 0, blocking);}
00513     size_t PutModifiable2(byte *begin, size_t length, int messageEnd, bool blocking)
00514         {return m_owner.AttachedTransformation()->PutModifiable2(begin, length, m_passSignal ? messageEnd : 0, blocking);}
00515     void Initialize(const NameValuePairs &parameters=g_nullNameValuePairs, int propagation=-1)
00516         {if (m_passSignal) m_owner.AttachedTransformation()->Initialize(parameters, propagation);}
00517     bool Flush(bool hardFlush, int propagation=-1, bool blocking=true)
00518         {return m_passSignal ? m_owner.AttachedTransformation()->Flush(hardFlush, propagation, blocking) : false;}
00519     bool MessageSeriesEnd(int propagation=-1, bool blocking=true)
00520         {return m_passSignal ? m_owner.AttachedTransformation()->MessageSeriesEnd(propagation, blocking) : false;}
00521 
00522     byte * ChannelCreatePutSpace(const std::string &channel, size_t &size)
00523         {return m_owner.AttachedTransformation()->ChannelCreatePutSpace(channel, size);}
00524     size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
00525         {return m_owner.AttachedTransformation()->ChannelPut2(channel, begin, length, m_passSignal ? messageEnd : 0, blocking);}
00526     size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking)
00527         {return m_owner.AttachedTransformation()->ChannelPutModifiable2(channel, begin, length, m_passSignal ? messageEnd : 0, blocking);}
00528     bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true)
00529         {return m_passSignal ? m_owner.AttachedTransformation()->ChannelFlush(channel, completeFlush, propagation, blocking) : false;}
00530     bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true)
00531         {return m_passSignal ? m_owner.AttachedTransformation()->ChannelMessageSeriesEnd(channel, propagation, blocking) : false;}
00532 
00533 private:
00534     BufferedTransformation &m_owner;
00535     bool m_passSignal;
00536 };
00537 
00538 //! Base class for Filter classes that are proxies for a chain of other filters.
00539 class CRYPTOPP_DLL ProxyFilter : public FilterWithBufferedInput
00540 {
00541 public:
00542     ProxyFilter(BufferedTransformation *filter, size_t firstSize, size_t lastSize, BufferedTransformation *attachment);
00543 
00544     bool IsolatedFlush(bool hardFlush, bool blocking);
00545 
00546     void SetFilter(Filter *filter);
00547     void NextPutMultiple(const byte *s, size_t len);
00548     void NextPutModifiable(byte *inString, size_t length);
00549 
00550 protected:
00551     member_ptr<BufferedTransformation> m_filter;
00552 };
00553 
00554 //! simple proxy filter that doesn't modify the underlying filter's input or output
00555 class CRYPTOPP_DLL SimpleProxyFilter : public ProxyFilter
00556 {
00557 public:
00558     SimpleProxyFilter(BufferedTransformation *filter, BufferedTransformation *attachment)
00559         : ProxyFilter(filter, 0, 0, attachment) {}
00560 
00561     void FirstPut(const byte *) {}
00562     void LastPut(const byte *, size_t) {m_filter->MessageEnd();}
00563 };
00564 
00565 //! proxy for the filter created by PK_Encryptor::CreateEncryptionFilter
00566 /*! This class is here just to provide symmetry with VerifierFilter. */
00567 class CRYPTOPP_DLL PK_EncryptorFilter : public SimpleProxyFilter
00568 {
00569 public:
00570     PK_EncryptorFilter(RandomNumberGenerator &rng, const PK_Encryptor &encryptor, BufferedTransformation *attachment = NULL)
00571         : SimpleProxyFilter(encryptor.CreateEncryptionFilter(rng), attachment) {}
00572 };
00573 
00574 //! proxy for the filter created by PK_Decryptor::CreateDecryptionFilter
00575 /*! This class is here just to provide symmetry with SignerFilter. */
00576 class CRYPTOPP_DLL PK_DecryptorFilter : public SimpleProxyFilter
00577 {
00578 public:
00579     PK_DecryptorFilter(RandomNumberGenerator &rng, const PK_Decryptor &decryptor, BufferedTransformation *attachment = NULL)
00580         : SimpleProxyFilter(decryptor.CreateDecryptionFilter(rng), attachment) {}
00581 };
00582 
00583 //! Append input to a string object
00584 template <class T>
00585 class StringSinkTemplate : public Bufferless<Sink>
00586 {
00587 public:
00588     // VC60 workaround: no T::char_type
00589     typedef typename T::traits_type::char_type char_type;
00590 
00591     StringSinkTemplate(T &output)
00592         : m_output(&output) {assert(sizeof(output[0])==1);}
00593 
00594     void IsolatedInitialize(const NameValuePairs &parameters)
00595         {if (!parameters.GetValue("OutputStringPointer", m_output)) throw InvalidArgument("StringSink: OutputStringPointer not specified");}
00596 
00597     size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
00598     {
00599         if (length > 0)
00600         {
00601             typename T::size_type size = m_output->size();
00602             if (length < size && size + length > m_output->capacity())
00603                 m_output->reserve(2*size);
00604         m_output->append((const char_type *)begin, (const char_type *)begin+length);
00605         }
00606         return 0;
00607     }
00608 
00609 private:    
00610     T *m_output;
00611 };
00612 
00613 //! Append input to an std::string
00614 CRYPTOPP_DLL_TEMPLATE_CLASS StringSinkTemplate<std::string>;
00615 typedef StringSinkTemplate<std::string> StringSink;
00616 
00617 //! incorporates input into RNG as additional entropy
00618 class RandomNumberSink : public Bufferless<Sink>
00619 {
00620 public:
00621     RandomNumberSink()
00622         : m_rng(NULL) {}
00623 
00624     RandomNumberSink(RandomNumberGenerator &rng)
00625         : m_rng(&rng) {}
00626 
00627     void IsolatedInitialize(const NameValuePairs &parameters);
00628     size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
00629 
00630 private:
00631     RandomNumberGenerator *m_rng;
00632 };
00633 
00634 //! Copy input to a memory buffer
00635 class CRYPTOPP_DLL ArraySink : public Bufferless<Sink>
00636 {
00637 public:
00638     ArraySink(const NameValuePairs &parameters = g_nullNameValuePairs) {IsolatedInitialize(parameters);}
00639     ArraySink(byte *buf, size_t size) : m_buf(buf), m_size(size), m_total(0) {}
00640 
00641     size_t AvailableSize() {return SaturatingSubtract(m_size, m_total);}
00642     lword TotalPutLength() {return m_total;}
00643 
00644     void IsolatedInitialize(const NameValuePairs &parameters);
00645     byte * CreatePutSpace(size_t &size);
00646     size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
00647 
00648 protected:
00649     byte *m_buf;
00650     size_t m_size;
00651     lword m_total;
00652 };
00653 
00654 //! Xor input to a memory buffer
00655 class CRYPTOPP_DLL ArrayXorSink : public ArraySink
00656 {
00657 public:
00658     ArrayXorSink(byte *buf, size_t size)
00659         : ArraySink(buf, size) {}
00660 
00661     size_t Put2(const byte *begin, size_t length, int messageEnd, bool blocking);
00662     byte * CreatePutSpace(size_t &size) {return BufferedTransformation::CreatePutSpace(size);}
00663 };
00664 
00665 //! string-based implementation of Store interface
00666 class StringStore : public Store
00667 {
00668 public:
00669     StringStore(const char *string = NULL)
00670         {StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string)));}
00671     StringStore(const byte *string, size_t length)
00672         {StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string, length)));}
00673     template <class T> StringStore(const T &string)
00674         {StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string)));}
00675 
00676     CRYPTOPP_DLL size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
00677     CRYPTOPP_DLL size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
00678 
00679 private:
00680     CRYPTOPP_DLL void StoreInitialize(const NameValuePairs &parameters);
00681 
00682     const byte *m_store;
00683     size_t m_length, m_count;
00684 };
00685 
00686 //! RNG-based implementation of Source interface
00687 class CRYPTOPP_DLL RandomNumberStore : public Store
00688 {
00689 public:
00690     RandomNumberStore()
00691         : m_rng(NULL), m_length(0), m_count(0) {}
00692 
00693     RandomNumberStore(RandomNumberGenerator &rng, lword length)
00694         : m_rng(&rng), m_length(length), m_count(0) {}
00695 
00696     bool AnyRetrievable() const {return MaxRetrievable() != 0;}
00697     lword MaxRetrievable() const {return m_length-m_count;}
00698 
00699     size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
00700     size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const
00701     {
00702         throw NotImplemented("RandomNumberStore: CopyRangeTo2() is not supported by this store");
00703     }
00704 
00705 private:
00706     void StoreInitialize(const NameValuePairs &parameters);
00707 
00708     RandomNumberGenerator *m_rng;
00709     lword m_length, m_count;
00710 };
00711 
00712 //! empty store
00713 class CRYPTOPP_DLL NullStore : public Store
00714 {
00715 public:
00716     NullStore(lword size = ULONG_MAX) : m_size(size) {}
00717     void StoreInitialize(const NameValuePairs &parameters) {}
00718     lword MaxRetrievable() const {return m_size;}
00719     size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
00720     size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
00721 
00722 private:
00723     lword m_size;
00724 };
00725 
00726 //! A Filter that pumps data into its attachment as input
00727 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Source : public InputRejecting<Filter>
00728 {
00729 public:
00730     Source(BufferedTransformation *attachment = NULL)
00731         {Source::Detach(attachment);}
00732 
00733     lword Pump(lword pumpMax=size_t(0)-1)
00734         {Pump2(pumpMax); return pumpMax;}
00735     unsigned int PumpMessages(unsigned int count=UINT_MAX)
00736         {PumpMessages2(count); return count;}
00737     void PumpAll()
00738         {PumpAll2();}
00739     virtual size_t Pump2(lword &byteCount, bool blocking=true) =0;
00740     virtual size_t PumpMessages2(unsigned int &messageCount, bool blocking=true) =0;
00741     virtual size_t PumpAll2(bool blocking=true);
00742     virtual bool SourceExhausted() const =0;
00743 
00744 protected:
00745     void SourceInitialize(bool pumpAll, const NameValuePairs &parameters)
00746     {
00747         IsolatedInitialize(parameters);
00748         if (pumpAll)
00749             PumpAll();
00750     }
00751 };
00752 
00753 //! Turn a Store into a Source
00754 template <class T>
00755 class SourceTemplate : public Source
00756 {
00757 public:
00758     SourceTemplate<T>(BufferedTransformation *attachment)
00759         : Source(attachment) {}
00760     void IsolatedInitialize(const NameValuePairs &parameters)
00761         {m_store.IsolatedInitialize(parameters);}
00762     size_t Pump2(lword &byteCount, bool blocking=true)
00763         {return m_store.TransferTo2(*AttachedTransformation(), byteCount, DEFAULT_CHANNEL, blocking);}
00764     size_t PumpMessages2(unsigned int &messageCount, bool blocking=true)
00765         {return m_store.TransferMessagesTo2(*AttachedTransformation(), messageCount, DEFAULT_CHANNEL, blocking);}
00766     size_t PumpAll2(bool blocking=true)
00767         {return m_store.TransferAllTo2(*AttachedTransformation(), DEFAULT_CHANNEL, blocking);}
00768     bool SourceExhausted() const
00769         {return !m_store.AnyRetrievable() && !m_store.AnyMessages();}
00770     void SetAutoSignalPropagation(int propagation)
00771         {m_store.SetAutoSignalPropagation(propagation);}
00772     int GetAutoSignalPropagation() const
00773         {return m_store.GetAutoSignalPropagation();}
00774 
00775 protected:
00776     T m_store;
00777 };
00778 
00779 //! string-based implementation of Source interface
00780 class CRYPTOPP_DLL StringSource : public SourceTemplate<StringStore>
00781 {
00782 public:
00783     StringSource(BufferedTransformation *attachment = NULL)
00784         : SourceTemplate<StringStore>(attachment) {}
00785     //! zero terminated string as source
00786     StringSource(const char *string, bool pumpAll, BufferedTransformation *attachment = NULL)
00787         : SourceTemplate<StringStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string)));}
00788     //! binary byte array as source
00789     StringSource(const byte *string, size_t length, bool pumpAll, BufferedTransformation *attachment = NULL)
00790         : SourceTemplate<StringStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string, length)));}
00791     //! std::string as source
00792     StringSource(const std::string &string, bool pumpAll, BufferedTransformation *attachment = NULL)
00793         : SourceTemplate<StringStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string)));}
00794 };
00795 
00796 //! use the third constructor for an array source
00797 typedef StringSource ArraySource;
00798 
00799 //! RNG-based implementation of Source interface
00800 class CRYPTOPP_DLL RandomNumberSource : public SourceTemplate<RandomNumberStore>
00801 {
00802 public:
00803     RandomNumberSource(RandomNumberGenerator &rng, int length, bool pumpAll, BufferedTransformation *attachment = NULL)
00804         : SourceTemplate<RandomNumberStore>(attachment) 
00805         {SourceInitialize(pumpAll, MakeParameters("RandomNumberGeneratorPointer", &rng)("RandomNumberStoreSize", length));}
00806 };
00807 
00808 NAMESPACE_END
00809 
00810 #endif