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 = BlockSize();
00023 unsigned int num = ModPowerOf2(oldCountLo, blockSize);
00024
00025 if (num != 0)
00026 {
00027 if ((num+len) >= blockSize)
00028 {
00029 memcpy((byte *)m_data.begin()+num, input, blockSize-num);
00030 HashBlock(m_data);
00031 input += (blockSize-num);
00032 len-=(blockSize - num);
00033 num=0;
00034
00035 }
00036 else
00037 {
00038 memcpy((byte *)m_data.begin()+num, input, len);
00039 return;
00040 }
00041 }
00042
00043
00044 if (len >= blockSize)
00045 {
00046 if (input == (byte *)m_data.begin())
00047 {
00048 assert(len == blockSize);
00049 HashBlock(m_data);
00050 return;
00051 }
00052 else if (IsAligned<T>(input))
00053 {
00054 size_t leftOver = HashMultipleBlocks((T *)input, len);
00055 input += (len - leftOver);
00056 len = leftOver;
00057 }
00058 else
00059 do
00060 {
00061 memcpy(m_data, input, blockSize);
00062 HashBlock(m_data);
00063 input+=blockSize;
00064 len-=blockSize;
00065 } while (len >= blockSize);
00066 }
00067
00068 memcpy(m_data, input, len);
00069 }
00070
00071 template <class T, class BASE> byte * IteratedHashBase<T, BASE>::CreateUpdateSpace(size_t &size)
00072 {
00073 unsigned int blockSize = BlockSize();
00074 unsigned int num = ModPowerOf2(m_countLo, blockSize);
00075 size = blockSize - num;
00076 return (byte *)m_data.begin() + num;
00077 }
00078
00079 template <class T, class BASE> size_t IteratedHashBase<T, BASE>::HashMultipleBlocks(const T *input, size_t length)
00080 {
00081 unsigned int blockSize = BlockSize();
00082 bool noReverse = NativeByteOrderIs(GetByteOrder());
00083 do
00084 {
00085 if (noReverse)
00086 HashEndianCorrectedBlock(input);
00087 else
00088 {
00089 ByteReverse(this->m_data.begin(), input, this->BlockSize());
00090 HashEndianCorrectedBlock(this->m_data);
00091 }
00092
00093 input += blockSize/sizeof(T);
00094 length -= blockSize;
00095 }
00096 while (length >= blockSize);
00097 return length;
00098 }
00099
00100 template <class T, class BASE> void IteratedHashBase<T, BASE>::PadLastBlock(unsigned int lastBlockSize, byte padFirst)
00101 {
00102 unsigned int blockSize = BlockSize();
00103 unsigned int num = ModPowerOf2(m_countLo, blockSize);
00104 ((byte *)m_data.begin())[num++]=padFirst;
00105 if (num <= lastBlockSize)
00106 memset((byte *)m_data.begin()+num, 0, lastBlockSize-num);
00107 else
00108 {
00109 memset((byte *)m_data.begin()+num, 0, blockSize-num);
00110 HashBlock(m_data);
00111 memset(m_data, 0, lastBlockSize);
00112 }
00113 }
00114
00115 template <class T, class BASE> void IteratedHashBase<T, BASE>::Restart()
00116 {
00117 m_countLo = m_countHi = 0;
00118 Init();
00119 }
00120
00121 template <class T, class BASE> void IteratedHashBase<T, BASE>::TruncatedFinal(byte *digest, size_t size)
00122 {
00123 this->ThrowIfInvalidTruncatedSize(size);
00124
00125 PadLastBlock(this->BlockSize() - 2*sizeof(HashWordType));
00126 ByteOrder order = this->GetByteOrder();
00127 ConditionalByteReverse<HashWordType>(order, this->m_data, this->m_data, this->BlockSize() - 2*sizeof(HashWordType));
00128
00129 this->m_data[this->m_data.size()-2] = order ? this->GetBitCountHi() : this->GetBitCountLo();
00130 this->m_data[this->m_data.size()-1] = order ? this->GetBitCountLo() : this->GetBitCountHi();
00131
00132 HashEndianCorrectedBlock(this->m_data);
00133 ConditionalByteReverse<HashWordType>(order, this->m_digest, this->m_digest, this->DigestSize());
00134 memcpy(digest, this->m_digest, size);
00135
00136 this->Restart();
00137 }
00138
00139 NAMESPACE_END
00140
00141 #endif