00001
00002
00003 #include "pch.h"
00004
00005
00006 #if !defined(__SUNPRO_CC) || defined(CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES)
00007
00008 #include "iterhash.h"
00009 #include "misc.h"
00010
00011 NAMESPACE_BEGIN(CryptoPP)
00012
00013 template <class T, class BASE> void IteratedHashBase<T, BASE>::Update(const byte *input, size_t len)
00014 {
00015 HashWordType oldCountLo = m_countLo, oldCountHi = m_countHi;
00016 if ((m_countLo = oldCountLo + HashWordType(len)) < oldCountLo)
00017 m_countHi++;
00018 m_countHi += (HashWordType)SafeRightShift<8*sizeof(HashWordType)>(len);
00019 if (m_countHi < oldCountHi || SafeRightShift<2*8*sizeof(HashWordType)>(len) != 0)
00020 throw HashInputTooLong(this->AlgorithmName());
00021
00022 unsigned int blockSize = this->BlockSize();
00023 unsigned int num = ModPowerOf2(oldCountLo, blockSize);
00024 T* dataBuf = this->DataBuf();
00025 byte* data = (byte *)dataBuf;
00026
00027 if (num != 0)
00028 {
00029 if ((num+len) >= blockSize)
00030 {
00031 memcpy(data+num, input, blockSize-num);
00032 HashBlock(dataBuf);
00033 input += (blockSize-num);
00034 len-=(blockSize - num);
00035 num=0;
00036
00037 }
00038 else
00039 {
00040 memcpy(data+num, input, len);
00041 return;
00042 }
00043 }
00044
00045
00046 if (len >= blockSize)
00047 {
00048 if (input == data)
00049 {
00050 assert(len == blockSize);
00051 HashBlock(dataBuf);
00052 return;
00053 }
00054 else if (IsAligned<T>(input))
00055 {
00056 size_t leftOver = HashMultipleBlocks((T *)input, len);
00057 input += (len - leftOver);
00058 len = leftOver;
00059 }
00060 else
00061 do
00062 {
00063 memcpy(data, input, blockSize);
00064 HashBlock(dataBuf);
00065 input+=blockSize;
00066 len-=blockSize;
00067 } while (len >= blockSize);
00068 }
00069
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 ConditionalByteReverse<HashWordType>(order, dataBuf, dataBuf, blockSize - 2*sizeof(HashWordType));
00137
00138 dataBuf[blockSize/sizeof(T)-2] = order ? this->GetBitCountHi() : this->GetBitCountLo();
00139 dataBuf[blockSize/sizeof(T)-1] = order ? this->GetBitCountLo() : this->GetBitCountHi();
00140
00141 HashEndianCorrectedBlock(dataBuf);
00142 ConditionalByteReverse<HashWordType>(order, stateBuf, stateBuf, this->DigestSize());
00143 memcpy(digest, stateBuf, size);
00144
00145 this->Restart();
00146 }
00147
00148 NAMESPACE_END
00149
00150 #endif