#ifndef ITERHASH_H #define ITERHASH_H #include "cryptlib.h" #include "misc.h" /* The following classes are explicitly instantiated in iterhash.cpp IteratedHash IteratedHash // #ifdef WORD64_AVAILABLE */ template class IteratedHash : public virtual HashModule { public: IteratedHash(unsigned int blockSize, unsigned int digestSize); ~IteratedHash(); void Update(const uint8_t *input, unsigned int length); typedef T HashWordType; protected: void PadLastBlock(unsigned int lastBlockSize, uint8_t padFirst=0x80); virtual void Init() =0; virtual void HashBlock(const T *input) =0; unsigned int blockSize; word32 countLo, countHi; // 64-bit bit count SecBlock data; // Data buffer SecBlock digest; // Message digest }; template IteratedHash::IteratedHash(unsigned int blockSize, unsigned int digestSize) : blockSize(blockSize), data(blockSize/sizeof(T)), digest(digestSize/sizeof(T)) { } template IteratedHash::~IteratedHash() { } template void IteratedHash::Update(const uint8_t *input, unsigned int len) { word32 tmp = countLo; if ((countLo = tmp + ((word32)len << 3)) < tmp) countHi++; // Carry from low to high countHi += len >> 29; 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((uint8_t *)data.ptr+num, input, blockSize-num); HashBlock(data); input += (blockSize-num); len-=(blockSize - num); num=0; // drop through and do the rest } else { memcpy((uint8_t *)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 ((ptr_size_type)input % sizeof(T)) // test for alignment do { // copy input first if it's not aligned correctly memcpy(data, input, blockSize); HashBlock(data); input+=blockSize; len-=blockSize; } while (len >= blockSize); else do { HashBlock((T *)input); input+=blockSize; len-=blockSize; } while (len >= blockSize); } memcpy(data, input, len); } template void IteratedHash::PadLastBlock(unsigned int lastBlockSize, uint8_t padFirst) { unsigned int num = (unsigned int)(countLo >> 3) & (blockSize-1); assert(num < blockSize); ((uint8_t *)data.ptr)[num++]=padFirst; if (num <= lastBlockSize) memset((uint8_t *)data.ptr+num, 0, lastBlockSize-num); else { memset((uint8_t *)data.ptr+num, 0, blockSize-num); HashBlock(data); memset(data, 0, lastBlockSize); } } // provide empty definitions to avoid instantiation warnings //template void IteratedHash::Init() {} //template void IteratedHash::HashBlock(const T *input) {} #endif