summaryrefslogtreecommitdiff
path: root/iterhash.cpp
diff options
context:
space:
mode:
authorweidai <weidai11@users.noreply.github.com>2002-10-04 17:31:41 +0000
committerweidai <weidai11@users.noreply.github.com>2002-10-04 17:31:41 +0000
commita3b6ece7ab341b5b14135baeccea7d5e4c086771 (patch)
tree8b045309c238226c32a563b1df6b9c30a2f0e0b3 /iterhash.cpp
downloadcryptopp-git-a3b6ece7ab341b5b14135baeccea7d5e4c086771.tar.gz
Initial revision
Diffstat (limited to 'iterhash.cpp')
-rw-r--r--iterhash.cpp123
1 files changed, 123 insertions, 0 deletions
diff --git a/iterhash.cpp b/iterhash.cpp
new file mode 100644
index 00000000..08f76261
--- /dev/null
+++ b/iterhash.cpp
@@ -0,0 +1,123 @@
+// iterhash.cpp - written and placed in the public domain by Wei Dai
+
+#include "pch.h"
+#include "iterhash.h"
+#include "misc.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+template <class T, class BASE>
+IteratedHashBase<T, BASE>::IteratedHashBase(unsigned int blockSize, unsigned int digestSize)
+ : m_data(blockSize/sizeof(T)), m_digest(digestSize/sizeof(T))
+ , m_countHi(0), m_countLo(0)
+{
+}
+
+template <class T, class BASE> void IteratedHashBase<T, BASE>::Update(const byte *input, unsigned int len)
+{
+ HashWordType tmp = m_countLo;
+ if ((m_countLo = tmp + len) < tmp)
+ m_countHi++; // Carry from low to high
+ m_countHi += SafeRightShift<8*sizeof(HashWordType)>(len);
+
+ unsigned int blockSize = BlockSize();
+ unsigned int num = (unsigned int)(tmp & (blockSize-1));
+
+ if (num != 0)
+ {
+ if ((num+len) >= blockSize)
+ {
+ memcpy((byte *)m_data.begin()+num, input, blockSize-num);
+ HashBlock(m_data);
+ input += (blockSize-num);
+ len-=(blockSize - num);
+ num=0;
+ // drop through and do the rest
+ }
+ else
+ {
+ memcpy((byte *)m_data.begin()+num, input, len);
+ return;
+ }
+ }
+
+ // we now can process the input data in blocks of blockSize
+ // chars and save the leftovers to this->data.
+ if (len >= blockSize)
+ {
+ if (input == (byte *)m_data.begin())
+ {
+ assert(len == blockSize);
+ HashBlock(m_data);
+ return;
+ }
+ else if (IsAligned<T>(input))
+ {
+ unsigned int leftOver = HashMultipleBlocks((T *)input, len);
+ input += (len - leftOver);
+ len = leftOver;
+ }
+ else
+ do
+ { // copy input first if it's not aligned correctly
+ memcpy(m_data, input, blockSize);
+ HashBlock(m_data);
+ input+=blockSize;
+ len-=blockSize;
+ } while (len >= blockSize);
+ }
+
+ memcpy(m_data, input, len);
+}
+
+template <class T, class BASE> byte * IteratedHashBase<T, BASE>::CreateUpdateSpace(unsigned int &size)
+{
+ unsigned int blockSize = BlockSize();
+ unsigned int num = ModPowerOf2(m_countLo, blockSize);
+ size = blockSize - num;
+ return (byte *)m_data.begin() + num;
+}
+
+template <class T, class BASE> unsigned int IteratedHashBase<T, BASE>::HashMultipleBlocks(const T *input, unsigned int length)
+{
+ unsigned int blockSize = BlockSize();
+ do
+ {
+ HashBlock(input);
+ input += blockSize/sizeof(T);
+ length -= blockSize;
+ }
+ while (length >= blockSize);
+ return length;
+}
+
+template <class T, class BASE> void IteratedHashBase<T, BASE>::PadLastBlock(unsigned int lastBlockSize, byte padFirst)
+{
+ unsigned int blockSize = BlockSize();
+ unsigned int num = ModPowerOf2(m_countLo, blockSize);
+ ((byte *)m_data.begin())[num++]=padFirst;
+ if (num <= lastBlockSize)
+ memset((byte *)m_data.begin()+num, 0, lastBlockSize-num);
+ else
+ {
+ memset((byte *)m_data.begin()+num, 0, blockSize-num);
+ HashBlock(m_data);
+ memset(m_data, 0, lastBlockSize);
+ }
+}
+
+template <class T, class BASE> void IteratedHashBase<T, BASE>::Restart()
+{
+ m_countLo = m_countHi = 0;
+ Init();
+}
+
+#ifdef WORD64_AVAILABLE
+template class IteratedHashBase<word64, HashTransformation>;
+template class IteratedHashBase<word64, MessageAuthenticationCode>;
+#endif
+
+template class IteratedHashBase<word32, HashTransformation>;
+template class IteratedHashBase<word32, MessageAuthenticationCode>;
+
+NAMESPACE_END