fuzz coverage

Coverage Report

Created: 2025-06-01 19:34

/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
3.20k
uint32_t inline Ch(uint32_t x, uint32_t y, uint32_t z) { return z ^ (x & (y ^ z)); }
72
3.20k
uint32_t inline Maj(uint32_t x, uint32_t y, uint32_t z) { return (x & y) | (z & (x | y)); }
73
3.20k
uint32_t inline Sigma0(uint32_t x) { return (x >> 2 | x << 30) ^ (x >> 13 | x << 19) ^ (x >> 22 | x << 10); }
74
3.20k
uint32_t inline Sigma1(uint32_t x) { return (x >> 6 | x << 26) ^ (x >> 11 | x << 21) ^ (x >> 25 | x << 7); }
75
2.40k
uint32_t inline sigma0(uint32_t x) { return (x >> 7 | x << 25) ^ (x >> 18 | x << 14) ^ (x >> 3); }
76
2.40k
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
3.20k
{
81
3.20k
    uint32_t t1 = h + Sigma1(e) + Ch(e, f, g) + k;
82
3.20k
    uint32_t t2 = Sigma0(a) + Maj(a, b, c);
83
3.20k
    d += t1;
84
3.20k
    h = t1 + t2;
85
3.20k
}
86
87
/** Initialize SHA-256 state. */
88
void inline Initialize(uint32_t* s)
89
392M
{
90
392M
    s[0] = 0x6a09e667ul;
91
392M
    s[1] = 0xbb67ae85ul;
92
392M
    s[2] = 0x3c6ef372ul;
93
392M
    s[3] = 0xa54ff53aul;
94
392M
    s[4] = 0x510e527ful;
95
392M
    s[5] = 0x9b05688cul;
96
392M
    s[6] = 0x1f83d9abul;
97
392M
    s[7] = 0x5be0cd19ul;
98
392M
}
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
50
{
103
100
    while (blocks--) {
104
50
        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
50
        uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;
106
107
50
        Round(a, b, c, d, e, f, g, h, 0x428a2f98 + (w0 = ReadBE32(chunk + 0)));
108
50
        Round(h, a, b, c, d, e, f, g, 0x71374491 + (w1 = ReadBE32(chunk + 4)));
109
50
        Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf + (w2 = ReadBE32(chunk + 8)));
110
50
        Round(f, g, h, a, b, c, d, e, 0xe9b5dba5 + (w3 = ReadBE32(chunk + 12)));
111
50
        Round(e, f, g, h, a, b, c, d, 0x3956c25b + (w4 = ReadBE32(chunk + 16)));
112
50
        Round(d, e, f, g, h, a, b, c, 0x59f111f1 + (w5 = ReadBE32(chunk + 20)));
113
50
        Round(c, d, e, f, g, h, a, b, 0x923f82a4 + (w6 = ReadBE32(chunk + 24)));
114
50
        Round(b, c, d, e, f, g, h, a, 0xab1c5ed5 + (w7 = ReadBE32(chunk + 28)));
115
50
        Round(a, b, c, d, e, f, g, h, 0xd807aa98 + (w8 = ReadBE32(chunk + 32)));
116
50
        Round(h, a, b, c, d, e, f, g, 0x12835b01 + (w9 = ReadBE32(chunk + 36)));
117
50
        Round(g, h, a, b, c, d, e, f, 0x243185be + (w10 = ReadBE32(chunk + 40)));
118
50
        Round(f, g, h, a, b, c, d, e, 0x550c7dc3 + (w11 = ReadBE32(chunk + 44)));
119
50
        Round(e, f, g, h, a, b, c, d, 0x72be5d74 + (w12 = ReadBE32(chunk + 48)));
120
50
        Round(d, e, f, g, h, a, b, c, 0x80deb1fe + (w13 = ReadBE32(chunk + 52)));
121
50
        Round(c, d, e, f, g, h, a, b, 0x9bdc06a7 + (w14 = ReadBE32(chunk + 56)));
122
50
        Round(b, c, d, e, f, g, h, a, 0xc19bf174 + (w15 = ReadBE32(chunk + 60)));
123
124
50
        Round(a, b, c, d, e, f, g, h, 0xe49b69c1 + (w0 += sigma1(w14) + w9 + sigma0(w1)));
125
50
        Round(h, a, b, c, d, e, f, g, 0xefbe4786 + (w1 += sigma1(w15) + w10 + sigma0(w2)));
126
50
        Round(g, h, a, b, c, d, e, f, 0x0fc19dc6 + (w2 += sigma1(w0) + w11 + sigma0(w3)));
127
50
        Round(f, g, h, a, b, c, d, e, 0x240ca1cc + (w3 += sigma1(w1) + w12 + sigma0(w4)));
128
50
        Round(e, f, g, h, a, b, c, d, 0x2de92c6f + (w4 += sigma1(w2) + w13 + sigma0(w5)));
129
50
        Round(d, e, f, g, h, a, b, c, 0x4a7484aa + (w5 += sigma1(w3) + w14 + sigma0(w6)));
130
50
        Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc + (w6 += sigma1(w4) + w15 + sigma0(w7)));
131
50
        Round(b, c, d, e, f, g, h, a, 0x76f988da + (w7 += sigma1(w5) + w0 + sigma0(w8)));
132
50
        Round(a, b, c, d, e, f, g, h, 0x983e5152 + (w8 += sigma1(w6) + w1 + sigma0(w9)));
133
50
        Round(h, a, b, c, d, e, f, g, 0xa831c66d + (w9 += sigma1(w7) + w2 + sigma0(w10)));
134
50
        Round(g, h, a, b, c, d, e, f, 0xb00327c8 + (w10 += sigma1(w8) + w3 + sigma0(w11)));
135
50
        Round(f, g, h, a, b, c, d, e, 0xbf597fc7 + (w11 += sigma1(w9) + w4 + sigma0(w12)));
136
50
        Round(e, f, g, h, a, b, c, d, 0xc6e00bf3 + (w12 += sigma1(w10) + w5 + sigma0(w13)));
137
50
        Round(d, e, f, g, h, a, b, c, 0xd5a79147 + (w13 += sigma1(w11) + w6 + sigma0(w14)));
138
50
        Round(c, d, e, f, g, h, a, b, 0x06ca6351 + (w14 += sigma1(w12) + w7 + sigma0(w15)));
139
50
        Round(b, c, d, e, f, g, h, a, 0x14292967 + (w15 += sigma1(w13) + w8 + sigma0(w0)));
140
141
50
        Round(a, b, c, d, e, f, g, h, 0x27b70a85 + (w0 += sigma1(w14) + w9 + sigma0(w1)));
142
50
        Round(h, a, b, c, d, e, f, g, 0x2e1b2138 + (w1 += sigma1(w15) + w10 + sigma0(w2)));
143
50
        Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc + (w2 += sigma1(w0) + w11 + sigma0(w3)));
144
50
        Round(f, g, h, a, b, c, d, e, 0x53380d13 + (w3 += sigma1(w1) + w12 + sigma0(w4)));
145
50
        Round(e, f, g, h, a, b, c, d, 0x650a7354 + (w4 += sigma1(w2) + w13 + sigma0(w5)));
146
50
        Round(d, e, f, g, h, a, b, c, 0x766a0abb + (w5 += sigma1(w3) + w14 + sigma0(w6)));
147
50
        Round(c, d, e, f, g, h, a, b, 0x81c2c92e + (w6 += sigma1(w4) + w15 + sigma0(w7)));
148
50
        Round(b, c, d, e, f, g, h, a, 0x92722c85 + (w7 += sigma1(w5) + w0 + sigma0(w8)));
149
50
        Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1 + (w8 += sigma1(w6) + w1 + sigma0(w9)));
150
50
        Round(h, a, b, c, d, e, f, g, 0xa81a664b + (w9 += sigma1(w7) + w2 + sigma0(w10)));
151
50
        Round(g, h, a, b, c, d, e, f, 0xc24b8b70 + (w10 += sigma1(w8) + w3 + sigma0(w11)));
152
50
        Round(f, g, h, a, b, c, d, e, 0xc76c51a3 + (w11 += sigma1(w9) + w4 + sigma0(w12)));
153
50
        Round(e, f, g, h, a, b, c, d, 0xd192e819 + (w12 += sigma1(w10) + w5 + sigma0(w13)));
154
50
        Round(d, e, f, g, h, a, b, c, 0xd6990624 + (w13 += sigma1(w11) + w6 + sigma0(w14)));
155
50
        Round(c, d, e, f, g, h, a, b, 0xf40e3585 + (w14 += sigma1(w12) + w7 + sigma0(w15)));
156
50
        Round(b, c, d, e, f, g, h, a, 0x106aa070 + (w15 += sigma1(w13) + w8 + sigma0(w0)));
157
158
50
        Round(a, b, c, d, e, f, g, h, 0x19a4c116 + (w0 += sigma1(w14) + w9 + sigma0(w1)));
159
50
        Round(h, a, b, c, d, e, f, g, 0x1e376c08 + (w1 += sigma1(w15) + w10 + sigma0(w2)));
160
50
        Round(g, h, a, b, c, d, e, f, 0x2748774c + (w2 += sigma1(w0) + w11 + sigma0(w3)));
161
50
        Round(f, g, h, a, b, c, d, e, 0x34b0bcb5 + (w3 += sigma1(w1) + w12 + sigma0(w4)));
162
50
        Round(e, f, g, h, a, b, c, d, 0x391c0cb3 + (w4 += sigma1(w2) + w13 + sigma0(w5)));
163
50
        Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a + (w5 += sigma1(w3) + w14 + sigma0(w6)));
164
50
        Round(c, d, e, f, g, h, a, b, 0x5b9cca4f + (w6 += sigma1(w4) + w15 + sigma0(w7)));
165
50
        Round(b, c, d, e, f, g, h, a, 0x682e6ff3 + (w7 += sigma1(w5) + w0 + sigma0(w8)));
166
50
        Round(a, b, c, d, e, f, g, h, 0x748f82ee + (w8 += sigma1(w6) + w1 + sigma0(w9)));
167
50
        Round(h, a, b, c, d, e, f, g, 0x78a5636f + (w9 += sigma1(w7) + w2 + sigma0(w10)));
168
50
        Round(g, h, a, b, c, d, e, f, 0x84c87814 + (w10 += sigma1(w8) + w3 + sigma0(w11)));
169
50
        Round(f, g, h, a, b, c, d, e, 0x8cc70208 + (w11 += sigma1(w9) + w4 + sigma0(w12)));
170
50
        Round(e, f, g, h, a, b, c, d, 0x90befffa + (w12 += sigma1(w10) + w5 + sigma0(w13)));
171
50
        Round(d, e, f, g, h, a, b, c, 0xa4506ceb + (w13 += sigma1(w11) + w6 + sigma0(w14)));
172
50
        Round(c, d, e, f, g, h, a, b, 0xbef9a3f7 + (w14 + sigma1(w12) + w7 + sigma0(w15)));
173
50
        Round(b, c, d, e, f, g, h, a, 0xc67178f2 + (w15 + sigma1(w13) + w8 + sigma0(w0)));
174
175
50
        s[0] += a;
176
50
        s[1] += b;
177
50
        s[2] += c;
178
50
        s[3] += d;
179
50
        s[4] += e;
180
50
        s[5] += f;
181
50
        s[6] += g;
182
50
        s[7] += h;
183
50
        chunk += 64;
184
50
    }
185
50
}
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
71.7k
{
446
71.7k
    uint32_t s[8];
447
71.7k
    static const unsigned char padding1[64] = {
448
71.7k
        0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
449
71.7k
        0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
450
71.7k
        0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
451
71.7k
        0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0
452
71.7k
    };
453
71.7k
    unsigned char buffer2[64] = {
454
71.7k
        0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
455
71.7k
        0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
456
71.7k
        0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
457
71.7k
        0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0
458
71.7k
    };
459
71.7k
    sha256::Initialize(s);
460
71.7k
    tr(s, in, 1);
461
71.7k
    tr(s, padding1, 1);
462
71.7k
    WriteBE32(buffer2 + 0, s[0]);
463
71.7k
    WriteBE32(buffer2 + 4, s[1]);
464
71.7k
    WriteBE32(buffer2 + 8, s[2]);
465
71.7k
    WriteBE32(buffer2 + 12, s[3]);
466
71.7k
    WriteBE32(buffer2 + 16, s[4]);
467
71.7k
    WriteBE32(buffer2 + 20, s[5]);
468
71.7k
    WriteBE32(buffer2 + 24, s[6]);
469
71.7k
    WriteBE32(buffer2 + 28, s[7]);
470
71.7k
    sha256::Initialize(s);
471
71.7k
    tr(s, buffer2, 1);
472
71.7k
    WriteBE32(out + 0, s[0]);
473
71.7k
    WriteBE32(out + 4, s[1]);
474
71.7k
    WriteBE32(out + 8, s[2]);
475
71.7k
    WriteBE32(out + 12, s[3]);
476
71.7k
    WriteBE32(out + 16, s[4]);
477
71.7k
    WriteBE32(out + 20, s[5]);
478
71.7k
    WriteBE32(out + 24, s[6]);
479
71.7k
    WriteBE32(out + 28, s[7]);
480
71.7k
}
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
1
bool SelfTest() {
489
    // Input state (equal to the initial SHA256 state)
490
1
    static const uint32_t init[8] = {
491
1
        0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul
492
1
    };
493
    // Some random input data to test with
494
1
    static const unsigned char data[641] = "-" // Intentionally not aligned
495
1
        "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do "
496
1
        "eiusmod tempor incididunt ut labore et dolore magna aliqua. Et m"
497
1
        "olestie ac feugiat sed lectus vestibulum mattis ullamcorper. Mor"
498
1
        "bi blandit cursus risus at ultrices mi tempus imperdiet nulla. N"
499
1
        "unc congue nisi vita suscipit tellus mauris. Imperdiet proin fer"
500
1
        "mentum leo vel orci. Massa tempor nec feugiat nisl pretium fusce"
501
1
        " id velit. Telus in metus vulputate eu scelerisque felis. Mi tem"
502
1
        "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
1
    static const uint32_t result[9][8] = {
505
1
        {0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul},
506
1
        {0x91f8ec6bul, 0x4da10fe3ul, 0x1c9c292cul, 0x45e18185ul, 0x435cc111ul, 0x3ca26f09ul, 0xeb954caeul, 0x402a7069ul},
507
1
        {0xcabea5acul, 0x374fb97cul, 0x182ad996ul, 0x7bd69cbful, 0x450ff900ul, 0xc1d2be8aul, 0x6a41d505ul, 0xe6212dc3ul},
508
1
        {0xbcff09d6ul, 0x3e76f36eul, 0x3ecb2501ul, 0x78866e97ul, 0xe1c1e2fdul, 0x32f4eafful, 0x8aa6c4e5ul, 0xdfc024bcul},
509
1
        {0xa08c5d94ul, 0x0a862f93ul, 0x6b7f2f40ul, 0x8f9fae76ul, 0x6d40439ful, 0x79dcee0cul, 0x3e39ff3aul, 0xdc3bdbb1ul},
510
1
        {0x216a0895ul, 0x9f1a3662ul, 0xe99946f9ul, 0x87ba4364ul, 0x0fb5db2cul, 0x12bed3d3ul, 0x6689c0c7ul, 0x292f1b04ul},
511
1
        {0xca3067f8ul, 0xbc8c2656ul, 0x37cb7e0dul, 0x9b6b8b0ful, 0x46dc380bul, 0xf1287f57ul, 0xc42e4b23ul, 0x3fefe94dul},
512
1
        {0x3e4c4039ul, 0xbb6fca8cul, 0x6f27d2f7ul, 0x301e44a4ul, 0x8352ba14ul, 0x5769ce37ul, 0x48a1155ful, 0xc0e1c4c6ul},
513
1
        {0xfe2fa9ddul, 0x69d0862bul, 0x1ae0db23ul, 0x471f9244ul, 0xf55c0145ul, 0xc30f9c3bul, 0x40a84ea0ul, 0x5b8a266cul},
514
1
    };
515
    // Expected output for each of the individual 8 64-byte messages under full double SHA256 (including padding).
516
1
    static const unsigned char result_d64[256] = {
517
1
        0x09, 0x3a, 0xc4, 0xd0, 0x0f, 0xf7, 0x57, 0xe1, 0x72, 0x85, 0x79, 0x42, 0xfe, 0xe7, 0xe0, 0xa0,
518
1
        0xfc, 0x52, 0xd7, 0xdb, 0x07, 0x63, 0x45, 0xfb, 0x53, 0x14, 0x7d, 0x17, 0x22, 0x86, 0xf0, 0x52,
519
1
        0x48, 0xb6, 0x11, 0x9e, 0x6e, 0x48, 0x81, 0x6d, 0xcc, 0x57, 0x1f, 0xb2, 0x97, 0xa8, 0xd5, 0x25,
520
1
        0x9b, 0x82, 0xaa, 0x89, 0xe2, 0xfd, 0x2d, 0x56, 0xe8, 0x28, 0x83, 0x0b, 0xe2, 0xfa, 0x53, 0xb7,
521
1
        0xd6, 0x6b, 0x07, 0x85, 0x83, 0xb0, 0x10, 0xa2, 0xf5, 0x51, 0x3c, 0xf9, 0x60, 0x03, 0xab, 0x45,
522
1
        0x6c, 0x15, 0x6e, 0xef, 0xb5, 0xac, 0x3e, 0x6c, 0xdf, 0xb4, 0x92, 0x22, 0x2d, 0xce, 0xbf, 0x3e,
523
1
        0xe9, 0xe5, 0xf6, 0x29, 0x0e, 0x01, 0x4f, 0xd2, 0xd4, 0x45, 0x65, 0xb3, 0xbb, 0xf2, 0x4c, 0x16,
524
1
        0x37, 0x50, 0x3c, 0x6e, 0x49, 0x8c, 0x5a, 0x89, 0x2b, 0x1b, 0xab, 0xc4, 0x37, 0xd1, 0x46, 0xe9,
525
1
        0x3d, 0x0e, 0x85, 0xa2, 0x50, 0x73, 0xa1, 0x5e, 0x54, 0x37, 0xd7, 0x94, 0x17, 0x56, 0xc2, 0xd8,
526
1
        0xe5, 0x9f, 0xed, 0x4e, 0xae, 0x15, 0x42, 0x06, 0x0d, 0x74, 0x74, 0x5e, 0x24, 0x30, 0xce, 0xd1,
527
1
        0x9e, 0x50, 0xa3, 0x9a, 0xb8, 0xf0, 0x4a, 0x57, 0x69, 0x78, 0x67, 0x12, 0x84, 0x58, 0xbe, 0xc7,
528
1
        0x36, 0xaa, 0xee, 0x7c, 0x64, 0xa3, 0x76, 0xec, 0xff, 0x55, 0x41, 0x00, 0x2a, 0x44, 0x68, 0x4d,
529
1
        0xb6, 0x53, 0x9e, 0x1c, 0x95, 0xb7, 0xca, 0xdc, 0x7f, 0x7d, 0x74, 0x27, 0x5c, 0x8e, 0xa6, 0x84,
530
1
        0xb5, 0xac, 0x87, 0xa9, 0xf3, 0xff, 0x75, 0xf2, 0x34, 0xcd, 0x1a, 0x3b, 0x82, 0x2c, 0x2b, 0x4e,
531
1
        0x6a, 0x46, 0x30, 0xa6, 0x89, 0x86, 0x23, 0xac, 0xf8, 0xa5, 0x15, 0xe9, 0x0a, 0xaa, 0x1e, 0x9a,
532
1
        0xd7, 0x93, 0x6b, 0x28, 0xe4, 0x3b, 0xfd, 0x59, 0xc6, 0xed, 0x7c, 0x5f, 0xa5, 0x41, 0xcb, 0x51
533
1
    };
534
535
536
    // Test Transform() for 0 through 8 transformations.
537
10
    for (size_t i = 0; i <= 8; 
++i9
) {
538
9
        uint32_t state[8];
539
9
        std::copy(init, init + 8, state);
540
9
        Transform(state, data + 1, i);
541
9
        if (!std::equal(state, state + 8, result[i])) 
return false0
;
542
9
    }
543
544
    // Test TransformD64
545
1
    unsigned char out[32];
546
1
    TransformD64(out, data + 1);
547
1
    if (!std::equal(out, out + 32, result_d64)) 
return false0
;
548
549
    // Test TransformD64_2way, if available.
550
1
    if (TransformD64_2way) {
551
1
        unsigned char out[64];
552
1
        TransformD64_2way(out, data + 1);
553
1
        if (!std::equal(out, out + 64, result_d64)) 
return false0
;
554
1
    }
555
556
    // Test TransformD64_4way, if available.
557
1
    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
1
    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
1
    return true;
571
1
}
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
1
{
589
1
    std::string ret = "standard";
590
1
    Transform = sha256::Transform;
591
1
    TransformD64 = sha256::TransformD64;
592
1
    TransformD64_2way = nullptr;
593
1
    TransformD64_4way = nullptr;
594
1
    TransformD64_8way = nullptr;
595
596
1
#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
1
#if defined(ENABLE_ARM_SHANI)
657
1
    bool have_arm_shani = false;
658
1
    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
1
#if defined(__APPLE__)
673
1
        int val = 0;
674
1
        size_t len = sizeof(val);
675
1
        if (sysctlbyname("hw.optional.arm.FEAT_SHA256", &val, &len, nullptr, 0) == 0) {
676
1
            have_arm_shani = val != 0;
677
1
        }
678
1
#endif
679
1
    }
680
681
1
    if (have_arm_shani) {
682
1
        Transform = sha256_arm_shani::Transform;
683
1
        TransformD64 = TransformD64Wrapper<sha256_arm_shani::Transform>;
684
1
        TransformD64_2way = sha256d64_arm_shani::Transform_2way;
685
1
        ret = "arm_shani(1way,2way)";
686
1
    }
687
1
#endif
688
1
#endif // DISABLE_OPTIMIZED_SHA256
689
690
1
    assert(SelfTest());
691
1
    return ret;
692
1
}
693
694
////// SHA-256
695
696
CSHA256::CSHA256()
697
195M
{
698
195M
    sha256::Initialize(s);
699
195M
}
700
701
CSHA256& CSHA256::Write(const unsigned char* data, size_t len)
702
2.43G
{
703
2.43G
    const unsigned char* end = data + len;
704
2.43G
    size_t bufsize = bytes % 64;
705
2.43G
    if (bufsize && 
bufsize + len >= 642.02G
) {
706
        // Fill the buffer, and process it.
707
590M
        memcpy(buf + bufsize, data, 64 - bufsize);
708
590M
        bytes += 64 - bufsize;
709
590M
        data += 64 - bufsize;
710
590M
        Transform(s, buf, 1);
711
590M
        bufsize = 0;
712
590M
    }
713
2.43G
    if (end - data >= 64) {
714
1.82M
        size_t blocks = (end - data) / 64;
715
1.82M
        Transform(s, data, blocks);
716
1.82M
        data += 64 * blocks;
717
1.82M
        bytes += 64 * blocks;
718
1.82M
    }
719
2.43G
    if (end > data) {
720
        // Fill the buffer with what remains.
721
2.02G
        memcpy(buf + bufsize, data, end - data);
722
2.02G
        bytes += end - data;
723
2.02G
    }
724
2.43G
    return *this;
725
2.43G
}
726
727
void CSHA256::Finalize(unsigned char hash[OUTPUT_SIZE])
728
391M
{
729
391M
    static const unsigned char pad[64] = {0x80};
730
391M
    unsigned char sizedesc[8];
731
391M
    WriteBE64(sizedesc, bytes << 3);
732
391M
    Write(pad, 1 + ((119 - (bytes % 64)) % 64));
733
391M
    Write(sizedesc, 8);
734
391M
    WriteBE32(hash, s[0]);
735
391M
    WriteBE32(hash + 4, s[1]);
736
391M
    WriteBE32(hash + 8, s[2]);
737
391M
    WriteBE32(hash + 12, s[3]);
738
391M
    WriteBE32(hash + 16, s[4]);
739
391M
    WriteBE32(hash + 20, s[5]);
740
391M
    WriteBE32(hash + 24, s[6]);
741
391M
    WriteBE32(hash + 28, s[7]);
742
391M
}
743
744
CSHA256& CSHA256::Reset()
745
196M
{
746
196M
    bytes = 0;
747
196M
    sha256::Initialize(s);
748
196M
    return *this;
749
196M
}
750
751
void SHA256D64(unsigned char* out, const unsigned char* in, size_t blocks)
752
120k
{
753
120k
    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
120k
    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
120k
    if (TransformD64_2way) {
770
220k
        while (blocks >= 2) {
771
99.9k
            TransformD64_2way(out, in);
772
99.9k
            out += 64;
773
99.9k
            in += 128;
774
99.9k
            blocks -= 2;
775
99.9k
        }
776
120k
    }
777
192k
    while (blocks) {
778
71.7k
        TransformD64(out, in);
779
71.7k
        out += 32;
780
71.7k
        in += 64;
781
71.7k
        --blocks;
782
71.7k
    }
783
120k
}