1 // filters.h - written and placed in the public domain by Wei Dai
2 
3 //! \file filters.h
4 //! \brief Implementation of BufferedTransformation's attachment interface.
5 
6 #ifndef CRYPTOPP_FILTERS_H
7 #define CRYPTOPP_FILTERS_H
8 
9 #include "cryptlib.h"
10 
11 #if CRYPTOPP_MSC_VERSION
12 # pragma warning(push)
13 # pragma warning(disable: 4127 4189 4514)
14 #endif
15 
16 #include "cryptlib.h"
17 #include "simple.h"
18 #include "secblock.h"
19 #include "misc.h"
20 #include "smartptr.h"
21 #include "queue.h"
22 #include "algparam.h"
23 #include "stdcpp.h"
24 
NAMESPACE_BEGIN(CryptoPP)25 NAMESPACE_BEGIN(CryptoPP)
26 
27 //! \class Filter
28 //! \brief Implementation of BufferedTransformation's attachment interface
29 //! \details Filter is a cornerstone of the Pipeline trinitiy. Data flows from
30 //!   Sources, through Filters, and then terminates in Sinks. The difference
31 //!   between a Source and Filter is a Source \a pumps data, while a Filter does
32 //!   not. The difference between a Filter and a Sink is a Filter allows an
33 //!   attached transformation, while a Sink does not.
34 //! \details See the discussion of BufferedTransformation in cryptlib.h for
35 //!   more details.
36 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Filter : public BufferedTransformation, public NotCopyable
37 {
38 public:
39 	virtual ~Filter() {}
40 
41 	//!	\name ATTACHMENT
42 	//@{
43 
44 	//! \brief Construct a Filter
45 	//! \param attachment an optional attached transformation
46 	//! \details attachment can be \p NULL.
47 	Filter(BufferedTransformation *attachment = NULL);
48 
49 	//! \brief Determine if attachable
50 	//! \returns \p true if the object allows attached transformations, \p false otherwise.
51 	//! \note Source and Filter offer attached transformations; while Sink does not.
52 	bool Attachable() {return true;}
53 
54 	//! \brief Retrieve attached transformation
55 	//! \returns pointer to a BufferedTransformation if there is an attached transformation, \p NULL otherwise.
56 	BufferedTransformation *AttachedTransformation();
57 
58 	//! \brief Retrieve attached transformation
59 	//! \returns pointer to a BufferedTransformation if there is an attached transformation, \p NULL otherwise.
60 	const BufferedTransformation *AttachedTransformation() const;
61 
62 	//! \brief Replace an attached transformation
63 	//! \param newAttachment an optional attached transformation
64 	//! \details newAttachment can be a single filter, a chain of filters or \p NULL.
65 	//!    Pass \p NULL to remove an existing BufferedTransformation or chain of filters
66 	void Detach(BufferedTransformation *newAttachment = NULL);
67 
68 	//@}
69 
70 	// See the documentation for BufferedTransformation in cryptlib.h
71 	size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
72 	size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
73 
74 	// See the documentation for BufferedTransformation in cryptlib.h
75 	void Initialize(const NameValuePairs &parameters=g_nullNameValuePairs, int propagation=-1);
76 	bool Flush(bool hardFlush, int propagation=-1, bool blocking=true);
77 	bool MessageSeriesEnd(int propagation=-1, bool blocking=true);
78 
79 protected:
80 	virtual BufferedTransformation * NewDefaultAttachment() const;
81 	void Insert(Filter *nextFilter);	// insert filter after this one
82 
83 	virtual bool ShouldPropagateMessageEnd() const {return true;}
84 	virtual bool ShouldPropagateMessageSeriesEnd() const {return true;}
85 
86 	void PropagateInitialize(const NameValuePairs &parameters, int propagation);
87 
88 	//! \brief Forward processed data on to attached transformation
89 	//! \param outputSite unknown, system crash between keyboard and chair...
90 	//! \param inString the byte buffer to process
91 	//! \param length the size of the string, in bytes
92 	//! \param messageEnd means how many filters to signal MessageEnd() to, including this one
93 	//! \param blocking specifies whether the object should block when processing input
94 	//! \param channel the channel to process the data
95 	//! \returns the number of bytes that remain in the block (i.e., bytes not processed)
96 	size_t Output(int outputSite, const byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel=DEFAULT_CHANNEL);
97 
98 	//! \brief Output multiple bytes that may be modified by callee.
99 	//! \param outputSite unknown, system crash between keyboard and chair...
100 	//! \param inString the byte buffer to process
101 	//! \param length the size of the string, in bytes
102 	//! \param messageEnd means how many filters to signal MessageEnd() to, including this one
103 	//! \param blocking specifies whether the object should block when processing input
104 	//! \param channel the channel to process the data
105 	//! \returns the number of bytes that remain in the block (i.e., bytes not processed)
106 	size_t OutputModifiable(int outputSite, byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel=DEFAULT_CHANNEL);
107 
108 	//! \brief Signals the end of messages to the object
109 	//! \param outputSite unknown, system crash between keyboard and chair...
110 	//! \param propagation the number of attached transformations the  MessageEnd() signal should be passed
111 	//! \param blocking specifies whether the object should block when processing input
112 	//! \param channel the channel to process the data
113 	//! \returns TODO
114 	//! \details propagation count includes this object. Setting  propagation to <tt>1</tt> means this
115 	//!   object only. Setting propagation to <tt>-1</tt> means unlimited propagation.
116 	bool OutputMessageEnd(int outputSite, int propagation, bool blocking, const std::string &channel=DEFAULT_CHANNEL);
117 
118 	//! \brief Flush buffered input and/or output, with signal propagation
119 	//! \param outputSite unknown, system crash between keyboard and chair...
120 	//! \param hardFlush is used to indicate whether all data should be flushed
121 	//! \param propagation the number of attached transformations the  Flush() signal should be passed
122 	//! \param blocking specifies whether the object should block when processing input
123 	//! \param channel the channel to process the data
124 	//! \returns TODO
125 	//! \details propagation count includes this object. Setting  propagation to <tt>1</tt> means this
126 	//!   object only. Setting  propagation to <tt>-1</tt> means unlimited propagation.
127 	//! \note Hard flushes must be used with care. It means try to process and output everything, even if
128 	//!   there may not be enough data to complete the action. For example, hard flushing a  HexDecoder
129 	//!   would cause an error if you do it after inputing an odd number of hex encoded characters.
130 	//! \note For some types of filters, like  ZlibDecompressor, hard flushes can only
131 	//!   be done at "synchronization points". These synchronization points are positions in the data
132 	//!   stream that are created by hard flushes on the corresponding reverse filters, in this
133 	//!   example ZlibCompressor. This is useful when zlib compressed data is moved across a
134 	//!   network in packets and compression state is preserved across packets, as in the SSH2 protocol.
135 	bool OutputFlush(int outputSite, bool hardFlush, int propagation, bool blocking, const std::string &channel=DEFAULT_CHANNEL);
136 
137 	//! \brief Marks the end of a series of messages, with signal propagation
138 	//! \param outputSite unknown, system crash between keyboard and chair...
139 	//! \param propagation the number of attached transformations the  MessageSeriesEnd() signal should be passed
140 	//! \param blocking specifies whether the object should block when processing input
141 	//! \param channel the channel to process the data
142 	//! \returns TODO
143 	//! \details Each object that receives the signal will perform its processing, decrement
144 	//!    propagation, and then pass the signal on to attached transformations if the value is not 0.
145 	//! \details propagation count includes this object. Setting  propagation to <tt>1</tt> means this
146 	//!   object only. Setting  propagation to <tt>-1</tt> means unlimited propagation.
147 	//! \note There should be a MessageEnd() immediately before MessageSeriesEnd().
148 	bool OutputMessageSeriesEnd(int outputSite, int propagation, bool blocking, const std::string &channel=DEFAULT_CHANNEL);
149 
150 private:
151 	member_ptr<BufferedTransformation> m_attachment;
152 
153 protected:
154 	size_t m_inputPosition;
155 	int m_continueAt;
156 };
157 
158 //! \class FilterPutSpaceHelper
159 //! \brief Create a working space in a BufferedTransformation
160 struct CRYPTOPP_DLL FilterPutSpaceHelper
161 {
~FilterPutSpaceHelperFilterPutSpaceHelper162 	virtual ~FilterPutSpaceHelper() {}
163 
164 	//! \brief Create a working space in a BufferedTransformation
165 	//! \param target BufferedTransformation for the working space
166 	//! \param channel channel for the working space
167 	//! \param minSize minimum size of the allocation, in bytes
168 	//! \param desiredSize preferred size of the allocation, in bytes
169 	//! \param bufferSize actual size of the allocation, in bytes
170 	//! \pre <tt>desiredSize >= minSize</tt> and <tt>bufferSize >= minSize</tt>.
171 	//! \details \p bufferSize is an IN and OUT parameter. If HelpCreatePutSpace() returns a non-NULL value, then
172 	//!    bufferSize is valid and provides the size of the working space created for the caller.
173 	//! \details Internally, HelpCreatePutSpace() calls \ref BufferedTransformation::ChannelCreatePutSpace
174 	//!   "ChannelCreatePutSpace()" using \p desiredSize. If the target returns \p desiredSize with a size less
175 	//!   than \p minSize (i.e., the request could not be fulfilled), then an internal SecByteBlock
176 	//!   called \p m_tempSpace is resized and used for the caller.
HelpCreatePutSpaceFilterPutSpaceHelper177 	byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, size_t minSize, size_t desiredSize, size_t &bufferSize)
178 	{
179 		CRYPTOPP_ASSERT(desiredSize >= minSize && bufferSize >= minSize);
180 		if (m_tempSpace.size() < minSize)
181 		{
182 			byte *result = target.ChannelCreatePutSpace(channel, desiredSize);
183 			if (desiredSize >= minSize)
184 			{
185 				bufferSize = desiredSize;
186 				return result;
187 			}
188 			m_tempSpace.New(bufferSize);
189 		}
190 
191 		bufferSize = m_tempSpace.size();
192 		return m_tempSpace.begin();
193 	}
194 
195 	//! \brief Create a working space in a BufferedTransformation
196 	//! \param target the BufferedTransformation for the working space
197 	//! \param channel channel for the working space
198 	//! \param minSize minimum size of the allocation, in bytes
199 	//! \details Internally, the overload calls HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, size_t minSize, size_t desiredSize, size_t &bufferSize) using \p minSize for missing arguments.
HelpCreatePutSpaceFilterPutSpaceHelper200 	byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, size_t minSize)
201 		{return HelpCreatePutSpace(target, channel, minSize, minSize, minSize);}
202 
203 	//! \brief Create a working space in a BufferedTransformation
204 	//! \param target the BufferedTransformation for the working space
205 	//! \param channel channel for the working space
206 	//! \param minSize minimum size of the allocation, in bytes
207 	//! \param bufferSize the actual size of the allocation, in bytes
208 	//! \details Internally, the overload calls HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, size_t minSize, size_t desiredSize, size_t &bufferSize) using \p minSize for missing arguments.
HelpCreatePutSpaceFilterPutSpaceHelper209 	byte *HelpCreatePutSpace(BufferedTransformation &target, const std::string &channel, size_t minSize, size_t bufferSize)
210 		{return HelpCreatePutSpace(target, channel, minSize, minSize, bufferSize);}
211 
212 	//! \brief Temporay working space
213 	SecByteBlock m_tempSpace;
214 };
215 
216 //! \class MeterFilter
217 //! \brief Measure how many bytes and messages pass through the filter
218 //! \details measure how many bytes and messages pass through the filter. The filter also serves as valve by
219 //!   maintaining a list of ranges to skip during processing.
220 class CRYPTOPP_DLL MeterFilter : public Bufferless<Filter>
221 {
222 public:
~MeterFilter()223 	virtual ~MeterFilter() {}
224 
225 	//! \brief Construct a MeterFilter
226 	//! \param attachment an optional attached transformation
227 	//! \param transparent flag indicating if the filter should function transparently
228 	//! \details \p attachment can be \p NULL. The filter is transparent by default. If the filter is
229 	//!   transparent, then PutMaybeModifiable() does not process a request and always returns 0.
230 	MeterFilter(BufferedTransformation *attachment=NULL, bool transparent=true)
m_transparent(transparent)231 		: m_transparent(transparent), m_currentMessageBytes(0), m_totalBytes(0)
232 		, m_currentSeriesMessages(0), m_totalMessages(0), m_totalMessageSeries(0)
233 		, m_begin(NULL), m_length(0) {Detach(attachment); ResetMeter();}
234 
235 	//! \brief Set or change the transparent mode of this object
236 	//! \param transparent the new transparent mode
SetTransparent(bool transparent)237 	void SetTransparent(bool transparent) {m_transparent = transparent;}
238 
239 	//! \brief Adds a range to skip during processing
240 	//! \param message the message to apply the range
241 	//! \param position the 0-based index in the current stream
242 	//! \param size the length of the range
243 	//! \param sortNow flag indicating whether the range should be sorted
244 	//! \details Internally, MeterFilter maitains a deque of ranges to skip. As messages are processed,
245 	//!   ranges of bytes are skipped according to the list of ranges.
246 	void AddRangeToSkip(unsigned int message, lword position, lword size, bool sortNow = true);
247 
248 	//! \brief Resets the meter
249 	//! \details ResetMeter() reinitializes the meter by setting counters to 0 and removing previous
250 	//!   skip ranges.
251 	void ResetMeter();
252 
IsolatedInitialize(const NameValuePairs & parameters)253 	void IsolatedInitialize(const NameValuePairs &parameters)
254 		{CRYPTOPP_UNUSED(parameters); ResetMeter();}
255 
GetCurrentMessageBytes()256 	lword GetCurrentMessageBytes() const {return m_currentMessageBytes;}
GetTotalBytes()257 	lword GetTotalBytes() const {return m_totalBytes;}
GetCurrentSeriesMessages()258 	unsigned int GetCurrentSeriesMessages() const {return m_currentSeriesMessages;}
GetTotalMessages()259 	unsigned int GetTotalMessages() const {return m_totalMessages;}
GetTotalMessageSeries()260 	unsigned int GetTotalMessageSeries() const {return m_totalMessageSeries;}
261 
CreatePutSpace(size_t & size)262 	byte * CreatePutSpace(size_t &size)
263 		{return AttachedTransformation()->CreatePutSpace(size);}
264 	size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking);
265 	size_t PutModifiable2(byte *inString, size_t length, int messageEnd, bool blocking);
266 	bool IsolatedMessageSeriesEnd(bool blocking);
267 
268 private:
269 	size_t PutMaybeModifiable(byte *inString, size_t length, int messageEnd, bool blocking, bool modifiable);
ShouldPropagateMessageEnd()270 	bool ShouldPropagateMessageEnd() const {return m_transparent;}
ShouldPropagateMessageSeriesEnd()271 	bool ShouldPropagateMessageSeriesEnd() const {return m_transparent;}
272 
273 	struct MessageRange
274 	{
275 		inline bool operator<(const MessageRange &b) const	// BCB2006 workaround: this has to be a member function
276 			{return message < b.message || (message == b.message && position < b.position);}
277 		unsigned int message; lword position; lword size;
278 	};
279 
280 	bool m_transparent;
281 	lword m_currentMessageBytes, m_totalBytes;
282 	unsigned int m_currentSeriesMessages, m_totalMessages, m_totalMessageSeries;
283 	std::deque<MessageRange> m_rangesToSkip;
284 	byte *m_begin;
285 	size_t m_length;
286 };
287 
288 //! \class TransparentFilter
289 //! \brief A transparent MeterFilter
290 //! \sa MeterFilter, OpaqueFilter
291 class CRYPTOPP_DLL TransparentFilter : public MeterFilter
292 {
293 public:
294 	//! \brief Construct a TransparentFilter
295 	//! \param attachment an optional attached transformation
MeterFilter(attachment,true)296 	TransparentFilter(BufferedTransformation *attachment=NULL) : MeterFilter(attachment, true) {}
297 };
298 
299 //! \class OpaqueFilter
300 //! \brief A non-transparent MeterFilter
301 //! \sa MeterFilter, TransparentFilter
302 class CRYPTOPP_DLL OpaqueFilter : public MeterFilter
303 {
304 public:
305 	//! \brief Construct an OpaqueFilter
306 	//! \param attachment an optional attached transformation
MeterFilter(attachment,false)307 	OpaqueFilter(BufferedTransformation *attachment=NULL) : MeterFilter(attachment, false) {}
308 };
309 
310 //! \class FilterWithBufferedInput
311 //! \brief Divides an input stream into discrete blocks
312 //! \details FilterWithBufferedInput divides the input stream into a first block, a number of
313 //!   middle blocks, and a last block. First and last blocks are optional, and middle blocks may
314 //!   be a stream instead (i.e. <tt>blockSize == 1</tt>).
315 //! \sa AuthenticatedEncryptionFilter, AuthenticatedDecryptionFilter, HashVerificationFilter,
316 //!   SignatureVerificationFilter, StreamTransformationFilter
317 class CRYPTOPP_DLL FilterWithBufferedInput : public Filter
318 {
319 public:
~FilterWithBufferedInput()320 	virtual ~FilterWithBufferedInput() {}
321 
322 	//! \brief Construct a FilterWithBufferedInput with an attached transformation
323 	//! \param attachment an attached transformation
324 	FilterWithBufferedInput(BufferedTransformation *attachment);
325 
326 	//! \brief Construct a FilterWithBufferedInput with an attached transformation
327 	//! \param firstSize the size of the first block
328 	//! \param blockSize the size of middle blocks
329 	//! \param lastSize the size of the last block
330 	//! \param attachment an attached transformation
331 	//! \details \p firstSize and \p lastSize may be 0. \p blockSize must be at least 1.
332 	FilterWithBufferedInput(size_t firstSize, size_t blockSize, size_t lastSize, BufferedTransformation *attachment);
333 
334 	void IsolatedInitialize(const NameValuePairs &parameters);
Put2(const byte * inString,size_t length,int messageEnd,bool blocking)335 	size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
336 	{
337 		return PutMaybeModifiable(const_cast<byte *>(inString), length, messageEnd, blocking, false);
338 	}
PutModifiable2(byte * inString,size_t length,int messageEnd,bool blocking)339 	size_t PutModifiable2(byte *inString, size_t length, int messageEnd, bool blocking)
340 	{
341 		return PutMaybeModifiable(inString, length, messageEnd, blocking, true);
342 	}
343 
344 	//! \brief Flushes data buffered by this object, without signal propagation
345 	//! \param hardFlush indicates whether all data should be flushed
346 	//! \param blocking specifies whether the object should block when processing input
347 	//! \details IsolatedFlush() calls ForceNextPut() if hardFlush is true
348 	//! \note  hardFlush must be used with care
349 	bool IsolatedFlush(bool hardFlush, bool blocking);
350 
351 	//! \brief Flushes data buffered by this object
352 	//! \details The input buffer may contain more than blockSize bytes if <tt>lastSize != 0</tt>.
353 	//!   ForceNextPut() forces a call to NextPut() if this is the case.
354 	void ForceNextPut();
355 
356 protected:
DidFirstPut()357 	virtual bool DidFirstPut() const {return m_firstInputDone;}
GetFirstPutSize()358 	virtual size_t GetFirstPutSize() const {return m_firstSize;}
GetBlockPutSize()359 	virtual size_t GetBlockPutSize() const {return m_blockSize;}
GetLastPutSize()360 	virtual size_t GetLastPutSize() const {return m_lastSize;}
361 
InitializeDerivedAndReturnNewSizes(const NameValuePairs & parameters,size_t & firstSize,size_t & blockSize,size_t & lastSize)362 	virtual void InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
363 		{CRYPTOPP_UNUSED(parameters); CRYPTOPP_UNUSED(firstSize); CRYPTOPP_UNUSED(blockSize); CRYPTOPP_UNUSED(lastSize); InitializeDerived(parameters);}
InitializeDerived(const NameValuePairs & parameters)364 	virtual void InitializeDerived(const NameValuePairs &parameters)
365 		{CRYPTOPP_UNUSED(parameters);}
366 	// FirstPut() is called if (firstSize != 0 and totalLength >= firstSize)
367 	// or (firstSize == 0 and (totalLength > 0 or a MessageEnd() is received)).
368 	// inString is m_firstSize in length.
369 	virtual void FirstPut(const byte *inString) =0;
370 	// NextPut() is called if totalLength >= firstSize+blockSize+lastSize
NextPutSingle(const byte * inString)371 	virtual void NextPutSingle(const byte *inString)
372 		{CRYPTOPP_UNUSED(inString); CRYPTOPP_ASSERT(false);}
373 	// Same as NextPut() except length can be a multiple of blockSize
374 	// Either NextPut() or NextPutMultiple() must be overridden
375 	virtual void NextPutMultiple(const byte *inString, size_t length);
376 	// Same as NextPutMultiple(), but inString can be modified
NextPutModifiable(byte * inString,size_t length)377 	virtual void NextPutModifiable(byte *inString, size_t length)
378 		{NextPutMultiple(inString, length);}
379 	//! \brief Input the last block of data
380 	//! \param inString the input byte buffer
381 	//! \param length the size of the input buffer, in bytes
382 	//! \details LastPut() processes the last block of data and signals attached filters to do the same.
383 	//!   LastPut() is always called. The pseudo algorithm for the logic is:
384 	//! <pre>
385 	//!     if totalLength < firstSize then length == totalLength
386 	//!     else if totalLength <= firstSize+lastSize then length == totalLength-firstSize
387 	//!     else lastSize <= length < lastSize+blockSize
388 	//! </pre>
389 	virtual void LastPut(const byte *inString, size_t length) =0;
FlushDerived()390 	virtual void FlushDerived() {}
391 
392 protected:
393 	size_t PutMaybeModifiable(byte *begin, size_t length, int messageEnd, bool blocking, bool modifiable);
NextPutMaybeModifiable(byte * inString,size_t length,bool modifiable)394 	void NextPutMaybeModifiable(byte *inString, size_t length, bool modifiable)
395 	{
396 		if (modifiable) NextPutModifiable(inString, length);
397 		else NextPutMultiple(inString, length);
398 	}
399 
400 	// This function should no longer be used, put this here to cause a compiler error
401 	// if someone tries to override NextPut().
NextPut(const byte * inString,size_t length)402 	virtual int NextPut(const byte *inString, size_t length)
403 		{CRYPTOPP_UNUSED(inString); CRYPTOPP_UNUSED(length); CRYPTOPP_ASSERT(false); return 0;}
404 
405 	class BlockQueue
406 	{
407 	public:
408 		void ResetQueue(size_t blockSize, size_t maxBlocks);
409 		byte *GetBlock();
410 		byte *GetContigousBlocks(size_t &numberOfBytes);
411 		size_t GetAll(byte *outString);
412 		void Put(const byte *inString, size_t length);
CurrentSize()413 		size_t CurrentSize() const {return m_size;}
MaxSize()414 		size_t MaxSize() const {return m_buffer.size();}
415 
416 	private:
417 		SecByteBlock m_buffer;
418 		size_t m_blockSize, m_maxBlocks, m_size;
419 		byte *m_begin;
420 	};
421 
422 	size_t m_firstSize, m_blockSize, m_lastSize;
423 	bool m_firstInputDone;
424 	BlockQueue m_queue;
425 };
426 
427 //! \class FilterWithInputQueue
428 //! \brief A filter that buffers input using a ByteQueue
429 //! \details FilterWithInputQueue will buffer input using a ByteQueue. When the filter receives
430 //!   a \ref BufferedTransformation::MessageEnd() "MessageEnd()" signal it will pass the data
431 //!   on to its attached transformation.
432 class CRYPTOPP_DLL FilterWithInputQueue : public Filter
433 {
434 public:
~FilterWithInputQueue()435 	virtual ~FilterWithInputQueue() {}
436 
437 	//! \brief Construct a FilterWithInputQueue
438 	//! \param attachment an optional attached transformation
Filter(attachment)439 	FilterWithInputQueue(BufferedTransformation *attachment=NULL) : Filter(attachment) {}
440 
Put2(const byte * inString,size_t length,int messageEnd,bool blocking)441 	size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
442 	{
443 		if (!blocking)
444 			throw BlockingInputOnly("FilterWithInputQueue");
445 
446 		m_inQueue.Put(inString, length);
447 		if (messageEnd)
448 		{
449 			IsolatedMessageEnd(blocking);
450 			Output(0, NULL, 0, messageEnd, blocking);
451 		}
452 		return 0;
453 	}
454 
455 protected:
456 	virtual bool IsolatedMessageEnd(bool blocking) =0;
IsolatedInitialize(const NameValuePairs & parameters)457 	void IsolatedInitialize(const NameValuePairs &parameters)
458 		{CRYPTOPP_UNUSED(parameters); m_inQueue.Clear();}
459 
460 	ByteQueue m_inQueue;
461 };
462 
463 //! \struct BlockPaddingSchemeDef
464 //! \brief Padding schemes used for block ciphers
465 struct BlockPaddingSchemeDef
466 {
467 	//! \enum BlockPaddingScheme
468 	//! \brief Padding schemes used for block ciphers.
469 	//! \details DEFAULT_PADDING means PKCS_PADDING if <tt>cipher.MandatoryBlockSize() > 1 &&
470 	//!   cipher.MinLastBlockSize() == 0</tt>, which holds for ECB or CBC mode. Otherwise,
471 	//!   NO_PADDING for modes like OFB, CFB, CTR, CBC-CTS.
472 	//! \sa <A HREF="http://www.weidai.com/scan-mirror/csp.html">Block Cipher Padding</A> for
473 	//!   additional details.
474 	enum BlockPaddingScheme {
475 		//! \brief No padding added to a block
476 		NO_PADDING,
477 		//! \brief 0's padding added to a block
478 		ZEROS_PADDING,
479 		//! \brief PKCS #5 padding added to a block
480 		PKCS_PADDING,
481 		//! \brief 1 and 0's padding added to a block
482 		ONE_AND_ZEROS_PADDING,
483 		//! \brief Default padding scheme
484 		DEFAULT_PADDING
485 	};
486 };
487 
488 //! \class StreamTransformationFilter
489 //! \brief Filter wrapper for StreamTransformation
490 //! \details StreamTransformationFilter is a filter wrapper for StreamTransformation. The filter will optionally handle padding/unpadding when needed
491 class CRYPTOPP_DLL StreamTransformationFilter : public FilterWithBufferedInput, public BlockPaddingSchemeDef, private FilterPutSpaceHelper
492 {
493 public:
~StreamTransformationFilter()494 	virtual ~StreamTransformationFilter() {}
495 
496 	//! \brief Construct a StreamTransformationFilter
497 	//! \param c reference to a StreamTransformation
498 	//! \param attachment an optional attached transformation
499 	//! \param padding the \ref BlockPaddingSchemeDef "padding scheme"
500 	//! \param allowAuthenticatedSymmetricCipher flag indicating whether the filter should allow authenticated encryption schemes
501 	StreamTransformationFilter(StreamTransformation &c, BufferedTransformation *attachment = NULL, BlockPaddingScheme padding = DEFAULT_PADDING, bool allowAuthenticatedSymmetricCipher = false);
502 
AlgorithmName()503 	std::string AlgorithmName() const {return m_cipher.AlgorithmName();}
504 
505 protected:
506 	void InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize);
507 	void FirstPut(const byte *inString);
508 	void NextPutMultiple(const byte *inString, size_t length);
509 	void NextPutModifiable(byte *inString, size_t length);
510 	void LastPut(const byte *inString, size_t length);
511 
512 	static size_t LastBlockSize(StreamTransformation &c, BlockPaddingScheme padding);
513 
514 	StreamTransformation &m_cipher;
515 	BlockPaddingScheme m_padding;
516 	unsigned int m_optimalBufferSize;
517 };
518 
519 //! \class HashFilter
520 //! \brief Filter wrapper for HashTransformation
521 class CRYPTOPP_DLL HashFilter : public Bufferless<Filter>, private FilterPutSpaceHelper
522 {
523 public:
~HashFilter()524 	virtual ~HashFilter() {}
525 
526 	//! \brief Construct a HashFilter
527 	//! \param hm reference to a HashTransformation
528 	//! \param attachment an optional attached transformation
529 	//! \param putMessage flag indicating whether the original message should be passed to an attached transformation
530 	//! \param truncatedDigestSize the size of the digest
531 	//! \param messagePutChannel the channel on which the message should be output
532 	//! \param hashPutChannel the channel on which the digest should be output
533 	HashFilter(HashTransformation &hm, BufferedTransformation *attachment = NULL, bool putMessage=false, int truncatedDigestSize=-1, const std::string &messagePutChannel=DEFAULT_CHANNEL, const std::string &hashPutChannel=DEFAULT_CHANNEL);
534 
AlgorithmName()535 	std::string AlgorithmName() const {return m_hashModule.AlgorithmName();}
536 	void IsolatedInitialize(const NameValuePairs &parameters);
537 	size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking);
CreatePutSpace(size_t & size)538 	byte * CreatePutSpace(size_t &size) {return m_hashModule.CreateUpdateSpace(size);}
539 
540 private:
541 	HashTransformation &m_hashModule;
542 	bool m_putMessage;
543 	unsigned int m_digestSize;
544 	byte *m_space;
545 	std::string m_messagePutChannel, m_hashPutChannel;
546 };
547 
548 //! \class HashVerificationFilter
549 //! \brief Filter wrapper for HashTransformation
550 class CRYPTOPP_DLL HashVerificationFilter : public FilterWithBufferedInput
551 {
552 public:
~HashVerificationFilter()553 	virtual ~HashVerificationFilter() {}
554 
555 	//! \class HashVerificationFailed
556 	//! \brief Exception thrown when a data integrity check failure is encountered
557 	class HashVerificationFailed : public Exception
558 	{
559 	public:
HashVerificationFailed()560 		HashVerificationFailed()
561 			: Exception(DATA_INTEGRITY_CHECK_FAILED, "HashVerificationFilter: message hash or MAC not valid") {}
562 	};
563 
564 	//! \enum Flags
565 	//! \brief Flags controlling filter behavior.
566 	//! \details The flags are a bitmask and can be OR'd together.
567 	enum Flags {
568 		//! \brief Indicates the hash is at the end of the message (i.e., concatenation of message+hash)
569 		HASH_AT_END=0,
570 		//! \brief Indicates the hash is at the beginning of the message (i.e., concatenation of hash+message)
571 		HASH_AT_BEGIN=1,
572 		//! \brief Indicates the message should be passed to an attached transformation
573 		PUT_MESSAGE=2,
574 		//! \brief Indicates the hash should be passed to an attached transformation
575 		PUT_HASH=4,
576 		//! \brief Indicates the result of the verification should be passed to an attached transformation
577 		PUT_RESULT=8,
578 		//! \brief Indicates the filter should throw a HashVerificationFailed if a failure is encountered
579 		THROW_EXCEPTION=16,
580 		//! \brief Default flags using \p HASH_AT_BEGIN and \p PUT_RESULT
581 		DEFAULT_FLAGS = HASH_AT_BEGIN | PUT_RESULT
582 	};
583 
584 	//! \brief Construct a HashVerificationFilter
585 	//! \param hm reference to a HashTransformation
586 	//! \param attachment an optional attached transformation
587 	//! \param flags flags indicating behaviors for the filter
588 	//! \param truncatedDigestSize the size of the digest
589 	//! \details <tt>truncatedDigestSize = -1</tt> indicates \ref HashTransformation::DigestSize() "DigestSize" should be used.
590 	HashVerificationFilter(HashTransformation &hm, BufferedTransformation *attachment = NULL, word32 flags = DEFAULT_FLAGS, int truncatedDigestSize=-1);
591 
AlgorithmName()592 	std::string AlgorithmName() const {return m_hashModule.AlgorithmName();}
GetLastResult()593 	bool GetLastResult() const {return m_verified;}
594 
595 protected:
596 	void InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize);
597 	void FirstPut(const byte *inString);
598 	void NextPutMultiple(const byte *inString, size_t length);
599 	void LastPut(const byte *inString, size_t length);
600 
601 private:
602 	friend class AuthenticatedDecryptionFilter;
603 
604 	HashTransformation &m_hashModule;
605 	word32 m_flags;
606 	unsigned int m_digestSize;
607 	bool m_verified;
608 	SecByteBlock m_expectedHash;
609 };
610 
611 //! \class AuthenticatedEncryptionFilter
612 //! \brief Filter wrapper for encrypting with AuthenticatedSymmetricCipher
613 //! \details AuthenticatedEncryptionFilter() is a wrapper for encrypting with AuthenticatedSymmetricCipher(),
614 //!   optionally handling padding/unpadding when needed.
615 //! \sa AuthenticatedDecryptionFilter, EAX, CCM, GCM, AuthenticatedSymmetricCipher
616 //! \since Crypto++ 5.6.0
617 class CRYPTOPP_DLL AuthenticatedEncryptionFilter : public StreamTransformationFilter
618 {
619 public:
~AuthenticatedEncryptionFilter()620 	virtual ~AuthenticatedEncryptionFilter() {}
621 
622 	//! \brief Construct a AuthenticatedEncryptionFilter
623 	//! \param c reference to a AuthenticatedSymmetricCipher
624 	//! \param attachment an optional attached transformation
625 	//! \param putAAD flag indicating whether the AAD should be passed to an attached transformation
626 	//! \param truncatedDigestSize the size of the digest
627 	//! \param macChannel the channel on which the MAC should be output
628 	//! \param padding the \ref BlockPaddingSchemeDef "padding scheme"
629 	//! \details <tt>truncatedDigestSize = -1</tt> indicates \ref HashTransformation::DigestSize() "DigestSize" should be used.
630 	//! \since Crypto++ 5.6.0
631 	AuthenticatedEncryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment = NULL, bool putAAD=false, int truncatedDigestSize=-1, const std::string &macChannel=DEFAULT_CHANNEL, BlockPaddingScheme padding = DEFAULT_PADDING);
632 
633 	void IsolatedInitialize(const NameValuePairs &parameters);
634 	byte * ChannelCreatePutSpace(const std::string &channel, size_t &size);
635 	size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking);
636 
637 	//! \brief Input the last block of data
638 	//! \param inString the input byte buffer
639 	//! \param length the size of the input buffer, in bytes
640 	//! \details LastPut() processes the last block of data and signals attached filters to do the same.
641 	//!   LastPut() is always called. The pseudo algorithm for the logic is:
642 	//! <pre>
643 	//!     if totalLength < firstSize then length == totalLength
644 	//!     else if totalLength <= firstSize+lastSize then length == totalLength-firstSize
645 	//!     else lastSize <= length < lastSize+blockSize
646 	//! </pre>
647 	void LastPut(const byte *inString, size_t length);
648 
649 protected:
650 	HashFilter m_hf;
651 };
652 
653 //! \class AuthenticatedDecryptionFilter
654 //! \brief Filter wrapper for decrypting with AuthenticatedSymmetricCipher
655 //! \details AuthenticatedDecryptionFilter() is a wrapper for decrypting with AuthenticatedSymmetricCipher(),
656 //!   optionally handling padding/unpadding when needed.
657 //! \sa AuthenticatedEncryptionFilter, EAX, CCM, GCM, AuthenticatedSymmetricCipher
658 //! \since Crypto++ 5.6.0
659 class CRYPTOPP_DLL AuthenticatedDecryptionFilter : public FilterWithBufferedInput, public BlockPaddingSchemeDef
660 {
661 public:
662 	//! \enum Flags
663 	//! \brief Flags controlling filter behavior.
664 	//! \details The flags are a bitmask and can be OR'd together.
665 	enum Flags {
666 		//! \brief Indicates the MAC is at the end of the message (i.e., concatenation of message+mac)
667 		MAC_AT_END=0,
668 		//! \brief Indicates the MAC is at the beginning of the message (i.e., concatenation of mac+message)
669 		MAC_AT_BEGIN=1,
670 		//! \brief Indicates the filter should throw a HashVerificationFailed if a failure is encountered
671 		THROW_EXCEPTION=16,
672 		//! \brief Default flags using \p THROW_EXCEPTION
673 		DEFAULT_FLAGS = THROW_EXCEPTION
674 	};
675 
~AuthenticatedDecryptionFilter()676 	virtual ~AuthenticatedDecryptionFilter() {}
677 
678 	//! \brief Construct a AuthenticatedDecryptionFilter
679 	//! \param c reference to a AuthenticatedSymmetricCipher
680 	//! \param attachment an optional attached transformation
681 	//! \param flags flags indicating behaviors for the filter
682 	//! \param truncatedDigestSize the size of the digest
683 	//! \param padding the \ref BlockPaddingSchemeDef "padding scheme"
684 	//! \details Additional authenticated data should be given in channel "AAD".
685 	//! \details <tt>truncatedDigestSize = -1</tt> indicates \ref HashTransformation::DigestSize() "DigestSize" should be used.
686 	//! \since Crypto++ 5.6.0
687 	AuthenticatedDecryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment = NULL, word32 flags = DEFAULT_FLAGS, int truncatedDigestSize=-1, BlockPaddingScheme padding = DEFAULT_PADDING);
688 
AlgorithmName()689 	std::string AlgorithmName() const {return m_hashVerifier.AlgorithmName();}
690 	byte * ChannelCreatePutSpace(const std::string &channel, size_t &size);
691 	size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking);
GetLastResult()692 	bool GetLastResult() const {return m_hashVerifier.GetLastResult();}
693 
694 protected:
695 	void InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize);
696 	void FirstPut(const byte *inString);
697 	void NextPutMultiple(const byte *inString, size_t length);
698 
699 	//! \brief Input the last block of data
700 	//! \param inString the input byte buffer
701 	//! \param length the size of the input buffer, in bytes
702 	//! \details LastPut() processes the last block of data and signals attached filters to do the same.
703 	//!   LastPut() is always called. The pseudo algorithm for the logic is:
704 	//! <pre>
705 	//!     if totalLength < firstSize then length == totalLength
706 	//!     else if totalLength <= firstSize+lastSize then length == totalLength-firstSize
707 	//!     else lastSize <= length < lastSize+blockSize
708 	//! </pre>
709 	void LastPut(const byte *inString, size_t length);
710 
711 	HashVerificationFilter m_hashVerifier;
712 	StreamTransformationFilter m_streamFilter;
713 };
714 
715 //! \class SignerFilter
716 //! \brief Filter wrapper for PK_Signer
717 class CRYPTOPP_DLL SignerFilter : public Unflushable<Filter>
718 {
719 public:
~SignerFilter()720 	virtual ~SignerFilter() {}
721 
722 	//! \brief Construct a SignerFilter
723 	//! \param rng a RandomNumberGenerator derived class
724 	//! \param signer a PK_Signer derived class
725 	//! \param attachment an optional attached transformation
726 	//! \param putMessage flag indicating whether the original message should be passed to an attached transformation
727 	SignerFilter(RandomNumberGenerator &rng, const PK_Signer &signer, BufferedTransformation *attachment = NULL, bool putMessage=false)
m_rng(rng)728 		: m_rng(rng), m_signer(signer), m_messageAccumulator(signer.NewSignatureAccumulator(rng)), m_putMessage(putMessage) {Detach(attachment);}
729 
AlgorithmName()730 	std::string AlgorithmName() const {return m_signer.AlgorithmName();}
731 
732 	void IsolatedInitialize(const NameValuePairs &parameters);
733 	size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking);
734 
735 private:
736 	RandomNumberGenerator &m_rng;
737 	const PK_Signer &m_signer;
738 	member_ptr<PK_MessageAccumulator> m_messageAccumulator;
739 	bool m_putMessage;
740 	SecByteBlock m_buf;
741 };
742 
743 //! \class SignatureVerificationFilter
744 //! \brief Filter wrapper for PK_Verifier
745 class CRYPTOPP_DLL SignatureVerificationFilter : public FilterWithBufferedInput
746 {
747 public:
748 	//! \brief Exception thrown when an invalid signature is encountered
749 	class SignatureVerificationFailed : public Exception
750 	{
751 	public:
SignatureVerificationFailed()752 		SignatureVerificationFailed()
753 			: Exception(DATA_INTEGRITY_CHECK_FAILED, "VerifierFilter: digital signature not valid") {}
754 	};
755 
756 	//! \enum Flags
757 	//! \brief Flags controlling filter behavior.
758 	//! \details The flags are a bitmask and can be OR'd together.
759 	enum Flags {
760 		//! \brief Indicates the signature is at the end of the message (i.e., concatenation of message+signature)
761 		SIGNATURE_AT_END=0,
762 		//! \brief Indicates the signature is at the beginning of the message (i.e., concatenation of signature+message)
763 		SIGNATURE_AT_BEGIN=1,
764 		//! \brief Indicates the message should be passed to an attached transformation
765 		PUT_MESSAGE=2,
766 		//! \brief Indicates the signature should be passed to an attached transformation
767 		PUT_SIGNATURE=4,
768 		//! \brief Indicates the result of the verification should be passed to an attached transformation
769 		PUT_RESULT=8,
770 		//! \brief Indicates the filter should throw a HashVerificationFailed if a failure is encountered
771 		THROW_EXCEPTION=16,
772 		//! \brief Default flags using \p SIGNATURE_AT_BEGIN and \p PUT_RESULT
773 		DEFAULT_FLAGS = SIGNATURE_AT_BEGIN | PUT_RESULT
774 	};
775 
~SignatureVerificationFilter()776 	virtual ~SignatureVerificationFilter() {}
777 
778 	//! \brief Construct a SignatureVerificationFilter
779 	//! \param verifier a PK_Verifier derived class
780 	//! \param attachment an optional attached transformation
781 	//! \param flags flags indicating behaviors for the filter
782 	SignatureVerificationFilter(const PK_Verifier &verifier, BufferedTransformation *attachment = NULL, word32 flags = DEFAULT_FLAGS);
783 
AlgorithmName()784 	std::string AlgorithmName() const {return m_verifier.AlgorithmName();}
785 
786 	//! \brief Retrieves the result of the last verification
787 	//! \returns true if the signature on the previosus message was valid, false otherwise
GetLastResult()788 	bool GetLastResult() const {return m_verified;}
789 
790 protected:
791 	void InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize);
792 	void FirstPut(const byte *inString);
793 	void NextPutMultiple(const byte *inString, size_t length);
794 	void LastPut(const byte *inString, size_t length);
795 
796 private:
797 	const PK_Verifier &m_verifier;
798 	member_ptr<PK_MessageAccumulator> m_messageAccumulator;
799 	word32 m_flags;
800 	SecByteBlock m_signature;
801 	bool m_verified;
802 };
803 
804 typedef SignatureVerificationFilter VerifierFilter;	// for backwards compatibility
805 
806 //! \class Redirector
807 //! \brief Redirect input to another BufferedTransformation without owning it
808 class CRYPTOPP_DLL Redirector : public CustomSignalPropagation<Sink>
809 {
810 public:
811 	//! \enum Behavior
812 	//! \brief Controls signal propagation behavior
813 	enum Behavior
814 	{
815 		//! \brief Pass data only
816 		DATA_ONLY = 0x00,
817 		//! \brief Pass signals
818 		PASS_SIGNALS = 0x01,
819 		//! \brief Pass wait events
820 		PASS_WAIT_OBJECTS = 0x02,
821 		//! \brief Pass everything
822 		//! \details PASS_EVERYTHING is default
823 		PASS_EVERYTHING = PASS_SIGNALS | PASS_WAIT_OBJECTS
824 	};
825 
~Redirector()826 	virtual ~Redirector() {}
827 
828 	//! \brief Construct a Redirector
Redirector()829 	Redirector() : m_target(NULL), m_behavior(PASS_EVERYTHING) {}
830 
831 	//! \brief Construct a Redirector
832 	//! \param target the destination BufferedTransformation
833 	//! \param behavior \ref Behavior "flags" specifying signal propagation
834 	Redirector(BufferedTransformation &target, Behavior behavior=PASS_EVERYTHING)
835 		: m_target(&target), m_behavior(behavior) {}
836 
837 	//! \brief Redirect input to another BufferedTransformation
838 	//! \param target the destination BufferedTransformation
Redirect(BufferedTransformation & target)839 	void Redirect(BufferedTransformation &target) {m_target = &target;}
840 	//! \brief Stop redirecting input
StopRedirection()841 	void StopRedirection() {m_target = NULL;}
842 
GetBehavior()843 	Behavior GetBehavior() {return (Behavior) m_behavior;}
SetBehavior(Behavior behavior)844 	void SetBehavior(Behavior behavior) {m_behavior=behavior;}
GetPassSignals()845 	bool GetPassSignals() const {return (m_behavior & PASS_SIGNALS) != 0;}
SetPassSignals(bool pass)846 	void SetPassSignals(bool pass) { if (pass) m_behavior |= PASS_SIGNALS; else m_behavior &= ~(word32) PASS_SIGNALS; }
GetPassWaitObjects()847 	bool GetPassWaitObjects() const {return (m_behavior & PASS_WAIT_OBJECTS) != 0;}
SetPassWaitObjects(bool pass)848 	void SetPassWaitObjects(bool pass) { if (pass) m_behavior |= PASS_WAIT_OBJECTS; else m_behavior &= ~(word32) PASS_WAIT_OBJECTS; }
849 
CanModifyInput()850 	bool CanModifyInput() const
851 		{return m_target ? m_target->CanModifyInput() : false;}
852 
853 	void Initialize(const NameValuePairs &parameters, int propagation);
CreatePutSpace(size_t & size)854 	byte * CreatePutSpace(size_t &size)
855 	{
856 		if (m_target)
857 			return m_target->CreatePutSpace(size);
858 		else
859 		{
860 			size = 0;
861 			return NULL;
862 		}
863 	}
Put2(const byte * inString,size_t length,int messageEnd,bool blocking)864 	size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
865 		{return m_target ? m_target->Put2(inString, length, GetPassSignals() ? messageEnd : 0, blocking) : 0;}
866 	bool Flush(bool hardFlush, int propagation=-1, bool blocking=true)
867 		{return m_target && GetPassSignals() ? m_target->Flush(hardFlush, propagation, blocking) : false;}
868 	bool MessageSeriesEnd(int propagation=-1, bool blocking=true)
869 		{return m_target && GetPassSignals() ? m_target->MessageSeriesEnd(propagation, blocking) : false;}
870 
ChannelCreatePutSpace(const std::string & channel,size_t & size)871 	byte * ChannelCreatePutSpace(const std::string &channel, size_t &size)
872 	{
873 		if (m_target)
874 			return m_target->ChannelCreatePutSpace(channel, size);
875 		else
876 		{
877 			size = 0;
878 			return NULL;
879 		}
880 	}
ChannelPut2(const std::string & channel,const byte * begin,size_t length,int messageEnd,bool blocking)881 	size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
882 		{return m_target ? m_target->ChannelPut2(channel, begin, length, GetPassSignals() ? messageEnd : 0, blocking) : 0;}
ChannelPutModifiable2(const std::string & channel,byte * begin,size_t length,int messageEnd,bool blocking)883 	size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking)
884 		{return m_target ? m_target->ChannelPutModifiable2(channel, begin, length, GetPassSignals() ? messageEnd : 0, blocking) : 0;}
885 	bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true)
886 		{return m_target && GetPassSignals() ? m_target->ChannelFlush(channel, completeFlush, propagation, blocking) : false;}
887 	bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true)
888 		{return m_target && GetPassSignals() ? m_target->ChannelMessageSeriesEnd(channel, propagation, blocking) : false;}
889 
GetMaxWaitObjectCount()890 	unsigned int GetMaxWaitObjectCount() const
891 		{ return m_target && GetPassWaitObjects() ? m_target->GetMaxWaitObjectCount() : 0; }
GetWaitObjects(WaitObjectContainer & container,CallStack const & callStack)892 	void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack)
893 		{ if (m_target && GetPassWaitObjects()) m_target->GetWaitObjects(container, callStack); }
894 
895 private:
896 	BufferedTransformation *m_target;
897 	word32 m_behavior;
898 };
899 
900 //! \class OutputProxy
901 //! \brief Filter class that is a proxy for a sink
902 //! \details Used By ProxyFilter
903 class CRYPTOPP_DLL OutputProxy : public CustomSignalPropagation<Sink>
904 {
905 public:
~OutputProxy()906 	virtual ~OutputProxy() {}
907 
908 	//! \brief Construct an OutputProxy
909 	//! \param owner the owning transformation
910 	//! \param passSignal flag indicating if signals should be passed
OutputProxy(BufferedTransformation & owner,bool passSignal)911 	OutputProxy(BufferedTransformation &owner, bool passSignal) : m_owner(owner), m_passSignal(passSignal) {}
912 
913 	//! \brief Retrieve passSignal flag
914 	//! \returns flag indicating if signals should be passed
GetPassSignal()915 	bool GetPassSignal() const {return m_passSignal;}
916 	//! \brief Set passSignal flag
917 	//! \param passSignal flag indicating if signals should be passed
SetPassSignal(bool passSignal)918 	void SetPassSignal(bool passSignal) {m_passSignal = passSignal;}
919 
CreatePutSpace(size_t & size)920 	byte * CreatePutSpace(size_t &size)
921 		{return m_owner.AttachedTransformation()->CreatePutSpace(size);}
Put2(const byte * inString,size_t length,int messageEnd,bool blocking)922 	size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
923 		{return m_owner.AttachedTransformation()->Put2(inString, length, m_passSignal ? messageEnd : 0, blocking);}
PutModifiable2(byte * begin,size_t length,int messageEnd,bool blocking)924 	size_t PutModifiable2(byte *begin, size_t length, int messageEnd, bool blocking)
925 		{return m_owner.AttachedTransformation()->PutModifiable2(begin, length, m_passSignal ? messageEnd : 0, blocking);}
926 	void Initialize(const NameValuePairs &parameters=g_nullNameValuePairs, int propagation=-1)
927 		{if (m_passSignal) m_owner.AttachedTransformation()->Initialize(parameters, propagation);}
928 	bool Flush(bool hardFlush, int propagation=-1, bool blocking=true)
929 		{return m_passSignal ? m_owner.AttachedTransformation()->Flush(hardFlush, propagation, blocking) : false;}
930 	bool MessageSeriesEnd(int propagation=-1, bool blocking=true)
931 		{return m_passSignal ? m_owner.AttachedTransformation()->MessageSeriesEnd(propagation, blocking) : false;}
932 
ChannelCreatePutSpace(const std::string & channel,size_t & size)933 	byte * ChannelCreatePutSpace(const std::string &channel, size_t &size)
934 		{return m_owner.AttachedTransformation()->ChannelCreatePutSpace(channel, size);}
ChannelPut2(const std::string & channel,const byte * begin,size_t length,int messageEnd,bool blocking)935 	size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
936 		{return m_owner.AttachedTransformation()->ChannelPut2(channel, begin, length, m_passSignal ? messageEnd : 0, blocking);}
ChannelPutModifiable2(const std::string & channel,byte * begin,size_t length,int messageEnd,bool blocking)937 	size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking)
938 		{return m_owner.AttachedTransformation()->ChannelPutModifiable2(channel, begin, length, m_passSignal ? messageEnd : 0, blocking);}
939 	bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true)
940 		{return m_passSignal ? m_owner.AttachedTransformation()->ChannelFlush(channel, completeFlush, propagation, blocking) : false;}
941 	bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true)
942 		{return m_passSignal ? m_owner.AttachedTransformation()->ChannelMessageSeriesEnd(channel, propagation, blocking) : false;}
943 
944 private:
945 	BufferedTransformation &m_owner;
946 	bool m_passSignal;
947 };
948 
949 //! \class ProxyFilter
950 //! \brief Base class for Filter classes that are proxies for a chain of other filters
951 class CRYPTOPP_DLL ProxyFilter : public FilterWithBufferedInput
952 {
953 public:
~ProxyFilter()954 	virtual ~ProxyFilter() {}
955 
956 	//! \brief Construct a ProxyFilter
957 	//! \param filter an output filter
958 	//! \param firstSize the first Put size
959 	//! \param lastSize the last Put size
960 	//! \param attachment an attached transformation
961 	ProxyFilter(BufferedTransformation *filter, size_t firstSize, size_t lastSize, BufferedTransformation *attachment);
962 
963 	bool IsolatedFlush(bool hardFlush, bool blocking);
964 
965 	//! \brief Sets the OutputProxy filter
966 	//! \param filter an OutputProxy filter
967 	void SetFilter(Filter *filter);
968 	void NextPutMultiple(const byte *s, size_t len);
969 	void NextPutModifiable(byte *inString, size_t length);
970 
971 protected:
972 	member_ptr<BufferedTransformation> m_filter;
973 };
974 
975 //! \class SimpleProxyFilter
976 //! \brief Proxy filter that doesn't modify the underlying filter's input or output
977 class CRYPTOPP_DLL SimpleProxyFilter : public ProxyFilter
978 {
979 public:
980 	//! \brief Construct a SimpleProxyFilter
981 	//! \param filter an output filter
982 	//! \param attachment an attached transformation
SimpleProxyFilter(BufferedTransformation * filter,BufferedTransformation * attachment)983 	SimpleProxyFilter(BufferedTransformation *filter, BufferedTransformation *attachment)
984 		: ProxyFilter(filter, 0, 0, attachment) {}
985 
FirstPut(const byte * inString)986 	void FirstPut(const byte * inString)
987 		{CRYPTOPP_UNUSED(inString);}
988 
989 	//! \brief Input the last block of data
990 	//! \param inString the input byte buffer
991 	//! \param length the size of the input buffer, in bytes
992 	//! \details LastPut() processes the last block of data and signals attached filters to do the same.
993 	//!   LastPut() is always called. The pseudo algorithm for the logic is:
994 	//! <pre>
995 	//!     if totalLength < firstSize then length == totalLength
996 	//!     else if totalLength <= firstSize+lastSize then length == totalLength-firstSize
997 	//!     else lastSize <= length < lastSize+blockSize
998 	//! </pre>
LastPut(const byte * inString,size_t length)999 	void LastPut(const byte *inString, size_t length)
1000 		{CRYPTOPP_UNUSED(inString), CRYPTOPP_UNUSED(length); m_filter->MessageEnd();}
1001 };
1002 
1003 //! \class PK_EncryptorFilter
1004 //! \brief Filter wrapper for PK_Encryptor
1005 //! \details PK_DecryptorFilter is a proxy for the filter created by PK_Encryptor::CreateEncryptionFilter.
1006 //!   This class provides symmetry with VerifierFilter.
1007 class CRYPTOPP_DLL PK_EncryptorFilter : public SimpleProxyFilter
1008 {
1009 public:
1010 	//! \brief Construct a PK_EncryptorFilter
1011 	//! \param rng a RandomNumberGenerator derived class
1012 	//! \param encryptor a PK_Encryptor derived class
1013 	//! \param attachment an optional attached transformation
1014 	PK_EncryptorFilter(RandomNumberGenerator &rng, const PK_Encryptor &encryptor, BufferedTransformation *attachment = NULL)
1015 		: SimpleProxyFilter(encryptor.CreateEncryptionFilter(rng), attachment) {}
1016 };
1017 
1018 //! \class PK_DecryptorFilter
1019 //! \brief Filter wrapper for PK_Decryptor
1020 //! \details PK_DecryptorFilter is a proxy for the filter created by PK_Decryptor::CreateDecryptionFilter.
1021 //!   This class provides symmetry with SignerFilter.
1022 class CRYPTOPP_DLL PK_DecryptorFilter : public SimpleProxyFilter
1023 {
1024 public:
1025 	//! \brief Construct a PK_DecryptorFilter
1026 	//! \param rng a RandomNumberGenerator derived class
1027 	//! \param decryptor a PK_Decryptor derived class
1028 	//! \param attachment an optional attached transformation
1029 	PK_DecryptorFilter(RandomNumberGenerator &rng, const PK_Decryptor &decryptor, BufferedTransformation *attachment = NULL)
1030 		: SimpleProxyFilter(decryptor.CreateDecryptionFilter(rng), attachment) {}
1031 };
1032 
1033 //! \class StringSinkTemplate
1034 //! \brief Append input to a string object
1035 //! \tparam T std::basic_string<char> type
1036 //! \details \ref StringSinkTemplate "StringSink" is a StringSinkTemplate typedef
1037 template <class T>
1038 class StringSinkTemplate : public Bufferless<Sink>
1039 {
1040 public:
~StringSinkTemplate()1041 	virtual ~StringSinkTemplate() {}
1042 
1043 	//! \brief Construct a StringSinkTemplate
1044 	//! \param output std::basic_string<char> type
StringSinkTemplate(T & output)1045 	StringSinkTemplate(T &output)
1046 		: m_output(&output) {CRYPTOPP_ASSERT(sizeof(output[0])==1);}
1047 
IsolatedInitialize(const NameValuePairs & parameters)1048 	void IsolatedInitialize(const NameValuePairs &parameters)
1049 		{if (!parameters.GetValue("OutputStringPointer", m_output)) throw InvalidArgument("StringSink: OutputStringPointer not specified");}
1050 
Put2(const byte * inString,size_t length,int messageEnd,bool blocking)1051 	size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
1052 	{
1053 		CRYPTOPP_UNUSED(messageEnd); CRYPTOPP_UNUSED(blocking);
1054 		typedef typename T::traits_type::char_type char_type;
1055 
1056 		if (length > 0)
1057 		{
1058 			typename T::size_type size = m_output->size();
1059 			if (length < size && size + length > m_output->capacity())
1060 				m_output->reserve(2*size);
1061 			m_output->append((const char_type *)inString, (const char_type *)inString+length);
1062 		}
1063 		return 0;
1064 	}
1065 
1066 private:
1067 	T *m_output;
1068 };
1069 
1070 //! \class StringSink
1071 //! \brief Append input to a string object
1072 //! \details StringSink is a typedef for StringSinkTemplate<std::string>.
1073 DOCUMENTED_TYPEDEF(StringSinkTemplate<std::string>, StringSink);
1074 CRYPTOPP_DLL_TEMPLATE_CLASS StringSinkTemplate<std::string>;
1075 
1076 //! \class RandomNumberSink
1077 //! \brief Incorporates input into RNG as additional entropy
1078 class RandomNumberSink : public Bufferless<Sink>
1079 {
1080 public:
~RandomNumberSink()1081 	virtual ~RandomNumberSink() {}
1082 
1083 	//! \brief Construct a RandomNumberSink
RandomNumberSink()1084 	RandomNumberSink()
1085 		: m_rng(NULL) {}
1086 
1087 	//! \brief Construct a RandomNumberSink
1088 	//! \param rng a RandomNumberGenerator derived class
RandomNumberSink(RandomNumberGenerator & rng)1089 	RandomNumberSink(RandomNumberGenerator &rng)
1090 		: m_rng(&rng) {}
1091 
1092 	void IsolatedInitialize(const NameValuePairs &parameters);
1093 	size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking);
1094 
1095 private:
1096 	RandomNumberGenerator *m_rng;
1097 };
1098 
1099 //! \class ArraySink
1100 //! \brief Copy input to a memory buffer
1101 class CRYPTOPP_DLL ArraySink : public Bufferless<Sink>
1102 {
1103 public:
~ArraySink()1104 	virtual ~ArraySink() {}
1105 
1106 	//! \brief Construct an ArraySink
1107 	//! \param parameters a set of NameValuePairs to initialize this object
1108 	//! \details Name::OutputBuffer() is a mandatory parameter using this constructor.
1109 	ArraySink(const NameValuePairs &parameters = g_nullNameValuePairs)
m_buf(NULL)1110 		: m_buf(NULL), m_size(0), m_total(0) {IsolatedInitialize(parameters);}
1111 
1112 	//! \brief Construct an ArraySink
1113 	//! \param buf pointer to a memory buffer
1114 	//! \param size length of the memory buffer
ArraySink(byte * buf,size_t size)1115 	ArraySink(byte *buf, size_t size)
1116 		: m_buf(buf), m_size(size), m_total(0) {}
1117 
1118 	//! \brief Provides the size remaining in the Sink
1119 	//! \returns size remaining in the Sink, in bytes
AvailableSize()1120 	size_t AvailableSize() {return SaturatingSubtract(m_size, m_total);}
1121 
1122 	//! \brief Provides the number of bytes written to the Sink
1123 	//! \returns number of bytes written to the Sink, in bytes
TotalPutLength()1124 	lword TotalPutLength() {return m_total;}
1125 
1126 	void IsolatedInitialize(const NameValuePairs &parameters);
1127 	byte * CreatePutSpace(size_t &size);
1128 	size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking);
1129 
1130 protected:
1131 	byte *m_buf;
1132 	size_t m_size;
1133 	lword m_total;
1134 };
1135 
1136 //! \class ArrayXorSink
1137 //! \brief Xor input to a memory buffer
1138 class CRYPTOPP_DLL ArrayXorSink : public ArraySink
1139 {
1140 public:
~ArrayXorSink()1141 	virtual ~ArrayXorSink() {}
1142 
1143 	//! \brief Construct an ArrayXorSink
1144 	//! \param buf pointer to a memory buffer
1145 	//! \param size length of the memory buffer
ArrayXorSink(byte * buf,size_t size)1146 	ArrayXorSink(byte *buf, size_t size)
1147 		: ArraySink(buf, size) {}
1148 
1149 	size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking);
CreatePutSpace(size_t & size)1150 	byte * CreatePutSpace(size_t &size) {return BufferedTransformation::CreatePutSpace(size);}
1151 };
1152 
1153 //! \class StringStore
1154 //! \brief String-based implementation of Store interface
1155 class StringStore : public Store
1156 {
1157 public:
1158 	//! \brief Construct a StringStore
1159 	//! \param string pointer to a C-String
1160 	StringStore(const char *string = NULL)
1161 		{StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string)));}
1162 
1163 	//! \brief Construct a StringStore
1164 	//! \param string pointer to a memory buffer
1165 	//! \param length size of the memory buffer
StringStore(const byte * string,size_t length)1166 	StringStore(const byte *string, size_t length)
1167 		{StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string, length)));}
1168 
1169 	//! \brief Construct a StringStore
1170 	//! \tparam T std::basic_string<char> type
1171 	//! \param string reference to a std::basic_string<char> type
StringStore(const T & string)1172 	template <class T> StringStore(const T &string)
1173 		{StoreInitialize(MakeParameters("InputBuffer", ConstByteArrayParameter(string)));}
1174 
1175 	CRYPTOPP_DLL size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
1176 	CRYPTOPP_DLL size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
1177 
1178 private:
1179 	CRYPTOPP_DLL void StoreInitialize(const NameValuePairs &parameters);
1180 
1181 	const byte *m_store;
1182 	size_t m_length, m_count;
1183 };
1184 
1185 //! RNG-based implementation of Source interface
1186 class CRYPTOPP_DLL RandomNumberStore : public Store
1187 {
1188 public:
~RandomNumberStore()1189 	virtual ~RandomNumberStore() {}
1190 
RandomNumberStore()1191 	RandomNumberStore()
1192 		: m_rng(NULL), m_length(0), m_count(0) {}
1193 
RandomNumberStore(RandomNumberGenerator & rng,lword length)1194 	RandomNumberStore(RandomNumberGenerator &rng, lword length)
1195 		: m_rng(&rng), m_length(length), m_count(0) {}
1196 
AnyRetrievable()1197 	bool AnyRetrievable() const {return MaxRetrievable() != 0;}
MaxRetrievable()1198 	lword MaxRetrievable() const {return m_length-m_count;}
1199 
1200 	size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
1201 	size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const
1202 	{
1203 		CRYPTOPP_UNUSED(target); CRYPTOPP_UNUSED(begin); CRYPTOPP_UNUSED(end); CRYPTOPP_UNUSED(channel); CRYPTOPP_UNUSED(blocking);
1204 		throw NotImplemented("RandomNumberStore: CopyRangeTo2() is not supported by this store");
1205 	}
1206 
1207 private:
1208 	void StoreInitialize(const NameValuePairs &parameters);
1209 
1210 	RandomNumberGenerator *m_rng;
1211 	lword m_length, m_count;
1212 };
1213 
1214 //! empty store
1215 class CRYPTOPP_DLL NullStore : public Store
1216 {
1217 public:
m_size(size)1218 	NullStore(lword size = ULONG_MAX) : m_size(size) {}
StoreInitialize(const NameValuePairs & parameters)1219 	void StoreInitialize(const NameValuePairs &parameters)
1220 		{CRYPTOPP_UNUSED(parameters);}
MaxRetrievable()1221 	lword MaxRetrievable() const {return m_size;}
1222 	size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
1223 	size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
1224 
1225 private:
1226 	lword m_size;
1227 };
1228 
1229 //! \class Source
1230 //! \brief Implementation of BufferedTransformation's attachment interface
1231 //! \details Source is a cornerstone of the Pipeline trinitiy. Data flows from
1232 //!   Sources, through Filters, and then terminates in Sinks. The difference
1233 //!   between a Source and Filter is a Source \a pumps data, while a Filter does
1234 //!   not. The difference between a Filter and a Sink is a Filter allows an
1235 //!   attached transformation, while a Sink does not.
1236 //! \details See the discussion of BufferedTransformation in cryptlib.h for
1237 //!   more details.
1238 //! \sa Store and SourceTemplate
1239 class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Source : public InputRejecting<Filter>
1240 {
1241 public:
~Source()1242 	virtual ~Source() {}
1243 
1244 	//! \brief Construct a Source
1245 	//! \param attachment an optional attached transformation
1246 	Source(BufferedTransformation *attachment = NULL)
1247 		{Source::Detach(attachment);}
1248 
1249 	//!	\name PIPELINE
1250 	//@{
1251 
1252 	//! \brief Pump data to attached transformation
1253 	//! \param pumpMax the maximpum number of bytes to pump
1254 	//! \returns the number of bytes that remain in the block (i.e., bytes not processed)
1255 	//! \details Internally, Pump() calls Pump2().
1256 	//! \note pumpMax is a \p lword, which is a 64-bit value that typically uses \p LWORD_MAX. The default
1257 	//!   argument is a \p size_t that uses \p SIZE_MAX, and it can be 32-bits or 64-bits.
1258 	lword Pump(lword pumpMax=(size_t)SIZE_MAX)
1259 		{Pump2(pumpMax); return pumpMax;}
1260 
1261 	//! \brief Pump messages to attached transformation
1262 	//! \param count the maximpum number of messages to pump
1263 	//! \returns TODO
1264 	//! \details Internally, PumpMessages() calls PumpMessages2().
1265 	unsigned int PumpMessages(unsigned int count=UINT_MAX)
1266 		{PumpMessages2(count); return count;}
1267 
1268 	//! \brief Pump all data to attached transformation
1269 	//! \details Internally, PumpAll() calls PumpAll2().
PumpAll()1270 	void PumpAll()
1271 		{PumpAll2();}
1272 
1273 	//! \brief Pump data to attached transformation
1274 	//! \param byteCount the maximpum number of bytes to pump
1275 	//! \param blocking specifies whether the object should block when processing input
1276 	//! \returns the number of bytes that remain in the block (i.e., bytes not processed)
1277 	//! \details byteCount is an \a IN and \a OUT parameter. When the call is made, byteCount is the
1278 	//!   requested size of the pump. When the call returns, byteCount is the number of bytes that
1279 	//!   were pumped.
1280 	virtual size_t Pump2(lword &byteCount, bool blocking=true) =0;
1281 
1282 	//! \brief Pump messages to attached transformation
1283 	//! \param messageCount the maximpum number of messages to pump
1284 	//! \param blocking specifies whether the object should block when processing input
1285 	//! \details messageCount is an IN and OUT parameter.
1286 	virtual size_t PumpMessages2(unsigned int &messageCount, bool blocking=true) =0;
1287 
1288 	//! \brief Pump all data to attached transformation
1289 	//! \param blocking specifies whether the object should block when processing input
1290 	//! \returns the number of bytes that remain in the block (i.e., bytes not processed)
1291 	virtual size_t PumpAll2(bool blocking=true);
1292 
1293 	//! \brief Determines if the Source is exhausted
1294 	//! \returns true if the source has been exhausted
1295 	virtual bool SourceExhausted() const =0;
1296 
1297 	//@}
1298 
1299 protected:
SourceInitialize(bool pumpAll,const NameValuePairs & parameters)1300 	void SourceInitialize(bool pumpAll, const NameValuePairs &parameters)
1301 	{
1302 		IsolatedInitialize(parameters);
1303 		if (pumpAll)
1304 			PumpAll();
1305 	}
1306 };
1307 
1308 //! \class SourceTemplate
1309 //! \brief Transform a Store into a Source
1310 //! \tparam T the class or type
1311 template <class T>
1312 class SourceTemplate : public Source
1313 {
1314 public:
~SourceTemplate()1315 	virtual ~SourceTemplate() {}
1316 
1317 	//! \brief Construct a SourceTemplate
1318 	//! \tparam T the class or type
1319 	//! \param attachment an attached transformation
1320 	SourceTemplate<T>(BufferedTransformation *attachment)
Source(attachment)1321 		: Source(attachment) {}
IsolatedInitialize(const NameValuePairs & parameters)1322 	void IsolatedInitialize(const NameValuePairs &parameters)
1323 		{m_store.IsolatedInitialize(parameters);}
1324 	size_t Pump2(lword &byteCount, bool blocking=true)
1325 		{return m_store.TransferTo2(*AttachedTransformation(), byteCount, DEFAULT_CHANNEL, blocking);}
1326 	size_t PumpMessages2(unsigned int &messageCount, bool blocking=true)
1327 		{return m_store.TransferMessagesTo2(*AttachedTransformation(), messageCount, DEFAULT_CHANNEL, blocking);}
1328 	size_t PumpAll2(bool blocking=true)
1329 		{return m_store.TransferAllTo2(*AttachedTransformation(), DEFAULT_CHANNEL, blocking);}
SourceExhausted()1330 	bool SourceExhausted() const
1331 		{return !m_store.AnyRetrievable() && !m_store.AnyMessages();}
SetAutoSignalPropagation(int propagation)1332 	void SetAutoSignalPropagation(int propagation)
1333 		{m_store.SetAutoSignalPropagation(propagation);}
GetAutoSignalPropagation()1334 	int GetAutoSignalPropagation() const
1335 		{return m_store.GetAutoSignalPropagation();}
1336 
1337 protected:
1338 	T m_store;
1339 };
1340 
1341 //! \class SourceTemplate
1342 //! \brief String-based implementation of the Source interface
1343 class CRYPTOPP_DLL StringSource : public SourceTemplate<StringStore>
1344 {
1345 public:
1346 	//! \brief Construct a StringSource
1347 	//! \param attachment an optional attached transformation
1348 	StringSource(BufferedTransformation *attachment = NULL)
1349 		: SourceTemplate<StringStore>(attachment) {}
1350 
1351 	//! \brief Construct a StringSource
1352 	//! \param string C-String
1353 	//! \param pumpAll flag indicating if source data should be pumped to its attached transformation
1354 	//! \param attachment an optional attached transformation
1355 	StringSource(const char *string, bool pumpAll, BufferedTransformation *attachment = NULL)
1356 		: SourceTemplate<StringStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string)));}
1357 
1358 	//! \brief Construct a StringSource
1359 	//! \param string binary byte array
1360 	//! \param length size of the byte array
1361 	//! \param pumpAll flag indicating if source data should be pumped to its attached transformation
1362 	//! \param attachment an optional attached transformation
1363 	StringSource(const byte *string, size_t length, bool pumpAll, BufferedTransformation *attachment = NULL)
1364 		: SourceTemplate<StringStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string, length)));}
1365 
1366 	//! \brief Construct a StringSource
1367 	//! \param string std::string
1368 	//! \param pumpAll flag indicating if source data should be pumped to its attached transformation
1369 	//! \param attachment an optional attached transformation
1370 	StringSource(const std::string &string, bool pumpAll, BufferedTransformation *attachment = NULL)
1371 		: SourceTemplate<StringStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputBuffer", ConstByteArrayParameter(string)));}
1372 };
1373 
1374 //! \class ArraySource
1375 //! \brief Pointer-based implementation of the Source interface
1376 //! \details ArraySource is a typedef for StringSource. Use the third constructor for an array source.
1377 //!   The third constructor takes a pointer and length.
1378 //! \since Crypto++ 5.6.0
1379 DOCUMENTED_TYPEDEF(StringSource, ArraySource);
1380 
1381 //! RNG-based implementation of Source interface
1382 class CRYPTOPP_DLL RandomNumberSource : public SourceTemplate<RandomNumberStore>
1383 {
1384 public:
1385 	RandomNumberSource(RandomNumberGenerator &rng, int length, bool pumpAll, BufferedTransformation *attachment = NULL)
1386 		: SourceTemplate<RandomNumberStore>(attachment)
1387 		{SourceInitialize(pumpAll, MakeParameters("RandomNumberGeneratorPointer", &rng)("RandomNumberStoreSize", length));}
1388 };
1389 
1390 NAMESPACE_END
1391 
1392 #if CRYPTOPP_MSC_VERSION
1393 # pragma warning(pop)
1394 #endif
1395 
1396 #endif
1397