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

Generated on Tue Aug 16 08:38:42 2005 for Crypto++ by  doxygen 1.3.9.1