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

# iterhash.cpp

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