~ubuntu-branches/debian/squeeze/pycryptopp/squeeze

« back to all changes in this revision

Viewing changes to cryptopp/filters.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Zooko O'Whielacronx
  • Date: 2009-06-22 22:20:50 UTC
  • Revision ID: james.westby@ubuntu.com-20090622222050-hbqmn50dt2kvoz5o
Tags: upstream-0.5.14
ImportĀ upstreamĀ versionĀ 0.5.14

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// filters.cpp - written and placed in the public domain by Wei Dai
 
2
 
 
3
#include "pch.h"
 
4
 
 
5
#ifndef CRYPTOPP_IMPORTS
 
6
 
 
7
#include "filters.h"
 
8
#include "mqueue.h"
 
9
#include "fltrimpl.h"
 
10
#include "argnames.h"
 
11
#include <memory>
 
12
#include <functional>
 
13
 
 
14
NAMESPACE_BEGIN(CryptoPP)
 
15
 
 
16
Filter::Filter(BufferedTransformation *attachment)
 
17
        : m_attachment(attachment), m_continueAt(0)
 
18
{
 
19
}
 
20
 
 
21
BufferedTransformation * Filter::NewDefaultAttachment() const
 
22
{
 
23
        return new MessageQueue;
 
24
}
 
25
 
 
26
BufferedTransformation * Filter::AttachedTransformation()
 
27
{
 
28
        if (m_attachment.get() == NULL)
 
29
                m_attachment.reset(NewDefaultAttachment());
 
30
        return m_attachment.get();
 
31
}
 
32
 
 
33
const BufferedTransformation *Filter::AttachedTransformation() const
 
34
{
 
35
        if (m_attachment.get() == NULL)
 
36
                const_cast<Filter *>(this)->m_attachment.reset(NewDefaultAttachment());
 
37
        return m_attachment.get();
 
38
}
 
39
 
 
40
void Filter::Detach(BufferedTransformation *newOut)
 
41
{
 
42
        m_attachment.reset(newOut);
 
43
}
 
44
 
 
45
void Filter::Insert(Filter *filter)
 
46
{
 
47
        filter->m_attachment.reset(m_attachment.release());
 
48
        m_attachment.reset(filter);
 
49
}
 
50
 
 
51
size_t Filter::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
 
52
{
 
53
        return AttachedTransformation()->CopyRangeTo2(target, begin, end, channel, blocking);
 
54
}
 
55
 
 
56
size_t Filter::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
 
57
{
 
58
        return AttachedTransformation()->TransferTo2(target, transferBytes, channel, blocking);
 
59
}
 
60
 
 
61
void Filter::Initialize(const NameValuePairs &parameters, int propagation)
 
62
{
 
63
        m_continueAt = 0;
 
64
        IsolatedInitialize(parameters);
 
65
        PropagateInitialize(parameters, propagation);
 
66
}
 
67
 
 
68
bool Filter::Flush(bool hardFlush, int propagation, bool blocking)
 
69
{
 
70
        switch (m_continueAt)
 
71
        {
 
72
        case 0:
 
73
                if (IsolatedFlush(hardFlush, blocking))
 
74
                        return true;
 
75
        case 1:
 
76
                if (OutputFlush(1, hardFlush, propagation, blocking))
 
77
                        return true;
 
78
        }
 
79
        return false;
 
80
}
 
81
 
 
82
bool Filter::MessageSeriesEnd(int propagation, bool blocking)
 
83
{
 
84
        switch (m_continueAt)
 
85
        {
 
86
        case 0:
 
87
                if (IsolatedMessageSeriesEnd(blocking))
 
88
                        return true;
 
89
        case 1:
 
90
                if (ShouldPropagateMessageSeriesEnd() && OutputMessageSeriesEnd(1, propagation, blocking))
 
91
                        return true;
 
92
        }
 
93
        return false;
 
94
}
 
95
 
 
96
void Filter::PropagateInitialize(const NameValuePairs &parameters, int propagation)
 
97
{
 
98
        if (propagation)
 
99
                AttachedTransformation()->Initialize(parameters, propagation-1);
 
100
}
 
101
 
 
102
size_t Filter::OutputModifiable(int outputSite, byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel)
 
103
{
 
104
        if (messageEnd)
 
105
                messageEnd--;
 
106
        size_t result = AttachedTransformation()->ChannelPutModifiable2(channel, inString, length, messageEnd, blocking);
 
107
        m_continueAt = result ? outputSite : 0;
 
108
        return result;
 
109
}
 
110
 
 
111
size_t Filter::Output(int outputSite, const byte *inString, size_t length, int messageEnd, bool blocking, const std::string &channel)
 
112
{
 
113
        if (messageEnd)
 
114
                messageEnd--;
 
115
        size_t result = AttachedTransformation()->ChannelPut2(channel, inString, length, messageEnd, blocking);
 
116
        m_continueAt = result ? outputSite : 0;
 
117
        return result;
 
118
}
 
119
 
 
120
bool Filter::OutputFlush(int outputSite, bool hardFlush, int propagation, bool blocking, const std::string &channel)
 
121
{
 
122
        if (propagation && AttachedTransformation()->ChannelFlush(channel, hardFlush, propagation-1, blocking))
 
123
        {
 
124
                m_continueAt = outputSite;
 
125
                return true;
 
126
        }
 
127
        m_continueAt = 0;
 
128
        return false;
 
129
}
 
130
 
 
131
bool Filter::OutputMessageSeriesEnd(int outputSite, int propagation, bool blocking, const std::string &channel)
 
132
{
 
133
        if (propagation && AttachedTransformation()->ChannelMessageSeriesEnd(channel, propagation-1, blocking))
 
134
        {
 
135
                m_continueAt = outputSite;
 
136
                return true;
 
137
        }
 
138
        m_continueAt = 0;
 
139
        return false;
 
140
}
 
141
 
 
142
// *************************************************************
 
143
 
 
144
void MeterFilter::ResetMeter()
 
145
{
 
146
        m_currentMessageBytes = m_totalBytes = m_currentSeriesMessages = m_totalMessages = m_totalMessageSeries = 0;
 
147
        m_rangesToSkip.clear();
 
148
}
 
149
 
 
150
void MeterFilter::AddRangeToSkip(unsigned int message, lword position, lword size, bool sortNow)
 
151
{
 
152
        MessageRange r = {message, position, size};
 
153
        m_rangesToSkip.push_back(r);
 
154
        if (sortNow)
 
155
                std::sort(m_rangesToSkip.begin(), m_rangesToSkip.end());
 
156
}
 
157
 
 
158
size_t MeterFilter::PutMaybeModifiable(byte *begin, size_t length, int messageEnd, bool blocking, bool modifiable)
 
159
{
 
160
        if (!m_transparent)
 
161
                return 0;
 
162
 
 
163
        size_t t;
 
164
        FILTER_BEGIN;
 
165
 
 
166
        m_begin = begin;
 
167
        m_length = length;
 
168
 
 
169
        while (m_length > 0 || messageEnd)
 
170
        {
 
171
                if (m_length > 0  && !m_rangesToSkip.empty() && m_rangesToSkip.front().message == m_totalMessages && m_currentMessageBytes + m_length > m_rangesToSkip.front().position)
 
172
                {
 
173
                        FILTER_OUTPUT_MAYBE_MODIFIABLE(1, m_begin, t = (size_t)SaturatingSubtract(m_rangesToSkip.front().position, m_currentMessageBytes), false, modifiable);
 
174
 
 
175
                        assert(t < m_length);
 
176
                        m_begin += t;
 
177
                        m_length -= t;
 
178
                        m_currentMessageBytes += t;
 
179
                        m_totalBytes += t;
 
180
 
 
181
                        if (m_currentMessageBytes + m_length < m_rangesToSkip.front().position + m_rangesToSkip.front().size)
 
182
                                t = m_length;
 
183
                        else
 
184
                        {
 
185
                                t = (size_t)SaturatingSubtract(m_rangesToSkip.front().position + m_rangesToSkip.front().size, m_currentMessageBytes);
 
186
                                assert(t <= m_length);
 
187
                                m_rangesToSkip.pop_front();
 
188
                        }
 
189
 
 
190
                        m_begin += t;
 
191
                        m_length -= t;
 
192
                        m_currentMessageBytes += t;
 
193
                        m_totalBytes += t;
 
194
                }
 
195
                else
 
196
                {
 
197
                        FILTER_OUTPUT_MAYBE_MODIFIABLE(2, m_begin, m_length, messageEnd, modifiable);
 
198
 
 
199
                        m_currentMessageBytes += m_length;
 
200
                        m_totalBytes += m_length;
 
201
                        m_length = 0;
 
202
 
 
203
                        if (messageEnd)
 
204
                        {
 
205
                                m_currentMessageBytes = 0;
 
206
                                m_currentSeriesMessages++;
 
207
                                m_totalMessages++;
 
208
                                messageEnd = false;
 
209
                        }
 
210
                }
 
211
        }
 
212
 
 
213
        FILTER_END_NO_MESSAGE_END;
 
214
}
 
215
 
 
216
size_t MeterFilter::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
 
217
{
 
218
        return PutMaybeModifiable(const_cast<byte *>(begin), length, messageEnd, blocking, false);
 
219
}
 
220
 
 
221
size_t MeterFilter::PutModifiable2(byte *begin, size_t length, int messageEnd, bool blocking)
 
222
{
 
223
        return PutMaybeModifiable(begin, length, messageEnd, blocking, true);
 
224
}
 
225
 
 
226
bool MeterFilter::IsolatedMessageSeriesEnd(bool blocking)
 
227
{
 
228
        m_currentMessageBytes = 0;
 
229
        m_currentSeriesMessages = 0;
 
230
        m_totalMessageSeries++;
 
231
        return false;
 
232
}
 
233
 
 
234
// *************************************************************
 
235
 
 
236
void FilterWithBufferedInput::BlockQueue::ResetQueue(size_t blockSize, size_t maxBlocks)
 
237
{
 
238
        m_buffer.New(blockSize * maxBlocks);
 
239
        m_blockSize = blockSize;
 
240
        m_maxBlocks = maxBlocks;
 
241
        m_size = 0;
 
242
        m_begin = m_buffer;
 
243
}
 
244
 
 
245
byte *FilterWithBufferedInput::BlockQueue::GetBlock()
 
246
{
 
247
        if (m_size >= m_blockSize)
 
248
        {
 
249
                byte *ptr = m_begin;
 
250
                if ((m_begin+=m_blockSize) == m_buffer.end())
 
251
                        m_begin = m_buffer;
 
252
                m_size -= m_blockSize;
 
253
                return ptr;
 
254
        }
 
255
        else
 
256
                return NULL;
 
257
}
 
258
 
 
259
byte *FilterWithBufferedInput::BlockQueue::GetContigousBlocks(size_t &numberOfBytes)
 
260
{
 
261
        numberOfBytes = STDMIN(numberOfBytes, STDMIN(size_t(m_buffer.end()-m_begin), m_size));
 
262
        byte *ptr = m_begin;
 
263
        m_begin += numberOfBytes;
 
264
        m_size -= numberOfBytes;
 
265
        if (m_size == 0 || m_begin == m_buffer.end())
 
266
                m_begin = m_buffer;
 
267
        return ptr;
 
268
}
 
269
 
 
270
size_t FilterWithBufferedInput::BlockQueue::GetAll(byte *outString)
 
271
{
 
272
        size_t size = m_size;
 
273
        size_t numberOfBytes = m_maxBlocks*m_blockSize;
 
274
        const byte *ptr = GetContigousBlocks(numberOfBytes);
 
275
        memcpy(outString, ptr, numberOfBytes);
 
276
        memcpy(outString+numberOfBytes, m_begin, m_size);
 
277
        m_size = 0;
 
278
        return size;
 
279
}
 
280
 
 
281
void FilterWithBufferedInput::BlockQueue::Put(const byte *inString, size_t length)
 
282
{
 
283
        assert(m_size + length <= m_buffer.size());
 
284
        byte *end = (m_size < size_t(m_buffer.end()-m_begin)) ? m_begin + m_size : m_begin + m_size - m_buffer.size();
 
285
        size_t len = STDMIN(length, size_t(m_buffer.end()-end));
 
286
        memcpy(end, inString, len);
 
287
        if (len < length)
 
288
                memcpy(m_buffer, inString+len, length-len);
 
289
        m_size += length;
 
290
}
 
291
 
 
292
FilterWithBufferedInput::FilterWithBufferedInput(BufferedTransformation *attachment)
 
293
        : Filter(attachment)
 
294
{
 
295
}
 
296
 
 
297
FilterWithBufferedInput::FilterWithBufferedInput(size_t firstSize, size_t blockSize, size_t lastSize, BufferedTransformation *attachment)
 
298
        : Filter(attachment), m_firstSize(firstSize), m_blockSize(blockSize), m_lastSize(lastSize)
 
299
        , m_firstInputDone(false)
 
300
{
 
301
        if (m_firstSize < 0 || m_blockSize < 1 || m_lastSize < 0)
 
302
                throw InvalidArgument("FilterWithBufferedInput: invalid buffer size");
 
303
 
 
304
        m_queue.ResetQueue(1, m_firstSize);
 
305
}
 
306
 
 
307
void FilterWithBufferedInput::IsolatedInitialize(const NameValuePairs &parameters)
 
308
{
 
309
        InitializeDerivedAndReturnNewSizes(parameters, m_firstSize, m_blockSize, m_lastSize);
 
310
        if (m_firstSize < 0 || m_blockSize < 1 || m_lastSize < 0)
 
311
                throw InvalidArgument("FilterWithBufferedInput: invalid buffer size");
 
312
        m_queue.ResetQueue(1, m_firstSize);
 
313
        m_firstInputDone = false;
 
314
}
 
315
 
 
316
bool FilterWithBufferedInput::IsolatedFlush(bool hardFlush, bool blocking)
 
317
{
 
318
        if (!blocking)
 
319
                throw BlockingInputOnly("FilterWithBufferedInput");
 
320
        
 
321
        if (hardFlush)
 
322
                ForceNextPut();
 
323
        FlushDerived();
 
324
        
 
325
        return false;
 
326
}
 
327
 
 
328
size_t FilterWithBufferedInput::PutMaybeModifiable(byte *inString, size_t length, int messageEnd, bool blocking, bool modifiable)
 
329
{
 
330
        if (!blocking)
 
331
                throw BlockingInputOnly("FilterWithBufferedInput");
 
332
 
 
333
        if (length != 0)
 
334
        {
 
335
                size_t newLength = m_queue.CurrentSize() + length;
 
336
 
 
337
                if (!m_firstInputDone && newLength >= m_firstSize)
 
338
                {
 
339
                        size_t len = m_firstSize - m_queue.CurrentSize();
 
340
                        m_queue.Put(inString, len);
 
341
                        FirstPut(m_queue.GetContigousBlocks(m_firstSize));
 
342
                        assert(m_queue.CurrentSize() == 0);
 
343
                        m_queue.ResetQueue(m_blockSize, (2*m_blockSize+m_lastSize-2)/m_blockSize);
 
344
 
 
345
                        inString += len;
 
346
                        newLength -= m_firstSize;
 
347
                        m_firstInputDone = true;
 
348
                }
 
349
 
 
350
                if (m_firstInputDone)
 
351
                {
 
352
                        if (m_blockSize == 1)
 
353
                        {
 
354
                                while (newLength > m_lastSize && m_queue.CurrentSize() > 0)
 
355
                                {
 
356
                                        size_t len = newLength - m_lastSize;
 
357
                                        byte *ptr = m_queue.GetContigousBlocks(len);
 
358
                                        NextPutModifiable(ptr, len);
 
359
                                        newLength -= len;
 
360
                                }
 
361
 
 
362
                                if (newLength > m_lastSize)
 
363
                                {
 
364
                                        size_t len = newLength - m_lastSize;
 
365
                                        NextPutMaybeModifiable(inString, len, modifiable);
 
366
                                        inString += len;
 
367
                                        newLength -= len;
 
368
                                }
 
369
                        }
 
370
                        else
 
371
                        {
 
372
                                while (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() >= m_blockSize)
 
373
                                {
 
374
                                        NextPutModifiable(m_queue.GetBlock(), m_blockSize);
 
375
                                        newLength -= m_blockSize;
 
376
                                }
 
377
 
 
378
                                if (newLength >= m_blockSize + m_lastSize && m_queue.CurrentSize() > 0)
 
379
                                {
 
380
                                        assert(m_queue.CurrentSize() < m_blockSize);
 
381
                                        size_t len = m_blockSize - m_queue.CurrentSize();
 
382
                                        m_queue.Put(inString, len);
 
383
                                        inString += len;
 
384
                                        NextPutModifiable(m_queue.GetBlock(), m_blockSize);
 
385
                                        newLength -= m_blockSize;
 
386
                                }
 
387
 
 
388
                                if (newLength >= m_blockSize + m_lastSize)
 
389
                                {
 
390
                                        size_t len = RoundDownToMultipleOf(newLength - m_lastSize, m_blockSize);
 
391
                                        NextPutMaybeModifiable(inString, len, modifiable);
 
392
                                        inString += len;
 
393
                                        newLength -= len;
 
394
                                }
 
395
                        }
 
396
                }
 
397
 
 
398
                m_queue.Put(inString, newLength - m_queue.CurrentSize());
 
399
        }
 
400
 
 
401
        if (messageEnd)
 
402
        {
 
403
                if (!m_firstInputDone && m_firstSize==0)
 
404
                        FirstPut(NULL);
 
405
 
 
406
                SecByteBlock temp(m_queue.CurrentSize());
 
407
                m_queue.GetAll(temp);
 
408
                LastPut(temp, temp.size());
 
409
 
 
410
                m_firstInputDone = false;
 
411
                m_queue.ResetQueue(1, m_firstSize);
 
412
 
 
413
                Output(1, NULL, 0, messageEnd, blocking);
 
414
        }
 
415
        return 0;
 
416
}
 
417
 
 
418
void FilterWithBufferedInput::ForceNextPut()
 
419
{
 
420
        if (!m_firstInputDone)
 
421
                return;
 
422
        
 
423
        if (m_blockSize > 1)
 
424
        {
 
425
                while (m_queue.CurrentSize() >= m_blockSize)
 
426
                        NextPutModifiable(m_queue.GetBlock(), m_blockSize);
 
427
        }
 
428
        else
 
429
        {
 
430
                size_t len;
 
431
                while ((len = m_queue.CurrentSize()) > 0)
 
432
                        NextPutModifiable(m_queue.GetContigousBlocks(len), len);
 
433
        }
 
434
}
 
435
 
 
436
void FilterWithBufferedInput::NextPutMultiple(const byte *inString, size_t length)
 
437
{
 
438
        assert(m_blockSize > 1);        // m_blockSize = 1 should always override this function
 
439
        while (length > 0)
 
440
        {
 
441
                assert(length >= m_blockSize);
 
442
                NextPutSingle(inString);
 
443
                inString += m_blockSize;
 
444
                length -= m_blockSize;
 
445
        }
 
446
}
 
447
 
 
448
// *************************************************************
 
449
 
 
450
void Redirector::Initialize(const NameValuePairs &parameters, int propagation)
 
451
{
 
452
        m_target = parameters.GetValueWithDefault("RedirectionTargetPointer", (BufferedTransformation*)NULL);
 
453
        m_behavior = parameters.GetIntValueWithDefault("RedirectionBehavior", PASS_EVERYTHING);
 
454
 
 
455
        if (m_target && GetPassSignals())
 
456
                m_target->Initialize(parameters, propagation);
 
457
}
 
458
 
 
459
// *************************************************************
 
460
 
 
461
ProxyFilter::ProxyFilter(BufferedTransformation *filter, size_t firstSize, size_t lastSize, BufferedTransformation *attachment)
 
462
        : FilterWithBufferedInput(firstSize, 1, lastSize, attachment), m_filter(filter)
 
463
{
 
464
        if (m_filter.get())
 
465
                m_filter->Attach(new OutputProxy(*this, false));
 
466
}
 
467
 
 
468
bool ProxyFilter::IsolatedFlush(bool hardFlush, bool blocking)
 
469
{
 
470
        return m_filter.get() ? m_filter->Flush(hardFlush, -1, blocking) : false;
 
471
}
 
472
 
 
473
void ProxyFilter::SetFilter(Filter *filter)
 
474
{
 
475
        m_filter.reset(filter);
 
476
        if (filter)
 
477
        {
 
478
                OutputProxy *proxy;
 
479
                std::auto_ptr<OutputProxy> temp(proxy = new OutputProxy(*this, false));
 
480
                m_filter->TransferAllTo(*proxy);
 
481
                m_filter->Attach(temp.release());
 
482
        }
 
483
}
 
484
 
 
485
void ProxyFilter::NextPutMultiple(const byte *s, size_t len)
 
486
{
 
487
        if (m_filter.get())
 
488
                m_filter->Put(s, len);
 
489
}
 
490
 
 
491
void ProxyFilter::NextPutModifiable(byte *s, size_t len)
 
492
{
 
493
        if (m_filter.get())
 
494
                m_filter->PutModifiable(s, len);
 
495
}
 
496
 
 
497
// *************************************************************
 
498
 
 
499
void RandomNumberSink::IsolatedInitialize(const NameValuePairs &parameters)
 
500
{
 
501
        parameters.GetRequiredParameter("RandomNumberSink", "RandomNumberGeneratorPointer", m_rng);
 
502
}
 
503
 
 
504
size_t RandomNumberSink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
 
505
{
 
506
        m_rng->IncorporateEntropy(begin, length);
 
507
        return 0;
 
508
}
 
509
 
 
510
size_t ArraySink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
 
511
{
 
512
        if (m_buf+m_total != begin)
 
513
                memcpy(m_buf+m_total, begin, STDMIN(length, SaturatingSubtract(m_size, m_total)));
 
514
        m_total += length;
 
515
        return 0;
 
516
}
 
517
 
 
518
byte * ArraySink::CreatePutSpace(size_t &size)
 
519
{
 
520
        size = SaturatingSubtract(m_size, m_total);
 
521
        return m_buf + m_total;
 
522
}
 
523
 
 
524
void ArraySink::IsolatedInitialize(const NameValuePairs &parameters)
 
525
{
 
526
        ByteArrayParameter array;
 
527
        if (!parameters.GetValue(Name::OutputBuffer(), array))
 
528
                throw InvalidArgument("ArraySink: missing OutputBuffer argument");
 
529
        m_buf = array.begin();
 
530
        m_size = array.size();
 
531
        m_total = 0;
 
532
}
 
533
 
 
534
size_t ArrayXorSink::Put2(const byte *begin, size_t length, int messageEnd, bool blocking)
 
535
{
 
536
        xorbuf(m_buf+m_total, begin, STDMIN(length, SaturatingSubtract(m_size, m_total)));
 
537
        m_total += length;
 
538
        return 0;
 
539
}
 
540
 
 
541
// *************************************************************
 
542
 
 
543
StreamTransformationFilter::StreamTransformationFilter(StreamTransformation &c, BufferedTransformation *attachment, BlockPaddingScheme padding, bool allowAuthenticatedSymmetricCipher)
 
544
   : FilterWithBufferedInput(attachment)
 
545
        , m_cipher(c)
 
546
{
 
547
        assert(c.MinLastBlockSize() == 0 || c.MinLastBlockSize() > c.MandatoryBlockSize());
 
548
 
 
549
        if (!allowAuthenticatedSymmetricCipher && dynamic_cast<AuthenticatedSymmetricCipher *>(&c) != 0)
 
550
                throw InvalidArgument("StreamTransformationFilter: please use AuthenticatedEncryptionFilter and AuthenticatedDecryptionFilter for AuthenticatedSymmetricCipher");
 
551
 
 
552
        IsolatedInitialize(MakeParameters(Name::BlockPaddingScheme(), padding));
 
553
}
 
554
 
 
555
size_t StreamTransformationFilter::LastBlockSize(StreamTransformation &c, BlockPaddingScheme padding)
 
556
{
 
557
        if (c.MinLastBlockSize() > 0)
 
558
                return c.MinLastBlockSize();
 
559
        else if (c.MandatoryBlockSize() > 1 && !c.IsForwardTransformation() && padding != NO_PADDING && padding != ZEROS_PADDING)
 
560
                return c.MandatoryBlockSize();
 
561
        else
 
562
                return 0;
 
563
}
 
564
 
 
565
void StreamTransformationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
 
566
{
 
567
        BlockPaddingScheme padding = parameters.GetValueWithDefault(Name::BlockPaddingScheme(), DEFAULT_PADDING);
 
568
        bool isBlockCipher = (m_cipher.MandatoryBlockSize() > 1 && m_cipher.MinLastBlockSize() == 0);
 
569
 
 
570
        if (padding == DEFAULT_PADDING)
 
571
                m_padding = isBlockCipher ? PKCS_PADDING : NO_PADDING;
 
572
        else
 
573
                m_padding = padding;
 
574
 
 
575
        if (!isBlockCipher && (m_padding == PKCS_PADDING || m_padding == ONE_AND_ZEROS_PADDING))
 
576
                throw InvalidArgument("StreamTransformationFilter: PKCS_PADDING and ONE_AND_ZEROS_PADDING cannot be used with " + m_cipher.AlgorithmName());
 
577
 
 
578
        firstSize = 0;
 
579
        blockSize = m_cipher.MandatoryBlockSize();
 
580
        lastSize = LastBlockSize(m_cipher, m_padding);
 
581
}
 
582
 
 
583
void StreamTransformationFilter::FirstPut(const byte *inString)
 
584
{
 
585
        m_optimalBufferSize = m_cipher.OptimalBlockSize();
 
586
        m_optimalBufferSize = (unsigned int)STDMAX(m_optimalBufferSize, RoundDownToMultipleOf(4096U, m_optimalBufferSize));
 
587
}
 
588
 
 
589
void StreamTransformationFilter::NextPutMultiple(const byte *inString, size_t length)
 
590
{
 
591
        if (!length)
 
592
                return;
 
593
 
 
594
        size_t s = m_cipher.MandatoryBlockSize();
 
595
 
 
596
        do
 
597
        {
 
598
                size_t len = m_optimalBufferSize;
 
599
                byte *space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, s, length, len);
 
600
                if (len < length)
 
601
                {
 
602
                        if (len == m_optimalBufferSize)
 
603
                                len -= m_cipher.GetOptimalBlockSizeUsed();
 
604
                        len = RoundDownToMultipleOf(len, s);
 
605
                }
 
606
                else
 
607
                        len = length;
 
608
                m_cipher.ProcessString(space, inString, len);
 
609
                AttachedTransformation()->PutModifiable(space, len);
 
610
                inString += len;
 
611
                length -= len;
 
612
        }
 
613
        while (length > 0);
 
614
}
 
615
 
 
616
void StreamTransformationFilter::NextPutModifiable(byte *inString, size_t length)
 
617
{
 
618
        m_cipher.ProcessString(inString, length);
 
619
        AttachedTransformation()->PutModifiable(inString, length);
 
620
}
 
621
 
 
622
void StreamTransformationFilter::LastPut(const byte *inString, size_t length)
 
623
{
 
624
        byte *space = NULL;
 
625
        
 
626
        switch (m_padding)
 
627
        {
 
628
        case NO_PADDING:
 
629
        case ZEROS_PADDING:
 
630
                if (length > 0)
 
631
                {
 
632
                        size_t minLastBlockSize = m_cipher.MinLastBlockSize();
 
633
                        bool isForwardTransformation = m_cipher.IsForwardTransformation();
 
634
 
 
635
                        if (isForwardTransformation && m_padding == ZEROS_PADDING && (minLastBlockSize == 0 || length < minLastBlockSize))
 
636
                        {
 
637
                                // do padding
 
638
                                size_t blockSize = STDMAX(minLastBlockSize, (size_t)m_cipher.MandatoryBlockSize());
 
639
                                space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, blockSize);
 
640
                                memcpy(space, inString, length);
 
641
                                memset(space + length, 0, blockSize - length);
 
642
                                m_cipher.ProcessLastBlock(space, space, blockSize);
 
643
                                AttachedTransformation()->Put(space, blockSize);
 
644
                        }
 
645
                        else
 
646
                        {
 
647
                                if (minLastBlockSize == 0)
 
648
                                {
 
649
                                        if (isForwardTransformation)
 
650
                                                throw InvalidDataFormat("StreamTransformationFilter: plaintext length is not a multiple of block size and NO_PADDING is specified");
 
651
                                        else
 
652
                                                throw InvalidCiphertext("StreamTransformationFilter: ciphertext length is not a multiple of block size");
 
653
                                }
 
654
 
 
655
                                space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, length, m_optimalBufferSize);
 
656
                                m_cipher.ProcessLastBlock(space, inString, length);
 
657
                                AttachedTransformation()->Put(space, length);
 
658
                        }
 
659
                }
 
660
                break;
 
661
 
 
662
        case PKCS_PADDING:
 
663
        case ONE_AND_ZEROS_PADDING:
 
664
                unsigned int s;
 
665
                s = m_cipher.MandatoryBlockSize();
 
666
                assert(s > 1);
 
667
                space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, s, m_optimalBufferSize);
 
668
                if (m_cipher.IsForwardTransformation())
 
669
                {
 
670
                        assert(length < s);
 
671
                        memcpy(space, inString, length);
 
672
                        if (m_padding == PKCS_PADDING)
 
673
                        {
 
674
                                assert(s < 256);
 
675
                                byte pad = byte(s-length);
 
676
                                memset(space+length, pad, s-length);
 
677
                        }
 
678
                        else
 
679
                        {
 
680
                                space[length] = 0x80;
 
681
                                memset(space+length+1, 0, s-length-1);
 
682
                        }
 
683
                        m_cipher.ProcessData(space, space, s);
 
684
                        AttachedTransformation()->Put(space, s);
 
685
                }
 
686
                else
 
687
                {
 
688
                        if (length != s)
 
689
                                throw InvalidCiphertext("StreamTransformationFilter: ciphertext length is not a multiple of block size");
 
690
                        m_cipher.ProcessData(space, inString, s);
 
691
                        if (m_padding == PKCS_PADDING)
 
692
                        {
 
693
                                byte pad = space[s-1];
 
694
                                if (pad < 1 || pad > s || std::find_if(space+s-pad, space+s, std::bind2nd(std::not_equal_to<byte>(), pad)) != space+s)
 
695
                                        throw InvalidCiphertext("StreamTransformationFilter: invalid PKCS #7 block padding found");
 
696
                                length = s-pad;
 
697
                        }
 
698
                        else
 
699
                        {
 
700
                                while (length > 1 && space[length-1] == 0)
 
701
                                        --length;
 
702
                                if (space[--length] != 0x80)
 
703
                                        throw InvalidCiphertext("StreamTransformationFilter: invalid ones-and-zeros padding found");
 
704
                        }
 
705
                        AttachedTransformation()->Put(space, length);
 
706
                }
 
707
                break;
 
708
 
 
709
        default:
 
710
                assert(false);
 
711
        }
 
712
}
 
713
 
 
714
// *************************************************************
 
715
 
 
716
HashFilter::HashFilter(HashTransformation &hm, BufferedTransformation *attachment, bool putMessage, int truncatedDigestSize, const std::string &messagePutChannel, const std::string &hashPutChannel)
 
717
        : m_hashModule(hm), m_putMessage(putMessage), m_messagePutChannel(messagePutChannel), m_hashPutChannel(hashPutChannel)
 
718
{
 
719
        m_digestSize = truncatedDigestSize < 0 ? m_hashModule.DigestSize() : truncatedDigestSize;
 
720
        Detach(attachment);
 
721
}
 
722
 
 
723
void HashFilter::IsolatedInitialize(const NameValuePairs &parameters)
 
724
{
 
725
        m_putMessage = parameters.GetValueWithDefault(Name::PutMessage(), false);
 
726
        int s = parameters.GetIntValueWithDefault(Name::TruncatedDigestSize(), -1);
 
727
        m_digestSize = s < 0 ? m_hashModule.DigestSize() : s;
 
728
}
 
729
 
 
730
size_t HashFilter::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
 
731
{
 
732
        FILTER_BEGIN;
 
733
        if (m_putMessage)
 
734
                FILTER_OUTPUT3(1, 0, inString, length, 0, m_messagePutChannel);
 
735
        m_hashModule.Update(inString, length);
 
736
        if (messageEnd)
 
737
        {
 
738
                {
 
739
                        size_t size;
 
740
                        m_space = HelpCreatePutSpace(*AttachedTransformation(), m_hashPutChannel, m_digestSize, m_digestSize, size = m_digestSize);
 
741
                        m_hashModule.TruncatedFinal(m_space, m_digestSize);
 
742
                }
 
743
                FILTER_OUTPUT3(2, 0, m_space, m_digestSize, messageEnd, m_hashPutChannel);
 
744
        }
 
745
        FILTER_END_NO_MESSAGE_END;
 
746
}
 
747
 
 
748
// *************************************************************
 
749
 
 
750
HashVerificationFilter::HashVerificationFilter(HashTransformation &hm, BufferedTransformation *attachment, word32 flags, int truncatedDigestSize)
 
751
        : FilterWithBufferedInput(attachment)
 
752
        , m_hashModule(hm)
 
753
{
 
754
        IsolatedInitialize(MakeParameters(Name::HashVerificationFilterFlags(), flags)(Name::TruncatedDigestSize(), truncatedDigestSize));
 
755
}
 
756
 
 
757
void HashVerificationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
 
758
{
 
759
        m_flags = parameters.GetValueWithDefault(Name::HashVerificationFilterFlags(), (word32)DEFAULT_FLAGS);
 
760
        int s = parameters.GetIntValueWithDefault(Name::TruncatedDigestSize(), -1);
 
761
        m_digestSize = s < 0 ? m_hashModule.DigestSize() : s;
 
762
        m_verified = false;
 
763
        firstSize = m_flags & HASH_AT_BEGIN ? m_digestSize : 0;
 
764
        blockSize = 1;
 
765
        lastSize = m_flags & HASH_AT_BEGIN ? 0 : m_digestSize;
 
766
}
 
767
 
 
768
void HashVerificationFilter::FirstPut(const byte *inString)
 
769
{
 
770
        if (m_flags & HASH_AT_BEGIN)
 
771
        {
 
772
                m_expectedHash.New(m_digestSize);
 
773
                memcpy(m_expectedHash, inString, m_expectedHash.size());
 
774
                if (m_flags & PUT_HASH)
 
775
                        AttachedTransformation()->Put(inString, m_expectedHash.size());
 
776
        }
 
777
}
 
778
 
 
779
void HashVerificationFilter::NextPutMultiple(const byte *inString, size_t length)
 
780
{
 
781
        m_hashModule.Update(inString, length);
 
782
        if (m_flags & PUT_MESSAGE)
 
783
                AttachedTransformation()->Put(inString, length);
 
784
}
 
785
 
 
786
void HashVerificationFilter::LastPut(const byte *inString, size_t length)
 
787
{
 
788
        if (m_flags & HASH_AT_BEGIN)
 
789
        {
 
790
                assert(length == 0);
 
791
                m_verified = m_hashModule.TruncatedVerify(m_expectedHash, m_digestSize);
 
792
        }
 
793
        else
 
794
        {
 
795
                m_verified = (length==m_digestSize && m_hashModule.TruncatedVerify(inString, length));
 
796
                if (m_flags & PUT_HASH)
 
797
                        AttachedTransformation()->Put(inString, length);
 
798
        }
 
799
 
 
800
        if (m_flags & PUT_RESULT)
 
801
                AttachedTransformation()->Put(m_verified);
 
802
 
 
803
        if ((m_flags & THROW_EXCEPTION) && !m_verified)
 
804
                throw HashVerificationFailed();
 
805
}
 
806
 
 
807
// *************************************************************
 
808
 
 
809
AuthenticatedEncryptionFilter::AuthenticatedEncryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment, 
 
810
                                                                bool putAAD, int truncatedDigestSize, const std::string &macChannel, BlockPaddingScheme padding)
 
811
        : StreamTransformationFilter(c, attachment, padding, true)
 
812
        , m_hf(c, new OutputProxy(*this, false), putAAD, truncatedDigestSize, AAD_CHANNEL, macChannel)
 
813
{
 
814
        assert(c.IsForwardTransformation());
 
815
}
 
816
 
 
817
void AuthenticatedEncryptionFilter::IsolatedInitialize(const NameValuePairs &parameters)
 
818
{
 
819
        m_hf.IsolatedInitialize(parameters);
 
820
        StreamTransformationFilter::IsolatedInitialize(parameters);
 
821
}
 
822
 
 
823
byte * AuthenticatedEncryptionFilter::ChannelCreatePutSpace(const std::string &channel, size_t &size)
 
824
{
 
825
        if (channel.empty())
 
826
                return StreamTransformationFilter::CreatePutSpace(size);
 
827
 
 
828
        if (channel == AAD_CHANNEL)
 
829
                return m_hf.CreatePutSpace(size);
 
830
 
 
831
        throw InvalidChannelName("AuthenticatedEncryptionFilter", channel);
 
832
}
 
833
 
 
834
size_t AuthenticatedEncryptionFilter::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
 
835
{
 
836
        if (channel.empty())
 
837
                return StreamTransformationFilter::Put2(begin, length, messageEnd, blocking);
 
838
 
 
839
        if (channel == AAD_CHANNEL)
 
840
                return m_hf.Put2(begin, length, 0, blocking);
 
841
 
 
842
        throw InvalidChannelName("AuthenticatedEncryptionFilter", channel);
 
843
}
 
844
 
 
845
void AuthenticatedEncryptionFilter::LastPut(const byte *inString, size_t length)
 
846
{
 
847
        StreamTransformationFilter::LastPut(inString, length);
 
848
        m_hf.MessageEnd();
 
849
}
 
850
 
 
851
// *************************************************************
 
852
 
 
853
AuthenticatedDecryptionFilter::AuthenticatedDecryptionFilter(AuthenticatedSymmetricCipher &c, BufferedTransformation *attachment, word32 flags, int truncatedDigestSize, BlockPaddingScheme padding)
 
854
        : FilterWithBufferedInput(attachment)
 
855
        , m_hashVerifier(c, new OutputProxy(*this, false))
 
856
        , m_streamFilter(c, new OutputProxy(*this, false), padding, true)
 
857
{
 
858
        assert(!c.IsForwardTransformation() || c.IsSelfInverting());
 
859
        IsolatedInitialize(MakeParameters(Name::BlockPaddingScheme(), padding)(Name::AuthenticatedDecryptionFilterFlags(), flags)(Name::TruncatedDigestSize(), truncatedDigestSize));
 
860
}
 
861
 
 
862
void AuthenticatedDecryptionFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
 
863
{
 
864
        word32 flags = parameters.GetValueWithDefault(Name::AuthenticatedDecryptionFilterFlags(), (word32)DEFAULT_FLAGS);
 
865
 
 
866
        m_hashVerifier.Initialize(CombinedNameValuePairs(parameters, MakeParameters(Name::HashVerificationFilterFlags(), flags)));
 
867
        m_streamFilter.Initialize(parameters);
 
868
 
 
869
        firstSize = m_hashVerifier.m_firstSize;
 
870
        blockSize = 1;
 
871
        lastSize = m_hashVerifier.m_lastSize;
 
872
}
 
873
 
 
874
byte * AuthenticatedDecryptionFilter::ChannelCreatePutSpace(const std::string &channel, size_t &size)
 
875
{
 
876
        if (channel.empty())
 
877
                return m_streamFilter.CreatePutSpace(size);
 
878
 
 
879
        if (channel == AAD_CHANNEL)
 
880
                return m_hashVerifier.CreatePutSpace(size);
 
881
 
 
882
        throw InvalidChannelName("AuthenticatedDecryptionFilter", channel);
 
883
}
 
884
 
 
885
size_t AuthenticatedDecryptionFilter::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
 
886
{
 
887
        if (channel.empty())
 
888
        {
 
889
                if (m_lastSize > 0)
 
890
                        m_hashVerifier.ForceNextPut();
 
891
                return FilterWithBufferedInput::Put2(begin, length, messageEnd, blocking);
 
892
        }
 
893
 
 
894
        if (channel == AAD_CHANNEL)
 
895
                return m_hashVerifier.Put2(begin, length, 0, blocking);
 
896
 
 
897
        throw InvalidChannelName("AuthenticatedDecryptionFilter", channel);
 
898
}
 
899
 
 
900
void AuthenticatedDecryptionFilter::FirstPut(const byte *inString)
 
901
{
 
902
        m_hashVerifier.Put(inString, m_firstSize);
 
903
}
 
904
 
 
905
void AuthenticatedDecryptionFilter::NextPutMultiple(const byte *inString, size_t length)
 
906
{
 
907
        m_streamFilter.Put(inString, length);
 
908
}
 
909
 
 
910
void AuthenticatedDecryptionFilter::LastPut(const byte *inString, size_t length)
 
911
{
 
912
        m_streamFilter.MessageEnd();
 
913
        m_hashVerifier.PutMessageEnd(inString, length);
 
914
}
 
915
 
 
916
// *************************************************************
 
917
 
 
918
void SignerFilter::IsolatedInitialize(const NameValuePairs &parameters)
 
919
{
 
920
        m_putMessage = parameters.GetValueWithDefault(Name::PutMessage(), false);
 
921
        m_messageAccumulator.reset(m_signer.NewSignatureAccumulator(m_rng));
 
922
}
 
923
 
 
924
size_t SignerFilter::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
 
925
{
 
926
        FILTER_BEGIN;
 
927
        m_messageAccumulator->Update(inString, length);
 
928
        if (m_putMessage)
 
929
                FILTER_OUTPUT(1, inString, length, 0);
 
930
        if (messageEnd)
 
931
        {
 
932
                m_buf.New(m_signer.SignatureLength());
 
933
                m_signer.Sign(m_rng, m_messageAccumulator.release(), m_buf);
 
934
                FILTER_OUTPUT(2, m_buf, m_buf.size(), messageEnd);
 
935
                m_messageAccumulator.reset(m_signer.NewSignatureAccumulator(m_rng));
 
936
        }
 
937
        FILTER_END_NO_MESSAGE_END;
 
938
}
 
939
 
 
940
SignatureVerificationFilter::SignatureVerificationFilter(const PK_Verifier &verifier, BufferedTransformation *attachment, word32 flags)
 
941
        : FilterWithBufferedInput(attachment)
 
942
        , m_verifier(verifier)
 
943
{
 
944
        IsolatedInitialize(MakeParameters(Name::SignatureVerificationFilterFlags(), flags));
 
945
}
 
946
 
 
947
void SignatureVerificationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
 
948
{
 
949
        m_flags = parameters.GetValueWithDefault(Name::SignatureVerificationFilterFlags(), (word32)DEFAULT_FLAGS);
 
950
        m_messageAccumulator.reset(m_verifier.NewVerificationAccumulator());
 
951
        size_t size = m_verifier.SignatureLength();
 
952
        assert(size != 0);      // TODO: handle recoverable signature scheme
 
953
        m_verified = false;
 
954
        firstSize = m_flags & SIGNATURE_AT_BEGIN ? size : 0;
 
955
        blockSize = 1;
 
956
        lastSize = m_flags & SIGNATURE_AT_BEGIN ? 0 : size;
 
957
}
 
958
 
 
959
void SignatureVerificationFilter::FirstPut(const byte *inString)
 
960
{
 
961
        if (m_flags & SIGNATURE_AT_BEGIN)
 
962
        {
 
963
                if (m_verifier.SignatureUpfront())
 
964
                        m_verifier.InputSignature(*m_messageAccumulator, inString, m_verifier.SignatureLength());
 
965
                else
 
966
                {
 
967
                        m_signature.New(m_verifier.SignatureLength());
 
968
                        memcpy(m_signature, inString, m_signature.size());
 
969
                }
 
970
 
 
971
                if (m_flags & PUT_SIGNATURE)
 
972
                        AttachedTransformation()->Put(inString, m_signature.size());
 
973
        }
 
974
        else
 
975
        {
 
976
                assert(!m_verifier.SignatureUpfront());
 
977
        }
 
978
}
 
979
 
 
980
void SignatureVerificationFilter::NextPutMultiple(const byte *inString, size_t length)
 
981
{
 
982
        m_messageAccumulator->Update(inString, length);
 
983
        if (m_flags & PUT_MESSAGE)
 
984
                AttachedTransformation()->Put(inString, length);
 
985
}
 
986
 
 
987
void SignatureVerificationFilter::LastPut(const byte *inString, size_t length)
 
988
{
 
989
        if (m_flags & SIGNATURE_AT_BEGIN)
 
990
        {
 
991
                assert(length == 0);
 
992
                m_verifier.InputSignature(*m_messageAccumulator, m_signature, m_signature.size());
 
993
                m_verified = m_verifier.VerifyAndRestart(*m_messageAccumulator);
 
994
        }
 
995
        else
 
996
        {
 
997
                m_verifier.InputSignature(*m_messageAccumulator, inString, length);
 
998
                m_verified = m_verifier.VerifyAndRestart(*m_messageAccumulator);
 
999
                if (m_flags & PUT_SIGNATURE)
 
1000
                        AttachedTransformation()->Put(inString, length);
 
1001
        }
 
1002
 
 
1003
        if (m_flags & PUT_RESULT)
 
1004
                AttachedTransformation()->Put(m_verified);
 
1005
 
 
1006
        if ((m_flags & THROW_EXCEPTION) && !m_verified)
 
1007
                throw SignatureVerificationFailed();
 
1008
}
 
1009
 
 
1010
// *************************************************************
 
1011
 
 
1012
size_t Source::PumpAll2(bool blocking)
 
1013
{
 
1014
        unsigned int messageCount = UINT_MAX;
 
1015
        do {
 
1016
                RETURN_IF_NONZERO(PumpMessages2(messageCount, blocking));
 
1017
        } while(messageCount == UINT_MAX);
 
1018
 
 
1019
        return 0;
 
1020
}
 
1021
 
 
1022
bool Store::GetNextMessage()
 
1023
{
 
1024
        if (!m_messageEnd && !AnyRetrievable())
 
1025
        {
 
1026
                m_messageEnd=true;
 
1027
                return true;
 
1028
        }
 
1029
        else
 
1030
                return false;
 
1031
}
 
1032
 
 
1033
unsigned int Store::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const
 
1034
{
 
1035
        if (m_messageEnd || count == 0)
 
1036
                return 0;
 
1037
        else
 
1038
        {
 
1039
                CopyTo(target, ULONG_MAX, channel);
 
1040
                if (GetAutoSignalPropagation())
 
1041
                        target.ChannelMessageEnd(channel, GetAutoSignalPropagation()-1);
 
1042
                return 1;
 
1043
        }
 
1044
}
 
1045
 
 
1046
void StringStore::StoreInitialize(const NameValuePairs &parameters)
 
1047
{
 
1048
        ConstByteArrayParameter array;
 
1049
        if (!parameters.GetValue(Name::InputBuffer(), array))
 
1050
                throw InvalidArgument("StringStore: missing InputBuffer argument");
 
1051
        m_store = array.begin();
 
1052
        m_length = array.size();
 
1053
        m_count = 0;
 
1054
}
 
1055
 
 
1056
size_t StringStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
 
1057
{
 
1058
        lword position = 0;
 
1059
        size_t blockedBytes = CopyRangeTo2(target, position, transferBytes, channel, blocking);
 
1060
        m_count += (size_t)position;
 
1061
        transferBytes = position;
 
1062
        return blockedBytes;
 
1063
}
 
1064
 
 
1065
size_t StringStore::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
 
1066
{
 
1067
        size_t i = UnsignedMin(m_length, m_count+begin);
 
1068
        size_t len = UnsignedMin(m_length-i, end-begin);
 
1069
        size_t blockedBytes = target.ChannelPut2(channel, m_store+i, len, 0, blocking);
 
1070
        if (!blockedBytes)
 
1071
                begin += len;
 
1072
        return blockedBytes;
 
1073
}
 
1074
 
 
1075
void RandomNumberStore::StoreInitialize(const NameValuePairs &parameters)
 
1076
{
 
1077
        parameters.GetRequiredParameter("RandomNumberStore", "RandomNumberGeneratorPointer", m_rng);
 
1078
        int length;
 
1079
        parameters.GetRequiredIntParameter("RandomNumberStore", "RandomNumberStoreSize", length);
 
1080
        m_length = length;
 
1081
}
 
1082
 
 
1083
size_t RandomNumberStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
 
1084
{
 
1085
        if (!blocking)
 
1086
                throw NotImplemented("RandomNumberStore: nonblocking transfer is not implemented by this object");
 
1087
 
 
1088
        transferBytes = UnsignedMin(transferBytes, m_length - m_count);
 
1089
        m_rng->GenerateIntoBufferedTransformation(target, channel, transferBytes);
 
1090
        m_count += transferBytes;
 
1091
 
 
1092
        return 0;
 
1093
}
 
1094
 
 
1095
size_t NullStore::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
 
1096
{
 
1097
        static const byte nullBytes[128] = {0};
 
1098
        while (begin < end)
 
1099
        {
 
1100
                size_t len = (size_t)STDMIN(end-begin, lword(128));
 
1101
                size_t blockedBytes = target.ChannelPut2(channel, nullBytes, len, 0, blocking);
 
1102
                if (blockedBytes)
 
1103
                        return blockedBytes;
 
1104
                begin += len;
 
1105
        }
 
1106
        return 0;
 
1107
}
 
1108
 
 
1109
size_t NullStore::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
 
1110
{
 
1111
        lword begin = 0;
 
1112
        size_t blockedBytes = NullStore::CopyRangeTo2(target, begin, transferBytes, channel, blocking);
 
1113
        transferBytes = begin;
 
1114
        m_size -= begin;
 
1115
        return blockedBytes;
 
1116
}
 
1117
 
 
1118
NAMESPACE_END
 
1119
 
 
1120
#endif