- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# iterhash.cpp

    00001 // iterhash.cpp - written and placed in the public domain by Wei Dai
    00002
    00003 #include "pch.h"
    00004
    00005 // prevent Sun's CC compiler from including this file automatically
    00006 #if !defined(__SUNPRO_CC) || defined(CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES)
    00007
    00008 #include "iterhash.h"
    00009 #include "misc.h"
    00010
    00011 NAMESPACE_BEGIN(CryptoPP)
    00012
    00013 template <class T, class BASE> void IteratedHashBase<T, BASE>::Update(const byte *input, size_t len)
    00014 {
    00015         HashWordType oldCountLo = m_countLo, oldCountHi = m_countHi;
    00016         if ((m_countLo = oldCountLo + HashWordType(len)) < oldCountLo)
    00017                 m_countHi++;             // carry from low to high
    00018         m_countHi += (HashWordType)SafeRightShift<8*sizeof(HashWordType)>(len);
    00019         if (m_countHi < oldCountHi || SafeRightShift<2*8*sizeof(HashWordType)>(len) != 0)
    00020                 throw HashInputTooLong(this->AlgorithmName());
    00021
    00022         unsigned int blockSize = this->BlockSize();
    00023         unsigned int num = ModPowerOf2(oldCountLo, blockSize);
    00024         T* dataBuf = this->DataBuf();
    00025         byte* data = (byte *)dataBuf;
    00026
    00027         if (num != 0)   // process left over data
    00028         {
    00029                 if ((num+len) >= blockSize)
    00030                 {
    00031                         memcpy(data+num, input, blockSize-num);
    00032                         HashBlock(dataBuf);
    00033                         input += (blockSize-num);
    00034                         len-=(blockSize - num);
    00035                         num=0;
    00036                         // drop through and do the rest
    00037                 }
    00038                 else
    00039                 {
    00040                         memcpy(data+num, input, len);
    00041                         return;
    00042                 }
    00043         }
    00044
    00045         // now process the input data in blocks of blockSize bytes and save the leftovers to m_data
    00046         if (len >= blockSize)
    00047         {
    00048                 if (input == data)
    00049                 {
    00050                         assert(len == blockSize);
    00051                         HashBlock(dataBuf);
    00052                         return;
    00053                 }
    00054                 else if (IsAligned<T>(input))
    00055                 {
    00056                         size_t leftOver = HashMultipleBlocks((T *)input, len);
    00057                         input += (len - leftOver);
    00058                         len = leftOver;
    00059                 }
    00060                 else
    00061                         do
    00062                         {   // copy input first if it's not aligned correctly
    00063                                 memcpy(data, input, blockSize);
    00064                                 HashBlock(dataBuf);
    00065                                 input+=blockSize;
    00066                                 len-=blockSize;
    00067                         } while (len >= blockSize);
    00068         }
    00069
    00070         memcpy(data, input, len);
    00071 }
    00072
    00073 template <class T, class BASE> byte * IteratedHashBase<T, BASE>::CreateUpdateSpace(size_t &size)
    00074 {
    00075         unsigned int blockSize = this->BlockSize();
    00076         unsigned int num = ModPowerOf2(m_countLo, blockSize);
    00077         size = blockSize - num;
    00078         return (byte *)DataBuf() + num;
    00079 }
    00080
    00081 template <class T, class BASE> size_t IteratedHashBase<T, BASE>::HashMultipleBlocks(const T *input, size_t length)
    00082 {
    00083         unsigned int blockSize = this->BlockSize();
    00084         bool noReverse = NativeByteOrderIs(this->GetByteOrder());
    00085         T* dataBuf = this->DataBuf();
    00086         do
    00087         {
    00088                 if (noReverse)
    00089                         this->HashEndianCorrectedBlock(input);
    00090                 else
    00091                 {
    00092                         ByteReverse(dataBuf, input, this->BlockSize());
    00093                         this->HashEndianCorrectedBlock(dataBuf);
    00094                 }
    00095
    00096                 input += blockSize/sizeof(T);
    00097                 length -= blockSize;
    00098         }
    00099         while (length >= blockSize);
    00100         return length;
    00101 }
    00102
    00103 template <class T, class BASE> void IteratedHashBase<T, BASE>::PadLastBlock(unsigned int lastBlockSize, byte padFirst)
    00104 {
    00105         unsigned int blockSize = this->BlockSize();
    00106         unsigned int num = ModPowerOf2(m_countLo, blockSize);
    00107         T* dataBuf = this->DataBuf();
    00108         byte* data = (byte *)dataBuf;
    00109         data[num++] = padFirst;
    00110         if (num <= lastBlockSize)
    00111                 memset(data+num, 0, lastBlockSize-num);
    00112         else
    00113         {
    00114                 memset(data+num, 0, blockSize-num);
    00115                 HashBlock(dataBuf);
    00116                 memset(data, 0, lastBlockSize);
    00117         }
    00118 }
    00119
    00120 template <class T, class BASE> void IteratedHashBase<T, BASE>::Restart()
    00121 {
    00122         m_countLo = m_countHi = 0;
    00123         Init();
    00124 }
    00125
    00126 template <class T, class BASE> void IteratedHashBase<T, BASE>::TruncatedFinal(byte *digest, size_t size)
    00127 {
    00128         this->ThrowIfInvalidTruncatedSize(size);
    00129
    00130         T* dataBuf = this->DataBuf();
    00131         T* stateBuf = this->StateBuf();
    00132         unsigned int blockSize = this->BlockSize();
    00133         ByteOrder order = this->GetByteOrder();
    00134
    00135         PadLastBlock(blockSize - 2*sizeof(HashWordType));
    00136         ConditionalByteReverse<HashWordType>(order, dataBuf, dataBuf, blockSize - 2*sizeof(HashWordType));
    00137
    00138         dataBuf[blockSize/sizeof(T)-2] = order ? this->GetBitCountHi() : this->GetBitCountLo();
    00139         dataBuf[blockSize/sizeof(T)-1] = order ? this->GetBitCountLo() : this->GetBitCountHi();
    00140
    00141         HashEndianCorrectedBlock(dataBuf);
    00142         ConditionalByteReverse<HashWordType>(order, stateBuf, stateBuf, this->DigestSize());
    00143         memcpy(digest, stateBuf, size);
    00144
    00145         this->Restart();                // reinit for next use
    00146 }
    00147
    00148 NAMESPACE_END
    00149
    00150 #endif