Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | File Members

# iterhash.cpp

    00001 // iterhash.cpp - written and placed in the public domain by Wei Dai
    00002
    00003 #include "pch.h"
    00004 #include "iterhash.h"
    00005 #include "misc.h"
    00006
    00007 NAMESPACE_BEGIN(CryptoPP)
    00008
    00009 template <class T, class BASE> void IteratedHashBase<T, BASE>::Update(const byte *input, unsigned int len)
    00010 {
    00011         HashWordType tmp = m_countLo;
    00012         if ((m_countLo = tmp + len) < tmp)
    00013                 m_countHi++;             // carry from low to high
    00014         m_countHi += SafeRightShift<8*sizeof(HashWordType)>(len);
    00015
    00016         unsigned int blockSize = BlockSize();
    00017         unsigned int num = ModPowerOf2(tmp, blockSize);
    00018
    00019         if (num != 0)   // process left over data
    00020         {
    00021                 if ((num+len) >= blockSize)
    00022                 {
    00023                         memcpy((byte *)m_data.begin()+num, input, blockSize-num);
    00024                         HashBlock(m_data);
    00025                         input += (blockSize-num);
    00026                         len-=(blockSize - num);
    00027                         num=0;
    00028                         // drop through and do the rest
    00029                 }
    00030                 else
    00031                 {
    00032                         memcpy((byte *)m_data.begin()+num, input, len);
    00033                         return;
    00034                 }
    00035         }
    00036
    00037         // now process the input data in blocks of blockSize bytes and save the leftovers to m_data
    00038         if (len >= blockSize)
    00039         {
    00040                 if (input == (byte *)m_data.begin())
    00041                 {
    00042                         assert(len == blockSize);
    00043                         HashBlock(m_data);
    00044                         return;
    00045                 }
    00046                 else if (IsAligned<T>(input))
    00047                 {
    00048                         unsigned int leftOver = HashMultipleBlocks((T *)input, len);
    00049                         input += (len - leftOver);
    00050                         len = leftOver;
    00051                 }
    00052                 else
    00053                         do
    00054                         {   // copy input first if it's not aligned correctly
    00055                                 memcpy(m_data, input, blockSize);
    00056                                 HashBlock(m_data);
    00057                                 input+=blockSize;
    00058                                 len-=blockSize;
    00059                         } while (len >= blockSize);
    00060         }
    00061
    00062         memcpy(m_data, input, len);
    00063 }
    00064
    00065 template <class T, class BASE> byte * IteratedHashBase<T, BASE>::CreateUpdateSpace(unsigned int &size)
    00066 {
    00067         unsigned int blockSize = BlockSize();
    00068         unsigned int num = ModPowerOf2(m_countLo, blockSize);
    00069         size = blockSize - num;
    00070         return (byte *)m_data.begin() + num;
    00071 }
    00072
    00073 template <class T, class BASE> unsigned int IteratedHashBase<T, BASE>::HashMultipleBlocks(const T *input, unsigned int length)
    00074 {
    00075         unsigned int blockSize = BlockSize();
    00076         do
    00077         {
    00078                 HashBlock(input);
    00079                 input += blockSize/sizeof(T);
    00080                 length -= blockSize;
    00081         }
    00082         while (length >= blockSize);
    00083         return length;
    00084 }
    00085
    00086 template <class T, class BASE> void IteratedHashBase<T, BASE>::PadLastBlock(unsigned int lastBlockSize, byte padFirst)
    00087 {
    00088         unsigned int blockSize = BlockSize();
    00089         unsigned int num = ModPowerOf2(m_countLo, blockSize);
    00090         ((byte *)m_data.begin())[num++]=padFirst;
    00091         if (num <= lastBlockSize)
    00092                 memset((byte *)m_data.begin()+num, 0, lastBlockSize-num);
    00093         else
    00094         {
    00095                 memset((byte *)m_data.begin()+num, 0, blockSize-num);
    00096                 HashBlock(m_data);
    00097                 memset(m_data, 0, lastBlockSize);
    00098         }
    00099 }
    00100
    00101 template <class T, class BASE> void IteratedHashBase<T, BASE>::Restart()
    00102 {
    00103         m_countLo = m_countHi = 0;
    00104         Init();
    00105 }
    00106
    00107 NAMESPACE_END