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>
00010 IteratedHashBase<T, BASE>::IteratedHashBase(unsigned int blockSize, unsigned int digestSize)
00011         : m_data(blockSize/sizeof(T)), m_digest(digestSize/sizeof(T))
00012         , m_countHi(0), m_countLo(0)
00013 {
00014 }
00015 
00016 template <class T, class BASE> void IteratedHashBase<T, BASE>::Update(const byte *input, unsigned int len)
00017 {
00018         HashWordType tmp = m_countLo;
00019         if ((m_countLo = tmp + len) < tmp)
00020                 m_countHi++;             // carry from low to high
00021         m_countHi += SafeRightShift<8*sizeof(HashWordType)>(len);
00022 
00023         unsigned int blockSize = BlockSize();
00024         unsigned int num = ModPowerOf2(tmp, blockSize);
00025 
00026         if (num != 0)   // process left over data
00027         {
00028                 if ((num+len) >= blockSize)
00029                 {
00030                         memcpy((byte *)m_data.begin()+num, input, blockSize-num);
00031                         HashBlock(m_data);
00032                         input += (blockSize-num);
00033                         len-=(blockSize - num);
00034                         num=0;
00035                         // drop through and do the rest
00036                 }
00037                 else
00038                 {
00039                         memcpy((byte *)m_data.begin()+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 == (byte *)m_data.begin())
00048                 {
00049                         assert(len == blockSize);
00050                         HashBlock(m_data);
00051                         return;
00052                 }
00053                 else if (IsAligned<T>(input))
00054                 {
00055                         unsigned int 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(m_data, input, blockSize);
00063                                 HashBlock(m_data);
00064                                 input+=blockSize;
00065                                 len-=blockSize;
00066                         } while (len >= blockSize);
00067         }
00068 
00069         memcpy(m_data, input, len);
00070 }
00071 
00072 template <class T, class BASE> byte * IteratedHashBase<T, BASE>::CreateUpdateSpace(unsigned int &size)
00073 {
00074         unsigned int blockSize = BlockSize();
00075         unsigned int num = ModPowerOf2(m_countLo, blockSize);
00076         size = blockSize - num;
00077         return (byte *)m_data.begin() + num;
00078 }
00079 
00080 template <class T, class BASE> unsigned int IteratedHashBase<T, BASE>::HashMultipleBlocks(const T *input, unsigned int length)
00081 {
00082         unsigned int blockSize = BlockSize();
00083         do
00084         {
00085                 HashBlock(input);
00086                 input += blockSize/sizeof(T);
00087                 length -= blockSize;
00088         }
00089         while (length >= blockSize);
00090         return length;
00091 }
00092 
00093 template <class T, class BASE> void IteratedHashBase<T, BASE>::PadLastBlock(unsigned int lastBlockSize, byte padFirst)
00094 {
00095         unsigned int blockSize = BlockSize();
00096         unsigned int num = ModPowerOf2(m_countLo, blockSize);
00097         ((byte *)m_data.begin())[num++]=padFirst;
00098         if (num <= lastBlockSize)
00099                 memset((byte *)m_data.begin()+num, 0, lastBlockSize-num);
00100         else
00101         {
00102                 memset((byte *)m_data.begin()+num, 0, blockSize-num);
00103                 HashBlock(m_data);
00104                 memset(m_data, 0, lastBlockSize);
00105         }
00106 }
00107 
00108 template <class T, class BASE> void IteratedHashBase<T, BASE>::Restart()
00109 {
00110         m_countLo = m_countHi = 0;
00111         Init();
00112 }
00113 
00114 #ifdef WORD64_AVAILABLE
00115 template class IteratedHashBase<word64, HashTransformation>;
00116 template class IteratedHashBase<word64, MessageAuthenticationCode>;
00117 #endif
00118 
00119 template class IteratedHashBase<word32, HashTransformation>;
00120 template class IteratedHashBase<word32, MessageAuthenticationCode>;
00121 
00122 NAMESPACE_END

Generated on Mon Apr 19 18:12:31 2004 for Crypto++ by doxygen 1.3.6-20040222