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

View File

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