00001
00002
00003 #ifndef __GNUC__
00004 #define CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES
00005 #endif
00006
00007 #include "iterhash.h"
00008 #include "misc.h"
00009
00010 NAMESPACE_BEGIN(CryptoPP)
00011
00012 template <class T, class BASE> void IteratedHashBase<T, BASE>::Update(const byte *input, size_t len)
00013 {
00014 HashWordType oldCountLo = m_countLo, oldCountHi = m_countHi;
00015 if ((m_countLo = oldCountLo + HashWordType(len)) < oldCountLo)
00016 m_countHi++;
00017 m_countHi += (HashWordType)SafeRightShift<8*sizeof(HashWordType)>(len);
00018 if (m_countHi < oldCountHi || SafeRightShift<2*8*sizeof(HashWordType)>(len) != 0)
00019 throw HashInputTooLong(this->AlgorithmName());
00020
00021 unsigned int blockSize = this->BlockSize();
00022 unsigned int num = ModPowerOf2(oldCountLo, blockSize);
00023 T* dataBuf = this->DataBuf();
00024 byte* data = (byte *)dataBuf;
00025
00026 if (num != 0)
00027 {
00028 if (num+len >= blockSize)
00029 {
00030 memcpy(data+num, input, blockSize-num);
00031 HashBlock(dataBuf);
00032 input += (blockSize-num);
00033 len -= (blockSize-num);
00034 num = 0;
00035
00036 }
00037 else
00038 {
00039 memcpy(data+num, input, len);
00040 return;
00041 }
00042 }
00043
00044
00045 if (len >= blockSize)
00046 {
00047 if (input == data)
00048 {
00049 assert(len == blockSize);
00050 HashBlock(dataBuf);
00051 return;
00052 }
00053 else if (IsAligned<T>(input))
00054 {
00055 size_t leftOver = HashMultipleBlocks((T *)input, len);
00056 input += (len - leftOver);
00057 len = leftOver;
00058 }
00059 else
00060 do
00061 {
00062 memcpy(data, input, blockSize);
00063 HashBlock(dataBuf);
00064 input+=blockSize;
00065 len-=blockSize;
00066 } while (len >= blockSize);
00067 }
00068
00069 memcpy(data, input, len);
00070 }
00071
00072 template <class T, class BASE> byte * IteratedHashBase<T, BASE>::CreateUpdateSpace(size_t &size)
00073 {
00074 unsigned int blockSize = this->BlockSize();
00075 unsigned int num = ModPowerOf2(m_countLo, blockSize);
00076 size = blockSize - num;
00077 return (byte *)DataBuf() + num;
00078 }
00079
00080 template <class T, class BASE> size_t IteratedHashBase<T, BASE>::HashMultipleBlocks(const T *input, size_t length)
00081 {
00082 unsigned int blockSize = this->BlockSize();
00083 bool noReverse = NativeByteOrderIs(this->GetByteOrder());
00084 T* dataBuf = this->DataBuf();
00085 do
00086 {
00087 if (noReverse)
00088 this->HashEndianCorrectedBlock(input);
00089 else
00090 {
00091 ByteReverse(dataBuf, input, this->BlockSize());
00092 this->HashEndianCorrectedBlock(dataBuf);
00093 }
00094
00095 input += blockSize/sizeof(T);
00096 length -= blockSize;
00097 }
00098 while (length >= blockSize);
00099 return length;
00100 }
00101
00102 template <class T, class BASE> void IteratedHashBase<T, BASE>::PadLastBlock(unsigned int lastBlockSize, byte padFirst)
00103 {
00104 unsigned int blockSize = this->BlockSize();
00105 unsigned int num = ModPowerOf2(m_countLo, blockSize);
00106 T* dataBuf = this->DataBuf();
00107 byte* data = (byte *)dataBuf;
00108 data[num++] = padFirst;
00109 if (num <= lastBlockSize)
00110 memset(data+num, 0, lastBlockSize-num);
00111 else
00112 {
00113 memset(data+num, 0, blockSize-num);
00114 HashBlock(dataBuf);
00115 memset(data, 0, lastBlockSize);
00116 }
00117 }
00118
00119 template <class T, class BASE> void IteratedHashBase<T, BASE>::Restart()
00120 {
00121 m_countLo = m_countHi = 0;
00122 Init();
00123 }
00124
00125 template <class T, class BASE> void IteratedHashBase<T, BASE>::TruncatedFinal(byte *digest, size_t size)
00126 {
00127 this->ThrowIfInvalidTruncatedSize(size);
00128
00129 T* dataBuf = this->DataBuf();
00130 T* stateBuf = this->StateBuf();
00131 unsigned int blockSize = this->BlockSize();
00132 ByteOrder order = this->GetByteOrder();
00133
00134 PadLastBlock(blockSize - 2*sizeof(HashWordType));
00135 dataBuf[blockSize/sizeof(T)-2+order] = ConditionalByteReverse(order, this->GetBitCountLo());
00136 dataBuf[blockSize/sizeof(T)-1-order] = ConditionalByteReverse(order, this->GetBitCountHi());
00137
00138 HashBlock(dataBuf);
00139
00140 if (IsAligned<HashWordType>(digest) && size%sizeof(HashWordType)==0)
00141 ConditionalByteReverse<HashWordType>(order, (HashWordType *)digest, stateBuf, size);
00142 else
00143 {
00144 ConditionalByteReverse<HashWordType>(order, stateBuf, stateBuf, this->DigestSize());
00145 memcpy(digest, stateBuf, size);
00146 }
00147
00148 this->Restart();
00149 }
00150
00151 #ifdef __GNUC__
00152 template class IteratedHashBase<word64, HashTransformation>;
00153 template class IteratedHashBase<word64, MessageAuthenticationCode>;
00154
00155 template class IteratedHashBase<word32, HashTransformation>;
00156 template class IteratedHashBase<word32, MessageAuthenticationCode>;
00157 #endif
00158
00159 NAMESPACE_END