sha256.cpp raw
1 // Copyright (c) 2014-2022 The Limenka 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 <limenka-build-config.h> // IWYU pragma: keep
6
7 #include <crypto/sha256.h>
8 #include <crypto/common.h>
9
10 #include <algorithm>
11 #include <cassert>
12 #include <cstring>
13
14 #if !defined(DISABLE_OPTIMIZED_SHA256)
15 #include <compat/cpuid.h>
16
17 #if defined(__linux__) && defined(ENABLE_ARM_SHANI)
18 #include <sys/auxv.h>
19 #include <asm/hwcap.h>
20 #endif
21
22 #if defined(__APPLE__) && defined(ENABLE_ARM_SHANI)
23 #include <sys/types.h>
24 #include <sys/sysctl.h>
25 #endif
26
27 #if defined(__x86_64__) || defined(__amd64__) || defined(__i386__)
28 namespace sha256_sse4
29 {
30 void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks);
31 }
32 #endif
33
34 namespace sha256d64_sse41
35 {
36 void Transform_4way(unsigned char* out, const unsigned char* in);
37 }
38
39 namespace sha256d64_avx2
40 {
41 void Transform_8way(unsigned char* out, const unsigned char* in);
42 }
43
44 namespace sha256d64_x86_shani
45 {
46 void Transform_2way(unsigned char* out, const unsigned char* in);
47 }
48
49 namespace sha256_x86_shani
50 {
51 void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks);
52 }
53
54 namespace sha256_arm_shani
55 {
56 void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks);
57 }
58
59 namespace sha256d64_arm_shani
60 {
61 void Transform_2way(unsigned char* out, const unsigned char* in);
62 }
63 #endif // DISABLE_OPTIMIZED_SHA256
64
65 #if defined(__linux__) && defined(ENABLE_POWER8)
66 #include <sys/auxv.h>
67 namespace sha256_power8
68 {
69 void Transform_4way(unsigned char* out, const unsigned char* in);
70 }
71 #endif
72
73
74 // Internal implementation code.
75 namespace
76 {
77 /// Internal SHA-256 implementation.
78 namespace sha256
79 {
80 uint32_t inline Ch(uint32_t x, uint32_t y, uint32_t z) { return z ^ (x & (y ^ z)); }
81 uint32_t inline Maj(uint32_t x, uint32_t y, uint32_t z) { return (x & y) | (z & (x | y)); }
82 uint32_t inline Sigma0(uint32_t x) { return (x >> 2 | x << 30) ^ (x >> 13 | x << 19) ^ (x >> 22 | x << 10); }
83 uint32_t inline Sigma1(uint32_t x) { return (x >> 6 | x << 26) ^ (x >> 11 | x << 21) ^ (x >> 25 | x << 7); }
84 uint32_t inline sigma0(uint32_t x) { return (x >> 7 | x << 25) ^ (x >> 18 | x << 14) ^ (x >> 3); }
85 uint32_t inline sigma1(uint32_t x) { return (x >> 17 | x << 15) ^ (x >> 19 | x << 13) ^ (x >> 10); }
86
87 /** One round of SHA-256. */
88 void inline Round(uint32_t a, uint32_t b, uint32_t c, uint32_t& d, uint32_t e, uint32_t f, uint32_t g, uint32_t& h, uint32_t k)
89 {
90 uint32_t t1 = h + Sigma1(e) + Ch(e, f, g) + k;
91 uint32_t t2 = Sigma0(a) + Maj(a, b, c);
92 d += t1;
93 h = t1 + t2;
94 }
95
96 /** Initialize SHA-256 state. */
97 void inline Initialize(uint32_t* s)
98 {
99 s[0] = 0x6a09e667ul;
100 s[1] = 0xbb67ae85ul;
101 s[2] = 0x3c6ef372ul;
102 s[3] = 0xa54ff53aul;
103 s[4] = 0x510e527ful;
104 s[5] = 0x9b05688cul;
105 s[6] = 0x1f83d9abul;
106 s[7] = 0x5be0cd19ul;
107 }
108
109 /** Perform a number of SHA-256 transformations, processing 64-byte chunks. */
110 void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks)
111 {
112 while (blocks--) {
113 uint32_t a = s[0], b = s[1], c = s[2], d = s[3], e = s[4], f = s[5], g = s[6], h = s[7];
114 uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;
115
116 Round(a, b, c, d, e, f, g, h, 0x428a2f98 + (w0 = ReadBE32(chunk + 0)));
117 Round(h, a, b, c, d, e, f, g, 0x71374491 + (w1 = ReadBE32(chunk + 4)));
118 Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf + (w2 = ReadBE32(chunk + 8)));
119 Round(f, g, h, a, b, c, d, e, 0xe9b5dba5 + (w3 = ReadBE32(chunk + 12)));
120 Round(e, f, g, h, a, b, c, d, 0x3956c25b + (w4 = ReadBE32(chunk + 16)));
121 Round(d, e, f, g, h, a, b, c, 0x59f111f1 + (w5 = ReadBE32(chunk + 20)));
122 Round(c, d, e, f, g, h, a, b, 0x923f82a4 + (w6 = ReadBE32(chunk + 24)));
123 Round(b, c, d, e, f, g, h, a, 0xab1c5ed5 + (w7 = ReadBE32(chunk + 28)));
124 Round(a, b, c, d, e, f, g, h, 0xd807aa98 + (w8 = ReadBE32(chunk + 32)));
125 Round(h, a, b, c, d, e, f, g, 0x12835b01 + (w9 = ReadBE32(chunk + 36)));
126 Round(g, h, a, b, c, d, e, f, 0x243185be + (w10 = ReadBE32(chunk + 40)));
127 Round(f, g, h, a, b, c, d, e, 0x550c7dc3 + (w11 = ReadBE32(chunk + 44)));
128 Round(e, f, g, h, a, b, c, d, 0x72be5d74 + (w12 = ReadBE32(chunk + 48)));
129 Round(d, e, f, g, h, a, b, c, 0x80deb1fe + (w13 = ReadBE32(chunk + 52)));
130 Round(c, d, e, f, g, h, a, b, 0x9bdc06a7 + (w14 = ReadBE32(chunk + 56)));
131 Round(b, c, d, e, f, g, h, a, 0xc19bf174 + (w15 = ReadBE32(chunk + 60)));
132
133 Round(a, b, c, d, e, f, g, h, 0xe49b69c1 + (w0 += sigma1(w14) + w9 + sigma0(w1)));
134 Round(h, a, b, c, d, e, f, g, 0xefbe4786 + (w1 += sigma1(w15) + w10 + sigma0(w2)));
135 Round(g, h, a, b, c, d, e, f, 0x0fc19dc6 + (w2 += sigma1(w0) + w11 + sigma0(w3)));
136 Round(f, g, h, a, b, c, d, e, 0x240ca1cc + (w3 += sigma1(w1) + w12 + sigma0(w4)));
137 Round(e, f, g, h, a, b, c, d, 0x2de92c6f + (w4 += sigma1(w2) + w13 + sigma0(w5)));
138 Round(d, e, f, g, h, a, b, c, 0x4a7484aa + (w5 += sigma1(w3) + w14 + sigma0(w6)));
139 Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc + (w6 += sigma1(w4) + w15 + sigma0(w7)));
140 Round(b, c, d, e, f, g, h, a, 0x76f988da + (w7 += sigma1(w5) + w0 + sigma0(w8)));
141 Round(a, b, c, d, e, f, g, h, 0x983e5152 + (w8 += sigma1(w6) + w1 + sigma0(w9)));
142 Round(h, a, b, c, d, e, f, g, 0xa831c66d + (w9 += sigma1(w7) + w2 + sigma0(w10)));
143 Round(g, h, a, b, c, d, e, f, 0xb00327c8 + (w10 += sigma1(w8) + w3 + sigma0(w11)));
144 Round(f, g, h, a, b, c, d, e, 0xbf597fc7 + (w11 += sigma1(w9) + w4 + sigma0(w12)));
145 Round(e, f, g, h, a, b, c, d, 0xc6e00bf3 + (w12 += sigma1(w10) + w5 + sigma0(w13)));
146 Round(d, e, f, g, h, a, b, c, 0xd5a79147 + (w13 += sigma1(w11) + w6 + sigma0(w14)));
147 Round(c, d, e, f, g, h, a, b, 0x06ca6351 + (w14 += sigma1(w12) + w7 + sigma0(w15)));
148 Round(b, c, d, e, f, g, h, a, 0x14292967 + (w15 += sigma1(w13) + w8 + sigma0(w0)));
149
150 Round(a, b, c, d, e, f, g, h, 0x27b70a85 + (w0 += sigma1(w14) + w9 + sigma0(w1)));
151 Round(h, a, b, c, d, e, f, g, 0x2e1b2138 + (w1 += sigma1(w15) + w10 + sigma0(w2)));
152 Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc + (w2 += sigma1(w0) + w11 + sigma0(w3)));
153 Round(f, g, h, a, b, c, d, e, 0x53380d13 + (w3 += sigma1(w1) + w12 + sigma0(w4)));
154 Round(e, f, g, h, a, b, c, d, 0x650a7354 + (w4 += sigma1(w2) + w13 + sigma0(w5)));
155 Round(d, e, f, g, h, a, b, c, 0x766a0abb + (w5 += sigma1(w3) + w14 + sigma0(w6)));
156 Round(c, d, e, f, g, h, a, b, 0x81c2c92e + (w6 += sigma1(w4) + w15 + sigma0(w7)));
157 Round(b, c, d, e, f, g, h, a, 0x92722c85 + (w7 += sigma1(w5) + w0 + sigma0(w8)));
158 Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1 + (w8 += sigma1(w6) + w1 + sigma0(w9)));
159 Round(h, a, b, c, d, e, f, g, 0xa81a664b + (w9 += sigma1(w7) + w2 + sigma0(w10)));
160 Round(g, h, a, b, c, d, e, f, 0xc24b8b70 + (w10 += sigma1(w8) + w3 + sigma0(w11)));
161 Round(f, g, h, a, b, c, d, e, 0xc76c51a3 + (w11 += sigma1(w9) + w4 + sigma0(w12)));
162 Round(e, f, g, h, a, b, c, d, 0xd192e819 + (w12 += sigma1(w10) + w5 + sigma0(w13)));
163 Round(d, e, f, g, h, a, b, c, 0xd6990624 + (w13 += sigma1(w11) + w6 + sigma0(w14)));
164 Round(c, d, e, f, g, h, a, b, 0xf40e3585 + (w14 += sigma1(w12) + w7 + sigma0(w15)));
165 Round(b, c, d, e, f, g, h, a, 0x106aa070 + (w15 += sigma1(w13) + w8 + sigma0(w0)));
166
167 Round(a, b, c, d, e, f, g, h, 0x19a4c116 + (w0 += sigma1(w14) + w9 + sigma0(w1)));
168 Round(h, a, b, c, d, e, f, g, 0x1e376c08 + (w1 += sigma1(w15) + w10 + sigma0(w2)));
169 Round(g, h, a, b, c, d, e, f, 0x2748774c + (w2 += sigma1(w0) + w11 + sigma0(w3)));
170 Round(f, g, h, a, b, c, d, e, 0x34b0bcb5 + (w3 += sigma1(w1) + w12 + sigma0(w4)));
171 Round(e, f, g, h, a, b, c, d, 0x391c0cb3 + (w4 += sigma1(w2) + w13 + sigma0(w5)));
172 Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a + (w5 += sigma1(w3) + w14 + sigma0(w6)));
173 Round(c, d, e, f, g, h, a, b, 0x5b9cca4f + (w6 += sigma1(w4) + w15 + sigma0(w7)));
174 Round(b, c, d, e, f, g, h, a, 0x682e6ff3 + (w7 += sigma1(w5) + w0 + sigma0(w8)));
175 Round(a, b, c, d, e, f, g, h, 0x748f82ee + (w8 += sigma1(w6) + w1 + sigma0(w9)));
176 Round(h, a, b, c, d, e, f, g, 0x78a5636f + (w9 += sigma1(w7) + w2 + sigma0(w10)));
177 Round(g, h, a, b, c, d, e, f, 0x84c87814 + (w10 += sigma1(w8) + w3 + sigma0(w11)));
178 Round(f, g, h, a, b, c, d, e, 0x8cc70208 + (w11 += sigma1(w9) + w4 + sigma0(w12)));
179 Round(e, f, g, h, a, b, c, d, 0x90befffa + (w12 += sigma1(w10) + w5 + sigma0(w13)));
180 Round(d, e, f, g, h, a, b, c, 0xa4506ceb + (w13 += sigma1(w11) + w6 + sigma0(w14)));
181 Round(c, d, e, f, g, h, a, b, 0xbef9a3f7 + (w14 + sigma1(w12) + w7 + sigma0(w15)));
182 Round(b, c, d, e, f, g, h, a, 0xc67178f2 + (w15 + sigma1(w13) + w8 + sigma0(w0)));
183
184 s[0] += a;
185 s[1] += b;
186 s[2] += c;
187 s[3] += d;
188 s[4] += e;
189 s[5] += f;
190 s[6] += g;
191 s[7] += h;
192 chunk += 64;
193 }
194 }
195
196 void TransformD64(unsigned char* out, const unsigned char* in)
197 {
198 // Transform 1
199 uint32_t a = 0x6a09e667ul;
200 uint32_t b = 0xbb67ae85ul;
201 uint32_t c = 0x3c6ef372ul;
202 uint32_t d = 0xa54ff53aul;
203 uint32_t e = 0x510e527ful;
204 uint32_t f = 0x9b05688cul;
205 uint32_t g = 0x1f83d9abul;
206 uint32_t h = 0x5be0cd19ul;
207
208 uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;
209
210 Round(a, b, c, d, e, f, g, h, 0x428a2f98ul + (w0 = ReadBE32(in + 0)));
211 Round(h, a, b, c, d, e, f, g, 0x71374491ul + (w1 = ReadBE32(in + 4)));
212 Round(g, h, a, b, c, d, e, f, 0xb5c0fbcful + (w2 = ReadBE32(in + 8)));
213 Round(f, g, h, a, b, c, d, e, 0xe9b5dba5ul + (w3 = ReadBE32(in + 12)));
214 Round(e, f, g, h, a, b, c, d, 0x3956c25bul + (w4 = ReadBE32(in + 16)));
215 Round(d, e, f, g, h, a, b, c, 0x59f111f1ul + (w5 = ReadBE32(in + 20)));
216 Round(c, d, e, f, g, h, a, b, 0x923f82a4ul + (w6 = ReadBE32(in + 24)));
217 Round(b, c, d, e, f, g, h, a, 0xab1c5ed5ul + (w7 = ReadBE32(in + 28)));
218 Round(a, b, c, d, e, f, g, h, 0xd807aa98ul + (w8 = ReadBE32(in + 32)));
219 Round(h, a, b, c, d, e, f, g, 0x12835b01ul + (w9 = ReadBE32(in + 36)));
220 Round(g, h, a, b, c, d, e, f, 0x243185beul + (w10 = ReadBE32(in + 40)));
221 Round(f, g, h, a, b, c, d, e, 0x550c7dc3ul + (w11 = ReadBE32(in + 44)));
222 Round(e, f, g, h, a, b, c, d, 0x72be5d74ul + (w12 = ReadBE32(in + 48)));
223 Round(d, e, f, g, h, a, b, c, 0x80deb1feul + (w13 = ReadBE32(in + 52)));
224 Round(c, d, e, f, g, h, a, b, 0x9bdc06a7ul + (w14 = ReadBE32(in + 56)));
225 Round(b, c, d, e, f, g, h, a, 0xc19bf174ul + (w15 = ReadBE32(in + 60)));
226 Round(a, b, c, d, e, f, g, h, 0xe49b69c1ul + (w0 += sigma1(w14) + w9 + sigma0(w1)));
227 Round(h, a, b, c, d, e, f, g, 0xefbe4786ul + (w1 += sigma1(w15) + w10 + sigma0(w2)));
228 Round(g, h, a, b, c, d, e, f, 0x0fc19dc6ul + (w2 += sigma1(w0) + w11 + sigma0(w3)));
229 Round(f, g, h, a, b, c, d, e, 0x240ca1ccul + (w3 += sigma1(w1) + w12 + sigma0(w4)));
230 Round(e, f, g, h, a, b, c, d, 0x2de92c6ful + (w4 += sigma1(w2) + w13 + sigma0(w5)));
231 Round(d, e, f, g, h, a, b, c, 0x4a7484aaul + (w5 += sigma1(w3) + w14 + sigma0(w6)));
232 Round(c, d, e, f, g, h, a, b, 0x5cb0a9dcul + (w6 += sigma1(w4) + w15 + sigma0(w7)));
233 Round(b, c, d, e, f, g, h, a, 0x76f988daul + (w7 += sigma1(w5) + w0 + sigma0(w8)));
234 Round(a, b, c, d, e, f, g, h, 0x983e5152ul + (w8 += sigma1(w6) + w1 + sigma0(w9)));
235 Round(h, a, b, c, d, e, f, g, 0xa831c66dul + (w9 += sigma1(w7) + w2 + sigma0(w10)));
236 Round(g, h, a, b, c, d, e, f, 0xb00327c8ul + (w10 += sigma1(w8) + w3 + sigma0(w11)));
237 Round(f, g, h, a, b, c, d, e, 0xbf597fc7ul + (w11 += sigma1(w9) + w4 + sigma0(w12)));
238 Round(e, f, g, h, a, b, c, d, 0xc6e00bf3ul + (w12 += sigma1(w10) + w5 + sigma0(w13)));
239 Round(d, e, f, g, h, a, b, c, 0xd5a79147ul + (w13 += sigma1(w11) + w6 + sigma0(w14)));
240 Round(c, d, e, f, g, h, a, b, 0x06ca6351ul + (w14 += sigma1(w12) + w7 + sigma0(w15)));
241 Round(b, c, d, e, f, g, h, a, 0x14292967ul + (w15 += sigma1(w13) + w8 + sigma0(w0)));
242 Round(a, b, c, d, e, f, g, h, 0x27b70a85ul + (w0 += sigma1(w14) + w9 + sigma0(w1)));
243 Round(h, a, b, c, d, e, f, g, 0x2e1b2138ul + (w1 += sigma1(w15) + w10 + sigma0(w2)));
244 Round(g, h, a, b, c, d, e, f, 0x4d2c6dfcul + (w2 += sigma1(w0) + w11 + sigma0(w3)));
245 Round(f, g, h, a, b, c, d, e, 0x53380d13ul + (w3 += sigma1(w1) + w12 + sigma0(w4)));
246 Round(e, f, g, h, a, b, c, d, 0x650a7354ul + (w4 += sigma1(w2) + w13 + sigma0(w5)));
247 Round(d, e, f, g, h, a, b, c, 0x766a0abbul + (w5 += sigma1(w3) + w14 + sigma0(w6)));
248 Round(c, d, e, f, g, h, a, b, 0x81c2c92eul + (w6 += sigma1(w4) + w15 + sigma0(w7)));
249 Round(b, c, d, e, f, g, h, a, 0x92722c85ul + (w7 += sigma1(w5) + w0 + sigma0(w8)));
250 Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1ul + (w8 += sigma1(w6) + w1 + sigma0(w9)));
251 Round(h, a, b, c, d, e, f, g, 0xa81a664bul + (w9 += sigma1(w7) + w2 + sigma0(w10)));
252 Round(g, h, a, b, c, d, e, f, 0xc24b8b70ul + (w10 += sigma1(w8) + w3 + sigma0(w11)));
253 Round(f, g, h, a, b, c, d, e, 0xc76c51a3ul + (w11 += sigma1(w9) + w4 + sigma0(w12)));
254 Round(e, f, g, h, a, b, c, d, 0xd192e819ul + (w12 += sigma1(w10) + w5 + sigma0(w13)));
255 Round(d, e, f, g, h, a, b, c, 0xd6990624ul + (w13 += sigma1(w11) + w6 + sigma0(w14)));
256 Round(c, d, e, f, g, h, a, b, 0xf40e3585ul + (w14 += sigma1(w12) + w7 + sigma0(w15)));
257 Round(b, c, d, e, f, g, h, a, 0x106aa070ul + (w15 += sigma1(w13) + w8 + sigma0(w0)));
258 Round(a, b, c, d, e, f, g, h, 0x19a4c116ul + (w0 += sigma1(w14) + w9 + sigma0(w1)));
259 Round(h, a, b, c, d, e, f, g, 0x1e376c08ul + (w1 += sigma1(w15) + w10 + sigma0(w2)));
260 Round(g, h, a, b, c, d, e, f, 0x2748774cul + (w2 += sigma1(w0) + w11 + sigma0(w3)));
261 Round(f, g, h, a, b, c, d, e, 0x34b0bcb5ul + (w3 += sigma1(w1) + w12 + sigma0(w4)));
262 Round(e, f, g, h, a, b, c, d, 0x391c0cb3ul + (w4 += sigma1(w2) + w13 + sigma0(w5)));
263 Round(d, e, f, g, h, a, b, c, 0x4ed8aa4aul + (w5 += sigma1(w3) + w14 + sigma0(w6)));
264 Round(c, d, e, f, g, h, a, b, 0x5b9cca4ful + (w6 += sigma1(w4) + w15 + sigma0(w7)));
265 Round(b, c, d, e, f, g, h, a, 0x682e6ff3ul + (w7 += sigma1(w5) + w0 + sigma0(w8)));
266 Round(a, b, c, d, e, f, g, h, 0x748f82eeul + (w8 += sigma1(w6) + w1 + sigma0(w9)));
267 Round(h, a, b, c, d, e, f, g, 0x78a5636ful + (w9 += sigma1(w7) + w2 + sigma0(w10)));
268 Round(g, h, a, b, c, d, e, f, 0x84c87814ul + (w10 += sigma1(w8) + w3 + sigma0(w11)));
269 Round(f, g, h, a, b, c, d, e, 0x8cc70208ul + (w11 += sigma1(w9) + w4 + sigma0(w12)));
270 Round(e, f, g, h, a, b, c, d, 0x90befffaul + (w12 += sigma1(w10) + w5 + sigma0(w13)));
271 Round(d, e, f, g, h, a, b, c, 0xa4506cebul + (w13 += sigma1(w11) + w6 + sigma0(w14)));
272 Round(c, d, e, f, g, h, a, b, 0xbef9a3f7ul + (w14 + sigma1(w12) + w7 + sigma0(w15)));
273 Round(b, c, d, e, f, g, h, a, 0xc67178f2ul + (w15 + sigma1(w13) + w8 + sigma0(w0)));
274
275 a += 0x6a09e667ul;
276 b += 0xbb67ae85ul;
277 c += 0x3c6ef372ul;
278 d += 0xa54ff53aul;
279 e += 0x510e527ful;
280 f += 0x9b05688cul;
281 g += 0x1f83d9abul;
282 h += 0x5be0cd19ul;
283
284 uint32_t t0 = a, t1 = b, t2 = c, t3 = d, t4 = e, t5 = f, t6 = g, t7 = h;
285
286 // Transform 2
287 Round(a, b, c, d, e, f, g, h, 0xc28a2f98ul);
288 Round(h, a, b, c, d, e, f, g, 0x71374491ul);
289 Round(g, h, a, b, c, d, e, f, 0xb5c0fbcful);
290 Round(f, g, h, a, b, c, d, e, 0xe9b5dba5ul);
291 Round(e, f, g, h, a, b, c, d, 0x3956c25bul);
292 Round(d, e, f, g, h, a, b, c, 0x59f111f1ul);
293 Round(c, d, e, f, g, h, a, b, 0x923f82a4ul);
294 Round(b, c, d, e, f, g, h, a, 0xab1c5ed5ul);
295 Round(a, b, c, d, e, f, g, h, 0xd807aa98ul);
296 Round(h, a, b, c, d, e, f, g, 0x12835b01ul);
297 Round(g, h, a, b, c, d, e, f, 0x243185beul);
298 Round(f, g, h, a, b, c, d, e, 0x550c7dc3ul);
299 Round(e, f, g, h, a, b, c, d, 0x72be5d74ul);
300 Round(d, e, f, g, h, a, b, c, 0x80deb1feul);
301 Round(c, d, e, f, g, h, a, b, 0x9bdc06a7ul);
302 Round(b, c, d, e, f, g, h, a, 0xc19bf374ul);
303 Round(a, b, c, d, e, f, g, h, 0x649b69c1ul);
304 Round(h, a, b, c, d, e, f, g, 0xf0fe4786ul);
305 Round(g, h, a, b, c, d, e, f, 0x0fe1edc6ul);
306 Round(f, g, h, a, b, c, d, e, 0x240cf254ul);
307 Round(e, f, g, h, a, b, c, d, 0x4fe9346ful);
308 Round(d, e, f, g, h, a, b, c, 0x6cc984beul);
309 Round(c, d, e, f, g, h, a, b, 0x61b9411eul);
310 Round(b, c, d, e, f, g, h, a, 0x16f988faul);
311 Round(a, b, c, d, e, f, g, h, 0xf2c65152ul);
312 Round(h, a, b, c, d, e, f, g, 0xa88e5a6dul);
313 Round(g, h, a, b, c, d, e, f, 0xb019fc65ul);
314 Round(f, g, h, a, b, c, d, e, 0xb9d99ec7ul);
315 Round(e, f, g, h, a, b, c, d, 0x9a1231c3ul);
316 Round(d, e, f, g, h, a, b, c, 0xe70eeaa0ul);
317 Round(c, d, e, f, g, h, a, b, 0xfdb1232bul);
318 Round(b, c, d, e, f, g, h, a, 0xc7353eb0ul);
319 Round(a, b, c, d, e, f, g, h, 0x3069bad5ul);
320 Round(h, a, b, c, d, e, f, g, 0xcb976d5ful);
321 Round(g, h, a, b, c, d, e, f, 0x5a0f118ful);
322 Round(f, g, h, a, b, c, d, e, 0xdc1eeefdul);
323 Round(e, f, g, h, a, b, c, d, 0x0a35b689ul);
324 Round(d, e, f, g, h, a, b, c, 0xde0b7a04ul);
325 Round(c, d, e, f, g, h, a, b, 0x58f4ca9dul);
326 Round(b, c, d, e, f, g, h, a, 0xe15d5b16ul);
327 Round(a, b, c, d, e, f, g, h, 0x007f3e86ul);
328 Round(h, a, b, c, d, e, f, g, 0x37088980ul);
329 Round(g, h, a, b, c, d, e, f, 0xa507ea32ul);
330 Round(f, g, h, a, b, c, d, e, 0x6fab9537ul);
331 Round(e, f, g, h, a, b, c, d, 0x17406110ul);
332 Round(d, e, f, g, h, a, b, c, 0x0d8cd6f1ul);
333 Round(c, d, e, f, g, h, a, b, 0xcdaa3b6dul);
334 Round(b, c, d, e, f, g, h, a, 0xc0bbbe37ul);
335 Round(a, b, c, d, e, f, g, h, 0x83613bdaul);
336 Round(h, a, b, c, d, e, f, g, 0xdb48a363ul);
337 Round(g, h, a, b, c, d, e, f, 0x0b02e931ul);
338 Round(f, g, h, a, b, c, d, e, 0x6fd15ca7ul);
339 Round(e, f, g, h, a, b, c, d, 0x521afacaul);
340 Round(d, e, f, g, h, a, b, c, 0x31338431ul);
341 Round(c, d, e, f, g, h, a, b, 0x6ed41a95ul);
342 Round(b, c, d, e, f, g, h, a, 0x6d437890ul);
343 Round(a, b, c, d, e, f, g, h, 0xc39c91f2ul);
344 Round(h, a, b, c, d, e, f, g, 0x9eccabbdul);
345 Round(g, h, a, b, c, d, e, f, 0xb5c9a0e6ul);
346 Round(f, g, h, a, b, c, d, e, 0x532fb63cul);
347 Round(e, f, g, h, a, b, c, d, 0xd2c741c6ul);
348 Round(d, e, f, g, h, a, b, c, 0x07237ea3ul);
349 Round(c, d, e, f, g, h, a, b, 0xa4954b68ul);
350 Round(b, c, d, e, f, g, h, a, 0x4c191d76ul);
351
352 w0 = t0 + a;
353 w1 = t1 + b;
354 w2 = t2 + c;
355 w3 = t3 + d;
356 w4 = t4 + e;
357 w5 = t5 + f;
358 w6 = t6 + g;
359 w7 = t7 + h;
360
361 // Transform 3
362 a = 0x6a09e667ul;
363 b = 0xbb67ae85ul;
364 c = 0x3c6ef372ul;
365 d = 0xa54ff53aul;
366 e = 0x510e527ful;
367 f = 0x9b05688cul;
368 g = 0x1f83d9abul;
369 h = 0x5be0cd19ul;
370
371 Round(a, b, c, d, e, f, g, h, 0x428a2f98ul + w0);
372 Round(h, a, b, c, d, e, f, g, 0x71374491ul + w1);
373 Round(g, h, a, b, c, d, e, f, 0xb5c0fbcful + w2);
374 Round(f, g, h, a, b, c, d, e, 0xe9b5dba5ul + w3);
375 Round(e, f, g, h, a, b, c, d, 0x3956c25bul + w4);
376 Round(d, e, f, g, h, a, b, c, 0x59f111f1ul + w5);
377 Round(c, d, e, f, g, h, a, b, 0x923f82a4ul + w6);
378 Round(b, c, d, e, f, g, h, a, 0xab1c5ed5ul + w7);
379 Round(a, b, c, d, e, f, g, h, 0x5807aa98ul);
380 Round(h, a, b, c, d, e, f, g, 0x12835b01ul);
381 Round(g, h, a, b, c, d, e, f, 0x243185beul);
382 Round(f, g, h, a, b, c, d, e, 0x550c7dc3ul);
383 Round(e, f, g, h, a, b, c, d, 0x72be5d74ul);
384 Round(d, e, f, g, h, a, b, c, 0x80deb1feul);
385 Round(c, d, e, f, g, h, a, b, 0x9bdc06a7ul);
386 Round(b, c, d, e, f, g, h, a, 0xc19bf274ul);
387 Round(a, b, c, d, e, f, g, h, 0xe49b69c1ul + (w0 += sigma0(w1)));
388 Round(h, a, b, c, d, e, f, g, 0xefbe4786ul + (w1 += 0xa00000ul + sigma0(w2)));
389 Round(g, h, a, b, c, d, e, f, 0x0fc19dc6ul + (w2 += sigma1(w0) + sigma0(w3)));
390 Round(f, g, h, a, b, c, d, e, 0x240ca1ccul + (w3 += sigma1(w1) + sigma0(w4)));
391 Round(e, f, g, h, a, b, c, d, 0x2de92c6ful + (w4 += sigma1(w2) + sigma0(w5)));
392 Round(d, e, f, g, h, a, b, c, 0x4a7484aaul + (w5 += sigma1(w3) + sigma0(w6)));
393 Round(c, d, e, f, g, h, a, b, 0x5cb0a9dcul + (w6 += sigma1(w4) + 0x100ul + sigma0(w7)));
394 Round(b, c, d, e, f, g, h, a, 0x76f988daul + (w7 += sigma1(w5) + w0 + 0x11002000ul));
395 Round(a, b, c, d, e, f, g, h, 0x983e5152ul + (w8 = 0x80000000ul + sigma1(w6) + w1));
396 Round(h, a, b, c, d, e, f, g, 0xa831c66dul + (w9 = sigma1(w7) + w2));
397 Round(g, h, a, b, c, d, e, f, 0xb00327c8ul + (w10 = sigma1(w8) + w3));
398 Round(f, g, h, a, b, c, d, e, 0xbf597fc7ul + (w11 = sigma1(w9) + w4));
399 Round(e, f, g, h, a, b, c, d, 0xc6e00bf3ul + (w12 = sigma1(w10) + w5));
400 Round(d, e, f, g, h, a, b, c, 0xd5a79147ul + (w13 = sigma1(w11) + w6));
401 Round(c, d, e, f, g, h, a, b, 0x06ca6351ul + (w14 = sigma1(w12) + w7 + 0x400022ul));
402 Round(b, c, d, e, f, g, h, a, 0x14292967ul + (w15 = 0x100ul + sigma1(w13) + w8 + sigma0(w0)));
403 Round(a, b, c, d, e, f, g, h, 0x27b70a85ul + (w0 += sigma1(w14) + w9 + sigma0(w1)));
404 Round(h, a, b, c, d, e, f, g, 0x2e1b2138ul + (w1 += sigma1(w15) + w10 + sigma0(w2)));
405 Round(g, h, a, b, c, d, e, f, 0x4d2c6dfcul + (w2 += sigma1(w0) + w11 + sigma0(w3)));
406 Round(f, g, h, a, b, c, d, e, 0x53380d13ul + (w3 += sigma1(w1) + w12 + sigma0(w4)));
407 Round(e, f, g, h, a, b, c, d, 0x650a7354ul + (w4 += sigma1(w2) + w13 + sigma0(w5)));
408 Round(d, e, f, g, h, a, b, c, 0x766a0abbul + (w5 += sigma1(w3) + w14 + sigma0(w6)));
409 Round(c, d, e, f, g, h, a, b, 0x81c2c92eul + (w6 += sigma1(w4) + w15 + sigma0(w7)));
410 Round(b, c, d, e, f, g, h, a, 0x92722c85ul + (w7 += sigma1(w5) + w0 + sigma0(w8)));
411 Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1ul + (w8 += sigma1(w6) + w1 + sigma0(w9)));
412 Round(h, a, b, c, d, e, f, g, 0xa81a664bul + (w9 += sigma1(w7) + w2 + sigma0(w10)));
413 Round(g, h, a, b, c, d, e, f, 0xc24b8b70ul + (w10 += sigma1(w8) + w3 + sigma0(w11)));
414 Round(f, g, h, a, b, c, d, e, 0xc76c51a3ul + (w11 += sigma1(w9) + w4 + sigma0(w12)));
415 Round(e, f, g, h, a, b, c, d, 0xd192e819ul + (w12 += sigma1(w10) + w5 + sigma0(w13)));
416 Round(d, e, f, g, h, a, b, c, 0xd6990624ul + (w13 += sigma1(w11) + w6 + sigma0(w14)));
417 Round(c, d, e, f, g, h, a, b, 0xf40e3585ul + (w14 += sigma1(w12) + w7 + sigma0(w15)));
418 Round(b, c, d, e, f, g, h, a, 0x106aa070ul + (w15 += sigma1(w13) + w8 + sigma0(w0)));
419 Round(a, b, c, d, e, f, g, h, 0x19a4c116ul + (w0 += sigma1(w14) + w9 + sigma0(w1)));
420 Round(h, a, b, c, d, e, f, g, 0x1e376c08ul + (w1 += sigma1(w15) + w10 + sigma0(w2)));
421 Round(g, h, a, b, c, d, e, f, 0x2748774cul + (w2 += sigma1(w0) + w11 + sigma0(w3)));
422 Round(f, g, h, a, b, c, d, e, 0x34b0bcb5ul + (w3 += sigma1(w1) + w12 + sigma0(w4)));
423 Round(e, f, g, h, a, b, c, d, 0x391c0cb3ul + (w4 += sigma1(w2) + w13 + sigma0(w5)));
424 Round(d, e, f, g, h, a, b, c, 0x4ed8aa4aul + (w5 += sigma1(w3) + w14 + sigma0(w6)));
425 Round(c, d, e, f, g, h, a, b, 0x5b9cca4ful + (w6 += sigma1(w4) + w15 + sigma0(w7)));
426 Round(b, c, d, e, f, g, h, a, 0x682e6ff3ul + (w7 += sigma1(w5) + w0 + sigma0(w8)));
427 Round(a, b, c, d, e, f, g, h, 0x748f82eeul + (w8 += sigma1(w6) + w1 + sigma0(w9)));
428 Round(h, a, b, c, d, e, f, g, 0x78a5636ful + (w9 += sigma1(w7) + w2 + sigma0(w10)));
429 Round(g, h, a, b, c, d, e, f, 0x84c87814ul + (w10 += sigma1(w8) + w3 + sigma0(w11)));
430 Round(f, g, h, a, b, c, d, e, 0x8cc70208ul + (w11 += sigma1(w9) + w4 + sigma0(w12)));
431 Round(e, f, g, h, a, b, c, d, 0x90befffaul + (w12 += sigma1(w10) + w5 + sigma0(w13)));
432 Round(d, e, f, g, h, a, b, c, 0xa4506cebul + (w13 += sigma1(w11) + w6 + sigma0(w14)));
433 Round(c, d, e, f, g, h, a, b, 0xbef9a3f7ul + (w14 + sigma1(w12) + w7 + sigma0(w15)));
434 Round(b, c, d, e, f, g, h, a, 0xc67178f2ul + (w15 + sigma1(w13) + w8 + sigma0(w0)));
435
436 // Output
437 WriteBE32(out + 0, a + 0x6a09e667ul);
438 WriteBE32(out + 4, b + 0xbb67ae85ul);
439 WriteBE32(out + 8, c + 0x3c6ef372ul);
440 WriteBE32(out + 12, d + 0xa54ff53aul);
441 WriteBE32(out + 16, e + 0x510e527ful);
442 WriteBE32(out + 20, f + 0x9b05688cul);
443 WriteBE32(out + 24, g + 0x1f83d9abul);
444 WriteBE32(out + 28, h + 0x5be0cd19ul);
445 }
446
447 } // namespace sha256
448
449 typedef void (*TransformType)(uint32_t*, const unsigned char*, size_t);
450 typedef void (*TransformD64Type)(unsigned char*, const unsigned char*);
451
452 template<TransformType tr>
453 void TransformD64Wrapper(unsigned char* out, const unsigned char* in)
454 {
455 uint32_t s[8];
456 static const unsigned char padding1[64] = {
457 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
458 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
459 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
460 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0
461 };
462 unsigned char buffer2[64] = {
463 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
464 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
465 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
466 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0
467 };
468 sha256::Initialize(s);
469 tr(s, in, 1);
470 tr(s, padding1, 1);
471 WriteBE32(buffer2 + 0, s[0]);
472 WriteBE32(buffer2 + 4, s[1]);
473 WriteBE32(buffer2 + 8, s[2]);
474 WriteBE32(buffer2 + 12, s[3]);
475 WriteBE32(buffer2 + 16, s[4]);
476 WriteBE32(buffer2 + 20, s[5]);
477 WriteBE32(buffer2 + 24, s[6]);
478 WriteBE32(buffer2 + 28, s[7]);
479 sha256::Initialize(s);
480 tr(s, buffer2, 1);
481 WriteBE32(out + 0, s[0]);
482 WriteBE32(out + 4, s[1]);
483 WriteBE32(out + 8, s[2]);
484 WriteBE32(out + 12, s[3]);
485 WriteBE32(out + 16, s[4]);
486 WriteBE32(out + 20, s[5]);
487 WriteBE32(out + 24, s[6]);
488 WriteBE32(out + 28, s[7]);
489 }
490
491 TransformType Transform = sha256::Transform;
492 TransformD64Type TransformD64 = sha256::TransformD64;
493 TransformD64Type TransformD64_2way = nullptr;
494 TransformD64Type TransformD64_4way = nullptr;
495 TransformD64Type TransformD64_8way = nullptr;
496
497 bool SelfTest() {
498 // Input state (equal to the initial SHA256 state)
499 static const uint32_t init[8] = {
500 0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul
501 };
502 // Some random input data to test with
503 static const unsigned char data[641] = "-" // Intentionally not aligned
504 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do "
505 "eiusmod tempor incididunt ut labore et dolore magna aliqua. Et m"
506 "olestie ac feugiat sed lectus vestibulum mattis ullamcorper. Mor"
507 "bi blandit cursus risus at ultrices mi tempus imperdiet nulla. N"
508 "unc congue nisi vita suscipit tellus mauris. Imperdiet proin fer"
509 "mentum leo vel orci. Massa tempor nec feugiat nisl pretium fusce"
510 " id velit. Telus in metus vulputate eu scelerisque felis. Mi tem"
511 "pus imperdiet nulla malesuada pellentesque. Tristique magna sit.";
512 // Expected output state for hashing the i*64 first input bytes above (excluding SHA256 padding).
513 static const uint32_t result[9][8] = {
514 {0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul},
515 {0x91f8ec6bul, 0x4da10fe3ul, 0x1c9c292cul, 0x45e18185ul, 0x435cc111ul, 0x3ca26f09ul, 0xeb954caeul, 0x402a7069ul},
516 {0xcabea5acul, 0x374fb97cul, 0x182ad996ul, 0x7bd69cbful, 0x450ff900ul, 0xc1d2be8aul, 0x6a41d505ul, 0xe6212dc3ul},
517 {0xbcff09d6ul, 0x3e76f36eul, 0x3ecb2501ul, 0x78866e97ul, 0xe1c1e2fdul, 0x32f4eafful, 0x8aa6c4e5ul, 0xdfc024bcul},
518 {0xa08c5d94ul, 0x0a862f93ul, 0x6b7f2f40ul, 0x8f9fae76ul, 0x6d40439ful, 0x79dcee0cul, 0x3e39ff3aul, 0xdc3bdbb1ul},
519 {0x216a0895ul, 0x9f1a3662ul, 0xe99946f9ul, 0x87ba4364ul, 0x0fb5db2cul, 0x12bed3d3ul, 0x6689c0c7ul, 0x292f1b04ul},
520 {0xca3067f8ul, 0xbc8c2656ul, 0x37cb7e0dul, 0x9b6b8b0ful, 0x46dc380bul, 0xf1287f57ul, 0xc42e4b23ul, 0x3fefe94dul},
521 {0x3e4c4039ul, 0xbb6fca8cul, 0x6f27d2f7ul, 0x301e44a4ul, 0x8352ba14ul, 0x5769ce37ul, 0x48a1155ful, 0xc0e1c4c6ul},
522 {0xfe2fa9ddul, 0x69d0862bul, 0x1ae0db23ul, 0x471f9244ul, 0xf55c0145ul, 0xc30f9c3bul, 0x40a84ea0ul, 0x5b8a266cul},
523 };
524 // Expected output for each of the individual 8 64-byte messages under full double SHA256 (including padding).
525 static const unsigned char result_d64[256] = {
526 0x09, 0x3a, 0xc4, 0xd0, 0x0f, 0xf7, 0x57, 0xe1, 0x72, 0x85, 0x79, 0x42, 0xfe, 0xe7, 0xe0, 0xa0,
527 0xfc, 0x52, 0xd7, 0xdb, 0x07, 0x63, 0x45, 0xfb, 0x53, 0x14, 0x7d, 0x17, 0x22, 0x86, 0xf0, 0x52,
528 0x48, 0xb6, 0x11, 0x9e, 0x6e, 0x48, 0x81, 0x6d, 0xcc, 0x57, 0x1f, 0xb2, 0x97, 0xa8, 0xd5, 0x25,
529 0x9b, 0x82, 0xaa, 0x89, 0xe2, 0xfd, 0x2d, 0x56, 0xe8, 0x28, 0x83, 0x0b, 0xe2, 0xfa, 0x53, 0xb7,
530 0xd6, 0x6b, 0x07, 0x85, 0x83, 0xb0, 0x10, 0xa2, 0xf5, 0x51, 0x3c, 0xf9, 0x60, 0x03, 0xab, 0x45,
531 0x6c, 0x15, 0x6e, 0xef, 0xb5, 0xac, 0x3e, 0x6c, 0xdf, 0xb4, 0x92, 0x22, 0x2d, 0xce, 0xbf, 0x3e,
532 0xe9, 0xe5, 0xf6, 0x29, 0x0e, 0x01, 0x4f, 0xd2, 0xd4, 0x45, 0x65, 0xb3, 0xbb, 0xf2, 0x4c, 0x16,
533 0x37, 0x50, 0x3c, 0x6e, 0x49, 0x8c, 0x5a, 0x89, 0x2b, 0x1b, 0xab, 0xc4, 0x37, 0xd1, 0x46, 0xe9,
534 0x3d, 0x0e, 0x85, 0xa2, 0x50, 0x73, 0xa1, 0x5e, 0x54, 0x37, 0xd7, 0x94, 0x17, 0x56, 0xc2, 0xd8,
535 0xe5, 0x9f, 0xed, 0x4e, 0xae, 0x15, 0x42, 0x06, 0x0d, 0x74, 0x74, 0x5e, 0x24, 0x30, 0xce, 0xd1,
536 0x9e, 0x50, 0xa3, 0x9a, 0xb8, 0xf0, 0x4a, 0x57, 0x69, 0x78, 0x67, 0x12, 0x84, 0x58, 0xbe, 0xc7,
537 0x36, 0xaa, 0xee, 0x7c, 0x64, 0xa3, 0x76, 0xec, 0xff, 0x55, 0x41, 0x00, 0x2a, 0x44, 0x68, 0x4d,
538 0xb6, 0x53, 0x9e, 0x1c, 0x95, 0xb7, 0xca, 0xdc, 0x7f, 0x7d, 0x74, 0x27, 0x5c, 0x8e, 0xa6, 0x84,
539 0xb5, 0xac, 0x87, 0xa9, 0xf3, 0xff, 0x75, 0xf2, 0x34, 0xcd, 0x1a, 0x3b, 0x82, 0x2c, 0x2b, 0x4e,
540 0x6a, 0x46, 0x30, 0xa6, 0x89, 0x86, 0x23, 0xac, 0xf8, 0xa5, 0x15, 0xe9, 0x0a, 0xaa, 0x1e, 0x9a,
541 0xd7, 0x93, 0x6b, 0x28, 0xe4, 0x3b, 0xfd, 0x59, 0xc6, 0xed, 0x7c, 0x5f, 0xa5, 0x41, 0xcb, 0x51
542 };
543
544
545 // Test Transform() for 0 through 8 transformations.
546 for (size_t i = 0; i <= 8; ++i) {
547 uint32_t state[8];
548 std::copy(init, init + 8, state);
549 Transform(state, data + 1, i);
550 if (!std::equal(state, state + 8, result[i])) return false;
551 }
552
553 // Test TransformD64
554 unsigned char out[32];
555 TransformD64(out, data + 1);
556 if (!std::equal(out, out + 32, result_d64)) return false;
557
558 // Test TransformD64_2way, if available.
559 if (TransformD64_2way) {
560 unsigned char out[64];
561 TransformD64_2way(out, data + 1);
562 if (!std::equal(out, out + 64, result_d64)) return false;
563 }
564
565 // Test TransformD64_4way, if available.
566 if (TransformD64_4way) {
567 unsigned char out[128];
568 TransformD64_4way(out, data + 1);
569 if (!std::equal(out, out + 128, result_d64)) return false;
570 }
571
572 // Test TransformD64_8way, if available.
573 if (TransformD64_8way) {
574 unsigned char out[256];
575 TransformD64_8way(out, data + 1);
576 if (!std::equal(out, out + 256, result_d64)) return false;
577 }
578
579 return true;
580 }
581
582 #if !defined(DISABLE_OPTIMIZED_SHA256)
583 #if (defined(__x86_64__) || defined(__amd64__) || defined(__i386__))
584 /** Check whether the OS has enabled AVX registers. */
585 bool AVXEnabled()
586 {
587 uint32_t a, d;
588 __asm__("xgetbv" : "=a"(a), "=d"(d) : "c"(0));
589 return (a & 6) == 6;
590 }
591 #endif
592 #endif // DISABLE_OPTIMIZED_SHA256
593 } // namespace
594
595
596 std::string SHA256AutoDetect(sha256_implementation::UseImplementation use_implementation)
597 {
598 std::string ret = "standard";
599 Transform = sha256::Transform;
600 TransformD64 = sha256::TransformD64;
601 TransformD64_2way = nullptr;
602 TransformD64_4way = nullptr;
603 TransformD64_8way = nullptr;
604
605 #if !defined(DISABLE_OPTIMIZED_SHA256)
606 #if defined(HAVE_GETCPUID)
607 bool have_sse4 = false;
608 bool have_xsave = false;
609 bool have_avx = false;
610 [[maybe_unused]] bool have_avx2 = false;
611 [[maybe_unused]] bool have_x86_shani = false;
612 [[maybe_unused]] bool enabled_avx = false;
613
614 uint32_t eax, ebx, ecx, edx;
615 GetCPUID(1, 0, eax, ebx, ecx, edx);
616 if (use_implementation & sha256_implementation::USE_SSE4) {
617 have_sse4 = (ecx >> 19) & 1;
618 }
619 have_xsave = (ecx >> 27) & 1;
620 have_avx = (ecx >> 28) & 1;
621 if (have_xsave && have_avx) {
622 enabled_avx = AVXEnabled();
623 }
624 if (have_sse4) {
625 GetCPUID(7, 0, eax, ebx, ecx, edx);
626 if (use_implementation & sha256_implementation::USE_AVX2) {
627 have_avx2 = (ebx >> 5) & 1;
628 }
629 if (use_implementation & sha256_implementation::USE_SHANI) {
630 have_x86_shani = (ebx >> 29) & 1;
631 }
632 }
633
634 #if defined(ENABLE_SSE41) && defined(ENABLE_X86_SHANI)
635 if (have_x86_shani) {
636 Transform = sha256_x86_shani::Transform;
637 TransformD64 = TransformD64Wrapper<sha256_x86_shani::Transform>;
638 TransformD64_2way = sha256d64_x86_shani::Transform_2way;
639 ret = "x86_shani(1way;2way)";
640 have_sse4 = false; // Disable SSE4/AVX2;
641 have_avx2 = false;
642 }
643 #endif
644
645 if (have_sse4) {
646 #if defined(__x86_64__) || defined(__amd64__)
647 Transform = sha256_sse4::Transform;
648 TransformD64 = TransformD64Wrapper<sha256_sse4::Transform>;
649 ret = "sse4(1way)";
650 #endif
651 #if defined(ENABLE_SSE41)
652 TransformD64_4way = sha256d64_sse41::Transform_4way;
653 ret += ";sse41(4way)";
654 #endif
655 }
656
657 #if defined(ENABLE_AVX2)
658 if (have_avx2 && have_avx && enabled_avx) {
659 TransformD64_8way = sha256d64_avx2::Transform_8way;
660 ret += ";avx2(8way)";
661 }
662 #endif
663 #elif (defined(__linux__)) && defined(ENABLE_POWER8)
664 if (getauxval(AT_HWCAP2) & 0x02000000) {
665 TransformD64_4way = sha256_power8::Transform_4way;
666 assert(SelfTest());
667 return "power8(4way),C(1way)";
668 }
669 #endif
670
671 #if defined(ENABLE_ARM_SHANI)
672 bool have_arm_shani = false;
673 if (use_implementation & sha256_implementation::USE_SHANI) {
674 #if defined(__linux__)
675 #if defined(__arm__) // 32-bit
676 if (getauxval(AT_HWCAP2) & HWCAP2_SHA2) {
677 have_arm_shani = true;
678 }
679 #endif
680 #if defined(__aarch64__) // 64-bit
681 if (getauxval(AT_HWCAP) & HWCAP_SHA2) {
682 have_arm_shani = true;
683 }
684 #endif
685 #endif
686
687 #if defined(__APPLE__)
688 int val = 0;
689 size_t len = sizeof(val);
690 if (sysctlbyname("hw.optional.arm.FEAT_SHA256", &val, &len, nullptr, 0) == 0) {
691 have_arm_shani = val != 0;
692 }
693 #endif
694 }
695
696 if (have_arm_shani) {
697 Transform = sha256_arm_shani::Transform;
698 TransformD64 = TransformD64Wrapper<sha256_arm_shani::Transform>;
699 TransformD64_2way = sha256d64_arm_shani::Transform_2way;
700 ret = "arm_shani(1way;2way)";
701 }
702 #endif
703 #endif // DISABLE_OPTIMIZED_SHA256
704
705 assert(SelfTest());
706 return ret;
707 }
708
709 ////// SHA-256
710
711 CSHA256::CSHA256()
712 {
713 sha256::Initialize(s);
714 }
715
716 CSHA256& CSHA256::Write(const unsigned char* data, size_t len)
717 {
718 const unsigned char* end = data + len;
719 size_t bufsize = bytes % 64;
720 if (bufsize && bufsize + len >= 64) {
721 // Fill the buffer, and process it.
722 memcpy(buf + bufsize, data, 64 - bufsize);
723 bytes += 64 - bufsize;
724 data += 64 - bufsize;
725 Transform(s, buf, 1);
726 bufsize = 0;
727 }
728 if (end - data >= 64) {
729 size_t blocks = (end - data) / 64;
730 Transform(s, data, blocks);
731 data += 64 * blocks;
732 bytes += 64 * blocks;
733 }
734 if (end > data) {
735 // Fill the buffer with what remains.
736 memcpy(buf + bufsize, data, end - data);
737 bytes += end - data;
738 }
739 return *this;
740 }
741
742 void CSHA256::Finalize(unsigned char hash[OUTPUT_SIZE])
743 {
744 static const unsigned char pad[64] = {0x80};
745 unsigned char sizedesc[8];
746 WriteBE64(sizedesc, bytes << 3);
747 Write(pad, 1 + ((119 - (bytes % 64)) % 64));
748 Write(sizedesc, 8);
749 WriteBE32(hash, s[0]);
750 WriteBE32(hash + 4, s[1]);
751 WriteBE32(hash + 8, s[2]);
752 WriteBE32(hash + 12, s[3]);
753 WriteBE32(hash + 16, s[4]);
754 WriteBE32(hash + 20, s[5]);
755 WriteBE32(hash + 24, s[6]);
756 WriteBE32(hash + 28, s[7]);
757 }
758
759 CSHA256& CSHA256::Reset()
760 {
761 bytes = 0;
762 sha256::Initialize(s);
763 return *this;
764 }
765
766 void SHA256D64(unsigned char* out, const unsigned char* in, size_t blocks)
767 {
768 if (TransformD64_8way) {
769 while (blocks >= 8) {
770 TransformD64_8way(out, in);
771 out += 256;
772 in += 512;
773 blocks -= 8;
774 }
775 }
776 if (TransformD64_4way) {
777 while (blocks >= 4) {
778 TransformD64_4way(out, in);
779 out += 128;
780 in += 256;
781 blocks -= 4;
782 }
783 }
784 if (TransformD64_2way) {
785 while (blocks >= 2) {
786 TransformD64_2way(out, in);
787 out += 64;
788 in += 128;
789 blocks -= 2;
790 }
791 }
792 while (blocks) {
793 TransformD64(out, in);
794 out += 32;
795 in += 64;
796 --blocks;
797 }
798 }
799