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
|
/*
* SipHash
* (C) 2014,2015 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
#include <botan/siphash.h>
namespace Botan {
namespace {
void SipRounds(uint64_t M, secure_vector<uint64_t>& V, size_t r)
{
uint64_t V0 = V[0], V1 = V[1], V2 = V[2], V3 = V[3];
V3 ^= M;
for(size_t i = 0; i != r; ++i)
{
V0 += V1; V2 += V3;
V1 = rotate_left(V1, 13);
V3 = rotate_left(V3, 16);
V1 ^= V0; V3 ^= V2;
V0 = rotate_left(V0, 32);
V2 += V1; V0 += V3;
V1 = rotate_left(V1, 17);
V3 = rotate_left(V3, 21);
V1 ^= V2; V3 ^= V0;
V2 = rotate_left(V2, 32);
}
V0 ^= M;
V[0] = V0; V[1] = V1; V[2] = V2; V[3] = V3;
}
}
void SipHash::add_data(const uint8_t input[], size_t length)
{
// SipHash counts the message length mod 256
m_words += static_cast<uint8_t>(length);
if(m_mbuf_pos)
{
while(length && m_mbuf_pos != 8)
{
m_mbuf = (m_mbuf >> 8) | (static_cast<uint64_t>(input[0]) << 56);
++m_mbuf_pos;
++input;
length--;
}
if(m_mbuf_pos == 8)
{
SipRounds(m_mbuf, m_V, m_C);
m_mbuf_pos = 0;
m_mbuf = 0;
}
}
while(length >= 8)
{
SipRounds(load_le<uint64_t>(input, 0), m_V, m_C);
input += 8;
length -= 8;
}
for(size_t i = 0; i != length; ++i)
{
m_mbuf = (m_mbuf >> 8) | (static_cast<uint64_t>(input[i]) << 56);
m_mbuf_pos++;
}
}
void SipHash::final_result(uint8_t mac[])
{
m_mbuf = (m_mbuf >> (64-m_mbuf_pos*8)) | (static_cast<uint64_t>(m_words) << 56);
SipRounds(m_mbuf, m_V, m_C);
m_V[2] ^= 0xFF;
SipRounds(0, m_V, m_D);
const uint64_t X = m_V[0] ^ m_V[1] ^ m_V[2] ^ m_V[3];
store_le(X, mac);
clear();
}
void SipHash::key_schedule(const uint8_t key[], size_t)
{
const uint64_t K0 = load_le<uint64_t>(key, 0);
const uint64_t K1 = load_le<uint64_t>(key, 1);
m_V.resize(4);
m_V[0] = K0 ^ 0x736F6D6570736575;
m_V[1] = K1 ^ 0x646F72616E646F6D;
m_V[2] = K0 ^ 0x6C7967656E657261;
m_V[3] = K1 ^ 0x7465646279746573;
}
void SipHash::clear()
{
m_V.clear();
m_mbuf = 0;
m_mbuf_pos = 0;
m_words = 0;
}
std::string SipHash::name() const
{
return "SipHash(" + std::to_string(m_C) + "," + std::to_string(m_D) + ")";
}
MessageAuthenticationCode* SipHash::clone() const
{
return new SipHash(m_C, m_D);
}
}
|