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