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
parent
365e65c2eb
commit
0c0b68a4a2
31
iterhash.cpp
31
iterhash.cpp
|
|
@ -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
|
||||||
|
|
|
||||||
14
iterhash.h
14
iterhash.h
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue