104 lines
2.3 KiB
C++
104 lines
2.3 KiB
C++
// filters.cpp - written and placed in the public domain by Wei Dai
|
|
|
|
#include "pch.h"
|
|
#include "filters.h"
|
|
#include "queue.h"
|
|
#include <memory>
|
|
|
|
#if __cplusplus >= 201103L
|
|
# define TW_UNIQUE_PTR std::unique_ptr
|
|
#else
|
|
# define TW_UNIQUE_PTR std::auto_ptr
|
|
#endif
|
|
|
|
Filter::Filter(BufferedTransformation *outQ)
|
|
: outQueue(outQ ? outQ : new ByteQueue)
|
|
{
|
|
}
|
|
|
|
Filter::Filter(const Filter &source)
|
|
: outQueue(new ByteQueue)
|
|
{
|
|
}
|
|
|
|
void Filter::Detach(BufferedTransformation *newOut)
|
|
{
|
|
TW_UNIQUE_PTR<BufferedTransformation> out(newOut ? newOut : new ByteQueue);
|
|
outQueue->Close();
|
|
outQueue->TransferTo(*out);
|
|
outQueue.reset(out.release());
|
|
}
|
|
|
|
void Filter::Attach(BufferedTransformation *newOut)
|
|
{
|
|
if (outQueue->Attachable())
|
|
outQueue->Attach(newOut);
|
|
else
|
|
Detach(newOut);
|
|
}
|
|
|
|
BlockFilterBase::BlockFilterBase(BlockTransformation &c,
|
|
BufferedTransformation *outQ)
|
|
: Filter(outQ), cipher(c), S(cipher.BlockSize()), inBuf(S)
|
|
{
|
|
inBufSize=0;
|
|
}
|
|
|
|
void BlockFilterBase::ProcessBuf()
|
|
{
|
|
cipher.ProcessBlock(inBuf);
|
|
outQueue->Put(inBuf, S);
|
|
inBufSize=0;
|
|
}
|
|
|
|
void BlockFilterBase::Put(const byte *inString, unsigned int length)
|
|
{
|
|
while (length--)
|
|
BlockFilterBase::Put(*inString++);
|
|
}
|
|
|
|
void BlockEncryptionFilter::InputFinished()
|
|
{
|
|
if (inBufSize == S)
|
|
ProcessBuf();
|
|
// pad last block
|
|
memset(inBuf+inBufSize, S-inBufSize, S-inBufSize);
|
|
ProcessBuf();
|
|
}
|
|
|
|
void BlockDecryptionFilter::InputFinished()
|
|
{
|
|
cipher.ProcessBlock(inBuf);
|
|
if (inBuf[S-1] > S)
|
|
inBuf[S-1] = 0; // something's wrong with the padding
|
|
outQueue->Put(inBuf, S-inBuf[S-1]);
|
|
inBufSize=0;
|
|
}
|
|
|
|
void StreamCipherFilter::Put(const byte *inString, unsigned int length)
|
|
{
|
|
SecByteBlock temp(length);
|
|
cipher.ProcessString(temp, inString, length);
|
|
outQueue->Put(temp, length);
|
|
}
|
|
|
|
void HashFilter::InputFinished()
|
|
{
|
|
SecByteBlock buf(hash.DigestSize());
|
|
hash.Final(buf);
|
|
outQueue->Put(buf, hash.DigestSize());
|
|
}
|
|
|
|
BufferedTransformation *Insert(const byte *in, unsigned int length, BufferedTransformation *outQueue)
|
|
{
|
|
outQueue->Put(in, length);
|
|
return outQueue;
|
|
}
|
|
|
|
unsigned int Extract(Source *source, byte *out, unsigned int length)
|
|
{
|
|
while (source->MaxRetrieveable() < length && source->Pump(1));
|
|
return source->Get(out, length);
|
|
}
|
|
|