upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/sha.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/sha.cpp')
-rw-r--r--src/sha.cpp554
1 files changed, 554 insertions, 0 deletions
diff --git a/src/sha.cpp b/src/sha.cpp
new file mode 100644
index 0000000..e691674
--- /dev/null
+++ b/src/sha.cpp
@@ -0,0 +1,554 @@
1// This file is public domain
2// SHA routines extracted as a standalone file from:
3// Crypto++: a C++ Class Library of Cryptographic Schemes
4// Version 5.5.2 (9/24/2007)
5// http://www.cryptopp.com
6
7// sha.cpp - modified by Wei Dai from Steve Reid's public domain sha1.c
8
9// Steve Reid implemented SHA-1. Wei Dai implemented SHA-2.
10// Both are in the public domain.
11
12#include <assert.h>
13#include <memory.h>
14#include "sha.h"
15
16namespace CryptoPP
17{
18
19// start of Steve Reid's code
20
21#define blk0(i) (W[i] = data[i])
22#define blk1(i) (W[i&15] = rotlFixed(W[(i+13)&15]^W[(i+8)&15]^W[(i+2)&15]^W[i&15],1))
23
24void SHA1::InitState(HashWordType *state)
25{
26 state[0] = 0x67452301L;
27 state[1] = 0xEFCDAB89L;
28 state[2] = 0x98BADCFEL;
29 state[3] = 0x10325476L;
30 state[4] = 0xC3D2E1F0L;
31}
32
33#define f1(x,y,z) (z^(x&(y^z)))
34#define f2(x,y,z) (x^y^z)
35#define f3(x,y,z) ((x&y)|(z&(x|y)))
36#define f4(x,y,z) (x^y^z)
37
38/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
39#define R0(v,w,x,y,z,i) z+=f1(w,x,y)+blk0(i)+0x5A827999+rotlFixed(v,5);w=rotlFixed(w,30);
40#define R1(v,w,x,y,z,i) z+=f1(w,x,y)+blk1(i)+0x5A827999+rotlFixed(v,5);w=rotlFixed(w,30);
41#define R2(v,w,x,y,z,i) z+=f2(w,x,y)+blk1(i)+0x6ED9EBA1+rotlFixed(v,5);w=rotlFixed(w,30);
42#define R3(v,w,x,y,z,i) z+=f3(w,x,y)+blk1(i)+0x8F1BBCDC+rotlFixed(v,5);w=rotlFixed(w,30);
43#define R4(v,w,x,y,z,i) z+=f4(w,x,y)+blk1(i)+0xCA62C1D6+rotlFixed(v,5);w=rotlFixed(w,30);
44
45void SHA1::Transform(word32 *state, const word32 *data)
46{
47 word32 W[16];
48 /* Copy context->state[] to working vars */
49 word32 a = state[0];
50 word32 b = state[1];
51 word32 c = state[2];
52 word32 d = state[3];
53 word32 e = state[4];
54 /* 4 rounds of 20 operations each. Loop unrolled. */
55 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);
56 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);
57 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);
58 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);
59 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);
60 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);
61 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);
62 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);
63 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);
64 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);
65 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);
66 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);
67 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);
68 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);
69 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);
70 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);
71 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);
72 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);
73 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);
74 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);
75 /* Add the working vars back into context.state[] */
76 state[0] += a;
77 state[1] += b;
78 state[2] += c;
79 state[3] += d;
80 state[4] += e;
81}
82
83// end of Steve Reid's code
84
85// *************************************************************
86
87void SHA224::InitState(HashWordType *state)
88{
89 static const word32 s[8] = {0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4};
90 memcpy(state, s, sizeof(s));
91}
92
93void SHA256::InitState(HashWordType *state)
94{
95 static const word32 s[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
96 memcpy(state, s, sizeof(s));
97}
98
99static const word32 SHA256_K[64] = {
100 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
101 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
102 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
103 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
104 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
105 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
106 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
107 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
108 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
109 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
110 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
111 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
112 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
113 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
114 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
115 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
116};
117
118#define blk2(i) (W[i&15]+=s1(W[(i-2)&15])+W[(i-7)&15]+s0(W[(i-15)&15]))
119
120#define Ch(x,y,z) (z^(x&(y^z)))
121#define Maj(x,y,z) ((x&y)|(z&(x|y)))
122
123#define a(i) T[(0-i)&7]
124#define b(i) T[(1-i)&7]
125#define c(i) T[(2-i)&7]
126#define d(i) T[(3-i)&7]
127#define e(i) T[(4-i)&7]
128#define f(i) T[(5-i)&7]
129#define g(i) T[(6-i)&7]
130#define h(i) T[(7-i)&7]
131
132#define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+SHA256_K[i+j]+(j?blk2(i):blk0(i));\
133 d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i))
134
135// for SHA256
136#define S0(x) (rotrFixed(x,2)^rotrFixed(x,13)^rotrFixed(x,22))
137#define S1(x) (rotrFixed(x,6)^rotrFixed(x,11)^rotrFixed(x,25))
138#define s0(x) (rotrFixed(x,7)^rotrFixed(x,18)^(x>>3))
139#define s1(x) (rotrFixed(x,17)^rotrFixed(x,19)^(x>>10))
140
141void SHA256::Transform(word32 *state, const word32 *data)
142{
143 word32 W[16];
144 word32 T[8];
145 /* Copy context->state[] to working vars */
146 memcpy(T, state, sizeof(T));
147 /* 64 operations, partially loop unrolled */
148 for (unsigned int j=0; j<64; j+=16)
149 {
150 R( 0); R( 1); R( 2); R( 3);
151 R( 4); R( 5); R( 6); R( 7);
152 R( 8); R( 9); R(10); R(11);
153 R(12); R(13); R(14); R(15);
154 }
155 /* Add the working vars back into context.state[] */
156 state[0] += a(0);
157 state[1] += b(0);
158 state[2] += c(0);
159 state[3] += d(0);
160 state[4] += e(0);
161 state[5] += f(0);
162 state[6] += g(0);
163 state[7] += h(0);
164}
165
166/*
167// smaller but slower
168void SHA256_Transform(word32 *state, const word32 *data)
169{
170 word32 T[20];
171 word32 W[32];
172 unsigned int i = 0, j = 0;
173 word32 *t = T+8;
174
175 memcpy(t, state, 8*4);
176 word32 e = t[4], a = t[0];
177
178 do
179 {
180 word32 w = data[j];
181 W[j] = w;
182 w += K[j];
183 w += t[7];
184 w += S1(e);
185 w += Ch(e, t[5], t[6]);
186 e = t[3] + w;
187 t[3] = t[3+8] = e;
188 w += S0(t[0]);
189 a = w + Maj(a, t[1], t[2]);
190 t[-1] = t[7] = a;
191 --t;
192 ++j;
193 if (j%8 == 0)
194 t += 8;
195 } while (j<16);
196
197 do
198 {
199 i = j&0xf;
200 word32 w = s1(W[i+16-2]) + s0(W[i+16-15]) + W[i] + W[i+16-7];
201 W[i+16] = W[i] = w;
202 w += K[j];
203 w += t[7];
204 w += S1(e);
205 w += Ch(e, t[5], t[6]);
206 e = t[3] + w;
207 t[3] = t[3+8] = e;
208 w += S0(t[0]);
209 a = w + Maj(a, t[1], t[2]);
210 t[-1] = t[7] = a;
211
212 w = s1(W[(i+1)+16-2]) + s0(W[(i+1)+16-15]) + W[(i+1)] + W[(i+1)+16-7];
213 W[(i+1)+16] = W[(i+1)] = w;
214 w += K[j+1];
215 w += (t-1)[7];
216 w += S1(e);
217 w += Ch(e, (t-1)[5], (t-1)[6]);
218 e = (t-1)[3] + w;
219 (t-1)[3] = (t-1)[3+8] = e;
220 w += S0((t-1)[0]);
221 a = w + Maj(a, (t-1)[1], (t-1)[2]);
222 (t-1)[-1] = (t-1)[7] = a;
223
224 t-=2;
225 j+=2;
226 if (j%8 == 0)
227 t += 8;
228 } while (j<64);
229
230 state[0] += a;
231 state[1] += t[1];
232 state[2] += t[2];
233 state[3] += t[3];
234 state[4] += e;
235 state[5] += t[5];
236 state[6] += t[6];
237 state[7] += t[7];
238}
239*/
240
241#undef S0
242#undef S1
243#undef s0
244#undef s1
245#undef R
246
247// *************************************************************
248
249#ifdef WORD64_AVAILABLE
250
251void SHA384::InitState(HashWordType *state)
252{
253 static const word64 s[8] = {
254 W64LIT(0xcbbb9d5dc1059ed8), W64LIT(0x629a292a367cd507),
255 W64LIT(0x9159015a3070dd17), W64LIT(0x152fecd8f70e5939),
256 W64LIT(0x67332667ffc00b31), W64LIT(0x8eb44a8768581511),
257 W64LIT(0xdb0c2e0d64f98fa7), W64LIT(0x47b5481dbefa4fa4)};
258 memcpy(state, s, sizeof(s));
259}
260
261void SHA512::InitState(HashWordType *state)
262{
263 static const word64 s[8] = {
264 W64LIT(0x6a09e667f3bcc908), W64LIT(0xbb67ae8584caa73b),
265 W64LIT(0x3c6ef372fe94f82b), W64LIT(0xa54ff53a5f1d36f1),
266 W64LIT(0x510e527fade682d1), W64LIT(0x9b05688c2b3e6c1f),
267 W64LIT(0x1f83d9abfb41bd6b), W64LIT(0x5be0cd19137e2179)};
268 memcpy(state, s, sizeof(s));
269}
270
271CRYPTOPP_ALIGN_DATA(16) static const word64 SHA512_K[80] CRYPTOPP_SECTION_ALIGN16 = {
272 W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd),
273 W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc),
274 W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019),
275 W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118),
276 W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe),
277 W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2),
278 W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1),
279 W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694),
280 W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3),
281 W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65),
282 W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483),
283 W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5),
284 W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210),
285 W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4),
286 W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725),
287 W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70),
288 W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926),
289 W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df),
290 W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8),
291 W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b),
292 W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001),
293 W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30),
294 W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910),
295 W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8),
296 W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53),
297 W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8),
298 W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb),
299 W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3),
300 W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60),
301 W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec),
302 W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9),
303 W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b),
304 W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207),
305 W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178),
306 W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6),
307 W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b),
308 W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493),
309 W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c),
310 W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a),
311 W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817)
312};
313
314#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86
315// put assembly version in separate function, otherwise MSVC 2005 SP1 doesn't generate correct code for the non-assembly version
316CRYPTOPP_NAKED static void CRYPTOPP_FASTCALL SHA512_SSE2_Transform(word64 *state, const word64 *data)
317{
318#ifdef __GNUC__
319 __asm__ __volatile__
320 (
321 ".intel_syntax noprefix;"
322 AS1( push ebx)
323 AS2( mov ebx, eax)
324#else
325 AS1( push ebx)
326 AS1( push esi)
327 AS1( push edi)
328 AS2( lea ebx, SHA512_K)
329#endif
330
331 AS2( mov eax, esp)
332 AS2( and esp, 0xfffffff0)
333 AS2( sub esp, 27*16) // 17*16 for expanded data, 20*8 for state
334 AS1( push eax)
335 AS2( xor eax, eax)
336 AS2( lea edi, [esp+4+8*8]) // start at middle of state buffer. will decrement pointer each round to avoid copying
337 AS2( lea esi, [esp+4+20*8+8]) // 16-byte alignment, then add 8
338
339 AS2( movq mm4, [ecx+0*8])
340 AS2( movq [edi+0*8], mm4)
341 AS2( movq mm0, [ecx+1*8])
342 AS2( movq [edi+1*8], mm0)
343 AS2( movq mm0, [ecx+2*8])
344 AS2( movq [edi+2*8], mm0)
345 AS2( movq mm0, [ecx+3*8])
346 AS2( movq [edi+3*8], mm0)
347 AS2( movq mm5, [ecx+4*8])
348 AS2( movq [edi+4*8], mm5)
349 AS2( movq mm0, [ecx+5*8])
350 AS2( movq [edi+5*8], mm0)
351 AS2( movq mm0, [ecx+6*8])
352 AS2( movq [edi+6*8], mm0)
353 AS2( movq mm0, [ecx+7*8])
354 AS2( movq [edi+7*8], mm0)
355 ASJ( jmp, 0, f)
356
357#define SSE2_S0_S1(r, a, b, c) \
358 AS2( movq mm6, r)\
359 AS2( psrlq r, a)\
360 AS2( movq mm7, r)\
361 AS2( psllq mm6, 64-c)\
362 AS2( pxor mm7, mm6)\
363 AS2( psrlq r, b-a)\
364 AS2( pxor mm7, r)\
365 AS2( psllq mm6, c-b)\
366 AS2( pxor mm7, mm6)\
367 AS2( psrlq r, c-b)\
368 AS2( pxor r, mm7)\
369 AS2( psllq mm6, b-a)\
370 AS2( pxor r, mm6)
371
372#define SSE2_s0(r, a, b, c) \
373 AS2( movdqa xmm6, r)\
374 AS2( psrlq r, a)\
375 AS2( movdqa xmm7, r)\
376 AS2( psllq xmm6, 64-c)\
377 AS2( pxor xmm7, xmm6)\
378 AS2( psrlq r, b-a)\
379 AS2( pxor xmm7, r)\
380 AS2( psrlq r, c-b)\
381 AS2( pxor r, xmm7)\
382 AS2( psllq xmm6, c-a)\
383 AS2( pxor r, xmm6)
384
385#define SSE2_s1(r, a, b, c) \
386 AS2( movdqa xmm6, r)\
387 AS2( psrlq r, a)\
388 AS2( movdqa xmm7, r)\
389 AS2( psllq xmm6, 64-c)\
390 AS2( pxor xmm7, xmm6)\
391 AS2( psrlq r, b-a)\
392 AS2( pxor xmm7, r)\
393 AS2( psllq xmm6, c-b)\
394 AS2( pxor xmm7, xmm6)\
395 AS2( psrlq r, c-b)\
396 AS2( pxor r, xmm7)
397
398 ASL(SHA512_Round)
399 // k + w is in mm0, a is in mm4, e is in mm5
400 AS2( paddq mm0, [edi+7*8]) // h
401 AS2( movq mm2, [edi+5*8]) // f
402 AS2( movq mm3, [edi+6*8]) // g
403 AS2( pxor mm2, mm3)
404 AS2( pand mm2, mm5)
405 SSE2_S0_S1(mm5,14,18,41)
406 AS2( pxor mm2, mm3)
407 AS2( paddq mm0, mm2) // h += Ch(e,f,g)
408 AS2( paddq mm5, mm0) // h += S1(e)
409 AS2( movq mm2, [edi+1*8]) // b
410 AS2( movq mm1, mm2)
411 AS2( por mm2, mm4)
412 AS2( pand mm2, [edi+2*8]) // c
413 AS2( pand mm1, mm4)
414 AS2( por mm1, mm2)
415 AS2( paddq mm1, mm5) // temp = h + Maj(a,b,c)
416 AS2( paddq mm5, [edi+3*8]) // e = d + h
417 AS2( movq [edi+3*8], mm5)
418 AS2( movq [edi+11*8], mm5)
419 SSE2_S0_S1(mm4,28,34,39) // S0(a)
420 AS2( paddq mm4, mm1) // a = temp + S0(a)
421 AS2( movq [edi-8], mm4)
422 AS2( movq [edi+7*8], mm4)
423 AS1( ret)
424
425 // first 16 rounds
426 ASL(0)
427 AS2( movq mm0, [edx+eax*8])
428 AS2( movq [esi+eax*8], mm0)
429 AS2( movq [esi+eax*8+16*8], mm0)
430 AS2( paddq mm0, [ebx+eax*8])
431 ASC( call, SHA512_Round)
432 AS1( inc eax)
433 AS2( sub edi, 8)
434 AS2( test eax, 7)
435 ASJ( jnz, 0, b)
436 AS2( add edi, 8*8)
437 AS2( cmp eax, 16)
438 ASJ( jne, 0, b)
439
440 // rest of the rounds
441 AS2( movdqu xmm0, [esi+(16-2)*8])
442 ASL(1)
443 // data expansion, W[i-2] already in xmm0
444 AS2( movdqu xmm3, [esi])
445 AS2( paddq xmm3, [esi+(16-7)*8])
446 AS2( movdqa xmm2, [esi+(16-15)*8])
447 SSE2_s1(xmm0, 6, 19, 61)
448 AS2( paddq xmm0, xmm3)
449 SSE2_s0(xmm2, 1, 7, 8)
450 AS2( paddq xmm0, xmm2)
451 AS2( movdq2q mm0, xmm0)
452 AS2( movhlps xmm1, xmm0)
453 AS2( paddq mm0, [ebx+eax*8])
454 AS2( movlps [esi], xmm0)
455 AS2( movlps [esi+8], xmm1)
456 AS2( movlps [esi+8*16], xmm0)
457 AS2( movlps [esi+8*17], xmm1)
458 // 2 rounds
459 ASC( call, SHA512_Round)
460 AS2( sub edi, 8)
461 AS2( movdq2q mm0, xmm1)
462 AS2( paddq mm0, [ebx+eax*8+8])
463 ASC( call, SHA512_Round)
464 // update indices and loop
465 AS2( add esi, 16)
466 AS2( add eax, 2)
467 AS2( sub edi, 8)
468 AS2( test eax, 7)
469 ASJ( jnz, 1, b)
470 // do housekeeping every 8 rounds
471 AS2( mov esi, 0xf)
472 AS2( and esi, eax)
473 AS2( lea esi, [esp+4+20*8+8+esi*8])
474 AS2( add edi, 8*8)
475 AS2( cmp eax, 80)
476 ASJ( jne, 1, b)
477
478#define SSE2_CombineState(i) \
479 AS2( movq mm0, [edi+i*8])\
480 AS2( paddq mm0, [ecx+i*8])\
481 AS2( movq [ecx+i*8], mm0)
482
483 SSE2_CombineState(0)
484 SSE2_CombineState(1)
485 SSE2_CombineState(2)
486 SSE2_CombineState(3)
487 SSE2_CombineState(4)
488 SSE2_CombineState(5)
489 SSE2_CombineState(6)
490 SSE2_CombineState(7)
491
492 AS1( pop esp)
493 AS1( emms)
494
495#if defined(__GNUC__)
496 AS1( pop ebx)
497 ".att_syntax prefix;"
498 :
499 : "a" (SHA512_K), "c" (state), "d" (data)
500 : "%esi", "%edi", "memory", "cc"
501 );
502#else
503 AS1( pop edi)
504 AS1( pop esi)
505 AS1( pop ebx)
506 AS1( ret)
507#endif
508}
509#endif // #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
510
511void SHA512::Transform(word64 *state, const word64 *data)
512{
513#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86
514 if (HasSSE2())
515 {
516 SHA512_SSE2_Transform(state, data);
517 return;
518 }
519#endif
520
521#define S0(x) (rotrFixed(x,28)^rotrFixed(x,34)^rotrFixed(x,39))
522#define S1(x) (rotrFixed(x,14)^rotrFixed(x,18)^rotrFixed(x,41))
523#define s0(x) (rotrFixed(x,1)^rotrFixed(x,8)^(x>>7))
524#define s1(x) (rotrFixed(x,19)^rotrFixed(x,61)^(x>>6))
525
526#define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+SHA512_K[i+j]+(j?blk2(i):blk0(i));\
527 d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i))
528
529 word64 W[16];
530 word64 T[8];
531 /* Copy context->state[] to working vars */
532 memcpy(T, state, sizeof(T));
533 /* 80 operations, partially loop unrolled */
534 for (unsigned int j=0; j<80; j+=16)
535 {
536 R( 0); R( 1); R( 2); R( 3);
537 R( 4); R( 5); R( 6); R( 7);
538 R( 8); R( 9); R(10); R(11);
539 R(12); R(13); R(14); R(15);
540 }
541 /* Add the working vars back into context.state[] */
542 state[0] += a(0);
543 state[1] += b(0);
544 state[2] += c(0);
545 state[3] += d(0);
546 state[4] += e(0);
547 state[5] += f(0);
548 state[6] += g(0);
549 state[7] += h(0);
550}
551
552#endif
553
554}