Branch data Line data Source code
1 : : // Copyright (c) 2016-present The Bitcoin Core developers
2 : : // Distributed under the MIT software license, see the accompanying
3 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 : :
5 : : #include <crypto/siphash.h>
6 : :
7 : : #include <uint256.h>
8 : :
9 : : #include <bit>
10 : : #include <cassert>
11 : : #include <span>
12 : :
13 : : #define SIPROUND do { \
14 : : v0 += v1; v1 = std::rotl(v1, 13); v1 ^= v0; \
15 : : v0 = std::rotl(v0, 32); \
16 : : v2 += v3; v3 = std::rotl(v3, 16); v3 ^= v2; \
17 : : v0 += v3; v3 = std::rotl(v3, 21); v3 ^= v0; \
18 : : v2 += v1; v1 = std::rotl(v1, 17); v1 ^= v2; \
19 : : v2 = std::rotl(v2, 32); \
20 : : } while (0)
21 : :
22 : 4442102 : CSipHasher::CSipHasher(uint64_t k0, uint64_t k1) : m_state{k0, k1} {}
23 : :
24 : 4113179 : CSipHasher& CSipHasher::Write(uint64_t data)
25 : : {
26 : 4113179 : uint64_t v0 = m_state.v[0], v1 = m_state.v[1], v2 = m_state.v[2], v3 = m_state.v[3];
27 : :
28 [ - + ]: 4113179 : assert(m_count % 8 == 0);
29 : :
30 : 4113179 : v3 ^= data;
31 : 4113179 : SIPROUND;
32 : 4113179 : SIPROUND;
33 : 4113179 : v0 ^= data;
34 : :
35 : 4113179 : m_state.v[0] = v0;
36 : 4113179 : m_state.v[1] = v1;
37 : 4113179 : m_state.v[2] = v2;
38 : 4113179 : m_state.v[3] = v3;
39 : :
40 : 4113179 : m_count += 8;
41 : 4113179 : return *this;
42 : : }
43 : :
44 : 4442184 : CSipHasher& CSipHasher::Write(std::span<const unsigned char> data)
45 : : {
46 : 4442184 : uint64_t v0 = m_state.v[0], v1 = m_state.v[1], v2 = m_state.v[2], v3 = m_state.v[3];
47 : 4442184 : uint64_t t = m_tmp;
48 : 4442184 : uint8_t c = m_count;
49 : :
50 [ + + ]: 138852072 : while (data.size() > 0) {
51 [ + + ]: 134409888 : t |= uint64_t{data.front()} << (8 * (c % 8));
52 : 134409888 : c++;
53 [ + + ]: 134409888 : if ((c & 7) == 0) {
54 : 16606582 : v3 ^= t;
55 : 16606582 : SIPROUND;
56 : 16606582 : SIPROUND;
57 : 16606582 : v0 ^= t;
58 : 16606582 : t = 0;
59 : : }
60 : 134409888 : data = data.subspan(1);
61 : : }
62 : :
63 : 4442184 : m_state.v[0] = v0;
64 : 4442184 : m_state.v[1] = v1;
65 : 4442184 : m_state.v[2] = v2;
66 : 4442184 : m_state.v[3] = v3;
67 : 4442184 : m_count = c;
68 : 4442184 : m_tmp = t;
69 : :
70 : 4442184 : return *this;
71 : : }
72 : :
73 : 4442196 : uint64_t CSipHasher::Finalize() const
74 : : {
75 : 4442196 : uint64_t v0 = m_state.v[0], v1 = m_state.v[1], v2 = m_state.v[2], v3 = m_state.v[3];
76 : :
77 : 4442196 : uint64_t t = m_tmp | (((uint64_t)m_count) << 56);
78 : :
79 : 4442196 : v3 ^= t;
80 : 4442196 : SIPROUND;
81 : 4442196 : SIPROUND;
82 : 4442196 : v0 ^= t;
83 : 4442196 : v2 ^= 0xFF;
84 : 4442196 : SIPROUND;
85 : 4442196 : SIPROUND;
86 : 4442196 : SIPROUND;
87 : 4442196 : SIPROUND;
88 : 4442196 : return v0 ^ v1 ^ v2 ^ v3;
89 : : }
90 : :
91 : 839929 : uint64_t PresaltedSipHasher::operator()(const uint256& val) const noexcept
92 : : {
93 : 839929 : uint64_t v0 = m_state.v[0], v1 = m_state.v[1], v2 = m_state.v[2], v3 = m_state.v[3];
94 : 839929 : uint64_t d = val.GetUint64(0);
95 : 839929 : v3 ^= d;
96 : :
97 : 839929 : SIPROUND;
98 : 839929 : SIPROUND;
99 : 839929 : v0 ^= d;
100 : 839929 : d = val.GetUint64(1);
101 : 839929 : v3 ^= d;
102 : 839929 : SIPROUND;
103 : 839929 : SIPROUND;
104 : 839929 : v0 ^= d;
105 : 839929 : d = val.GetUint64(2);
106 : 839929 : v3 ^= d;
107 : 839929 : SIPROUND;
108 : 839929 : SIPROUND;
109 : 839929 : v0 ^= d;
110 : 839929 : d = val.GetUint64(3);
111 : 839929 : v3 ^= d;
112 : 839929 : SIPROUND;
113 : 839929 : SIPROUND;
114 : 839929 : v0 ^= d;
115 : 839929 : v3 ^= (uint64_t{4}) << 59;
116 : 839929 : SIPROUND;
117 : 839929 : SIPROUND;
118 : 839929 : v0 ^= (uint64_t{4}) << 59;
119 : 839929 : v2 ^= 0xFF;
120 : 839929 : SIPROUND;
121 : 839929 : SIPROUND;
122 : 839929 : SIPROUND;
123 : 839929 : SIPROUND;
124 : 839929 : return v0 ^ v1 ^ v2 ^ v3;
125 : : }
126 : :
127 : : /** Specialized implementation for efficiency */
128 : 119921434 : uint64_t PresaltedSipHasher::operator()(const uint256& val, uint32_t extra) const noexcept
129 : : {
130 : 119921434 : uint64_t v0 = m_state.v[0], v1 = m_state.v[1], v2 = m_state.v[2], v3 = m_state.v[3];
131 : 119921434 : uint64_t d = val.GetUint64(0);
132 : 119921434 : v3 ^= d;
133 : 119921434 : SIPROUND;
134 : 119921434 : SIPROUND;
135 : 119921434 : v0 ^= d;
136 : 119921434 : d = val.GetUint64(1);
137 : 119921434 : v3 ^= d;
138 : 119921434 : SIPROUND;
139 : 119921434 : SIPROUND;
140 : 119921434 : v0 ^= d;
141 : 119921434 : d = val.GetUint64(2);
142 : 119921434 : v3 ^= d;
143 : 119921434 : SIPROUND;
144 : 119921434 : SIPROUND;
145 : 119921434 : v0 ^= d;
146 : 119921434 : d = val.GetUint64(3);
147 : 119921434 : v3 ^= d;
148 : 119921434 : SIPROUND;
149 : 119921434 : SIPROUND;
150 : 119921434 : v0 ^= d;
151 : 119921434 : d = ((uint64_t{36}) << 56) | extra;
152 : 119921434 : v3 ^= d;
153 : 119921434 : SIPROUND;
154 : 119921434 : SIPROUND;
155 : 119921434 : v0 ^= d;
156 : 119921434 : v2 ^= 0xFF;
157 : 119921434 : SIPROUND;
158 : 119921434 : SIPROUND;
159 : 119921434 : SIPROUND;
160 : 119921434 : SIPROUND;
161 : 119921434 : return v0 ^ v1 ^ v2 ^ v3;
162 : : }
|