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

Generated on Fri Jun 1 11:11:22 2007 for Crypto++ by  doxygen 1.5.2