Crypto++  8.8
Free C++ class library of cryptographic schemes
sha.cpp
1 // sha.cpp - modified by Wei Dai from Steve Reid's public domain sha1.c
2 
3 // Steve Reid implemented SHA-1. Wei Dai implemented SHA-2. Jeffrey
4 // Walton implemented Intel SHA extensions based on Intel articles and code
5 // by Sean Gulley. Jeffrey Walton implemented ARM SHA-1 and SHA-256 based
6 // on ARM code and code from Johannes Schneiders, Skip Hovsmith and
7 // Barry O'Rourke. Jeffrey Walton and Bill Schmidt implemented Power8
8 // SHA-256 and SHA-512. All code is in the public domain.
9 
10 // In August 2017 JW reworked the internals to align all the
11 // implementations. Formerly all hashes were software based, IterHashBase
12 // handled endian conversions, and IterHashBase dispatched a single to
13 // block SHA{N}::Transform. SHA{N}::Transform then performed the single
14 // block hashing. It was repeated for multiple blocks.
15 //
16 // The rework added SHA{N}::HashMultipleBlocks (class) and
17 // SHA{N}_HashMultipleBlocks (free standing). There are also hardware
18 // accelerated variations. Callers enter SHA{N}::HashMultipleBlocks (class)
19 // and the function calls SHA{N}_HashMultipleBlocks (free standing) or
20 // SHA{N}_HashBlock (free standing) as a fallback.
21 //
22 // An added wrinkle is hardware is little endian, C++ is big endian, and
23 // callers use big endian, so SHA{N}_HashMultipleBlock accepts a ByteOrder
24 // for the incoming data arrangement. Hardware based SHA{N}_HashMultipleBlock
25 // can often perform the endian swap much easier by setting an EPI mask.
26 // Endian swap incurs no penalty on Intel SHA, and 4-instruction penalty on
27 // ARM SHA. Under C++ the full software based swap penalty is incurred due
28 // to use of ReverseBytes().
29 //
30 // In May 2019 JW added Cryptogams ARMv7 and NEON implementations for SHA1,
31 // SHA256 and SHA512. The Cryptogams code closed a performance gap on modern
32 // 32-bit ARM devices. Cryptogams is Andy Polyakov's project used to create
33 // high speed crypto algorithms and share them with other developers. Andy's
34 // code runs 30% to 50% faster than C/C++ code. The Cryptogams code can be
35 // disabled in config_asm.h. An example of integrating Andy's code is at
36 // https://wiki.openssl.org/index.php/Cryptogams_SHA.
37 
38 // use "cl /EP /P /DCRYPTOPP_GENERATE_X64_MASM sha.cpp" to generate MASM code
39 
40 #include "pch.h"
41 #include "config.h"
42 
43 #if CRYPTOPP_MSC_VERSION
44 # pragma warning(disable: 4731)
45 #endif
46 
47 #ifndef CRYPTOPP_IMPORTS
48 #ifndef CRYPTOPP_GENERATE_X64_MASM
49 
50 #include "secblock.h"
51 #include "sha.h"
52 #include "misc.h"
53 #include "cpu.h"
54 
55 #if defined(CRYPTOPP_DISABLE_SHA_ASM)
56 # undef CRYPTOPP_X86_ASM_AVAILABLE
57 # undef CRYPTOPP_X32_ASM_AVAILABLE
58 # undef CRYPTOPP_X64_ASM_AVAILABLE
59 # undef CRYPTOPP_SSE2_ASM_AVAILABLE
60 #endif
61 
62 NAMESPACE_BEGIN(CryptoPP)
63 
64 #if CRYPTOPP_SHANI_AVAILABLE
65 extern void SHA1_HashMultipleBlocks_SHANI(word32 *state, const word32 *data, size_t length, ByteOrder order);
66 extern void SHA256_HashMultipleBlocks_SHANI(word32 *state, const word32 *data, size_t length, ByteOrder order);
67 #endif
68 
69 #if CRYPTOGAMS_ARM_SHA1
70 extern "C" void cryptogams_sha1_block_data_order(word32* state, const word32 *data, size_t blocks);
71 extern "C" void cryptogams_sha1_block_data_order_neon(word32* state, const word32 *data, size_t blocks);
72 #endif
73 
74 #if CRYPTOPP_ARM_SHA1_AVAILABLE
75 extern void SHA1_HashMultipleBlocks_ARMV8(word32 *state, const word32 *data, size_t length, ByteOrder order);
76 #endif
77 
78 #if CRYPTOPP_ARM_SHA2_AVAILABLE
79 extern void SHA256_HashMultipleBlocks_ARMV8(word32 *state, const word32 *data, size_t length, ByteOrder order);
80 #endif
81 
82 #if CRYPTOGAMS_ARM_SHA256
83 extern "C" void cryptogams_sha256_block_data_order(word32* state, const word32 *data, size_t blocks);
84 extern "C" void cryptogams_sha256_block_data_order_neon(word32* state, const word32 *data, size_t blocks);
85 #endif
86 
87 #if CRYPTOPP_ARM_SHA512_AVAILABLE
88 extern void SHA512_HashMultipleBlocks_ARMV8(word32 *state, const word32 *data, size_t length, ByteOrder order);
89 #endif
90 
91 #if CRYPTOPP_POWER8_SHA_AVAILABLE
92 extern void SHA256_HashMultipleBlocks_POWER8(word32 *state, const word32 *data, size_t length, ByteOrder order);
93 extern void SHA512_HashMultipleBlocks_POWER8(word64 *state, const word64 *data, size_t length, ByteOrder order);
94 #endif
95 
96 #if CRYPTOGAMS_ARM_SHA512
97 extern "C" void cryptogams_sha512_block_data_order(word64* state, const word64 *data, size_t blocks);
98 extern "C" void cryptogams_sha512_block_data_order_neon(word64* state, const word64 *data, size_t blocks);
99 #endif
100 
101 // We add extern to export table to sha_simd.cpp, but it
102 // cleared http://github.com/weidai11/cryptopp/issues/502
103 extern const word32 SHA256_K[64];
104 extern const word64 SHA512_K[80];
105 
106 CRYPTOPP_ALIGN_DATA(16)
107 const word64 SHA512_K[80] = {
108  W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd),
109  W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc),
110  W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019),
111  W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118),
112  W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe),
113  W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2),
114  W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1),
115  W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694),
116  W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3),
117  W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65),
118  W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483),
119  W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5),
120  W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210),
121  W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4),
122  W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725),
123  W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70),
124  W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926),
125  W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df),
126  W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8),
127  W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b),
128  W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001),
129  W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30),
130  W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910),
131  W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8),
132  W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53),
133  W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8),
134  W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb),
135  W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3),
136  W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60),
137  W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec),
138  W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9),
139  W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b),
140  W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207),
141  W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178),
142  W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6),
143  W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b),
144  W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493),
145  W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c),
146  W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a),
147  W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817)
148 };
149 
150 CRYPTOPP_ALIGN_DATA(16)
151 const word32 SHA256_K[64] = {
152 
153  0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
154  0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
155  0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
156  0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
157  0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
158  0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
159  0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
160  0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
161  0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
162  0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
163  0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
164  0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
165  0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
166  0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
167  0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
168  0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
169 };
170 
171 ////////////////////////////////
172 // start of Steve Reid's code //
173 ////////////////////////////////
174 
175 ANONYMOUS_NAMESPACE_BEGIN
176 
177 #define blk0(i) (W[i] = data[i])
178 #define blk1(i) (W[i&15] = rotlConstant<1>(W[(i+13)&15]^W[(i+8)&15]^W[(i+2)&15]^W[i&15]))
179 
180 #define f1(x,y,z) (z^(x&(y^z)))
181 #define f2(x,y,z) (x^y^z)
182 #define f3(x,y,z) ((x&y)|(z&(x|y)))
183 #define f4(x,y,z) (x^y^z)
184 
185 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
186 #define R0(v,w,x,y,z,i) z+=f1(w,x,y)+blk0(i)+0x5A827999+rotlConstant<5>(v);w=rotlConstant<30>(w);
187 #define R1(v,w,x,y,z,i) z+=f1(w,x,y)+blk1(i)+0x5A827999+rotlConstant<5>(v);w=rotlConstant<30>(w);
188 #define R2(v,w,x,y,z,i) z+=f2(w,x,y)+blk1(i)+0x6ED9EBA1+rotlConstant<5>(v);w=rotlConstant<30>(w);
189 #define R3(v,w,x,y,z,i) z+=f3(w,x,y)+blk1(i)+0x8F1BBCDC+rotlConstant<5>(v);w=rotlConstant<30>(w);
190 #define R4(v,w,x,y,z,i) z+=f4(w,x,y)+blk1(i)+0xCA62C1D6+rotlConstant<5>(v);w=rotlConstant<30>(w);
191 
192 void SHA1_HashBlock_CXX(word32 *state, const word32 *data)
193 {
194  CRYPTOPP_ASSERT(state);
195  CRYPTOPP_ASSERT(data);
196 
197  word32 W[16];
198  /* Copy context->state[] to working vars */
199  word32 a = state[0];
200  word32 b = state[1];
201  word32 c = state[2];
202  word32 d = state[3];
203  word32 e = state[4];
204  /* 4 rounds of 20 operations each. Loop unrolled. */
205  R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
206  R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
207  R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
208  R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
209  R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
210  R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
211  R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
212  R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
213  R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
214  R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
215  R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
216  R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
217  R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
218  R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
219  R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
220  R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
221  R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
222  R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
223  R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
224  R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
225  /* Add the working vars back into context.state[] */
226  state[0] += a;
227  state[1] += b;
228  state[2] += c;
229  state[3] += d;
230  state[4] += e;
231 }
232 
233 #undef blk0
234 #undef blk1
235 #undef f1
236 #undef f2
237 #undef f3
238 #undef f4
239 #undef R1
240 #undef R2
241 #undef R3
242 #undef R4
243 
244 ANONYMOUS_NAMESPACE_END
245 
246 //////////////////////////////
247 // end of Steve Reid's code //
248 //////////////////////////////
249 
250 std::string SHA1::AlgorithmProvider() const
251 {
252 #if CRYPTOPP_SHANI_AVAILABLE
253  if (HasSHA())
254  return "SHANI";
255 #endif
256 #if CRYPTOPP_SSE2_ASM_AVAILABLE
257  if (HasSSE2())
258  return "SSE2";
259 #endif
260 #if CRYPTOGAMS_ARM_SHA1
261 # if CRYPTOPP_ARM_NEON_AVAILABLE
262  if (HasNEON())
263  return "NEON";
264  else
265 # endif
266  if (HasARMv7())
267  return "ARMv7";
268 #endif
269 #if CRYPTOPP_ARM_SHA1_AVAILABLE
270  if (HasSHA1())
271  return "ARMv8";
272 #endif
273  return "C++";
274 }
275 
276 void SHA1::InitState(HashWordType *state)
277 {
278  state[0] = 0x67452301;
279  state[1] = 0xEFCDAB89;
280  state[2] = 0x98BADCFE;
281  state[3] = 0x10325476;
282  state[4] = 0xC3D2E1F0;
283 }
284 
285 void SHA1::Transform(word32 *state, const word32 *data)
286 {
287  CRYPTOPP_ASSERT(state);
288  CRYPTOPP_ASSERT(data);
289 
290 #if CRYPTOPP_SHANI_AVAILABLE
291  if (HasSHA())
292  {
293  SHA1_HashMultipleBlocks_SHANI(state, data, SHA1::BLOCKSIZE, LITTLE_ENDIAN_ORDER);
294  return;
295  }
296 #endif
297 // Disabled at the moment due to MDC and SEAL failures
298 #if CRYPTOGAMS_ARM_SHA1 && 0
299 # if CRYPTOPP_ARM_NEON_AVAILABLE
300  if (HasNEON())
301  {
302 # if defined(CRYPTOPP_LITTLE_ENDIAN)
303  word32 dataBuf[16];
304  ByteReverse(dataBuf, data, SHA1::BLOCKSIZE);
305  cryptogams_sha1_block_data_order_neon(state, dataBuf, 1);
306 # else
307  cryptogams_sha1_block_data_order_neon(state, data, 1);
308 # endif
309  return;
310  }
311  else
312 # endif
313  if (HasARMv7())
314  {
315 # if defined(CRYPTOPP_LITTLE_ENDIAN)
316  word32 dataBuf[16];
317  ByteReverse(dataBuf, data, SHA1::BLOCKSIZE);
318  cryptogams_sha1_block_data_order(state, data, 1);
319 # else
320  cryptogams_sha1_block_data_order(state, data, 1);
321 # endif
322  return;
323  }
324 #endif
325 #if CRYPTOPP_ARM_SHA1_AVAILABLE
326  if (HasSHA1())
327  {
328  SHA1_HashMultipleBlocks_ARMV8(state, data, SHA1::BLOCKSIZE, LITTLE_ENDIAN_ORDER);
329  return;
330  }
331 #endif
332 
333  SHA1_HashBlock_CXX(state, data);
334 }
335 
336 size_t SHA1::HashMultipleBlocks(const word32 *input, size_t length)
337 {
338  CRYPTOPP_ASSERT(input);
339  CRYPTOPP_ASSERT(length >= SHA1::BLOCKSIZE);
340 
341 #if CRYPTOPP_SHANI_AVAILABLE
342  if (HasSHA())
343  {
344  SHA1_HashMultipleBlocks_SHANI(m_state, input, length, BIG_ENDIAN_ORDER);
345  return length & (SHA1::BLOCKSIZE - 1);
346  }
347 #endif
348 #if CRYPTOGAMS_ARM_SHA1
349 # if CRYPTOPP_ARM_NEON_AVAILABLE
350  if (HasNEON())
351  {
352  cryptogams_sha1_block_data_order_neon(m_state, input, length / SHA1::BLOCKSIZE);
353  return length & (SHA1::BLOCKSIZE - 1);
354  }
355  else
356 # endif
357  if (HasARMv7())
358  {
359  cryptogams_sha1_block_data_order(m_state, input, length / SHA1::BLOCKSIZE);
360  return length & (SHA1::BLOCKSIZE - 1);
361  }
362 #endif
363 #if CRYPTOPP_ARM_SHA1_AVAILABLE
364  if (HasSHA1())
365  {
366  SHA1_HashMultipleBlocks_ARMV8(m_state, input, length, BIG_ENDIAN_ORDER);
367  return length & (SHA1::BLOCKSIZE - 1);
368  }
369 #endif
370 
371  const bool noReverse = NativeByteOrderIs(this->GetByteOrder());
372  word32 *dataBuf = this->DataBuf();
373  do
374  {
375  if (noReverse)
376  {
377  SHA1_HashBlock_CXX(m_state, input);
378  }
379  else
380  {
381  ByteReverse(dataBuf, input, SHA1::BLOCKSIZE);
382  SHA1_HashBlock_CXX(m_state, dataBuf);
383  }
384 
385  input += SHA1::BLOCKSIZE/sizeof(word32);
386  length -= SHA1::BLOCKSIZE;
387  }
388  while (length >= SHA1::BLOCKSIZE);
389  return length;
390 }
391 
392 // *************************************************************
393 
394 ANONYMOUS_NAMESPACE_BEGIN
395 
396 #define a(i) T[(0-i)&7]
397 #define b(i) T[(1-i)&7]
398 #define c(i) T[(2-i)&7]
399 #define d(i) T[(3-i)&7]
400 #define e(i) T[(4-i)&7]
401 #define f(i) T[(5-i)&7]
402 #define g(i) T[(6-i)&7]
403 #define h(i) T[(7-i)&7]
404 
405 #define blk0(i) (W[i] = data[i])
406 #define blk2(i) (W[i&15]+=s1(W[(i-2)&15])+W[(i-7)&15]+s0(W[(i-15)&15]))
407 
408 #define Ch(x,y,z) (z^(x&(y^z)))
409 #define Maj(x,y,z) (y^((x^y)&(y^z)))
410 
411 #define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+SHA256_K[i+j]+(j?blk2(i):blk0(i));\
412  d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i))
413 
414 // for SHA256
415 #define s0(x) (rotrConstant<7>(x)^rotrConstant<18>(x)^(x>>3))
416 #define s1(x) (rotrConstant<17>(x)^rotrConstant<19>(x)^(x>>10))
417 #define S0(x) (rotrConstant<2>(x)^rotrConstant<13>(x)^rotrConstant<22>(x))
418 #define S1(x) (rotrConstant<6>(x)^rotrConstant<11>(x)^rotrConstant<25>(x))
419 
420 void SHA256_HashBlock_CXX(word32 *state, const word32 *data)
421 {
422  word32 W[16]={0}, T[8];
423  /* Copy context->state[] to working vars */
424  std::memcpy(T, state, sizeof(T));
425  /* 64 operations, partially loop unrolled */
426  for (unsigned int j=0; j<64; j+=16)
427  {
428  R( 0); R( 1); R( 2); R( 3);
429  R( 4); R( 5); R( 6); R( 7);
430  R( 8); R( 9); R(10); R(11);
431  R(12); R(13); R(14); R(15);
432  }
433  /* Add the working vars back into context.state[] */
434  state[0] += a(0);
435  state[1] += b(0);
436  state[2] += c(0);
437  state[3] += d(0);
438  state[4] += e(0);
439  state[5] += f(0);
440  state[6] += g(0);
441  state[7] += h(0);
442 }
443 
444 #undef Ch
445 #undef Maj
446 #undef s0
447 #undef s1
448 #undef S0
449 #undef S1
450 #undef blk0
451 #undef blk1
452 #undef blk2
453 #undef R
454 
455 #undef a
456 #undef b
457 #undef c
458 #undef d
459 #undef e
460 #undef f
461 #undef g
462 #undef h
463 
464 ANONYMOUS_NAMESPACE_END
465 
466 std::string SHA256_AlgorithmProvider()
467 {
468 #if CRYPTOPP_SHANI_AVAILABLE
469  if (HasSHA())
470  return "SHANI";
471 #endif
472 #if CRYPTOPP_SSE2_ASM_AVAILABLE
473  if (HasSSE2())
474  return "SSE2";
475 #endif
476 #if CRYPTOGAMS_ARM_SHA256
477 # if CRYPTOPP_ARM_NEON_AVAILABLE
478  if (HasNEON())
479  return "NEON";
480  else
481 # endif
482  if (HasARMv7())
483  return "ARMv7";
484 #endif
485 #if CRYPTOPP_ARM_SHA2_AVAILABLE
486  if (HasSHA2())
487  return "ARMv8";
488 #endif
489 #if (CRYPTOPP_POWER8_SHA_AVAILABLE)
490  if (HasSHA256())
491  return "Power8";
492 #endif
493  return "C++";
494 }
495 
496 std::string SHA224::AlgorithmProvider() const
497 {
498  return SHA256_AlgorithmProvider();
499 }
500 
501 void SHA224::InitState(HashWordType *state)
502 {
503  static const word32 s[8] = {
504  0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
505  0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4};
506  std::memcpy(state, s, sizeof(s));
507 }
508 
509 void SHA256::InitState(HashWordType *state)
510 {
511  static const word32 s[8] = {
512  0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
513  0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
514  std::memcpy(state, s, sizeof(s));
515 }
516 #endif // Not CRYPTOPP_GENERATE_X64_MASM
517 
518 #if defined(CRYPTOPP_X86_ASM_AVAILABLE)
519 
520 ANONYMOUS_NAMESPACE_BEGIN
521 
522 void CRYPTOPP_FASTCALL SHA256_HashMultipleBlocks_SSE2(word32 *state, const word32 *data, size_t len)
523 {
524  #define LOCALS_SIZE 8*4 + 16*4 + 4*WORD_SZ
525  #define H(i) [BASE+ASM_MOD(1024+7-(i),8)*4]
526  #define G(i) H(i+1)
527  #define F(i) H(i+2)
528  #define E(i) H(i+3)
529  #define D(i) H(i+4)
530  #define C(i) H(i+5)
531  #define B(i) H(i+6)
532  #define A(i) H(i+7)
533  #define Wt(i) BASE+8*4+ASM_MOD(1024+15-(i),16)*4
534  #define Wt_2(i) Wt((i)-2)
535  #define Wt_15(i) Wt((i)-15)
536  #define Wt_7(i) Wt((i)-7)
537  #define K_END [BASE+8*4+16*4+0*WORD_SZ]
538  #define STATE_SAVE [BASE+8*4+16*4+1*WORD_SZ]
539  #define DATA_SAVE [BASE+8*4+16*4+2*WORD_SZ]
540  #define DATA_END [BASE+8*4+16*4+3*WORD_SZ]
541  #define Kt(i) WORD_REG(si)+(i)*4
542 #if CRYPTOPP_BOOL_X86
543  #define BASE esp+4
544 #elif defined(__GNUC__)
545  #define BASE r8
546 #else
547  #define BASE rsp
548 #endif
549 
550 #define RA0(i, edx, edi) \
551  AS2( add edx, [Kt(i)] )\
552  AS2( add edx, [Wt(i)] )\
553  AS2( add edx, H(i) )\
554 
555 #define RA1(i, edx, edi)
556 
557 #define RB0(i, edx, edi)
558 
559 #define RB1(i, edx, edi) \
560  AS2( mov AS_REG_7d, [Wt_2(i)] )\
561  AS2( mov edi, [Wt_15(i)])\
562  AS2( mov ebx, AS_REG_7d )\
563  AS2( shr AS_REG_7d, 10 )\
564  AS2( ror ebx, 17 )\
565  AS2( xor AS_REG_7d, ebx )\
566  AS2( ror ebx, 2 )\
567  AS2( xor ebx, AS_REG_7d )/* s1(W_t-2) */\
568  AS2( add ebx, [Wt_7(i)])\
569  AS2( mov AS_REG_7d, edi )\
570  AS2( shr AS_REG_7d, 3 )\
571  AS2( ror edi, 7 )\
572  AS2( add ebx, [Wt(i)])/* s1(W_t-2) + W_t-7 + W_t-16 */\
573  AS2( xor AS_REG_7d, edi )\
574  AS2( add edx, [Kt(i)])\
575  AS2( ror edi, 11 )\
576  AS2( add edx, H(i) )\
577  AS2( xor AS_REG_7d, edi )/* s0(W_t-15) */\
578  AS2( add AS_REG_7d, ebx )/* W_t = s1(W_t-2) + W_t-7 + s0(W_t-15) W_t-16*/\
579  AS2( mov [Wt(i)], AS_REG_7d)\
580  AS2( add edx, AS_REG_7d )\
581 
582 #define ROUND(i, r, eax, ecx, edi, edx)\
583  /* in: edi = E */\
584  /* unused: eax, ecx, temp: ebx, AS_REG_7d, out: edx = T1 */\
585  AS2( mov edx, F(i) )\
586  AS2( xor edx, G(i) )\
587  AS2( and edx, edi )\
588  AS2( xor edx, G(i) )/* Ch(E,F,G) = (G^(E&(F^G))) */\
589  AS2( mov AS_REG_7d, edi )\
590  AS2( ror edi, 6 )\
591  AS2( ror AS_REG_7d, 25 )\
592  RA##r(i, edx, edi )/* H + Wt + Kt + Ch(E,F,G) */\
593  AS2( xor AS_REG_7d, edi )\
594  AS2( ror edi, 5 )\
595  AS2( xor AS_REG_7d, edi )/* S1(E) */\
596  AS2( add edx, AS_REG_7d )/* T1 = S1(E) + Ch(E,F,G) + H + Wt + Kt */\
597  RB##r(i, edx, edi )/* H + Wt + Kt + Ch(E,F,G) */\
598  /* in: ecx = A, eax = B^C, edx = T1 */\
599  /* unused: edx, temp: ebx, AS_REG_7d, out: eax = A, ecx = B^C, edx = E */\
600  AS2( mov ebx, ecx )\
601  AS2( xor ecx, B(i) )/* A^B */\
602  AS2( and eax, ecx )\
603  AS2( xor eax, B(i) )/* Maj(A,B,C) = B^((A^B)&(B^C) */\
604  AS2( mov AS_REG_7d, ebx )\
605  AS2( ror ebx, 2 )\
606  AS2( add eax, edx )/* T1 + Maj(A,B,C) */\
607  AS2( add edx, D(i) )\
608  AS2( mov D(i), edx )\
609  AS2( ror AS_REG_7d, 22 )\
610  AS2( xor AS_REG_7d, ebx )\
611  AS2( ror ebx, 11 )\
612  AS2( xor AS_REG_7d, ebx )\
613  AS2( add eax, AS_REG_7d )/* T1 + S0(A) + Maj(A,B,C) */\
614  AS2( mov H(i), eax )\
615 
616 // Unroll the use of CRYPTOPP_BOOL_X64 in assembler math. The GAS assembler on X32 (version 2.25)
617 // complains "Error: invalid operands (*ABS* and *UND* sections) for `*` and `-`"
618 #if CRYPTOPP_BOOL_X64
619 #define SWAP_COPY(i) \
620  AS2( mov WORD_REG(bx), [WORD_REG(dx)+i*WORD_SZ])\
621  AS1( bswap WORD_REG(bx))\
622  AS2( mov [Wt(i*2+1)], WORD_REG(bx))
623 #else // X86 and X32
624 #define SWAP_COPY(i) \
625  AS2( mov WORD_REG(bx), [WORD_REG(dx)+i*WORD_SZ])\
626  AS1( bswap WORD_REG(bx))\
627  AS2( mov [Wt(i)], WORD_REG(bx))
628 #endif
629 
630 #if defined(__GNUC__)
631  #if CRYPTOPP_BOOL_X64
633  #endif
634  __asm__ __volatile__
635  (
637  "lea %4, %%r8;"
638  #endif
639  INTEL_NOPREFIX
640 #elif defined(CRYPTOPP_GENERATE_X64_MASM)
641  ALIGN 8
642  SHA256_HashMultipleBlocks_SSE2 PROC FRAME
643  rex_push_reg rsi
644  push_reg rdi
645  push_reg rbx
646  push_reg rbp
647  alloc_stack(LOCALS_SIZE+8)
648  .endprolog
649  mov rdi, r8
650  lea rsi, [?SHA256_K@CryptoPP@@3QBIB + 48*4]
651 #endif
652 
654  #ifndef __GNUC__
655  AS2( mov edi, [len])
656  AS2( lea WORD_REG(si), [SHA256_K+48*4])
657  #endif
658  #if !defined(CRYPTOPP_MSC_VERSION) || (CRYPTOPP_MSC_VERSION < 1400)
659  AS_PUSH_IF86(bx)
660  #endif
661 
662  AS_PUSH_IF86(bp)
663  AS2( mov ebx, esp)
664  AS2( and esp, -16)
665  AS2( sub WORD_REG(sp), LOCALS_SIZE)
666  AS_PUSH_IF86(bx)
667 #endif
668  AS2( mov STATE_SAVE, WORD_REG(cx))
669  AS2( mov DATA_SAVE, WORD_REG(dx))
670  AS2( lea WORD_REG(ax), [WORD_REG(di) + WORD_REG(dx)])
671  AS2( mov DATA_END, WORD_REG(ax))
672  AS2( mov K_END, WORD_REG(si))
673 
674 #if CRYPTOPP_SSE2_ASM_AVAILABLE
676  AS2( test edi, 1)
677  ASJ( jnz, 2, f)
678  AS1( dec DWORD PTR K_END)
679 #endif
680  AS2( movdqu xmm0, XMMWORD_PTR [WORD_REG(cx)+0*16])
681  AS2( movdqu xmm1, XMMWORD_PTR [WORD_REG(cx)+1*16])
682 #endif
683 
685 #if CRYPTOPP_SSE2_ASM_AVAILABLE
686  ASJ( jmp, 0, f)
687 #endif
688  ASL(2) // non-SSE2
689  AS2( mov esi, ecx)
690  AS2( lea edi, A(0))
691  AS2( mov ecx, 8)
692 ATT_NOPREFIX
693  AS1( rep movsd)
694 INTEL_NOPREFIX
695  AS2( mov esi, K_END)
696  ASJ( jmp, 3, f)
697 #endif
698 
699 #if CRYPTOPP_SSE2_ASM_AVAILABLE
700  ASL(0)
701  AS2( movdqu E(0), xmm1)
702  AS2( movdqu A(0), xmm0)
703 #endif
705  ASL(3)
706 #endif
707  AS2( sub WORD_REG(si), 48*4)
708  SWAP_COPY(0) SWAP_COPY(1) SWAP_COPY(2) SWAP_COPY(3)
709  SWAP_COPY(4) SWAP_COPY(5) SWAP_COPY(6) SWAP_COPY(7)
711  SWAP_COPY(8) SWAP_COPY(9) SWAP_COPY(10) SWAP_COPY(11)
712  SWAP_COPY(12) SWAP_COPY(13) SWAP_COPY(14) SWAP_COPY(15)
713 #endif
714  AS2( mov edi, E(0)) // E
715  AS2( mov eax, B(0)) // B
716  AS2( xor eax, C(0)) // B^C
717  AS2( mov ecx, A(0)) // A
718 
719  ROUND(0, 0, eax, ecx, edi, edx)
720  ROUND(1, 0, ecx, eax, edx, edi)
721  ROUND(2, 0, eax, ecx, edi, edx)
722  ROUND(3, 0, ecx, eax, edx, edi)
723  ROUND(4, 0, eax, ecx, edi, edx)
724  ROUND(5, 0, ecx, eax, edx, edi)
725  ROUND(6, 0, eax, ecx, edi, edx)
726  ROUND(7, 0, ecx, eax, edx, edi)
727  ROUND(8, 0, eax, ecx, edi, edx)
728  ROUND(9, 0, ecx, eax, edx, edi)
729  ROUND(10, 0, eax, ecx, edi, edx)
730  ROUND(11, 0, ecx, eax, edx, edi)
731  ROUND(12, 0, eax, ecx, edi, edx)
732  ROUND(13, 0, ecx, eax, edx, edi)
733  ROUND(14, 0, eax, ecx, edi, edx)
734  ROUND(15, 0, ecx, eax, edx, edi)
735 
736  ASL(1)
737  AS2(add WORD_REG(si), 4*16)
738  ROUND(0, 1, eax, ecx, edi, edx)
739  ROUND(1, 1, ecx, eax, edx, edi)
740  ROUND(2, 1, eax, ecx, edi, edx)
741  ROUND(3, 1, ecx, eax, edx, edi)
742  ROUND(4, 1, eax, ecx, edi, edx)
743  ROUND(5, 1, ecx, eax, edx, edi)
744  ROUND(6, 1, eax, ecx, edi, edx)
745  ROUND(7, 1, ecx, eax, edx, edi)
746  ROUND(8, 1, eax, ecx, edi, edx)
747  ROUND(9, 1, ecx, eax, edx, edi)
748  ROUND(10, 1, eax, ecx, edi, edx)
749  ROUND(11, 1, ecx, eax, edx, edi)
750  ROUND(12, 1, eax, ecx, edi, edx)
751  ROUND(13, 1, ecx, eax, edx, edi)
752  ROUND(14, 1, eax, ecx, edi, edx)
753  ROUND(15, 1, ecx, eax, edx, edi)
754  AS2( cmp WORD_REG(si), K_END)
755  ATT_NOPREFIX
756  ASJ( jb, 1, b)
757  INTEL_NOPREFIX
758 
759  AS2( mov WORD_REG(dx), DATA_SAVE)
760  AS2( add WORD_REG(dx), 64)
761  AS2( mov AS_REG_7, STATE_SAVE)
762  AS2( mov DATA_SAVE, WORD_REG(dx))
763 
764 #if CRYPTOPP_SSE2_ASM_AVAILABLE
766  AS2( test DWORD PTR K_END, 1)
767  ASJ( jz, 4, f)
768 #endif
769  AS2( movdqu xmm1, XMMWORD_PTR [AS_REG_7+1*16])
770  AS2( movdqu xmm0, XMMWORD_PTR [AS_REG_7+0*16])
771  AS2( paddd xmm1, E(0))
772  AS2( paddd xmm0, A(0))
773  AS2( movdqu [AS_REG_7+1*16], xmm1)
774  AS2( movdqu [AS_REG_7+0*16], xmm0)
775  AS2( cmp WORD_REG(dx), DATA_END)
776  ATT_NOPREFIX
777  ASJ( jb, 0, b)
778  INTEL_NOPREFIX
779 #endif
780 
782 #if CRYPTOPP_SSE2_ASM_AVAILABLE
783  ASJ( jmp, 5, f)
784  ASL(4) // non-SSE2
785 #endif
786  AS2( add [AS_REG_7+0*4], ecx) // A
787  AS2( add [AS_REG_7+4*4], edi) // E
788  AS2( mov eax, B(0))
789  AS2( mov ebx, C(0))
790  AS2( mov ecx, D(0))
791  AS2( add [AS_REG_7+1*4], eax)
792  AS2( add [AS_REG_7+2*4], ebx)
793  AS2( add [AS_REG_7+3*4], ecx)
794  AS2( mov eax, F(0))
795  AS2( mov ebx, G(0))
796  AS2( mov ecx, H(0))
797  AS2( add [AS_REG_7+5*4], eax)
798  AS2( add [AS_REG_7+6*4], ebx)
799  AS2( add [AS_REG_7+7*4], ecx)
800  AS2( mov ecx, AS_REG_7d)
801  AS2( cmp WORD_REG(dx), DATA_END)
802  ASJ( jb, 2, b)
803 #if CRYPTOPP_SSE2_ASM_AVAILABLE
804  ASL(5)
805 #endif
806 #endif
807 
808  AS_POP_IF86(sp)
809  AS_POP_IF86(bp)
810  #if !defined(CRYPTOPP_MSC_VERSION) || (CRYPTOPP_MSC_VERSION < 1400)
811  AS_POP_IF86(bx)
812  #endif
813 
814 #ifdef CRYPTOPP_GENERATE_X64_MASM
815  add rsp, LOCALS_SIZE+8
816  pop rbp
817  pop rbx
818  pop rdi
819  pop rsi
820  ret
821  SHA256_HashMultipleBlocks_SSE2 ENDP
822 #endif
823 
824 #ifdef __GNUC__
825  ATT_PREFIX
826  :
827  : "c" (state), "d" (data), "S" (SHA256_K+48), "D" (len)
829  , "m" (workspace[0])
830  #endif
831  : "memory", "cc", "%eax"
833  , PERCENT_REG(AS_REG_7), "%rbx", "%r8", "%r10", "%xmm0", "%xmm1"
834  #else
835  , "%ebx"
836  #endif
837  );
838 #endif
839 }
840 
841 ANONYMOUS_NAMESPACE_END
842 
843 #endif // CRYPTOPP_X86_ASM_AVAILABLE
844 
845 #ifndef CRYPTOPP_GENERATE_X64_MASM
846 
847 #ifdef CRYPTOPP_X64_MASM_AVAILABLE
848 extern "C" {
849 void CRYPTOPP_FASTCALL SHA256_HashMultipleBlocks_SSE2(word32 *state, const word32 *data, size_t len);
850 }
851 #endif
852 
853 std::string SHA256::AlgorithmProvider() const
854 {
855  return SHA256_AlgorithmProvider();
856 }
857 
858 void SHA256::Transform(word32 *state, const word32 *data)
859 {
860  CRYPTOPP_ASSERT(state);
861  CRYPTOPP_ASSERT(data);
862 
863 #if CRYPTOPP_SHANI_AVAILABLE
864  if (HasSHA())
865  {
866  SHA256_HashMultipleBlocks_SHANI(state, data, SHA256::BLOCKSIZE, LITTLE_ENDIAN_ORDER);
867  return;
868  }
869 #endif
870 // Disabled at the moment due to MDC and SEAL failures
871 #if CRYPTOGAMS_ARM_SHA256 && 0
872 # if CRYPTOPP_ARM_NEON_AVAILABLE
873  if (HasNEON())
874  {
875 # if defined(CRYPTOPP_LITTLE_ENDIAN)
876  word32 dataBuf[16];
877  ByteReverse(dataBuf, data, SHA256::BLOCKSIZE);
878  cryptogams_sha256_block_data_order_neon(state, dataBuf, 1);
879 # else
880  cryptogams_sha256_block_data_order_neon(state, data, 1);
881 # endif
882  return;
883  }
884  else
885 # endif
886  if (HasARMv7())
887  {
888 # if defined(CRYPTOPP_LITTLE_ENDIAN)
889  word32 dataBuf[16];
890  ByteReverse(dataBuf, data, SHA256::BLOCKSIZE);
891  cryptogams_sha256_block_data_order(state, data, 1);
892 # else
893  cryptogams_sha256_block_data_order(state, data, 1);
894 # endif
895  return;
896  }
897 #endif
898 #if CRYPTOPP_ARM_SHA2_AVAILABLE
899  if (HasSHA2())
900  {
901  SHA256_HashMultipleBlocks_ARMV8(state, data, SHA256::BLOCKSIZE, LITTLE_ENDIAN_ORDER);
902  return;
903  }
904 #endif
905 #if CRYPTOPP_POWER8_SHA_AVAILABLE
906  if (HasSHA256())
907  {
908  SHA256_HashMultipleBlocks_POWER8(state, data, SHA256::BLOCKSIZE, LITTLE_ENDIAN_ORDER);
909  return;
910  }
911 #endif
912 
913  SHA256_HashBlock_CXX(state, data);
914 }
915 
916 size_t SHA256::HashMultipleBlocks(const word32 *input, size_t length)
917 {
918  CRYPTOPP_ASSERT(input);
919  CRYPTOPP_ASSERT(length >= SHA256::BLOCKSIZE);
920 
921 #if CRYPTOPP_SHANI_AVAILABLE
922  if (HasSHA())
923  {
924  SHA256_HashMultipleBlocks_SHANI(m_state, input, length, BIG_ENDIAN_ORDER);
925  return length & (SHA256::BLOCKSIZE - 1);
926  }
927 #endif
928 #if CRYPTOPP_SSE2_ASM_AVAILABLE || CRYPTOPP_X64_MASM_AVAILABLE
929  if (HasSSE2())
930  {
931  const size_t res = length & (SHA256::BLOCKSIZE - 1);
932  SHA256_HashMultipleBlocks_SSE2(m_state, input, length-res);
933  return res;
934  }
935 #endif
936 #if CRYPTOGAMS_ARM_SHA256
937 # if CRYPTOPP_ARM_NEON_AVAILABLE
938  if (HasNEON())
939  {
940  cryptogams_sha256_block_data_order_neon(m_state, input, length / SHA256::BLOCKSIZE);
941  return length & (SHA256::BLOCKSIZE - 1);
942  }
943  else
944 # endif
945  if (HasARMv7())
946  {
947  cryptogams_sha256_block_data_order(m_state, input, length / SHA256::BLOCKSIZE);
948  return length & (SHA256::BLOCKSIZE - 1);
949  }
950 #endif
951 #if CRYPTOPP_ARM_SHA2_AVAILABLE
952  if (HasSHA2())
953  {
954  SHA256_HashMultipleBlocks_ARMV8(m_state, input, length, BIG_ENDIAN_ORDER);
955  return length & (SHA256::BLOCKSIZE - 1);
956  }
957 #endif
958 #if CRYPTOPP_POWER8_SHA_AVAILABLE
959  if (HasSHA256())
960  {
961  SHA256_HashMultipleBlocks_POWER8(m_state, input, length, BIG_ENDIAN_ORDER);
962  return length & (SHA256::BLOCKSIZE - 1);
963  }
964 #endif
965 
966  const bool noReverse = NativeByteOrderIs(this->GetByteOrder());
967  word32 *dataBuf = this->DataBuf();
968  do
969  {
970  if (noReverse)
971  {
972  SHA256_HashBlock_CXX(m_state, input);
973  }
974  else
975  {
976  ByteReverse(dataBuf, input, SHA256::BLOCKSIZE);
977  SHA256_HashBlock_CXX(m_state, dataBuf);
978  }
979 
980  input += SHA256::BLOCKSIZE/sizeof(word32);
981  length -= SHA256::BLOCKSIZE;
982  }
983  while (length >= SHA256::BLOCKSIZE);
984  return length;
985 }
986 
987 size_t SHA224::HashMultipleBlocks(const word32 *input, size_t length)
988 {
989  CRYPTOPP_ASSERT(input);
990  CRYPTOPP_ASSERT(length >= SHA256::BLOCKSIZE);
991 
992 #if CRYPTOPP_SHANI_AVAILABLE
993  if (HasSHA())
994  {
995  SHA256_HashMultipleBlocks_SHANI(m_state, input, length, BIG_ENDIAN_ORDER);
996  return length & (SHA256::BLOCKSIZE - 1);
997  }
998 #endif
999 #if CRYPTOPP_SSE2_ASM_AVAILABLE || CRYPTOPP_X64_MASM_AVAILABLE
1000  if (HasSSE2())
1001  {
1002  const size_t res = length & (SHA256::BLOCKSIZE - 1);
1003  SHA256_HashMultipleBlocks_SSE2(m_state, input, length-res);
1004  return res;
1005  }
1006 #endif
1007 #if CRYPTOGAMS_ARM_SHA256
1008 # if CRYPTOPP_ARM_NEON_AVAILABLE
1009  if (HasNEON())
1010  {
1011  cryptogams_sha256_block_data_order_neon(m_state, input, length / SHA256::BLOCKSIZE);
1012  return length & (SHA256::BLOCKSIZE - 1);
1013  }
1014  else
1015 # endif
1016  if (HasARMv7())
1017  {
1018  cryptogams_sha256_block_data_order(m_state, input, length / SHA256::BLOCKSIZE);
1019  return length & (SHA256::BLOCKSIZE - 1);
1020  }
1021 #endif
1022 #if CRYPTOPP_ARM_SHA2_AVAILABLE
1023  if (HasSHA2())
1024  {
1025  SHA256_HashMultipleBlocks_ARMV8(m_state, input, length, BIG_ENDIAN_ORDER);
1026  return length & (SHA256::BLOCKSIZE - 1);
1027  }
1028 #endif
1029 #if CRYPTOPP_POWER8_SHA_AVAILABLE
1030  if (HasSHA256())
1031  {
1032  SHA256_HashMultipleBlocks_POWER8(m_state, input, length, BIG_ENDIAN_ORDER);
1033  return length & (SHA256::BLOCKSIZE - 1);
1034  }
1035 #endif
1036 
1037  const bool noReverse = NativeByteOrderIs(this->GetByteOrder());
1038  word32 *dataBuf = this->DataBuf();
1039  do
1040  {
1041  if (noReverse)
1042  {
1043  SHA256_HashBlock_CXX(m_state, input);
1044  }
1045  else
1046  {
1047  ByteReverse(dataBuf, input, SHA256::BLOCKSIZE);
1048  SHA256_HashBlock_CXX(m_state, dataBuf);
1049  }
1050 
1051  input += SHA256::BLOCKSIZE/sizeof(word32);
1052  length -= SHA256::BLOCKSIZE;
1053  }
1054  while (length >= SHA256::BLOCKSIZE);
1055  return length;
1056 }
1057 
1058 // *************************************************************
1059 
1060 std::string SHA512_AlgorithmProvider()
1061 {
1062 #if CRYPTOPP_SSE2_ASM_AVAILABLE
1063  if (HasSSE2())
1064  return "SSE2";
1065 #endif
1066 #if CRYPTOGAMS_ARM_SHA512
1067 # if CRYPTOPP_ARM_NEON_AVAILABLE
1068  if (HasNEON())
1069  return "NEON";
1070  else
1071 # endif
1072  if (HasARMv7())
1073  return "ARMv7";
1074 #endif
1075 #if (CRYPTOPP_POWER8_SHA_AVAILABLE)
1076  if (HasSHA512())
1077  return "Power8";
1078 #endif
1079  return "C++";
1080 }
1081 
1082 std::string SHA384::AlgorithmProvider() const
1083 {
1084  return SHA512_AlgorithmProvider();
1085 }
1086 
1087 std::string SHA512::AlgorithmProvider() const
1088 {
1089  return SHA512_AlgorithmProvider();
1090 }
1091 
1092 void SHA384::InitState(HashWordType *state)
1093 {
1094  const word64 s[8] = {
1095  W64LIT(0xcbbb9d5dc1059ed8), W64LIT(0x629a292a367cd507),
1096  W64LIT(0x9159015a3070dd17), W64LIT(0x152fecd8f70e5939),
1097  W64LIT(0x67332667ffc00b31), W64LIT(0x8eb44a8768581511),
1098  W64LIT(0xdb0c2e0d64f98fa7), W64LIT(0x47b5481dbefa4fa4)};
1099  std::memcpy(state, s, sizeof(s));
1100 }
1101 
1102 void SHA512::InitState(HashWordType *state)
1103 {
1104  const word64 s[8] = {
1105  W64LIT(0x6a09e667f3bcc908), W64LIT(0xbb67ae8584caa73b),
1106  W64LIT(0x3c6ef372fe94f82b), W64LIT(0xa54ff53a5f1d36f1),
1107  W64LIT(0x510e527fade682d1), W64LIT(0x9b05688c2b3e6c1f),
1108  W64LIT(0x1f83d9abfb41bd6b), W64LIT(0x5be0cd19137e2179)};
1109  std::memcpy(state, s, sizeof(s));
1110 }
1111 
1112 #if CRYPTOPP_SSE2_ASM_AVAILABLE && (CRYPTOPP_BOOL_X86)
1113 
1114 ANONYMOUS_NAMESPACE_BEGIN
1115 
1116 // No inlining due to https://github.com/weidai11/cryptopp/issues/684
1117 // g++ -DNDEBUG -g2 -O3 -pthread -pipe -c sha.cpp
1118 // sha.cpp: Assembler messages:
1119 // sha.cpp:1155: Error: symbol `SHA512_Round' is already defined
1120 // sha.cpp:1155: Error: symbol `SHA512_Round' is already defined
1121 
1122 CRYPTOPP_NOINLINE CRYPTOPP_NAKED
1123 void CRYPTOPP_FASTCALL SHA512_HashBlock_SSE2(word64 *state, const word64 *data)
1124 {
1125 #ifdef __GNUC__
1126  __asm__ __volatile__
1127  (
1128  INTEL_NOPREFIX
1129  AS_PUSH_IF86( bx)
1130  AS2( mov ebx, eax)
1131 #else
1132  AS1( push ebx)
1133  AS1( push esi)
1134  AS1( push edi)
1135  AS2( lea ebx, SHA512_K)
1136 #endif
1137 
1138  AS2( mov eax, esp)
1139  AS2( and esp, 0xfffffff0)
1140  AS2( sub esp, 27*16) // 17*16 for expanded data, 20*8 for state
1141  AS_PUSH_IF86( ax)
1142  AS2( xor eax, eax)
1143 
1144  AS2( lea edi, [esp+4+8*8]) // start at middle of state buffer. will decrement pointer each round to avoid copying
1145  AS2( lea esi, [esp+4+20*8+8]) // 16-byte alignment, then add 8
1146 
1147  AS2( movdqu xmm0, [ecx+0*16])
1148  AS2( movdq2q mm4, xmm0)
1149  AS2( movdqu [edi+0*16], xmm0)
1150  AS2( movdqu xmm0, [ecx+1*16])
1151  AS2( movdqu [edi+1*16], xmm0)
1152  AS2( movdqu xmm0, [ecx+2*16])
1153  AS2( movdq2q mm5, xmm0)
1154  AS2( movdqu [edi+2*16], xmm0)
1155  AS2( movdqu xmm0, [ecx+3*16])
1156  AS2( movdqu [edi+3*16], xmm0)
1157  ASJ( jmp, 0, f)
1158 
1159 #define SSE2_S0_S1(r, a, b, c) \
1160  AS2( movq mm6, r)\
1161  AS2( psrlq r, a)\
1162  AS2( movq mm7, r)\
1163  AS2( psllq mm6, 64-c)\
1164  AS2( pxor mm7, mm6)\
1165  AS2( psrlq r, b-a)\
1166  AS2( pxor mm7, r)\
1167  AS2( psllq mm6, c-b)\
1168  AS2( pxor mm7, mm6)\
1169  AS2( psrlq r, c-b)\
1170  AS2( pxor r, mm7)\
1171  AS2( psllq mm6, b-a)\
1172  AS2( pxor r, mm6)
1173 
1174 #define SSE2_s0(r, a, b, c) \
1175  AS2( movdqu xmm6, r)\
1176  AS2( psrlq r, a)\
1177  AS2( movdqu xmm7, r)\
1178  AS2( psllq xmm6, 64-c)\
1179  AS2( pxor xmm7, xmm6)\
1180  AS2( psrlq r, b-a)\
1181  AS2( pxor xmm7, r)\
1182  AS2( psrlq r, c-b)\
1183  AS2( pxor r, xmm7)\
1184  AS2( psllq xmm6, c-a)\
1185  AS2( pxor r, xmm6)
1186 
1187 #define SSE2_s1(r, a, b, c) \
1188  AS2( movdqu xmm6, r)\
1189  AS2( psrlq r, a)\
1190  AS2( movdqu xmm7, r)\
1191  AS2( psllq xmm6, 64-c)\
1192  AS2( pxor xmm7, xmm6)\
1193  AS2( psrlq r, b-a)\
1194  AS2( pxor xmm7, r)\
1195  AS2( psllq xmm6, c-b)\
1196  AS2( pxor xmm7, xmm6)\
1197  AS2( psrlq r, c-b)\
1198  AS2( pxor r, xmm7)
1199  ASL(SHA512_Round)
1200 
1201  // k + w is in mm0, a is in mm4, e is in mm5
1202  AS2( paddq mm0, [edi+7*8]) // h
1203  AS2( movq mm2, [edi+5*8]) // f
1204  AS2( movq mm3, [edi+6*8]) // g
1205  AS2( pxor mm2, mm3)
1206  AS2( pand mm2, mm5)
1207  SSE2_S0_S1(mm5,14,18,41)
1208  AS2( pxor mm2, mm3)
1209  AS2( paddq mm0, mm2) // h += Ch(e,f,g)
1210  AS2( paddq mm5, mm0) // h += S1(e)
1211  AS2( movq mm2, [edi+1*8]) // b
1212  AS2( movq mm1, mm2)
1213  AS2( por mm2, mm4)
1214  AS2( pand mm2, [edi+2*8]) // c
1215  AS2( pand mm1, mm4)
1216  AS2( por mm1, mm2)
1217  AS2( paddq mm1, mm5) // temp = h + Maj(a,b,c)
1218  AS2( paddq mm5, [edi+3*8]) // e = d + h
1219  AS2( movq [edi+3*8], mm5)
1220  AS2( movq [edi+11*8], mm5)
1221  SSE2_S0_S1(mm4,28,34,39) // S0(a)
1222  AS2( paddq mm4, mm1) // a = temp + S0(a)
1223  AS2( movq [edi-8], mm4)
1224  AS2( movq [edi+7*8], mm4)
1225  AS1( ret)
1226 
1227  // first 16 rounds
1228  ASL(0)
1229  AS2( movq mm0, [edx+eax*8])
1230  AS2( movq [esi+eax*8], mm0)
1231  AS2( movq [esi+eax*8+16*8], mm0)
1232  AS2( paddq mm0, [ebx+eax*8])
1233  ASC( call, SHA512_Round)
1234 
1235  AS1( inc eax)
1236  AS2( sub edi, 8)
1237  AS2( test eax, 7)
1238  ASJ( jnz, 0, b)
1239  AS2( add edi, 8*8)
1240  AS2( cmp eax, 16)
1241  ASJ( jne, 0, b)
1242 
1243  // rest of the rounds
1244  AS2( movdqu xmm0, [esi+(16-2)*8])
1245  ASL(1)
1246  // data expansion, W[i-2] already in xmm0
1247  AS2( movdqu xmm3, [esi])
1248  AS2( paddq xmm3, [esi+(16-7)*8])
1249  AS2( movdqu xmm2, [esi+(16-15)*8])
1250  SSE2_s1(xmm0, 6, 19, 61)
1251  AS2( paddq xmm0, xmm3)
1252  SSE2_s0(xmm2, 1, 7, 8)
1253  AS2( paddq xmm0, xmm2)
1254  AS2( movdq2q mm0, xmm0)
1255  AS2( movhlps xmm1, xmm0)
1256  AS2( paddq mm0, [ebx+eax*8])
1257  AS2( movlps [esi], xmm0)
1258  AS2( movlps [esi+8], xmm1)
1259  AS2( movlps [esi+8*16], xmm0)
1260  AS2( movlps [esi+8*17], xmm1)
1261  // 2 rounds
1262  ASC( call, SHA512_Round)
1263  AS2( sub edi, 8)
1264  AS2( movdq2q mm0, xmm1)
1265  AS2( paddq mm0, [ebx+eax*8+8])
1266  ASC( call, SHA512_Round)
1267  // update indices and loop
1268  AS2( add esi, 16)
1269  AS2( add eax, 2)
1270  AS2( sub edi, 8)
1271  AS2( test eax, 7)
1272  ASJ( jnz, 1, b)
1273  // do housekeeping every 8 rounds
1274  AS2( mov esi, 0xf)
1275  AS2( and esi, eax)
1276  AS2( lea esi, [esp+4+20*8+8+esi*8])
1277  AS2( add edi, 8*8)
1278  AS2( cmp eax, 80)
1279  ASJ( jne, 1, b)
1280 
1281 #define SSE2_CombineState(i) \
1282  AS2( movdqu xmm0, [edi+i*16])\
1283  AS2( paddq xmm0, [ecx+i*16])\
1284  AS2( movdqu [ecx+i*16], xmm0)
1285 
1286  SSE2_CombineState(0)
1287  SSE2_CombineState(1)
1288  SSE2_CombineState(2)
1289  SSE2_CombineState(3)
1290 
1291  AS_POP_IF86( sp)
1292  AS1( emms)
1293 
1294 #if defined(__GNUC__)
1295  AS_POP_IF86( bx)
1296  ATT_PREFIX
1297  :
1298  : "a" (SHA512_K), "c" (state), "d" (data)
1299  : "%ebx", "%esi", "%edi", "memory", "cc"
1300 #if (CRYPTOPP_BOOL_X64)
1301  , "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5",
1302  "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7"
1303 #endif
1304  );
1305 #else
1306  AS1( pop edi)
1307  AS1( pop esi)
1308  AS1( pop ebx)
1309  AS1( ret)
1310 #endif
1311 }
1312 
1313 ANONYMOUS_NAMESPACE_END
1314 
1315 #endif // CRYPTOPP_SSE2_ASM_AVAILABLE
1316 
1317 ANONYMOUS_NAMESPACE_BEGIN
1318 
1319 #define a(i) T[(0-i)&7]
1320 #define b(i) T[(1-i)&7]
1321 #define c(i) T[(2-i)&7]
1322 #define d(i) T[(3-i)&7]
1323 #define e(i) T[(4-i)&7]
1324 #define f(i) T[(5-i)&7]
1325 #define g(i) T[(6-i)&7]
1326 #define h(i) T[(7-i)&7]
1327 
1328 #define blk0(i) (W[i]=data[i])
1329 #define blk2(i) (W[i&15]+=s1(W[(i-2)&15])+W[(i-7)&15]+s0(W[(i-15)&15]))
1330 
1331 #define Ch(x,y,z) (z^(x&(y^z)))
1332 #define Maj(x,y,z) (y^((x^y)&(y^z)))
1333 
1334 #define s0(x) (rotrConstant<1>(x)^rotrConstant<8>(x)^(x>>7))
1335 #define s1(x) (rotrConstant<19>(x)^rotrConstant<61>(x)^(x>>6))
1336 #define S0(x) (rotrConstant<28>(x)^rotrConstant<34>(x)^rotrConstant<39>(x))
1337 #define S1(x) (rotrConstant<14>(x)^rotrConstant<18>(x)^rotrConstant<41>(x))
1338 
1339 #define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+SHA512_K[i+j]+\
1340  (j?blk2(i):blk0(i));d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i));
1341 
1342 void SHA512_HashBlock_CXX(word64 *state, const word64 *data)
1343 {
1344  CRYPTOPP_ASSERT(state);
1345  CRYPTOPP_ASSERT(data);
1346 
1347  word64 W[16]={0}, T[8];
1348 
1349  /* Copy context->state[] to working vars */
1350  std::memcpy(T, state, sizeof(T));
1351 
1352  /* 80 operations, partially loop unrolled */
1353  for (unsigned int j=0; j<80; j+=16)
1354  {
1355  R( 0); R( 1); R( 2); R( 3);
1356  R( 4); R( 5); R( 6); R( 7);
1357  R( 8); R( 9); R(10); R(11);
1358  R(12); R(13); R(14); R(15);
1359  }
1360 
1361  state[0] += a(0);
1362  state[1] += b(0);
1363  state[2] += c(0);
1364  state[3] += d(0);
1365  state[4] += e(0);
1366  state[5] += f(0);
1367  state[6] += g(0);
1368  state[7] += h(0);
1369 }
1370 
1371 ANONYMOUS_NAMESPACE_END
1372 
1373 void SHA512::Transform(word64 *state, const word64 *data)
1374 {
1375  CRYPTOPP_ASSERT(state);
1376  CRYPTOPP_ASSERT(data);
1377 
1378 #if CRYPTOPP_SSE2_ASM_AVAILABLE && (CRYPTOPP_BOOL_X86)
1379  if (HasSSE2())
1380  {
1381  SHA512_HashBlock_SSE2(state, data);
1382  return;
1383  }
1384 #endif
1385 #if CRYPTOGAMS_ARM_SHA512
1386 # if CRYPTOPP_ARM_NEON_AVAILABLE
1387  if (HasNEON())
1388  {
1389 # if (CRYPTOPP_LITTLE_ENDIAN)
1390  word64 dataBuf[16];
1391  ByteReverse(dataBuf, data, SHA512::BLOCKSIZE);
1392  cryptogams_sha512_block_data_order_neon(state, dataBuf, 1);
1393 # else
1394  cryptogams_sha512_block_data_order_neon(state, data, 1);
1395 # endif
1396  return;
1397  }
1398  else
1399 # endif
1400  if (HasARMv7())
1401  {
1402 # if (CRYPTOPP_LITTLE_ENDIAN)
1403  word64 dataBuf[16];
1404  ByteReverse(dataBuf, data, SHA512::BLOCKSIZE);
1405  cryptogams_sha512_block_data_order(state, dataBuf, 1);
1406 # else
1407  cryptogams_sha512_block_data_order(state, data, 1);
1408 # endif
1409  return;
1410  }
1411 #endif
1412 #if CRYPTOPP_POWER8_SHA_AVAILABLE
1413  if (HasSHA512())
1414  {
1415  SHA512_HashMultipleBlocks_POWER8(state, data, SHA512::BLOCKSIZE, BIG_ENDIAN_ORDER);
1416  return;
1417  }
1418 #endif
1419 
1420  SHA512_HashBlock_CXX(state, data);
1421 }
1422 
1423 #undef Ch
1424 #undef Maj
1425 
1426 #undef s0
1427 #undef s1
1428 #undef S0
1429 #undef S1
1430 
1431 #undef blk0
1432 #undef blk1
1433 #undef blk2
1434 
1435 #undef R
1436 
1437 #undef a
1438 #undef b
1439 #undef c
1440 #undef d
1441 #undef e
1442 #undef f
1443 #undef g
1444 #undef h
1445 
1446 NAMESPACE_END
1447 
1448 #endif // Not CRYPTOPP_GENERATE_X64_MASM
1449 #endif // Not CRYPTOPP_IMPORTS
Fixed size stack-based SecBlock with 16-byte alignment.
Definition: secblock.h:1259
static void Transform(HashWordType *digest, const HashWordType *data)
Operate the hash.
static void InitState(HashWordType *state)
Initialize state array.
static void InitState(HashWordType *state)
Initialize state array.
static void InitState(HashWordType *state)
Initialize state array.
static void Transform(HashWordType *digest, const HashWordType *data)
Operate the hash.
static void InitState(HashWordType *state)
Initialize state array.
static void Transform(HashWordType *digest, const HashWordType *data)
Operate the hash.
static void InitState(HashWordType *state)
Initialize state array.
Library configuration file.
#define CRYPTOPP_BOOL_X86
32-bit x86 platform
Definition: config_cpu.h:52
#define CRYPTOPP_BOOL_X32
32-bit x32 platform
Definition: config_cpu.h:44
#define CRYPTOPP_BOOL_X64
32-bit x86 platform
Definition: config_cpu.h:48
#define W64LIT(x)
Declare an unsigned word64.
Definition: config_int.h:129
unsigned int word32
32-bit unsigned datatype
Definition: config_int.h:72
unsigned long long word64
64-bit unsigned datatype
Definition: config_int.h:101
Functions for CPU features and intrinsics.
ByteOrder
Provides the byte ordering.
Definition: cryptlib.h:148
@ LITTLE_ENDIAN_ORDER
byte order is little-endian
Definition: cryptlib.h:150
@ BIG_ENDIAN_ORDER
byte order is big-endian
Definition: cryptlib.h:152
Utility functions for the Crypto++ library.
byte ByteReverse(byte value)
Reverses bytes in a 8-bit value.
Definition: misc.h:2231
bool NativeByteOrderIs(ByteOrder order)
Determines whether order follows native byte ordering.
Definition: misc.h:1481
Crypto++ library namespace.
Precompiled header file.
Classes and functions for secure memory allocations.
Classes for SHA-1 and SHA-2 family of message digests.
#define CRYPTOPP_ASSERT(exp)
Debugging and diagnostic assertion.
Definition: trap.h:68