- 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 = BlockSize();
    00023         unsigned int num = ModPowerOf2(oldCountLo, blockSize);
    00024
    00025         if (num != 0)   // process left over data
    00026         {
    00027                 if ((num+len) >= blockSize)
    00028                 {
    00029                         memcpy((byte *)m_data.begin()+num, input, blockSize-num);
    00030                         HashBlock(m_data);
    00031                         input += (blockSize-num);
    00032                         len-=(blockSize - num);
    00033                         num=0;
    00034                         // drop through and do the rest
    00035                 }
    00036                 else
    00037                 {
    00038                         memcpy((byte *)m_data.begin()+num, input, len);
    00039                         return;
    00040                 }
    00041         }
    00042
    00043         // now process the input data in blocks of blockSize bytes and save the leftovers to m_data
    00044         if (len >= blockSize)
    00045         {
    00046                 if (input == (byte *)m_data.begin())
    00047                 {
    00048                         assert(len == blockSize);
    00049                         HashBlock(m_data);
    00050                         return;
    00051                 }
    00052                 else if (IsAligned<T>(input))
    00053                 {
    00054                         size_t leftOver = HashMultipleBlocks((T *)input, len);
    00055                         input += (len - leftOver);
    00056                         len = leftOver;
    00057                 }
    00058                 else
    00059                         do
    00060                         {   // copy input first if it's not aligned correctly
    00061                                 memcpy(m_data, input, blockSize);
    00062                                 HashBlock(m_data);
    00063                                 input+=blockSize;
    00064                                 len-=blockSize;
    00065                         } while (len >= blockSize);
    00066         }
    00067
    00068         memcpy(m_data, input, len);
    00069 }
    00070
    00071 template <class T, class BASE> byte * IteratedHashBase<T, BASE>::CreateUpdateSpace(size_t &size)
    00072 {
    00073         unsigned int blockSize = BlockSize();
    00074         unsigned int num = ModPowerOf2(m_countLo, blockSize);
    00075         size = blockSize - num;
    00076         return (byte *)m_data.begin() + num;
    00077 }
    00078
    00079 template <class T, class BASE> size_t IteratedHashBase<T, BASE>::HashMultipleBlocks(const T *input, size_t length)
    00080 {
    00081         unsigned int blockSize = BlockSize();
    00082         bool noReverse = NativeByteOrderIs(GetByteOrder());
    00083         do
    00084         {
    00085                 if (noReverse)
    00086                         HashEndianCorrectedBlock(input);
    00087                 else
    00088                 {
    00089                         ByteReverse(this->m_data.begin(), input, this->BlockSize());
    00090                         HashEndianCorrectedBlock(this->m_data);
    00091                 }
    00092
    00093                 input += blockSize/sizeof(T);
    00094                 length -= blockSize;
    00095         }
    00096         while (length >= blockSize);
    00097         return length;
    00098 }
    00099
    00100 template <class T, class BASE> void IteratedHashBase<T, BASE>::PadLastBlock(unsigned int lastBlockSize, byte padFirst)
    00101 {
    00102         unsigned int blockSize = BlockSize();
    00103         unsigned int num = ModPowerOf2(m_countLo, blockSize);
    00104         ((byte *)m_data.begin())[num++]=padFirst;
    00105         if (num <= lastBlockSize)
    00106                 memset((byte *)m_data.begin()+num, 0, lastBlockSize-num);
    00107         else
    00108         {
    00109                 memset((byte *)m_data.begin()+num, 0, blockSize-num);
    00110                 HashBlock(m_data);
    00111                 memset(m_data, 0, lastBlockSize);
    00112         }
    00113 }
    00114
    00115 template <class T, class BASE> void IteratedHashBase<T, BASE>::Restart()
    00116 {
    00117         m_countLo = m_countHi = 0;
    00118         Init();
    00119 }
    00120
    00121 template <class T, class BASE> void IteratedHashBase<T, BASE>::TruncatedFinal(byte *digest, size_t size)
    00122 {
    00123         this->ThrowIfInvalidTruncatedSize(size);
    00124
    00125         PadLastBlock(this->BlockSize() - 2*sizeof(HashWordType));
    00126         ByteOrder order = this->GetByteOrder();
    00127         ConditionalByteReverse<HashWordType>(order, this->m_data, this->m_data, this->BlockSize() - 2*sizeof(HashWordType));
    00128
    00129         this->m_data[this->m_data.size()-2] = order ? this->GetBitCountHi() : this->GetBitCountLo();
    00130         this->m_data[this->m_data.size()-1] = order ? this->GetBitCountLo() : this->GetBitCountHi();
    00131
    00132         HashEndianCorrectedBlock(this->m_data);
    00133         ConditionalByteReverse<HashWordType>(order, this->m_digest, this->m_digest, this->DigestSize());
    00134         memcpy(digest, this->m_digest, size);
    00135
    00136         this->Restart();                // reinit for next use
    00137 }
    00138
    00139 NAMESPACE_END
    00140
    00141 #endif