sha256.cpp raw

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