From b21162cf8e06f40baa1f58be6a8c17435cebc34d Mon Sep 17 00:00:00 2001 From: weidai Date: Fri, 4 Oct 2002 17:31:41 +0000 Subject: Initial revision git-svn-id: svn://svn.code.sf.net/p/cryptopp/code/trunk/c5@2 57ff6487-cd31-0410-9ec3-f628ee90f5f0 --- iterhash.cpp | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 iterhash.cpp (limited to 'iterhash.cpp') diff --git a/iterhash.cpp b/iterhash.cpp new file mode 100644 index 0000000..08f7626 --- /dev/null +++ b/iterhash.cpp @@ -0,0 +1,123 @@ +// iterhash.cpp - written and placed in the public domain by Wei Dai + +#include "pch.h" +#include "iterhash.h" +#include "misc.h" + +NAMESPACE_BEGIN(CryptoPP) + +template +IteratedHashBase::IteratedHashBase(unsigned int blockSize, unsigned int digestSize) + : m_data(blockSize/sizeof(T)), m_digest(digestSize/sizeof(T)) + , m_countHi(0), m_countLo(0) +{ +} + +template void IteratedHashBase::Update(const byte *input, unsigned int len) +{ + HashWordType tmp = m_countLo; + if ((m_countLo = tmp + len) < tmp) + m_countHi++; // Carry from low to high + m_countHi += SafeRightShift<8*sizeof(HashWordType)>(len); + + unsigned int blockSize = BlockSize(); + unsigned int num = (unsigned int)(tmp & (blockSize-1)); + + if (num != 0) + { + if ((num+len) >= blockSize) + { + memcpy((byte *)m_data.begin()+num, input, blockSize-num); + HashBlock(m_data); + input += (blockSize-num); + len-=(blockSize - num); + num=0; + // drop through and do the rest + } + else + { + memcpy((byte *)m_data.begin()+num, input, len); + return; + } + } + + // we now can process the input data in blocks of blockSize + // chars and save the leftovers to this->data. + if (len >= blockSize) + { + if (input == (byte *)m_data.begin()) + { + assert(len == blockSize); + HashBlock(m_data); + return; + } + else if (IsAligned(input)) + { + unsigned int leftOver = HashMultipleBlocks((T *)input, len); + input += (len - leftOver); + len = leftOver; + } + else + do + { // copy input first if it's not aligned correctly + memcpy(m_data, input, blockSize); + HashBlock(m_data); + input+=blockSize; + len-=blockSize; + } while (len >= blockSize); + } + + memcpy(m_data, input, len); +} + +template byte * IteratedHashBase::CreateUpdateSpace(unsigned int &size) +{ + unsigned int blockSize = BlockSize(); + unsigned int num = ModPowerOf2(m_countLo, blockSize); + size = blockSize - num; + return (byte *)m_data.begin() + num; +} + +template unsigned int IteratedHashBase::HashMultipleBlocks(const T *input, unsigned int length) +{ + unsigned int blockSize = BlockSize(); + do + { + HashBlock(input); + input += blockSize/sizeof(T); + length -= blockSize; + } + while (length >= blockSize); + return length; +} + +template void IteratedHashBase::PadLastBlock(unsigned int lastBlockSize, byte padFirst) +{ + unsigned int blockSize = BlockSize(); + unsigned int num = ModPowerOf2(m_countLo, blockSize); + ((byte *)m_data.begin())[num++]=padFirst; + if (num <= lastBlockSize) + memset((byte *)m_data.begin()+num, 0, lastBlockSize-num); + else + { + memset((byte *)m_data.begin()+num, 0, blockSize-num); + HashBlock(m_data); + memset(m_data, 0, lastBlockSize); + } +} + +template void IteratedHashBase::Restart() +{ + m_countLo = m_countHi = 0; + Init(); +} + +#ifdef WORD64_AVAILABLE +template class IteratedHashBase; +template class IteratedHashBase; +#endif + +template class IteratedHashBase; +template class IteratedHashBase; + +NAMESPACE_END -- cgit v1.2.1