1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
// 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 = ModPowerOf2(tmp, blockSize);
if (num != 0) // process left over data
{
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;
}
}
// now process the input data in blocks of blockSize bytes and save the leftovers to m_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
|