Removed m_authenticated member variable
Add m_isSpecial, m_mandatoryBlockSize and m_optimalBufferSize members. The additional members stabilize running times and avoid some unnecessary calculations. Previously we were calculating some values in each call to Put and LastPut.pull/484/merge
parent
04d15304f1
commit
73928489f9
75
filters.cpp
75
filters.cpp
|
|
@ -580,21 +580,25 @@ size_t ArrayXorSink::Put2(const byte *begin, size_t length, int messageEnd, bool
|
||||||
// *************************************************************
|
// *************************************************************
|
||||||
|
|
||||||
StreamTransformationFilter::StreamTransformationFilter(StreamTransformation &c, BufferedTransformation *attachment, BlockPaddingScheme padding)
|
StreamTransformationFilter::StreamTransformationFilter(StreamTransformation &c, BufferedTransformation *attachment, BlockPaddingScheme padding)
|
||||||
: FilterWithBufferedInput(attachment)
|
: FilterWithBufferedInput(attachment), m_cipher(c), m_padding(DEFAULT_PADDING)
|
||||||
, m_cipher(c), m_padding(DEFAULT_PADDING), m_optimalBufferSize(0), m_authenticated(false)
|
|
||||||
{
|
{
|
||||||
CRYPTOPP_ASSERT(c.MinLastBlockSize() == 0 || c.MinLastBlockSize() > c.MandatoryBlockSize());
|
CRYPTOPP_ASSERT(c.MinLastBlockSize() == 0 || c.MinLastBlockSize() > c.MandatoryBlockSize());
|
||||||
|
|
||||||
const bool authenticatedFilter = dynamic_cast<AuthenticatedSymmetricCipher *>(&c) != NULLPTR;
|
const bool authenticatedFilter = dynamic_cast<AuthenticatedSymmetricCipher *>(&c) != NULLPTR;
|
||||||
if (authenticatedFilter && !m_authenticated)
|
if (authenticatedFilter)
|
||||||
throw InvalidArgument("StreamTransformationFilter: please use AuthenticatedEncryptionFilter and AuthenticatedDecryptionFilter for AuthenticatedSymmetricCipher");
|
throw InvalidArgument("StreamTransformationFilter: please use AuthenticatedEncryptionFilter and AuthenticatedDecryptionFilter for AuthenticatedSymmetricCipher");
|
||||||
|
|
||||||
|
// InitializeDerivedAndReturnNewSizes may override some of these
|
||||||
|
m_mandatoryBlockSize = m_cipher.MandatoryBlockSize();
|
||||||
|
m_optimalBufferSize = m_cipher.OptimalBlockSize();
|
||||||
|
m_isSpecial = m_cipher.IsLastBlockSpecial() && m_mandatoryBlockSize > 1;
|
||||||
|
m_reservedBufferSize = STDMAX(2*m_mandatoryBlockSize, m_optimalBufferSize);
|
||||||
|
|
||||||
IsolatedInitialize(MakeParameters(Name::BlockPaddingScheme(), padding));
|
IsolatedInitialize(MakeParameters(Name::BlockPaddingScheme(), padding));
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamTransformationFilter::StreamTransformationFilter(StreamTransformation &c, BufferedTransformation *attachment, BlockPaddingScheme padding, bool authenticated)
|
StreamTransformationFilter::StreamTransformationFilter(StreamTransformation &c, BufferedTransformation *attachment, BlockPaddingScheme padding, bool authenticated)
|
||||||
: FilterWithBufferedInput(attachment)
|
: FilterWithBufferedInput(attachment), m_cipher(c), m_padding(DEFAULT_PADDING)
|
||||||
, m_cipher(c), m_padding(DEFAULT_PADDING), m_optimalBufferSize(0), m_authenticated(authenticated)
|
|
||||||
{
|
{
|
||||||
const bool authenticatedFilter = dynamic_cast<AuthenticatedSymmetricCipher *>(&c) != NULLPTR;
|
const bool authenticatedFilter = dynamic_cast<AuthenticatedSymmetricCipher *>(&c) != NULLPTR;
|
||||||
if (!authenticatedFilter)
|
if (!authenticatedFilter)
|
||||||
|
|
@ -602,9 +606,15 @@ StreamTransformationFilter::StreamTransformationFilter(StreamTransformation &c,
|
||||||
CRYPTOPP_ASSERT(c.MinLastBlockSize() == 0 || c.MinLastBlockSize() > c.MandatoryBlockSize());
|
CRYPTOPP_ASSERT(c.MinLastBlockSize() == 0 || c.MinLastBlockSize() > c.MandatoryBlockSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (authenticatedFilter && !m_authenticated)
|
if (authenticatedFilter && !authenticated)
|
||||||
throw InvalidArgument("StreamTransformationFilter: please use AuthenticatedEncryptionFilter and AuthenticatedDecryptionFilter for AuthenticatedSymmetricCipher");
|
throw InvalidArgument("StreamTransformationFilter: please use AuthenticatedEncryptionFilter and AuthenticatedDecryptionFilter for AuthenticatedSymmetricCipher");
|
||||||
|
|
||||||
|
// InitializeDerivedAndReturnNewSizes may override some of these
|
||||||
|
m_mandatoryBlockSize = m_cipher.MandatoryBlockSize();
|
||||||
|
m_optimalBufferSize = m_cipher.OptimalBlockSize();
|
||||||
|
m_isSpecial = m_cipher.IsLastBlockSpecial() && m_mandatoryBlockSize > 1;
|
||||||
|
m_reservedBufferSize = STDMAX(2*m_mandatoryBlockSize, m_optimalBufferSize);
|
||||||
|
|
||||||
IsolatedInitialize(MakeParameters(Name::BlockPaddingScheme(), padding));
|
IsolatedInitialize(MakeParameters(Name::BlockPaddingScheme(), padding));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -614,14 +624,14 @@ size_t StreamTransformationFilter::LastBlockSize(StreamTransformation &c, BlockP
|
||||||
return c.MinLastBlockSize();
|
return c.MinLastBlockSize();
|
||||||
else if (c.MandatoryBlockSize() > 1 && !c.IsForwardTransformation() && padding != NO_PADDING && padding != ZEROS_PADDING)
|
else if (c.MandatoryBlockSize() > 1 && !c.IsForwardTransformation() && padding != NO_PADDING && padding != ZEROS_PADDING)
|
||||||
return c.MandatoryBlockSize();
|
return c.MandatoryBlockSize();
|
||||||
else
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StreamTransformationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
|
void StreamTransformationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs ¶meters, size_t &firstSize, size_t &blockSize, size_t &lastSize)
|
||||||
{
|
{
|
||||||
BlockPaddingScheme padding = parameters.GetValueWithDefault(Name::BlockPaddingScheme(), DEFAULT_PADDING);
|
BlockPaddingScheme padding = parameters.GetValueWithDefault(Name::BlockPaddingScheme(), DEFAULT_PADDING);
|
||||||
bool isBlockCipher = (m_cipher.MandatoryBlockSize() > 1 && m_cipher.MinLastBlockSize() == 0);
|
bool isBlockCipher = (m_mandatoryBlockSize > 1 && m_cipher.MinLastBlockSize() == 0);
|
||||||
|
|
||||||
if (padding == DEFAULT_PADDING)
|
if (padding == DEFAULT_PADDING)
|
||||||
m_padding = isBlockCipher ? PKCS_PADDING : NO_PADDING;
|
m_padding = isBlockCipher ? PKCS_PADDING : NO_PADDING;
|
||||||
|
|
@ -639,24 +649,22 @@ void StreamTransformationFilter::InitializeDerivedAndReturnNewSizes(const NameVa
|
||||||
}
|
}
|
||||||
|
|
||||||
firstSize = 0;
|
firstSize = 0;
|
||||||
blockSize = m_cipher.MandatoryBlockSize();
|
blockSize = m_mandatoryBlockSize;
|
||||||
lastSize = LastBlockSize(m_cipher, m_padding);
|
lastSize = LastBlockSize(m_cipher, m_padding);
|
||||||
}
|
}
|
||||||
|
|
||||||
void StreamTransformationFilter::FirstPut(const byte* inString)
|
void StreamTransformationFilter::FirstPut(const byte* inString)
|
||||||
{
|
{
|
||||||
CRYPTOPP_UNUSED(inString);
|
CRYPTOPP_UNUSED(inString);
|
||||||
m_optimalBufferSize = m_cipher.OptimalBlockSize();
|
m_optimalBufferSize = STDMAX<unsigned int>(m_optimalBufferSize, RoundDownToMultipleOf(4096U, m_optimalBufferSize));
|
||||||
m_optimalBufferSize = (unsigned int)STDMAX(m_optimalBufferSize, RoundDownToMultipleOf(4096U, m_optimalBufferSize));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StreamTransformationFilter::NextPutMultiple(const byte *inString, size_t length)
|
void StreamTransformationFilter::NextPutMultiple(const byte *inString, size_t length)
|
||||||
{
|
{
|
||||||
if (!length)
|
if (!length)
|
||||||
return;
|
{return;}
|
||||||
|
|
||||||
size_t s = m_cipher.MandatoryBlockSize();
|
|
||||||
|
|
||||||
|
const size_t s = m_cipher.MandatoryBlockSize();
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
size_t len = m_optimalBufferSize;
|
size_t len = m_optimalBufferSize;
|
||||||
|
|
@ -700,25 +708,17 @@ void StreamTransformationFilter::LastPut(const byte *inString, size_t length)
|
||||||
// response we hacked a IsLastBlockSpecial(). When true StreamTransformationFilter
|
// response we hacked a IsLastBlockSpecial(). When true StreamTransformationFilter
|
||||||
// defers to the mode for processing of the last block.
|
// defers to the mode for processing of the last block.
|
||||||
// The behavior supplied when IsLastBlockSpecial() will likely have to evolve to capture
|
// The behavior supplied when IsLastBlockSpecial() will likely have to evolve to capture
|
||||||
// more complex beahviors of different authenc modes. I suspect it will have to change
|
// more complex cases from different authenc modes. I suspect it will have to change
|
||||||
// from a simple bool to something that conveys more information, like "last block
|
// from a simple bool to something that conveys more information, like "last block
|
||||||
// no padding" or "custom padding applied by cipher".
|
// no padding" or "custom padding applied by cipher".
|
||||||
// In some respect we have already hit the need for more information. For example, OCB
|
// In some respect we have already hit the need for more information. For example, OCB
|
||||||
// calculates the checksum on the cipher text at the same time, so we don't need the
|
// calculates the checksum on the cipher text at the same time, so we don't need the
|
||||||
// disjoint behavior of calling "EncryptBlock" followed by a separate "AuthenticateBlock".
|
// disjoint behavior of calling "EncryptBlock" followed by a separate "AuthenticateBlock".
|
||||||
// Additional information may allow us to avoid the two spearate calls.
|
// Additional information may allow us to avoid the two spearate calls.
|
||||||
// Finally, GCC optimizes things best when isSpecial uses the two predicates. If the
|
if (m_isSpecial)
|
||||||
// 'm_cipher.MandatoryBlockSize() > 0' is removed, then some block ciphers and modes
|
|
||||||
// lose up to 0.2 cpb. Apparently GCC can optimize away the second predicate easier
|
|
||||||
// than the first predicate.
|
|
||||||
const bool isSpecial = m_cipher.IsLastBlockSpecial() && m_cipher.MandatoryBlockSize() != 0;
|
|
||||||
if (isSpecial)
|
|
||||||
{
|
{
|
||||||
const size_t mandatoryBlockSize = m_cipher.MandatoryBlockSize();
|
const size_t leftOver = length % m_mandatoryBlockSize;
|
||||||
const size_t optimalBlockSize = m_cipher.OptimalBlockSize();
|
space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, m_reservedBufferSize);
|
||||||
const size_t leftOver = length % mandatoryBlockSize;
|
|
||||||
const size_t minReserve = STDMAX(2*mandatoryBlockSize, optimalBlockSize) + leftOver;
|
|
||||||
space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, mandatoryBlockSize, minReserve);
|
|
||||||
|
|
||||||
length -= leftOver;
|
length -= leftOver;
|
||||||
if (length)
|
if (length)
|
||||||
|
|
@ -732,13 +732,13 @@ void StreamTransformationFilter::LastPut(const byte *inString, size_t length)
|
||||||
if (leftOver)
|
if (leftOver)
|
||||||
{
|
{
|
||||||
// Process final partial block
|
// Process final partial block
|
||||||
length = m_cipher.ProcessLastBlock(space, minReserve, inString, leftOver);
|
length = m_cipher.ProcessLastBlock(space, m_reservedBufferSize, inString, leftOver);
|
||||||
AttachedTransformation()->Put(space, length);
|
AttachedTransformation()->Put(space, length);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Process final empty block
|
// Process final empty block
|
||||||
length = m_cipher.ProcessLastBlock(space, minReserve, NULLPTR, 0);
|
length = m_cipher.ProcessLastBlock(space, m_reservedBufferSize, NULLPTR, 0);
|
||||||
AttachedTransformation()->Put(space, length);
|
AttachedTransformation()->Put(space, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -752,18 +752,17 @@ void StreamTransformationFilter::LastPut(const byte *inString, size_t length)
|
||||||
case ZEROS_PADDING:
|
case ZEROS_PADDING:
|
||||||
if (length > 0)
|
if (length > 0)
|
||||||
{
|
{
|
||||||
size_t minLastBlockSize = m_cipher.MinLastBlockSize();
|
const size_t minLastBlockSize = m_cipher.MinLastBlockSize();
|
||||||
size_t reserve = 2*m_cipher.MandatoryBlockSize();
|
const bool isForwardTransformation = m_cipher.IsForwardTransformation();
|
||||||
bool isForwardTransformation = m_cipher.IsForwardTransformation();
|
|
||||||
|
|
||||||
if (isForwardTransformation && m_padding == ZEROS_PADDING && (minLastBlockSize == 0 || length < minLastBlockSize))
|
if (isForwardTransformation && m_padding == ZEROS_PADDING && (minLastBlockSize == 0 || length < minLastBlockSize))
|
||||||
{
|
{
|
||||||
// do padding
|
// do padding
|
||||||
size_t blockSize = STDMAX(minLastBlockSize, (size_t)m_cipher.MandatoryBlockSize());
|
size_t blockSize = STDMAX(minLastBlockSize, (size_t)m_mandatoryBlockSize);
|
||||||
space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, blockSize+reserve);
|
space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, blockSize);
|
||||||
if (inString) {memcpy(space, inString, length);}
|
if (inString) {memcpy(space, inString, length);}
|
||||||
memset(space + length, 0, blockSize - length);
|
memset(space + length, 0, blockSize - length);
|
||||||
size_t used = m_cipher.ProcessLastBlock(space, blockSize+reserve, space, blockSize);
|
size_t used = m_cipher.ProcessLastBlock(space, blockSize, space, blockSize);
|
||||||
AttachedTransformation()->Put(space, used);
|
AttachedTransformation()->Put(space, used);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -776,8 +775,8 @@ void StreamTransformationFilter::LastPut(const byte *inString, size_t length)
|
||||||
throw InvalidCiphertext("StreamTransformationFilter: ciphertext length is not a multiple of block size");
|
throw InvalidCiphertext("StreamTransformationFilter: ciphertext length is not a multiple of block size");
|
||||||
}
|
}
|
||||||
|
|
||||||
space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, length, m_optimalBufferSize+reserve);
|
space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, length, m_optimalBufferSize);
|
||||||
size_t used = m_cipher.ProcessLastBlock(space, length+reserve, inString, length);
|
size_t used = m_cipher.ProcessLastBlock(space, length, inString, length);
|
||||||
AttachedTransformation()->Put(space, used);
|
AttachedTransformation()->Put(space, used);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -787,7 +786,7 @@ void StreamTransformationFilter::LastPut(const byte *inString, size_t length)
|
||||||
case W3C_PADDING:
|
case W3C_PADDING:
|
||||||
case ONE_AND_ZEROS_PADDING:
|
case ONE_AND_ZEROS_PADDING:
|
||||||
unsigned int s;
|
unsigned int s;
|
||||||
s = m_cipher.MandatoryBlockSize();
|
s = m_mandatoryBlockSize;
|
||||||
CRYPTOPP_ASSERT(s > 1);
|
CRYPTOPP_ASSERT(s > 1);
|
||||||
space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, s, m_optimalBufferSize);
|
space = HelpCreatePutSpace(*AttachedTransformation(), DEFAULT_CHANNEL, s, m_optimalBufferSize);
|
||||||
if (m_cipher.IsForwardTransformation())
|
if (m_cipher.IsForwardTransformation())
|
||||||
|
|
|
||||||
|
|
@ -547,9 +547,10 @@ protected:
|
||||||
|
|
||||||
StreamTransformation &m_cipher;
|
StreamTransformation &m_cipher;
|
||||||
BlockPaddingScheme m_padding;
|
BlockPaddingScheme m_padding;
|
||||||
|
unsigned int m_mandatoryBlockSize;
|
||||||
unsigned int m_optimalBufferSize;
|
unsigned int m_optimalBufferSize;
|
||||||
// TODO: do we need this?
|
unsigned int m_reservedBufferSize;
|
||||||
bool m_authenticated;
|
bool m_isSpecial;
|
||||||
};
|
};
|
||||||
|
|
||||||
//! \class HashFilter
|
//! \class HashFilter
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue