Align input buffer in HashMultipleBlocks

IteratedHashBase::Update aligns the buffer, but IteratedHashBase::HashBlock does not. It was causing a fair number of asserts to fire when the code was instrumented with alignment checks. Linux benchmarks shows the code does not run materially slower on i686 or x86_64.
pull/696/head
Jeffrey Walton 2018-07-20 18:56:41 -04:00
parent 365e65c2eb
commit 0c0b68a4a2
No known key found for this signature in database
GPG Key ID: B36AB348921B1838
2 changed files with 37 additions and 10 deletions

View File

@ -27,13 +27,14 @@ template <class T, class BASE> void IteratedHashBase<T, BASE>::Update(const byte
T* dataBuf = this->DataBuf();
byte* data = (byte *)dataBuf;
CRYPTOPP_ASSERT(dataBuf && data);
if (num != 0) // process left over data
{
if (num+length >= blockSize)
{
if (data && input) {memcpy(data+num, input, blockSize-num);}
if (input)
{memcpy(data+num, input, blockSize-num);}
HashBlock(dataBuf);
input += (blockSize-num);
length -= (blockSize-num);
@ -42,7 +43,8 @@ template <class T, class BASE> void IteratedHashBase<T, BASE>::Update(const byte
}
else
{
if (data && input && length) {memcpy(data+num, input, length);}
if (input && length)
{memcpy(data+num, input, length);}
return;
}
}
@ -63,16 +65,20 @@ template <class T, class BASE> void IteratedHashBase<T, BASE>::Update(const byte
length = leftOver;
}
else
{
do
{ // copy input first if it's not aligned correctly
if (data && input) memcpy(data, input, blockSize);
if (input)
{ memcpy(data, input, blockSize); }
HashBlock(dataBuf);
input+=blockSize;
length-=blockSize;
} while (length >= blockSize);
}
}
if (data && input && data != input)
if (input && data != input)
memcpy(data, input, length);
}
@ -89,11 +95,23 @@ template <class T, class BASE> size_t IteratedHashBase<T, BASE>::HashMultipleBlo
unsigned int blockSize = this->BlockSize();
bool noReverse = NativeByteOrderIs(this->GetByteOrder());
T* dataBuf = this->DataBuf();
// IteratedHashBase Update calls this with an aligned input,
// but HashBlock may call it with an unaligned buffer.
do
{
if (noReverse)
{
if (IsAligned<word64>(input))
this->HashEndianCorrectedBlock(input);
else
{
std::memcpy(dataBuf, input, this->BlockSize());
this->HashEndianCorrectedBlock(dataBuf);
}
}
else
{
ByteReverse(dataBuf, input, this->BlockSize());
this->HashEndianCorrectedBlock(dataBuf);
@ -112,6 +130,7 @@ template <class T, class BASE> void IteratedHashBase<T, BASE>::PadLastBlock(unsi
unsigned int num = ModPowerOf2(m_countLo, blockSize);
T* dataBuf = this->DataBuf();
byte* data = (byte *)dataBuf;
data[num++] = padFirst;
if (num <= lastBlockSize)
memset(data+num, 0, lastBlockSize-num);
@ -150,7 +169,7 @@ template <class T, class BASE> void IteratedHashBase<T, BASE>::TruncatedFinal(by
else
{
ConditionalByteReverse<HashWordType>(order, stateBuf, stateBuf, this->DigestSize());
memcpy(digest, stateBuf, size);
std::memcpy(digest, stateBuf, size);
}
this->Restart(); // reinit for next use

View File

@ -95,8 +95,10 @@ public:
virtual std::string AlgorithmProvider() const { return "C++"; }
protected:
inline T GetBitCountHi() const {return (m_countLo >> (8*sizeof(T)-3)) + (m_countHi << 3);}
inline T GetBitCountLo() const {return m_countLo << 3;}
inline T GetBitCountHi() const
{return (m_countLo >> (8*sizeof(T)-3)) + (m_countHi << 3);}
inline T GetBitCountLo() const
{return m_countLo << 3;}
void PadLastBlock(unsigned int lastBlockSize, byte padFirst=0x80);
virtual void Init() =0;
@ -104,7 +106,8 @@ protected:
virtual ByteOrder GetByteOrder() const =0;
virtual void HashEndianCorrectedBlock(const HashWordType *data) =0;
virtual size_t HashMultipleBlocks(const T *input, size_t length);
void HashBlock(const HashWordType *input) {HashMultipleBlocks(input, this->BlockSize());}
void HashBlock(const HashWordType *input)
{HashMultipleBlocks(input, this->BlockSize());}
virtual T* DataBuf() =0;
virtual T* StateBuf() =0;
@ -151,6 +154,11 @@ public:
/// \details CorrectEndianess() calls ConditionalByteReverse() using <tt>T_Endianness</tt>.
inline void CorrectEndianess(HashWordType *out, const HashWordType *in, size_t byteCount)
{
CRYPTOPP_ASSERT(in != NULLPTR);
CRYPTOPP_ASSERT(out != NULLPTR);
CRYPTOPP_ASSERT(IsAligned<T_HashWordType>(in));
CRYPTOPP_ASSERT(IsAligned<T_HashWordType>(out));
ConditionalByteReverse(T_Endianness::ToEnum(), out, in, byteCount);
}