Raven Core  3.0.0
P2P Digital Currency
sha256.cpp
Go to the documentation of this file.
1 // Copyright (c) 2014 The Bitcoin Core developers
2 // Copyright (c) 2017-2019 The Raven Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include "crypto/sha256.h"
7 #include "crypto/common.h"
8 
9 #include <assert.h>
10 #include <string.h>
11 #include <atomic>
12 
13 #if defined(__x86_64__) || defined(__amd64__)
14 #if defined(USE_ASM)
15 #include <cpuid.h>
16 namespace sha256_sse4
17 {
18 void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks);
19 }
20 #endif
21 #endif
22 
23 // Internal implementation code.
24 namespace
25 {
27 namespace sha256
28 {
29 uint32_t inline Ch(uint32_t x, uint32_t y, uint32_t z) { return z ^ (x & (y ^ z)); }
30 uint32_t inline Maj(uint32_t x, uint32_t y, uint32_t z) { return (x & y) | (z & (x | y)); }
31 uint32_t inline Sigma0(uint32_t x) { return (x >> 2 | x << 30) ^ (x >> 13 | x << 19) ^ (x >> 22 | x << 10); }
32 uint32_t inline Sigma1(uint32_t x) { return (x >> 6 | x << 26) ^ (x >> 11 | x << 21) ^ (x >> 25 | x << 7); }
33 uint32_t inline sigma0(uint32_t x) { return (x >> 7 | x << 25) ^ (x >> 18 | x << 14) ^ (x >> 3); }
34 uint32_t inline sigma1(uint32_t x) { return (x >> 17 | x << 15) ^ (x >> 19 | x << 13) ^ (x >> 10); }
35 
37 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, uint32_t w)
38 {
39  uint32_t t1 = h + Sigma1(e) + Ch(e, f, g) + k + w;
40  uint32_t t2 = Sigma0(a) + Maj(a, b, c);
41  d += t1;
42  h = t1 + t2;
43 }
44 
46 void inline Initialize(uint32_t* s)
47 {
48  s[0] = 0x6a09e667ul;
49  s[1] = 0xbb67ae85ul;
50  s[2] = 0x3c6ef372ul;
51  s[3] = 0xa54ff53aul;
52  s[4] = 0x510e527ful;
53  s[5] = 0x9b05688cul;
54  s[6] = 0x1f83d9abul;
55  s[7] = 0x5be0cd19ul;
56 }
57 
59 void Transform(uint32_t* s, const unsigned char* chunk, size_t blocks)
60 {
61  while (blocks--) {
62  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];
63  uint32_t w0, w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12, w13, w14, w15;
64 
65  Round(a, b, c, d, e, f, g, h, 0x428a2f98, w0 = ReadBE32(chunk + 0));
66  Round(h, a, b, c, d, e, f, g, 0x71374491, w1 = ReadBE32(chunk + 4));
67  Round(g, h, a, b, c, d, e, f, 0xb5c0fbcf, w2 = ReadBE32(chunk + 8));
68  Round(f, g, h, a, b, c, d, e, 0xe9b5dba5, w3 = ReadBE32(chunk + 12));
69  Round(e, f, g, h, a, b, c, d, 0x3956c25b, w4 = ReadBE32(chunk + 16));
70  Round(d, e, f, g, h, a, b, c, 0x59f111f1, w5 = ReadBE32(chunk + 20));
71  Round(c, d, e, f, g, h, a, b, 0x923f82a4, w6 = ReadBE32(chunk + 24));
72  Round(b, c, d, e, f, g, h, a, 0xab1c5ed5, w7 = ReadBE32(chunk + 28));
73  Round(a, b, c, d, e, f, g, h, 0xd807aa98, w8 = ReadBE32(chunk + 32));
74  Round(h, a, b, c, d, e, f, g, 0x12835b01, w9 = ReadBE32(chunk + 36));
75  Round(g, h, a, b, c, d, e, f, 0x243185be, w10 = ReadBE32(chunk + 40));
76  Round(f, g, h, a, b, c, d, e, 0x550c7dc3, w11 = ReadBE32(chunk + 44));
77  Round(e, f, g, h, a, b, c, d, 0x72be5d74, w12 = ReadBE32(chunk + 48));
78  Round(d, e, f, g, h, a, b, c, 0x80deb1fe, w13 = ReadBE32(chunk + 52));
79  Round(c, d, e, f, g, h, a, b, 0x9bdc06a7, w14 = ReadBE32(chunk + 56));
80  Round(b, c, d, e, f, g, h, a, 0xc19bf174, w15 = ReadBE32(chunk + 60));
81 
82  Round(a, b, c, d, e, f, g, h, 0xe49b69c1, w0 += sigma1(w14) + w9 + sigma0(w1));
83  Round(h, a, b, c, d, e, f, g, 0xefbe4786, w1 += sigma1(w15) + w10 + sigma0(w2));
84  Round(g, h, a, b, c, d, e, f, 0x0fc19dc6, w2 += sigma1(w0) + w11 + sigma0(w3));
85  Round(f, g, h, a, b, c, d, e, 0x240ca1cc, w3 += sigma1(w1) + w12 + sigma0(w4));
86  Round(e, f, g, h, a, b, c, d, 0x2de92c6f, w4 += sigma1(w2) + w13 + sigma0(w5));
87  Round(d, e, f, g, h, a, b, c, 0x4a7484aa, w5 += sigma1(w3) + w14 + sigma0(w6));
88  Round(c, d, e, f, g, h, a, b, 0x5cb0a9dc, w6 += sigma1(w4) + w15 + sigma0(w7));
89  Round(b, c, d, e, f, g, h, a, 0x76f988da, w7 += sigma1(w5) + w0 + sigma0(w8));
90  Round(a, b, c, d, e, f, g, h, 0x983e5152, w8 += sigma1(w6) + w1 + sigma0(w9));
91  Round(h, a, b, c, d, e, f, g, 0xa831c66d, w9 += sigma1(w7) + w2 + sigma0(w10));
92  Round(g, h, a, b, c, d, e, f, 0xb00327c8, w10 += sigma1(w8) + w3 + sigma0(w11));
93  Round(f, g, h, a, b, c, d, e, 0xbf597fc7, w11 += sigma1(w9) + w4 + sigma0(w12));
94  Round(e, f, g, h, a, b, c, d, 0xc6e00bf3, w12 += sigma1(w10) + w5 + sigma0(w13));
95  Round(d, e, f, g, h, a, b, c, 0xd5a79147, w13 += sigma1(w11) + w6 + sigma0(w14));
96  Round(c, d, e, f, g, h, a, b, 0x06ca6351, w14 += sigma1(w12) + w7 + sigma0(w15));
97  Round(b, c, d, e, f, g, h, a, 0x14292967, w15 += sigma1(w13) + w8 + sigma0(w0));
98 
99  Round(a, b, c, d, e, f, g, h, 0x27b70a85, w0 += sigma1(w14) + w9 + sigma0(w1));
100  Round(h, a, b, c, d, e, f, g, 0x2e1b2138, w1 += sigma1(w15) + w10 + sigma0(w2));
101  Round(g, h, a, b, c, d, e, f, 0x4d2c6dfc, w2 += sigma1(w0) + w11 + sigma0(w3));
102  Round(f, g, h, a, b, c, d, e, 0x53380d13, w3 += sigma1(w1) + w12 + sigma0(w4));
103  Round(e, f, g, h, a, b, c, d, 0x650a7354, w4 += sigma1(w2) + w13 + sigma0(w5));
104  Round(d, e, f, g, h, a, b, c, 0x766a0abb, w5 += sigma1(w3) + w14 + sigma0(w6));
105  Round(c, d, e, f, g, h, a, b, 0x81c2c92e, w6 += sigma1(w4) + w15 + sigma0(w7));
106  Round(b, c, d, e, f, g, h, a, 0x92722c85, w7 += sigma1(w5) + w0 + sigma0(w8));
107  Round(a, b, c, d, e, f, g, h, 0xa2bfe8a1, w8 += sigma1(w6) + w1 + sigma0(w9));
108  Round(h, a, b, c, d, e, f, g, 0xa81a664b, w9 += sigma1(w7) + w2 + sigma0(w10));
109  Round(g, h, a, b, c, d, e, f, 0xc24b8b70, w10 += sigma1(w8) + w3 + sigma0(w11));
110  Round(f, g, h, a, b, c, d, e, 0xc76c51a3, w11 += sigma1(w9) + w4 + sigma0(w12));
111  Round(e, f, g, h, a, b, c, d, 0xd192e819, w12 += sigma1(w10) + w5 + sigma0(w13));
112  Round(d, e, f, g, h, a, b, c, 0xd6990624, w13 += sigma1(w11) + w6 + sigma0(w14));
113  Round(c, d, e, f, g, h, a, b, 0xf40e3585, w14 += sigma1(w12) + w7 + sigma0(w15));
114  Round(b, c, d, e, f, g, h, a, 0x106aa070, w15 += sigma1(w13) + w8 + sigma0(w0));
115 
116  Round(a, b, c, d, e, f, g, h, 0x19a4c116, w0 += sigma1(w14) + w9 + sigma0(w1));
117  Round(h, a, b, c, d, e, f, g, 0x1e376c08, w1 += sigma1(w15) + w10 + sigma0(w2));
118  Round(g, h, a, b, c, d, e, f, 0x2748774c, w2 += sigma1(w0) + w11 + sigma0(w3));
119  Round(f, g, h, a, b, c, d, e, 0x34b0bcb5, w3 += sigma1(w1) + w12 + sigma0(w4));
120  Round(e, f, g, h, a, b, c, d, 0x391c0cb3, w4 += sigma1(w2) + w13 + sigma0(w5));
121  Round(d, e, f, g, h, a, b, c, 0x4ed8aa4a, w5 += sigma1(w3) + w14 + sigma0(w6));
122  Round(c, d, e, f, g, h, a, b, 0x5b9cca4f, w6 += sigma1(w4) + w15 + sigma0(w7));
123  Round(b, c, d, e, f, g, h, a, 0x682e6ff3, w7 += sigma1(w5) + w0 + sigma0(w8));
124  Round(a, b, c, d, e, f, g, h, 0x748f82ee, w8 += sigma1(w6) + w1 + sigma0(w9));
125  Round(h, a, b, c, d, e, f, g, 0x78a5636f, w9 += sigma1(w7) + w2 + sigma0(w10));
126  Round(g, h, a, b, c, d, e, f, 0x84c87814, w10 += sigma1(w8) + w3 + sigma0(w11));
127  Round(f, g, h, a, b, c, d, e, 0x8cc70208, w11 += sigma1(w9) + w4 + sigma0(w12));
128  Round(e, f, g, h, a, b, c, d, 0x90befffa, w12 += sigma1(w10) + w5 + sigma0(w13));
129  Round(d, e, f, g, h, a, b, c, 0xa4506ceb, w13 += sigma1(w11) + w6 + sigma0(w14));
130  Round(c, d, e, f, g, h, a, b, 0xbef9a3f7, w14 + sigma1(w12) + w7 + sigma0(w15));
131  Round(b, c, d, e, f, g, h, a, 0xc67178f2, w15 + sigma1(w13) + w8 + sigma0(w0));
132 
133  s[0] += a;
134  s[1] += b;
135  s[2] += c;
136  s[3] += d;
137  s[4] += e;
138  s[5] += f;
139  s[6] += g;
140  s[7] += h;
141  chunk += 64;
142  }
143 }
144 
145 } // namespace sha256
146 
147 typedef void (*TransformType)(uint32_t*, const unsigned char*, size_t);
148 
149 bool SelfTest(TransformType tr) {
150  static const unsigned char in1[65] = {0, 0x80};
151  static const unsigned char in2[129] = {
152  0,
153  32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
154  32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,
155  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
156  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0
157  };
158  static const uint32_t init[8] = {0x6a09e667ul, 0xbb67ae85ul, 0x3c6ef372ul, 0xa54ff53aul, 0x510e527ful, 0x9b05688cul, 0x1f83d9abul, 0x5be0cd19ul};
159  static const uint32_t out1[8] = {0xe3b0c442ul, 0x98fc1c14ul, 0x9afbf4c8ul, 0x996fb924ul, 0x27ae41e4ul, 0x649b934cul, 0xa495991bul, 0x7852b855ul};
160  static const uint32_t out2[8] = {0xce4153b0ul, 0x147c2a86ul, 0x3ed4298eul, 0xe0676bc8ul, 0x79fc77a1ul, 0x2abe1f49ul, 0xb2b055dful, 0x1069523eul};
161  uint32_t buf[8];
162  memcpy(buf, init, sizeof(buf));
163  // Process nothing, and check we remain in the initial state.
164  tr(buf, nullptr, 0);
165  if (memcmp(buf, init, sizeof(buf))) return false;
166  // Process the padded empty string (unaligned)
167  tr(buf, in1 + 1, 1);
168  if (memcmp(buf, out1, sizeof(buf))) return false;
169  // Process 64 spaces (unaligned)
170  memcpy(buf, init, sizeof(buf));
171  tr(buf, in2 + 1, 2);
172  if (memcmp(buf, out2, sizeof(buf))) return false;
173  return true;
174 }
175 
176 TransformType Transform = sha256::Transform;
177 
178 } // namespace
179 
180 std::string SHA256AutoDetect()
181 {
182 #if defined(USE_ASM) && (defined(__x86_64__) || defined(__amd64__))
183  uint32_t eax, ebx, ecx, edx;
184  if (__get_cpuid(1, &eax, &ebx, &ecx, &edx) && (ecx >> 19) & 1) {
185  Transform = sha256_sse4::Transform;
186  assert(SelfTest(Transform));
187  return "sse4";
188  }
189 #endif
190 
191  assert(SelfTest(Transform));
192  return "standard";
193 }
194 
196 
197 CSHA256::CSHA256() : bytes(0)
198 {
199  sha256::Initialize(s);
200 }
201 
202 CSHA256& CSHA256::Write(const unsigned char* data, size_t len)
203 {
204  const unsigned char* end = data + len;
205  size_t bufsize = bytes % 64;
206  if (bufsize && bufsize + len >= 64) {
207  // Fill the buffer, and process it.
208  memcpy(buf + bufsize, data, 64 - bufsize);
209  bytes += 64 - bufsize;
210  data += 64 - bufsize;
211  Transform(s, buf, 1);
212  bufsize = 0;
213  }
214  if (end - data >= 64) {
215  size_t blocks = (end - data) / 64;
216  Transform(s, data, blocks);
217  data += 64 * blocks;
218  bytes += 64 * blocks;
219  }
220  if (end > data) {
221  // Fill the buffer with what remains.
222  memcpy(buf + bufsize, data, end - data);
223  bytes += end - data;
224  }
225  return *this;
226 }
227 
228 void CSHA256::Finalize(unsigned char hash[OUTPUT_SIZE])
229 {
230  static const unsigned char pad[64] = {0x80};
231  unsigned char sizedesc[8];
232  WriteBE64(sizedesc, bytes << 3);
233  Write(pad, 1 + ((119 - (bytes % 64)) % 64));
234  Write(sizedesc, 8);
235  WriteBE32(hash, s[0]);
236  WriteBE32(hash + 4, s[1]);
237  WriteBE32(hash + 8, s[2]);
238  WriteBE32(hash + 12, s[3]);
239  WriteBE32(hash + 16, s[4]);
240  WriteBE32(hash + 20, s[5]);
241  WriteBE32(hash + 24, s[6]);
242  WriteBE32(hash + 28, s[7]);
243 }
244 
246 {
247  bytes = 0;
248  sha256::Initialize(s);
249  return *this;
250 }
CSHA256 & Write(const unsigned char *data, size_t len)
Definition: sha256.cpp:202
#define Round(a, b, c, d, e, f, g, h, k, w)
Definition: hash_impl.h:23
uint32_t s[8]
Definition: sha256.h:17
#define Ch(x, y, z)
Definition: sha2.c:51
#define sigma1(x)
Definition: hash_impl.h:21
std::string SHA256AutoDetect()
Autodetect the best available SHA256 implementation.
Definition: sha256.cpp:180
#define sigma0(x)
Definition: hash_impl.h:20
CSHA256 & Reset()
Definition: sha256.cpp:245
#define Sigma0(x)
Definition: hash_impl.h:18
void Finalize(unsigned char hash[OUTPUT_SIZE])
Definition: sha256.cpp:228
#define Sigma1(x)
Definition: hash_impl.h:19
uint64_t bytes
Definition: sha256.h:19
void * memcpy(void *a, const void *b, size_t c)
Internal SHA-256 implementation.
Definition: sha256.cpp:27
#define Maj(x, y, z)
Definition: sha2.c:52
static const size_t OUTPUT_SIZE
Definition: sha256.h:22
CSHA256()
Definition: sha256.cpp:197
unsigned char buf[64]
Definition: sha256.h:18
A hasher class for SHA-256.
Definition: sha256.h:14