Main Page | Namespace List | Class Hierarchy | Alphabetical List | Compound List | File List | Namespace Members | Compound Members | File Members

iterhash.cpp

00001 // iterhash.cpp - written and placed in the public domain by Wei Dai
00002 
00003 #include "pch.h"
00004 
00005 #ifndef CRYPTOPP_IMPORTS
00006 
00007 #include "iterhash.h"
00008 #include "misc.h"
00009 
00010 NAMESPACE_BEGIN(CryptoPP)
00011 
00012 template <class T, class BASE>
00013 IteratedHashBase<T, BASE>::IteratedHashBase(unsigned int blockSize, unsigned int digestSize)
00014         : m_data(blockSize/sizeof(T)), m_digest(digestSize/sizeof(T))
00015         , m_countHi(0), m_countLo(0)
00016 {
00017 }
00018 
00019 template <class T, class BASE> void IteratedHashBase<T, BASE>::Update(const byte *input, unsigned int len)
00020 {
00021         HashWordType tmp = m_countLo;
00022         if ((m_countLo = tmp + len) < tmp)
00023                 m_countHi++;             // Carry from low to high
00024         m_countHi += SafeRightShift<8*sizeof(HashWordType)>(len);
00025 
00026         unsigned int blockSize = BlockSize();
00027         unsigned int num = (unsigned int)(tmp & (blockSize-1));
00028 
00029         if (num != 0)
00030         {
00031                 if ((num+len) >= blockSize)
00032                 {
00033                         memcpy((byte *)m_data.begin()+num, input, blockSize-num);
00034                         HashBlock(m_data);
00035                         input += (blockSize-num);
00036                         len-=(blockSize - num);
00037                         num=0;
00038                         // drop through and do the rest
00039                 }
00040                 else
00041                 {
00042                         memcpy((byte *)m_data.begin()+num, input, len);
00043                         return;
00044                 }
00045         }
00046 
00047         // we now can process the input data in blocks of blockSize
00048         // chars and save the leftovers to this->data.
00049         if (len >= blockSize)
00050         {
00051                 if (input == (byte *)m_data.begin())
00052                 {
00053                         assert(len == blockSize);
00054                         HashBlock(m_data);
00055                         return;
00056                 }
00057                 else if (IsAligned<T>(input))
00058                 {
00059                         unsigned int leftOver = HashMultipleBlocks((T *)input, len);
00060                         input += (len - leftOver);
00061                         len = leftOver;
00062                 }
00063                 else
00064                         do
00065                         {   // copy input first if it's not aligned correctly
00066                                 memcpy(m_data, input, blockSize);
00067                                 HashBlock(m_data);
00068                                 input+=blockSize;
00069                                 len-=blockSize;
00070                         } while (len >= blockSize);
00071         }
00072 
00073         memcpy(m_data, input, len);
00074 }
00075 
00076 template <class T, class BASE> byte * IteratedHashBase<T, BASE>::CreateUpdateSpace(unsigned int &size)
00077 {
00078         unsigned int blockSize = BlockSize();
00079         unsigned int num = ModPowerOf2(m_countLo, blockSize);
00080         size = blockSize - num;
00081         return (byte *)m_data.begin() + num;
00082 }
00083 
00084 template <class T, class BASE> unsigned int IteratedHashBase<T, BASE>::HashMultipleBlocks(const T *input, unsigned int length)
00085 {
00086         unsigned int blockSize = BlockSize();
00087         do
00088         {
00089                 HashBlock(input);
00090                 input += blockSize/sizeof(T);
00091                 length -= blockSize;
00092         }
00093         while (length >= blockSize);
00094         return length;
00095 }
00096 
00097 template <class T, class BASE> void IteratedHashBase<T, BASE>::PadLastBlock(unsigned int lastBlockSize, byte padFirst)
00098 {
00099         unsigned int blockSize = BlockSize();
00100         unsigned int num = ModPowerOf2(m_countLo, blockSize);
00101         ((byte *)m_data.begin())[num++]=padFirst;
00102         if (num <= lastBlockSize)
00103                 memset((byte *)m_data.begin()+num, 0, lastBlockSize-num);
00104         else
00105         {
00106                 memset((byte *)m_data.begin()+num, 0, blockSize-num);
00107                 HashBlock(m_data);
00108                 memset(m_data, 0, lastBlockSize);
00109         }
00110 }
00111 
00112 template <class T, class BASE> void IteratedHashBase<T, BASE>::Restart()
00113 {
00114         m_countLo = m_countHi = 0;
00115         Init();
00116 }
00117 
00118 NAMESPACE_END
00119 
00120 #endif

Generated on Tue Jul 8 23:34:19 2003 for Crypto++ by doxygen 1.3.2