00001
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++;
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)
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
00031 }
00032 else
00033 {
00034 memcpy((byte *)m_data.begin()+num, input, len);
00035 return;
00036 }
00037 }
00038
00039
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 {
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();
00133 }
00134
00135 NAMESPACE_END