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