• 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 #ifndef __GNUC__
00004 #define CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
00005 #endif
00006 
00007 #include "iterhash.h"
00008 #include "misc.h"
00009 
00010 NAMESPACE_BEGIN(CryptoPP)
00011 
00012 template <class T, class BASE> void IteratedHashBase<T, BASE>::Update(const byte *input, size_t len)
00013 {
00014         HashWordType oldCountLo = m_countLo, oldCountHi = m_countHi;
00015         if ((m_countLo = oldCountLo + HashWordType(len)) < oldCountLo)
00016                 m_countHi++;             // carry from low to high
00017         m_countHi += (HashWordType)SafeRightShift<8*sizeof(HashWordType)>(len);
00018         if (m_countHi < oldCountHi || SafeRightShift<2*8*sizeof(HashWordType)>(len) != 0)
00019                 throw HashInputTooLong(this->AlgorithmName());
00020 
00021         unsigned int blockSize = this->BlockSize();
00022         unsigned int num = ModPowerOf2(oldCountLo, blockSize);
00023         T* dataBuf = this->DataBuf();
00024         byte* data = (byte *)dataBuf;
00025 
00026         if (num != 0)   // process left over data
00027         {
00028                 if (num+len >= blockSize)
00029                 {
00030                         memcpy(data+num, input, blockSize-num);
00031                         HashBlock(dataBuf);
00032                         input += (blockSize-num);
00033                         len -= (blockSize-num);
00034                         num = 0;
00035                         // drop through and do the rest
00036                 }
00037                 else
00038                 {
00039                         memcpy(data+num, input, len);
00040                         return;
00041                 }
00042         }
00043 
00044         // now process the input data in blocks of blockSize bytes and save the leftovers to m_data
00045         if (len >= blockSize)
00046         {
00047                 if (input == data)
00048                 {
00049                         assert(len == blockSize);
00050                         HashBlock(dataBuf);
00051                         return;
00052                 }
00053                 else if (IsAligned<T>(input))
00054                 {
00055                         size_t leftOver = HashMultipleBlocks((T *)input, len);
00056                         input += (len - leftOver);
00057                         len = leftOver;
00058                 }
00059                 else
00060                         do
00061                         {   // copy input first if it's not aligned correctly
00062                                 memcpy(data, input, blockSize);
00063                                 HashBlock(dataBuf);
00064                                 input+=blockSize;
00065                                 len-=blockSize;
00066                         } while (len >= blockSize);
00067         }
00068 
00069         if (len && data != input)
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         dataBuf[blockSize/sizeof(T)-2+order] = ConditionalByteReverse(order, this->GetBitCountLo());
00137         dataBuf[blockSize/sizeof(T)-1-order] = ConditionalByteReverse(order, this->GetBitCountHi());
00138 
00139         HashBlock(dataBuf);
00140 
00141         if (IsAligned<HashWordType>(digest) && size%sizeof(HashWordType)==0)
00142                 ConditionalByteReverse<HashWordType>(order, (HashWordType *)digest, stateBuf, size);
00143         else
00144         {
00145                 ConditionalByteReverse<HashWordType>(order, stateBuf, stateBuf, this->DigestSize());
00146                 memcpy(digest, stateBuf, size);
00147         }
00148 
00149         this->Restart();                // reinit for next use
00150 }
00151 
00152 #ifdef __GNUC__
00153         template class IteratedHashBase<word64, HashTransformation>;
00154         template class IteratedHashBase<word64, MessageAuthenticationCode>;
00155 
00156         template class IteratedHashBase<word32, HashTransformation>;
00157         template class IteratedHashBase<word32, MessageAuthenticationCode>;
00158 #endif
00159 
00160 NAMESPACE_END

Generated on Mon Aug 9 2010 15:56:34 for Crypto++ by  doxygen 1.7.1