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 : 4482036 : CSipHasher::CSipHasher(uint64_t k0, uint64_t k1)
23 : : {
24 : 4482036 : v[0] = 0x736f6d6570736575ULL ^ k0;
25 : 4482036 : v[1] = 0x646f72616e646f6dULL ^ k1;
26 : 4482036 : v[2] = 0x6c7967656e657261ULL ^ k0;
27 : 4482036 : v[3] = 0x7465646279746573ULL ^ k1;
28 : 4482036 : count = 0;
29 : 4482036 : tmp = 0;
30 : 4482036 : }
31 : :
32 : 4151137 : CSipHasher& CSipHasher::Write(uint64_t data)
33 : : {
34 : 4151137 : uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3];
35 : :
36 [ - + ]: 4151137 : assert(count % 8 == 0);
37 : :
38 : 4151137 : v3 ^= data;
39 : 4151137 : SIPROUND;
40 : 4151137 : SIPROUND;
41 : 4151137 : v0 ^= data;
42 : :
43 : 4151137 : v[0] = v0;
44 : 4151137 : v[1] = v1;
45 : 4151137 : v[2] = v2;
46 : 4151137 : v[3] = v3;
47 : :
48 : 4151137 : count += 8;
49 : 4151137 : return *this;
50 : : }
51 : :
52 : 4482118 : CSipHasher& CSipHasher::Write(std::span<const unsigned char> data)
53 : : {
54 : 4482118 : uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3];
55 : 4482118 : uint64_t t = tmp;
56 : 4482118 : uint8_t c = count;
57 : :
58 [ + + ]: 140225791 : while (data.size() > 0) {
59 [ + + ]: 135743673 : t |= uint64_t{data.front()} << (8 * (c % 8));
60 : 135743673 : c++;
61 [ + + ]: 135743673 : if ((c & 7) == 0) {
62 : 16774303 : v3 ^= t;
63 : 16774303 : SIPROUND;
64 : 16774303 : SIPROUND;
65 : 16774303 : v0 ^= t;
66 : 16774303 : t = 0;
67 : : }
68 : 135743673 : data = data.subspan(1);
69 : : }
70 : :
71 : 4482118 : v[0] = v0;
72 : 4482118 : v[1] = v1;
73 : 4482118 : v[2] = v2;
74 : 4482118 : v[3] = v3;
75 : 4482118 : count = c;
76 : 4482118 : tmp = t;
77 : :
78 : 4482118 : return *this;
79 : : }
80 : :
81 : 4482130 : uint64_t CSipHasher::Finalize() const
82 : : {
83 : 4482130 : uint64_t v0 = v[0], v1 = v[1], v2 = v[2], v3 = v[3];
84 : :
85 : 4482130 : uint64_t t = tmp | (((uint64_t)count) << 56);
86 : :
87 : 4482130 : v3 ^= t;
88 : 4482130 : SIPROUND;
89 : 4482130 : SIPROUND;
90 : 4482130 : v0 ^= t;
91 : 4482130 : v2 ^= 0xFF;
92 : 4482130 : SIPROUND;
93 : 4482130 : SIPROUND;
94 : 4482130 : SIPROUND;
95 : 4482130 : SIPROUND;
96 : 4482130 : return v0 ^ v1 ^ v2 ^ v3;
97 : : }
98 : :
99 : 3196466 : uint64_t SipHashUint256(uint64_t k0, uint64_t k1, const uint256& val)
100 : : {
101 : : /* Specialized implementation for efficiency */
102 : 3196466 : uint64_t d = val.GetUint64(0);
103 : :
104 : 3196466 : uint64_t v0 = 0x736f6d6570736575ULL ^ k0;
105 : 3196466 : uint64_t v1 = 0x646f72616e646f6dULL ^ k1;
106 : 3196466 : uint64_t v2 = 0x6c7967656e657261ULL ^ k0;
107 : 3196466 : uint64_t v3 = 0x7465646279746573ULL ^ k1 ^ d;
108 : :
109 : 3196466 : SIPROUND;
110 : 3196466 : SIPROUND;
111 : 3196466 : v0 ^= d;
112 : 3196466 : d = val.GetUint64(1);
113 : 3196466 : v3 ^= d;
114 : 3196466 : SIPROUND;
115 : 3196466 : SIPROUND;
116 : 3196466 : v0 ^= d;
117 : 3196466 : d = val.GetUint64(2);
118 : 3196466 : v3 ^= d;
119 : 3196466 : SIPROUND;
120 : 3196466 : SIPROUND;
121 : 3196466 : v0 ^= d;
122 : 3196466 : d = val.GetUint64(3);
123 : 3196466 : v3 ^= d;
124 : 3196466 : SIPROUND;
125 : 3196466 : SIPROUND;
126 : 3196466 : v0 ^= d;
127 : 3196466 : v3 ^= (uint64_t{4}) << 59;
128 : 3196466 : SIPROUND;
129 : 3196466 : SIPROUND;
130 : 3196466 : v0 ^= (uint64_t{4}) << 59;
131 : 3196466 : v2 ^= 0xFF;
132 : 3196466 : SIPROUND;
133 : 3196466 : SIPROUND;
134 : 3196466 : SIPROUND;
135 : 3196466 : SIPROUND;
136 : 3196466 : return v0 ^ v1 ^ v2 ^ v3;
137 : : }
138 : :
139 : 111529211 : uint64_t SipHashUint256Extra(uint64_t k0, uint64_t k1, const uint256& val, uint32_t extra)
140 : : {
141 : : /* Specialized implementation for efficiency */
142 : 111529211 : uint64_t d = val.GetUint64(0);
143 : :
144 : 111529211 : uint64_t v0 = 0x736f6d6570736575ULL ^ k0;
145 : 111529211 : uint64_t v1 = 0x646f72616e646f6dULL ^ k1;
146 : 111529211 : uint64_t v2 = 0x6c7967656e657261ULL ^ k0;
147 : 111529211 : uint64_t v3 = 0x7465646279746573ULL ^ k1 ^ d;
148 : :
149 : 111529211 : SIPROUND;
150 : 111529211 : SIPROUND;
151 : 111529211 : v0 ^= d;
152 : 111529211 : d = val.GetUint64(1);
153 : 111529211 : v3 ^= d;
154 : 111529211 : SIPROUND;
155 : 111529211 : SIPROUND;
156 : 111529211 : v0 ^= d;
157 : 111529211 : d = val.GetUint64(2);
158 : 111529211 : v3 ^= d;
159 : 111529211 : SIPROUND;
160 : 111529211 : SIPROUND;
161 : 111529211 : v0 ^= d;
162 : 111529211 : d = val.GetUint64(3);
163 : 111529211 : v3 ^= d;
164 : 111529211 : SIPROUND;
165 : 111529211 : SIPROUND;
166 : 111529211 : v0 ^= d;
167 : 111529211 : d = ((uint64_t{36}) << 56) | extra;
168 : 111529211 : v3 ^= d;
169 : 111529211 : SIPROUND;
170 : 111529211 : SIPROUND;
171 : 111529211 : v0 ^= d;
172 : 111529211 : v2 ^= 0xFF;
173 : 111529211 : SIPROUND;
174 : 111529211 : SIPROUND;
175 : 111529211 : SIPROUND;
176 : 111529211 : SIPROUND;
177 : 111529211 : return v0 ^ v1 ^ v2 ^ v3;
178 : : }
|