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
Jeffrey Walton 2017-10-03 21:49:59 -04:00
parent 04d15304f1
commit 73928489f9
No known key found for this signature in database
GPG Key ID: B36AB348921B1838
2 changed files with 40 additions and 40 deletions

View File

@ -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 &parameters, size_t &firstSize, size_t &blockSize, size_t &lastSize) void StreamTransformationFilter::InitializeDerivedAndReturnNewSizes(const NameValuePairs &parameters, 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())

View File

@ -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