/* * Modification History * * 2002-August-8 Jason Rohrer * Hacked to work on Mac OS X. */ // iterhash.cpp - written and placed in the public domain by Wei Dai #include "pch.h" #include "iterhash.h" NAMESPACE_BEGIN(CryptoPP) template IteratedHashBase::IteratedHashBase(unsigned int blockSize, unsigned int digestSize) : blockSize(blockSize), countLo(0), countHi(0) , data(blockSize/sizeof(T)), digest(digestSize/sizeof(T)) { } template void IteratedHashBase::Update(const byte *input, unsigned int len) { HashWordType tmp = countLo; if ((countLo = tmp + ((word32)len << 3)) < tmp) countHi++; // Carry from low to high countHi += len >> (8*sizeof(HashWordType)-3); assert((blockSize & (blockSize-1)) == 0); // blockSize is a power of 2 unsigned int num = (unsigned int)(tmp >> 3) & (blockSize-1); if (num != 0) { if ((num+len) >= blockSize) { memcpy((byte *)data.ptr+num, input, blockSize-num); HashBlock(data); input += (blockSize-num); len-=(blockSize - num); num=0; // drop through and do the rest } else { memcpy((byte *)data.ptr+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 (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(data, input, blockSize); HashBlock(data); input+=blockSize; len-=blockSize; } while (len >= blockSize); } memcpy(data, input, len); } template unsigned int IteratedHashBase::HashMultipleBlocks(const T *input, unsigned int length) { 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 num = (unsigned int)(countLo >> 3) & (blockSize-1); assert(num < blockSize); ((byte *)data.ptr)[num++]=padFirst; if (num <= lastBlockSize) memset((byte *)data.ptr+num, 0, lastBlockSize-num); else { memset((byte *)data.ptr+num, 0, blockSize-num); HashBlock(data); memset(data, 0, lastBlockSize); } } template void IteratedHashBase::Reinit() { countLo = countHi = 0; Init(); } // provide empty definitions to avoid instantiation warnings template void IteratedHashBase::Init() {} template void IteratedHashBase::HashBlock(const T *input) {} #ifdef WORD64_AVAILABLE //template class IteratedHashBase; #endif //template class IteratedHashBase; template <> IteratedHashBase::IteratedHashBase(unsigned int blockSize, unsigned int digestSize) : blockSize(blockSize), countLo(0), countHi(0) , data(blockSize/sizeof(word32)), digest(digestSize/sizeof(word32)) { } // provide empty definitions to avoid instantiation warnings template <> void IteratedHashBase::HashBlock(const word32 *input) {} template <> void IteratedHashBase::Init() {} template <> unsigned int IteratedHashBase::HashMultipleBlocks(const word32 *input, unsigned int length) { do { HashBlock(input); input += blockSize/sizeof(word32); length -= blockSize; } while (length >= blockSize); return length; } template <> void IteratedHashBase::Update(const byte *input, unsigned int len) { HashWordType tmp = countLo; if ((countLo = tmp + ((word32)len << 3)) < tmp) countHi++; // Carry from low to high countHi += len >> (8*sizeof(HashWordType)-3); assert((blockSize & (blockSize-1)) == 0); // blockSize is a power of 2 unsigned int num = (unsigned int)(tmp >> 3) & (blockSize-1); if (num != 0) { if ((num+len) >= blockSize) { memcpy((byte *)data.ptr+num, input, blockSize-num); HashBlock(data); input += (blockSize-num); len-=(blockSize - num); num=0; // drop through and do the rest } else { memcpy((byte *)data.ptr+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 (IsAligned(input)) { unsigned int leftOver = HashMultipleBlocks((word32 *)input, len); input += (len - leftOver); len = leftOver; } else do { // copy input first if it's not aligned correctly memcpy(data, input, blockSize); HashBlock(data); input+=blockSize; len-=blockSize; } while (len >= blockSize); } memcpy(data, input, len); } template <> void IteratedHashBase::PadLastBlock(unsigned int lastBlockSize, byte padFirst) { unsigned int num = (unsigned int)(countLo >> 3) & (blockSize-1); assert(num < blockSize); ((byte *)data.ptr)[num++]=padFirst; if (num <= lastBlockSize) memset((byte *)data.ptr+num, 0, lastBlockSize-num); else { memset((byte *)data.ptr+num, 0, blockSize-num); HashBlock(data); memset(data, 0, lastBlockSize); } } template <> void IteratedHashBase::Reinit() { countLo = countHi = 0; Init(); } template <> IteratedHashBase::IteratedHashBase(unsigned int blockSize, unsigned int digestSize) : blockSize(blockSize), countLo(0), countHi(0) , data(blockSize/sizeof(word64)), digest(digestSize/sizeof(word64)) { } // provide empty definitions to avoid instantiation warnings template <> void IteratedHashBase::Init() {} template <> void IteratedHashBase::HashBlock(const word64 *input) {} template <> unsigned int IteratedHashBase::HashMultipleBlocks(const word64 *input, unsigned int length) { do { HashBlock(input); input += blockSize/sizeof(word64); length -= blockSize; } while (length >= blockSize); return length; } template <> void IteratedHashBase::Update(const byte *input, unsigned int len) { HashWordType tmp = countLo; if ((countLo = tmp + ((word32)len << 3)) < tmp) countHi++; // Carry from low to high countHi += len >> (8*sizeof(HashWordType)-3); assert((blockSize & (blockSize-1)) == 0); // blockSize is a power of 2 unsigned int num = (unsigned int)(tmp >> 3) & (blockSize-1); if (num != 0) { if ((num+len) >= blockSize) { memcpy((byte *)data.ptr+num, input, blockSize-num); HashBlock(data); input += (blockSize-num); len-=(blockSize - num); num=0; // drop through and do the rest } else { memcpy((byte *)data.ptr+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 (IsAligned(input)) { unsigned int leftOver = HashMultipleBlocks((word64 *)input, len); input += (len - leftOver); len = leftOver; } else do { // copy input first if it's not aligned correctly memcpy(data, input, blockSize); HashBlock(data); input+=blockSize; len-=blockSize; } while (len >= blockSize); } memcpy(data, input, len); } template <> void IteratedHashBase::PadLastBlock(unsigned int lastBlockSize, byte padFirst) { unsigned int num = (unsigned int)(countLo >> 3) & (blockSize-1); assert(num < blockSize); ((byte *)data.ptr)[num++]=padFirst; if (num <= lastBlockSize) memset((byte *)data.ptr+num, 0, lastBlockSize-num); else { memset((byte *)data.ptr+num, 0, blockSize-num); HashBlock(data); memset(data, 0, lastBlockSize); } } template <> void IteratedHashBase::Reinit() { countLo = countHi = 0; Init(); } NAMESPACE_END