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();
|
||||
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
|
||||
|
|
|
|||
14
iterhash.h
14
iterhash.h
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue