Crypto++ 8.7
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: 4100 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
62NAMESPACE_BEGIN(CryptoPP)
63
64#if CRYPTOPP_SHANI_AVAILABLE
65extern void SHA1_HashMultipleBlocks_SHANI(word32 *state, const word32 *data, size_t length, ByteOrder order);
66extern void SHA256_HashMultipleBlocks_SHANI(word32 *state, const word32 *data, size_t length, ByteOrder order);
67#endif
68
69#if CRYPTOGAMS_ARM_SHA1
70extern "C" void cryptogams_sha1_block_data_order(word32* state, const word32 *data, size_t blocks);
71extern "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
75extern void SHA1_HashMultipleBlocks_ARMV8(word32 *state, const word32 *data, size_t length, ByteOrder order);
76#endif
77
78#if CRYPTOPP_ARM_SHA2_AVAILABLE
79extern void SHA256_HashMultipleBlocks_ARMV8(word32 *state, const word32 *data, size_t length, ByteOrder order);
80#endif
81
82#if CRYPTOGAMS_ARM_SHA256
83extern "C" void cryptogams_sha256_block_data_order(word32* state, const word32 *data, size_t blocks);
84extern "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
88extern void SHA512_HashMultipleBlocks_ARMV8(word32 *state, const word32 *data, size_t length, ByteOrder order);
89#endif
90
91#if CRYPTOPP_POWER8_SHA_AVAILABLE
92extern void SHA256_HashMultipleBlocks_POWER8(word32 *state, const word32 *data, size_t length, ByteOrder order);
93extern void SHA512_HashMultipleBlocks_POWER8(word64 *state, const word64 *data, size_t length, ByteOrder order);
94#endif
95
96#if CRYPTOGAMS_ARM_SHA512
97extern "C" void cryptogams_sha512_block_data_order(word64* state, const word64 *data, size_t blocks);
98extern "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
103extern const word32 SHA256_K[64];
104extern const word64 SHA512_K[80];
105
106CRYPTOPP_ALIGN_DATA(16)
107const 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
150CRYPTOPP_ALIGN_DATA(16)
151const 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
175ANONYMOUS_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
192void 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
244ANONYMOUS_NAMESPACE_END
245
246//////////////////////////////
247// end of Steve Reid's code //
248//////////////////////////////
249
250std::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
276void 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
285void 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
336size_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
394ANONYMOUS_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
420void SHA256_HashBlock_CXX(word32 *state, const word32 *data)
421{
422 word32 W[16]={0}, T[8];
423 /* Copy context->state[] to working vars */
424 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
464ANONYMOUS_NAMESPACE_END
465
466std::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
496std::string SHA224::AlgorithmProvider() const
497{
498 return SHA256_AlgorithmProvider();
499}
500
501void SHA224::InitState(HashWordType *state)
502{
503 static const word32 s[8] = {
504 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
505 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4};
506 memcpy(state, s, sizeof(s));
507}
508
509void SHA256::InitState(HashWordType *state)
510{
511 static const word32 s[8] = {
512 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
513 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
514 memcpy(state, s, sizeof(s));
515}
516#endif // Not CRYPTOPP_GENERATE_X64_MASM
517
518#if defined(CRYPTOPP_X86_ASM_AVAILABLE)
519
520ANONYMOUS_NAMESPACE_BEGIN
521
522void 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(_MSC_VER) || (_MSC_VER < 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)
692ATT_NOPREFIX
693 AS1( rep movsd)
694INTEL_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(_MSC_VER) || (_MSC_VER < 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
841ANONYMOUS_NAMESPACE_END
842
843#endif // CRYPTOPP_X86_ASM_AVAILABLE
844
845#ifndef CRYPTOPP_GENERATE_X64_MASM
846
847#ifdef CRYPTOPP_X64_MASM_AVAILABLE
848extern "C" {
849void CRYPTOPP_FASTCALL SHA256_HashMultipleBlocks_SSE2(word32 *state, const word32 *data, size_t len);
850}
851#endif
852
853std::string SHA256::AlgorithmProvider() const
854{
855 return SHA256_AlgorithmProvider();
856}
857
858void 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
916size_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
987size_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
1060std::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
1082std::string SHA384::AlgorithmProvider() const
1083{
1084 return SHA512_AlgorithmProvider();
1085}
1086
1087std::string SHA512::AlgorithmProvider() const
1088{
1089 return SHA512_AlgorithmProvider();
1090}
1091
1092void 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 memcpy(state, s, sizeof(s));
1100}
1101
1102void 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 memcpy(state, s, sizeof(s));
1110}
1111
1112#if CRYPTOPP_SSE2_ASM_AVAILABLE && (CRYPTOPP_BOOL_X86)
1113
1114ANONYMOUS_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
1122CRYPTOPP_NOINLINE CRYPTOPP_NAKED
1123void 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"
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
1313ANONYMOUS_NAMESPACE_END
1314
1315#endif // CRYPTOPP_SSE2_ASM_AVAILABLE
1316
1317ANONYMOUS_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
1342void 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
1371ANONYMOUS_NAMESPACE_END
1372
1373void 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
1446NAMESPACE_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
ByteOrder GetByteOrder() const
Provides the byte order of the hash.
Definition: iterhash.h:147
static void Transform(HashWordType *digest, const HashWordType *data)
Operate the hash.
static void InitState(HashWordType *state)
Initialize state array.
std::string AlgorithmProvider() const
Retrieve the provider of this algorithm.
static void InitState(HashWordType *state)
Initialize state array.
std::string AlgorithmProvider() const
Retrieve the provider of this algorithm.
static void InitState(HashWordType *state)
Initialize state array.
static void Transform(HashWordType *digest, const HashWordType *data)
Operate the hash.
std::string AlgorithmProvider() const
Retrieve the provider of this algorithm.
std::string AlgorithmProvider() const
Retrieve the provider of this algorithm.
static void InitState(HashWordType *state)
Initialize state array.
static void Transform(HashWordType *digest, const HashWordType *data)
Operate the hash.
std::string AlgorithmProvider() const
Retrieve the provider of this algorithm.
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:119
unsigned int word32
32-bit unsigned datatype
Definition: config_int.h:62
unsigned long long word64
64-bit unsigned datatype
Definition: config_int.h:91
Functions for CPU features and intrinsics.
ByteOrder
Provides the byte ordering.
Definition: cryptlib.h:143
@ LITTLE_ENDIAN_ORDER
byte order is little-endian
Definition: cryptlib.h:145
@ BIG_ENDIAN_ORDER
byte order is big-endian
Definition: cryptlib.h:147
Utility functions for the Crypto++ library.
byte ByteReverse(byte value)
Reverses bytes in a 8-bit value.
Definition: misc.h:2022
bool NativeByteOrderIs(ByteOrder order)
Determines whether order follows native byte ordering.
Definition: misc.h:1272
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