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 ¶meters=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 ¶meters, 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 ¶meters)
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 ¶meters);
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 ¶meters, 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 ¶meters)
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 ¶meters)
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 ¶meters, 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 ¶meters);
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 ¶meters, 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 ¶meters);
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 ¶meters, 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 ¶meters);
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 ¶meters, 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 = ⌖}
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 ¶meters, 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 ¶meters=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 ¶meters)
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 ¶meters);
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 ¶meters = 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 ¶meters);
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 ¶meters);
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 ¶meters);
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 ¶meters)
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 ¶meters)
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 ¶meters)
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