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