fuzz coverage

Coverage Report

Created: 2025-08-28 15:26

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