directory re-organization (keeps the old build system)
[novacoin.git] / src / cryptopp / 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.
4 // Both are in the public domain.
5
6 // use "cl /EP /P /DCRYPTOPP_GENERATE_X64_MASM sha.cpp" to generate MASM code
7
8 #include "pch.h"
9
10 #ifndef CRYPTOPP_IMPORTS
11 #ifndef CRYPTOPP_GENERATE_X64_MASM
12
13 #include "sha.h"
14 #include "misc.h"
15 #include "cpu.h"
16
17 NAMESPACE_BEGIN(CryptoPP)
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
24 void 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
45 void 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
87 void 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
93 void 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
99 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
100 CRYPTOPP_ALIGN_DATA(16) extern const word32 SHA256_K[64] CRYPTOPP_SECTION_ALIGN16 = {
101 #else
102 extern const word32 SHA256_K[64] = {
103 #endif
104         0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
105         0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
106         0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
107         0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
108         0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
109         0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
110         0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
111         0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
112         0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
113         0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
114         0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
115         0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
116         0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
117         0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
118         0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
119         0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
120 };
121
122 #endif // #ifndef CRYPTOPP_GENERATE_X64_MASM
123
124 #if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_GENERATE_X64_MASM)
125
126 #pragma warning(disable: 4731)  // frame pointer register 'ebp' modified by inline assembly code
127
128 static void CRYPTOPP_FASTCALL X86_SHA256_HashBlocks(word32 *state, const word32 *data, size_t len
129 #if defined(_MSC_VER) && (_MSC_VER == 1200)
130         , ...   // VC60 workaround: prevent VC 6 from inlining this function
131 #endif
132         )
133 {
134 #if defined(_MSC_VER) && (_MSC_VER == 1200)
135         AS2(mov ecx, [state])
136         AS2(mov edx, [data])
137 #endif
138
139         #define LOCALS_SIZE     8*4 + 16*4 + 4*WORD_SZ
140         #define H(i)            [BASE+ASM_MOD(1024+7-(i),8)*4]
141         #define G(i)            H(i+1)
142         #define F(i)            H(i+2)
143         #define E(i)            H(i+3)
144         #define D(i)            H(i+4)
145         #define C(i)            H(i+5)
146         #define B(i)            H(i+6)
147         #define A(i)            H(i+7)
148         #define Wt(i)           BASE+8*4+ASM_MOD(1024+15-(i),16)*4
149         #define Wt_2(i)         Wt((i)-2)
150         #define Wt_15(i)        Wt((i)-15)
151         #define Wt_7(i)         Wt((i)-7)
152         #define K_END           [BASE+8*4+16*4+0*WORD_SZ]
153         #define STATE_SAVE      [BASE+8*4+16*4+1*WORD_SZ]
154         #define DATA_SAVE       [BASE+8*4+16*4+2*WORD_SZ]
155         #define DATA_END        [BASE+8*4+16*4+3*WORD_SZ]
156         #define Kt(i)           WORD_REG(si)+(i)*4
157 #if CRYPTOPP_BOOL_X86
158         #define BASE            esp+4
159 #elif defined(__GNUC__)
160         #define BASE            r8
161 #else
162         #define BASE            rsp
163 #endif
164
165 #define RA0(i, edx, edi)                \
166         AS2(    add edx, [Kt(i)]        )\
167         AS2(    add edx, [Wt(i)]        )\
168         AS2(    add edx, H(i)           )\
169
170 #define RA1(i, edx, edi)
171
172 #define RB0(i, edx, edi)
173
174 #define RB1(i, edx, edi)        \
175         AS2(    mov AS_REG_7d, [Wt_2(i)]        )\
176         AS2(    mov edi, [Wt_15(i)])\
177         AS2(    mov ebx, AS_REG_7d      )\
178         AS2(    shr AS_REG_7d, 10               )\
179         AS2(    ror ebx, 17             )\
180         AS2(    xor AS_REG_7d, ebx      )\
181         AS2(    ror ebx, 2              )\
182         AS2(    xor ebx, AS_REG_7d      )/* s1(W_t-2) */\
183         AS2(    add ebx, [Wt_7(i)])\
184         AS2(    mov AS_REG_7d, edi      )\
185         AS2(    shr AS_REG_7d, 3                )\
186         AS2(    ror edi, 7              )\
187         AS2(    add ebx, [Wt(i)])/* s1(W_t-2) + W_t-7 + W_t-16 */\
188         AS2(    xor AS_REG_7d, edi      )\
189         AS2(    add edx, [Kt(i)])\
190         AS2(    ror edi, 11             )\
191         AS2(    add edx, H(i)   )\
192         AS2(    xor AS_REG_7d, edi      )/* s0(W_t-15) */\
193         AS2(    add AS_REG_7d, ebx      )/* W_t = s1(W_t-2) + W_t-7 + s0(W_t-15) W_t-16*/\
194         AS2(    mov [Wt(i)], AS_REG_7d)\
195         AS2(    add edx, AS_REG_7d      )\
196
197 #define ROUND(i, r, eax, ecx, edi, edx)\
198         /* in: edi = E  */\
199         /* unused: eax, ecx, temp: ebx, AS_REG_7d, out: edx = T1 */\
200         AS2(    mov edx, F(i)   )\
201         AS2(    xor edx, G(i)   )\
202         AS2(    and edx, edi    )\
203         AS2(    xor edx, G(i)   )/* Ch(E,F,G) = (G^(E&(F^G))) */\
204         AS2(    mov AS_REG_7d, edi      )\
205         AS2(    ror edi, 6              )\
206         AS2(    ror AS_REG_7d, 25               )\
207         RA##r(i, edx, edi               )/* H + Wt + Kt + Ch(E,F,G) */\
208         AS2(    xor AS_REG_7d, edi      )\
209         AS2(    ror edi, 5              )\
210         AS2(    xor AS_REG_7d, edi      )/* S1(E) */\
211         AS2(    add edx, AS_REG_7d      )/* T1 = S1(E) + Ch(E,F,G) + H + Wt + Kt */\
212         RB##r(i, edx, edi               )/* H + Wt + Kt + Ch(E,F,G) */\
213         /* in: ecx = A, eax = B^C, edx = T1 */\
214         /* unused: edx, temp: ebx, AS_REG_7d, out: eax = A, ecx = B^C, edx = E */\
215         AS2(    mov ebx, ecx    )\
216         AS2(    xor ecx, B(i)   )/* A^B */\
217         AS2(    and eax, ecx    )\
218         AS2(    xor eax, B(i)   )/* Maj(A,B,C) = B^((A^B)&(B^C) */\
219         AS2(    mov AS_REG_7d, ebx      )\
220         AS2(    ror ebx, 2              )\
221         AS2(    add eax, edx    )/* T1 + Maj(A,B,C) */\
222         AS2(    add edx, D(i)   )\
223         AS2(    mov D(i), edx   )\
224         AS2(    ror AS_REG_7d, 22               )\
225         AS2(    xor AS_REG_7d, ebx      )\
226         AS2(    ror ebx, 11             )\
227         AS2(    xor AS_REG_7d, ebx      )\
228         AS2(    add eax, AS_REG_7d      )/* T1 + S0(A) + Maj(A,B,C) */\
229         AS2(    mov H(i), eax   )\
230
231 #define SWAP_COPY(i)            \
232         AS2(    mov             WORD_REG(bx), [WORD_REG(dx)+i*WORD_SZ])\
233         AS1(    bswap   WORD_REG(bx))\
234         AS2(    mov             [Wt(i*(1+CRYPTOPP_BOOL_X64)+CRYPTOPP_BOOL_X64)], WORD_REG(bx))
235
236 #if defined(__GNUC__)
237         #if CRYPTOPP_BOOL_X64
238                 FixedSizeAlignedSecBlock<byte, LOCALS_SIZE> workspace;
239         #endif
240         __asm__ __volatile__
241         (
242         #if CRYPTOPP_BOOL_X64
243                 "lea %4, %%r8;"
244         #endif
245         ".intel_syntax noprefix;"
246 #elif defined(CRYPTOPP_GENERATE_X64_MASM)
247                 ALIGN   8
248         X86_SHA256_HashBlocks   PROC FRAME
249                 rex_push_reg rsi
250                 push_reg rdi
251                 push_reg rbx
252                 push_reg rbp
253                 alloc_stack(LOCALS_SIZE+8)
254                 .endprolog
255                 mov rdi, r8
256                 lea rsi, [?SHA256_K@CryptoPP@@3QBIB + 48*4]
257 #endif
258
259 #if CRYPTOPP_BOOL_X86
260         #ifndef __GNUC__
261                 AS2(    mov             edi, [len])
262                 AS2(    lea             WORD_REG(si), [SHA256_K+48*4])
263         #endif
264         #if !defined(_MSC_VER) || (_MSC_VER < 1400)
265                 AS_PUSH_IF86(bx)
266         #endif
267
268         AS_PUSH_IF86(bp)
269         AS2(    mov             ebx, esp)
270         AS2(    and             esp, -16)
271         AS2(    sub             WORD_REG(sp), LOCALS_SIZE)
272         AS_PUSH_IF86(bx)
273 #endif
274         AS2(    mov             STATE_SAVE, WORD_REG(cx))
275         AS2(    mov             DATA_SAVE, WORD_REG(dx))
276         AS2(    add             WORD_REG(di), WORD_REG(dx))
277         AS2(    mov             DATA_END, WORD_REG(di))
278         AS2(    mov             K_END, WORD_REG(si))
279
280 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
281 #if CRYPTOPP_BOOL_X86
282         AS2(    test    edi, 1)
283         ASJ(    jnz,    2, f)
284 #endif
285         AS2(    movdqa  xmm0, XMMWORD_PTR [WORD_REG(cx)+0*16])
286         AS2(    movdqa  xmm1, XMMWORD_PTR [WORD_REG(cx)+1*16])
287 #endif
288
289 #if CRYPTOPP_BOOL_X86
290 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
291         ASJ(    jmp,    0, f)
292 #endif
293         ASL(2)  // non-SSE2
294         AS2(    mov             esi, ecx)
295         AS2(    lea             edi, A(0))
296         AS2(    mov             ecx, 8)
297         AS1(    rep movsd)
298         AS2(    mov             esi, K_END)
299         ASJ(    jmp,    3, f)
300 #endif
301
302 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
303         ASL(0)
304         AS2(    movdqa  E(0), xmm1)
305         AS2(    movdqa  A(0), xmm0)
306 #endif
307 #if CRYPTOPP_BOOL_X86
308         ASL(3)
309 #endif
310         AS2(    sub             WORD_REG(si), 48*4)
311         SWAP_COPY(0)    SWAP_COPY(1)    SWAP_COPY(2)    SWAP_COPY(3)
312         SWAP_COPY(4)    SWAP_COPY(5)    SWAP_COPY(6)    SWAP_COPY(7)
313 #if CRYPTOPP_BOOL_X86
314         SWAP_COPY(8)    SWAP_COPY(9)    SWAP_COPY(10)   SWAP_COPY(11)
315         SWAP_COPY(12)   SWAP_COPY(13)   SWAP_COPY(14)   SWAP_COPY(15)
316 #endif
317         AS2(    mov             edi, E(0))      // E
318         AS2(    mov             eax, B(0))      // B
319         AS2(    xor             eax, C(0))      // B^C
320         AS2(    mov             ecx, A(0))      // A
321
322         ROUND(0, 0, eax, ecx, edi, edx)
323         ROUND(1, 0, ecx, eax, edx, edi)
324         ROUND(2, 0, eax, ecx, edi, edx)
325         ROUND(3, 0, ecx, eax, edx, edi)
326         ROUND(4, 0, eax, ecx, edi, edx)
327         ROUND(5, 0, ecx, eax, edx, edi)
328         ROUND(6, 0, eax, ecx, edi, edx)
329         ROUND(7, 0, ecx, eax, edx, edi)
330         ROUND(8, 0, eax, ecx, edi, edx)
331         ROUND(9, 0, ecx, eax, edx, edi)
332         ROUND(10, 0, eax, ecx, edi, edx)
333         ROUND(11, 0, ecx, eax, edx, edi)
334         ROUND(12, 0, eax, ecx, edi, edx)
335         ROUND(13, 0, ecx, eax, edx, edi)
336         ROUND(14, 0, eax, ecx, edi, edx)
337         ROUND(15, 0, ecx, eax, edx, edi)
338
339         ASL(1)
340         AS2(add WORD_REG(si), 4*16)
341         ROUND(0, 1, eax, ecx, edi, edx)
342         ROUND(1, 1, ecx, eax, edx, edi)
343         ROUND(2, 1, eax, ecx, edi, edx)
344         ROUND(3, 1, ecx, eax, edx, edi)
345         ROUND(4, 1, eax, ecx, edi, edx)
346         ROUND(5, 1, ecx, eax, edx, edi)
347         ROUND(6, 1, eax, ecx, edi, edx)
348         ROUND(7, 1, ecx, eax, edx, edi)
349         ROUND(8, 1, eax, ecx, edi, edx)
350         ROUND(9, 1, ecx, eax, edx, edi)
351         ROUND(10, 1, eax, ecx, edi, edx)
352         ROUND(11, 1, ecx, eax, edx, edi)
353         ROUND(12, 1, eax, ecx, edi, edx)
354         ROUND(13, 1, ecx, eax, edx, edi)
355         ROUND(14, 1, eax, ecx, edi, edx)
356         ROUND(15, 1, ecx, eax, edx, edi)
357         AS2(    cmp             WORD_REG(si), K_END)
358         ASJ(    jne,    1, b)
359
360         AS2(    mov             WORD_REG(dx), DATA_SAVE)
361         AS2(    add             WORD_REG(dx), 64)
362         AS2(    mov             AS_REG_7, STATE_SAVE)
363         AS2(    mov             DATA_SAVE, WORD_REG(dx))
364
365 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
366 #if CRYPTOPP_BOOL_X86
367         AS2(    test    DWORD PTR DATA_END, 1)
368         ASJ(    jnz,    4, f)
369 #endif
370         AS2(    movdqa  xmm1, XMMWORD_PTR [AS_REG_7+1*16])
371         AS2(    movdqa  xmm0, XMMWORD_PTR [AS_REG_7+0*16])
372         AS2(    paddd   xmm1, E(0))
373         AS2(    paddd   xmm0, A(0))
374         AS2(    movdqa  [AS_REG_7+1*16], xmm1)
375         AS2(    movdqa  [AS_REG_7+0*16], xmm0)
376         AS2(    cmp             WORD_REG(dx), DATA_END)
377         ASJ(    jl,             0, b)
378 #endif
379
380 #if CRYPTOPP_BOOL_X86
381 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
382         ASJ(    jmp,    5, f)
383         ASL(4)  // non-SSE2
384 #endif
385         AS2(    add             [AS_REG_7+0*4], ecx)    // A
386         AS2(    add             [AS_REG_7+4*4], edi)    // E
387         AS2(    mov             eax, B(0))
388         AS2(    mov             ebx, C(0))
389         AS2(    mov             ecx, D(0))
390         AS2(    add             [AS_REG_7+1*4], eax)
391         AS2(    add             [AS_REG_7+2*4], ebx)
392         AS2(    add             [AS_REG_7+3*4], ecx)
393         AS2(    mov             eax, F(0))
394         AS2(    mov             ebx, G(0))
395         AS2(    mov             ecx, H(0))
396         AS2(    add             [AS_REG_7+5*4], eax)
397         AS2(    add             [AS_REG_7+6*4], ebx)
398         AS2(    add             [AS_REG_7+7*4], ecx)
399         AS2(    mov             ecx, AS_REG_7d)
400         AS2(    cmp             WORD_REG(dx), DATA_END)
401         ASJ(    jl,             2, b)
402 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
403         ASL(5)
404 #endif
405 #endif
406
407         AS_POP_IF86(sp)
408         AS_POP_IF86(bp)
409         #if !defined(_MSC_VER) || (_MSC_VER < 1400)
410                 AS_POP_IF86(bx)
411         #endif
412
413 #ifdef CRYPTOPP_GENERATE_X64_MASM
414         add             rsp, LOCALS_SIZE+8
415         pop             rbp
416         pop             rbx
417         pop             rdi
418         pop             rsi
419         ret
420         X86_SHA256_HashBlocks ENDP
421 #endif
422
423 #ifdef __GNUC__
424         ".att_syntax prefix;"
425         : 
426         : "c" (state), "d" (data), "S" (SHA256_K+48), "D" (len)
427         #if CRYPTOPP_BOOL_X64
428                 , "m" (workspace[0])
429         #endif
430         : "memory", "cc", "%eax"
431         #if CRYPTOPP_BOOL_X64
432                 , "%rbx", "%r8"
433         #endif
434         );
435 #endif
436 }
437
438 #endif  // #if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_GENERATE_X64_MASM)
439
440 #ifndef CRYPTOPP_GENERATE_X64_MASM
441
442 #ifdef CRYPTOPP_X64_MASM_AVAILABLE
443 extern "C" {
444 void CRYPTOPP_FASTCALL X86_SHA256_HashBlocks(word32 *state, const word32 *data, size_t len);
445 }
446 #endif
447
448 #if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_X64_MASM_AVAILABLE)
449
450 size_t SHA256::HashMultipleBlocks(const word32 *input, size_t length)
451 {
452         X86_SHA256_HashBlocks(m_state, input, (length&(size_t(0)-BLOCKSIZE)) - !HasSSE2());
453         return length % BLOCKSIZE;
454 }
455
456 size_t SHA224::HashMultipleBlocks(const word32 *input, size_t length)
457 {
458         X86_SHA256_HashBlocks(m_state, input, (length&(size_t(0)-BLOCKSIZE)) - !HasSSE2());
459         return length % BLOCKSIZE;
460 }
461
462 #endif
463
464 #define blk2(i) (W[i&15]+=s1(W[(i-2)&15])+W[(i-7)&15]+s0(W[(i-15)&15]))
465
466 #define Ch(x,y,z) (z^(x&(y^z)))
467 #define Maj(x,y,z) (y^((x^y)&(y^z)))
468
469 #define a(i) T[(0-i)&7]
470 #define b(i) T[(1-i)&7]
471 #define c(i) T[(2-i)&7]
472 #define d(i) T[(3-i)&7]
473 #define e(i) T[(4-i)&7]
474 #define f(i) T[(5-i)&7]
475 #define g(i) T[(6-i)&7]
476 #define h(i) T[(7-i)&7]
477
478 #define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+SHA256_K[i+j]+(j?blk2(i):blk0(i));\
479         d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i))
480
481 // for SHA256
482 #define S0(x) (rotrFixed(x,2)^rotrFixed(x,13)^rotrFixed(x,22))
483 #define S1(x) (rotrFixed(x,6)^rotrFixed(x,11)^rotrFixed(x,25))
484 #define s0(x) (rotrFixed(x,7)^rotrFixed(x,18)^(x>>3))
485 #define s1(x) (rotrFixed(x,17)^rotrFixed(x,19)^(x>>10))
486
487 void SHA256::Transform(word32 *state, const word32 *data)
488 {
489         word32 W[16];
490 #if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_X64_MASM_AVAILABLE)
491         // this byte reverse is a waste of time, but this function is only called by MDC
492         ByteReverse(W, data, BLOCKSIZE);
493         X86_SHA256_HashBlocks(state, W, BLOCKSIZE - !HasSSE2());
494 #else
495         word32 T[8];
496     /* Copy context->state[] to working vars */
497         memcpy(T, state, sizeof(T));
498     /* 64 operations, partially loop unrolled */
499         for (unsigned int j=0; j<64; j+=16)
500         {
501                 R( 0); R( 1); R( 2); R( 3);
502                 R( 4); R( 5); R( 6); R( 7);
503                 R( 8); R( 9); R(10); R(11);
504                 R(12); R(13); R(14); R(15);
505         }
506     /* Add the working vars back into context.state[] */
507     state[0] += a(0);
508     state[1] += b(0);
509     state[2] += c(0);
510     state[3] += d(0);
511     state[4] += e(0);
512     state[5] += f(0);
513     state[6] += g(0);
514     state[7] += h(0);
515 #endif
516 }
517
518 /* 
519 // smaller but slower
520 void SHA256::Transform(word32 *state, const word32 *data)
521 {
522         word32 T[20];
523         word32 W[32];
524         unsigned int i = 0, j = 0;
525         word32 *t = T+8;
526
527         memcpy(t, state, 8*4);
528         word32 e = t[4], a = t[0];
529
530         do 
531         {
532                 word32 w = data[j];
533                 W[j] = w;
534                 w += SHA256_K[j];
535                 w += t[7];
536                 w += S1(e);
537                 w += Ch(e, t[5], t[6]);
538                 e = t[3] + w;
539                 t[3] = t[3+8] = e;
540                 w += S0(t[0]);
541                 a = w + Maj(a, t[1], t[2]);
542                 t[-1] = t[7] = a;
543                 --t;
544                 ++j;
545                 if (j%8 == 0)
546                         t += 8;
547         } while (j<16);
548
549         do
550         {
551                 i = j&0xf;
552                 word32 w = s1(W[i+16-2]) + s0(W[i+16-15]) + W[i] + W[i+16-7];
553                 W[i+16] = W[i] = w;
554                 w += SHA256_K[j];
555                 w += t[7];
556                 w += S1(e);
557                 w += Ch(e, t[5], t[6]);
558                 e = t[3] + w;
559                 t[3] = t[3+8] = e;
560                 w += S0(t[0]);
561                 a = w + Maj(a, t[1], t[2]);
562                 t[-1] = t[7] = a;
563
564                 w = s1(W[(i+1)+16-2]) + s0(W[(i+1)+16-15]) + W[(i+1)] + W[(i+1)+16-7];
565                 W[(i+1)+16] = W[(i+1)] = w;
566                 w += SHA256_K[j+1];
567                 w += (t-1)[7];
568                 w += S1(e);
569                 w += Ch(e, (t-1)[5], (t-1)[6]);
570                 e = (t-1)[3] + w;
571                 (t-1)[3] = (t-1)[3+8] = e;
572                 w += S0((t-1)[0]);
573                 a = w + Maj(a, (t-1)[1], (t-1)[2]);
574                 (t-1)[-1] = (t-1)[7] = a;
575
576                 t-=2;
577                 j+=2;
578                 if (j%8 == 0)
579                         t += 8;
580         } while (j<64);
581
582     state[0] += a;
583     state[1] += t[1];
584     state[2] += t[2];
585     state[3] += t[3];
586     state[4] += e;
587     state[5] += t[5];
588     state[6] += t[6];
589     state[7] += t[7];
590 }
591 */
592
593 #undef S0
594 #undef S1
595 #undef s0
596 #undef s1
597 #undef R
598
599 // *************************************************************
600
601 void SHA384::InitState(HashWordType *state)
602 {
603         static const word64 s[8] = {
604                 W64LIT(0xcbbb9d5dc1059ed8), W64LIT(0x629a292a367cd507),
605                 W64LIT(0x9159015a3070dd17), W64LIT(0x152fecd8f70e5939),
606                 W64LIT(0x67332667ffc00b31), W64LIT(0x8eb44a8768581511),
607                 W64LIT(0xdb0c2e0d64f98fa7), W64LIT(0x47b5481dbefa4fa4)};
608         memcpy(state, s, sizeof(s));
609 }
610
611 void SHA512::InitState(HashWordType *state)
612 {
613         static const word64 s[8] = {
614                 W64LIT(0x6a09e667f3bcc908), W64LIT(0xbb67ae8584caa73b),
615                 W64LIT(0x3c6ef372fe94f82b), W64LIT(0xa54ff53a5f1d36f1),
616                 W64LIT(0x510e527fade682d1), W64LIT(0x9b05688c2b3e6c1f),
617                 W64LIT(0x1f83d9abfb41bd6b), W64LIT(0x5be0cd19137e2179)};
618         memcpy(state, s, sizeof(s));
619 }
620
621 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86
622 CRYPTOPP_ALIGN_DATA(16) static const word64 SHA512_K[80] CRYPTOPP_SECTION_ALIGN16 = {
623 #else
624 static const word64 SHA512_K[80] = {
625 #endif
626         W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd),
627         W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc),
628         W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019),
629         W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118),
630         W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe),
631         W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2),
632         W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1),
633         W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694),
634         W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3),
635         W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65),
636         W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483),
637         W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5),
638         W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210),
639         W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4),
640         W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725),
641         W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70),
642         W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926),
643         W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df),
644         W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8),
645         W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b),
646         W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001),
647         W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30),
648         W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910),
649         W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8),
650         W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53),
651         W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8),
652         W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb),
653         W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3),
654         W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60),
655         W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec),
656         W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9),
657         W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b),
658         W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207),
659         W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178),
660         W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6),
661         W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b),
662         W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493),
663         W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c),
664         W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a),
665         W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817)
666 };
667
668 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86
669 // put assembly version in separate function, otherwise MSVC 2005 SP1 doesn't generate correct code for the non-assembly version
670 CRYPTOPP_NAKED static void CRYPTOPP_FASTCALL SHA512_SSE2_Transform(word64 *state, const word64 *data)
671 {
672 #ifdef __GNUC__
673         __asm__ __volatile__
674         (
675                 ".intel_syntax noprefix;"
676         AS1(    push    ebx)
677         AS2(    mov             ebx, eax)
678 #else
679         AS1(    push    ebx)
680         AS1(    push    esi)
681         AS1(    push    edi)
682         AS2(    lea             ebx, SHA512_K)
683 #endif
684
685         AS2(    mov             eax, esp)
686         AS2(    and             esp, 0xfffffff0)
687         AS2(    sub             esp, 27*16)                             // 17*16 for expanded data, 20*8 for state
688         AS1(    push    eax)
689         AS2(    xor             eax, eax)
690         AS2(    lea             edi, [esp+4+8*8])               // start at middle of state buffer. will decrement pointer each round to avoid copying
691         AS2(    lea             esi, [esp+4+20*8+8])    // 16-byte alignment, then add 8
692
693         AS2(    movdqa  xmm0, [ecx+0*16])
694         AS2(    movdq2q mm4, xmm0)
695         AS2(    movdqa  [edi+0*16], xmm0)
696         AS2(    movdqa  xmm0, [ecx+1*16])
697         AS2(    movdqa  [edi+1*16], xmm0)
698         AS2(    movdqa  xmm0, [ecx+2*16])
699         AS2(    movdq2q mm5, xmm0)
700         AS2(    movdqa  [edi+2*16], xmm0)
701         AS2(    movdqa  xmm0, [ecx+3*16])
702         AS2(    movdqa  [edi+3*16], xmm0)
703         ASJ(    jmp,    0, f)
704
705 #define SSE2_S0_S1(r, a, b, c)  \
706         AS2(    movq    mm6, r)\
707         AS2(    psrlq   r, a)\
708         AS2(    movq    mm7, r)\
709         AS2(    psllq   mm6, 64-c)\
710         AS2(    pxor    mm7, mm6)\
711         AS2(    psrlq   r, b-a)\
712         AS2(    pxor    mm7, r)\
713         AS2(    psllq   mm6, c-b)\
714         AS2(    pxor    mm7, mm6)\
715         AS2(    psrlq   r, c-b)\
716         AS2(    pxor    r, mm7)\
717         AS2(    psllq   mm6, b-a)\
718         AS2(    pxor    r, mm6)
719
720 #define SSE2_s0(r, a, b, c)     \
721         AS2(    movdqa  xmm6, r)\
722         AS2(    psrlq   r, a)\
723         AS2(    movdqa  xmm7, r)\
724         AS2(    psllq   xmm6, 64-c)\
725         AS2(    pxor    xmm7, xmm6)\
726         AS2(    psrlq   r, b-a)\
727         AS2(    pxor    xmm7, r)\
728         AS2(    psrlq   r, c-b)\
729         AS2(    pxor    r, xmm7)\
730         AS2(    psllq   xmm6, c-a)\
731         AS2(    pxor    r, xmm6)
732
733 #define SSE2_s1(r, a, b, c)     \
734         AS2(    movdqa  xmm6, r)\
735         AS2(    psrlq   r, a)\
736         AS2(    movdqa  xmm7, r)\
737         AS2(    psllq   xmm6, 64-c)\
738         AS2(    pxor    xmm7, xmm6)\
739         AS2(    psrlq   r, b-a)\
740         AS2(    pxor    xmm7, r)\
741         AS2(    psllq   xmm6, c-b)\
742         AS2(    pxor    xmm7, xmm6)\
743         AS2(    psrlq   r, c-b)\
744         AS2(    pxor    r, xmm7)
745
746         ASL(SHA512_Round)
747         // k + w is in mm0, a is in mm4, e is in mm5
748         AS2(    paddq   mm0, [edi+7*8])         // h
749         AS2(    movq    mm2, [edi+5*8])         // f
750         AS2(    movq    mm3, [edi+6*8])         // g
751         AS2(    pxor    mm2, mm3)
752         AS2(    pand    mm2, mm5)
753         SSE2_S0_S1(mm5,14,18,41)
754         AS2(    pxor    mm2, mm3)
755         AS2(    paddq   mm0, mm2)                       // h += Ch(e,f,g)
756         AS2(    paddq   mm5, mm0)                       // h += S1(e)
757         AS2(    movq    mm2, [edi+1*8])         // b
758         AS2(    movq    mm1, mm2)
759         AS2(    por             mm2, mm4)
760         AS2(    pand    mm2, [edi+2*8])         // c
761         AS2(    pand    mm1, mm4)
762         AS2(    por             mm1, mm2)
763         AS2(    paddq   mm1, mm5)                       // temp = h + Maj(a,b,c)
764         AS2(    paddq   mm5, [edi+3*8])         // e = d + h
765         AS2(    movq    [edi+3*8], mm5)
766         AS2(    movq    [edi+11*8], mm5)
767         SSE2_S0_S1(mm4,28,34,39)                        // S0(a)
768         AS2(    paddq   mm4, mm1)                       // a = temp + S0(a)
769         AS2(    movq    [edi-8], mm4)
770         AS2(    movq    [edi+7*8], mm4)
771         AS1(    ret)
772
773         // first 16 rounds
774         ASL(0)
775         AS2(    movq    mm0, [edx+eax*8])
776         AS2(    movq    [esi+eax*8], mm0)
777         AS2(    movq    [esi+eax*8+16*8], mm0)
778         AS2(    paddq   mm0, [ebx+eax*8])
779         ASC(    call,   SHA512_Round)
780         AS1(    inc             eax)
781         AS2(    sub             edi, 8)
782         AS2(    test    eax, 7)
783         ASJ(    jnz,    0, b)
784         AS2(    add             edi, 8*8)
785         AS2(    cmp             eax, 16)
786         ASJ(    jne,    0, b)
787
788         // rest of the rounds
789         AS2(    movdqu  xmm0, [esi+(16-2)*8])
790         ASL(1)
791         // data expansion, W[i-2] already in xmm0
792         AS2(    movdqu  xmm3, [esi])
793         AS2(    paddq   xmm3, [esi+(16-7)*8])
794         AS2(    movdqa  xmm2, [esi+(16-15)*8])
795         SSE2_s1(xmm0, 6, 19, 61)
796         AS2(    paddq   xmm0, xmm3)
797         SSE2_s0(xmm2, 1, 7, 8)
798         AS2(    paddq   xmm0, xmm2)
799         AS2(    movdq2q mm0, xmm0)
800         AS2(    movhlps xmm1, xmm0)
801         AS2(    paddq   mm0, [ebx+eax*8])
802         AS2(    movlps  [esi], xmm0)
803         AS2(    movlps  [esi+8], xmm1)
804         AS2(    movlps  [esi+8*16], xmm0)
805         AS2(    movlps  [esi+8*17], xmm1)
806         // 2 rounds
807         ASC(    call,   SHA512_Round)
808         AS2(    sub             edi, 8)
809         AS2(    movdq2q mm0, xmm1)
810         AS2(    paddq   mm0, [ebx+eax*8+8])
811         ASC(    call,   SHA512_Round)
812         // update indices and loop
813         AS2(    add             esi, 16)
814         AS2(    add             eax, 2)
815         AS2(    sub             edi, 8)
816         AS2(    test    eax, 7)
817         ASJ(    jnz,    1, b)
818         // do housekeeping every 8 rounds
819         AS2(    mov             esi, 0xf)
820         AS2(    and             esi, eax)
821         AS2(    lea             esi, [esp+4+20*8+8+esi*8])
822         AS2(    add             edi, 8*8)
823         AS2(    cmp             eax, 80)
824         ASJ(    jne,    1, b)
825
826 #define SSE2_CombineState(i)    \
827         AS2(    movdqa  xmm0, [edi+i*16])\
828         AS2(    paddq   xmm0, [ecx+i*16])\
829         AS2(    movdqa  [ecx+i*16], xmm0)
830
831         SSE2_CombineState(0)
832         SSE2_CombineState(1)
833         SSE2_CombineState(2)
834         SSE2_CombineState(3)
835
836         AS1(    pop             esp)
837         AS1(    emms)
838
839 #if defined(__GNUC__)
840         AS1(    pop             ebx)
841         ".att_syntax prefix;"
842                 :
843                 : "a" (SHA512_K), "c" (state), "d" (data)
844                 : "%esi", "%edi", "memory", "cc"
845         );
846 #else
847         AS1(    pop             edi)
848         AS1(    pop             esi)
849         AS1(    pop             ebx)
850         AS1(    ret)
851 #endif
852 }
853 #endif  // #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
854
855 void SHA512::Transform(word64 *state, const word64 *data)
856 {
857 #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86
858         if (HasSSE2())
859         {
860                 SHA512_SSE2_Transform(state, data);
861                 return;
862         }
863 #endif
864
865 #define S0(x) (rotrFixed(x,28)^rotrFixed(x,34)^rotrFixed(x,39))
866 #define S1(x) (rotrFixed(x,14)^rotrFixed(x,18)^rotrFixed(x,41))
867 #define s0(x) (rotrFixed(x,1)^rotrFixed(x,8)^(x>>7))
868 #define s1(x) (rotrFixed(x,19)^rotrFixed(x,61)^(x>>6))
869
870 #define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+SHA512_K[i+j]+(j?blk2(i):blk0(i));\
871         d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i))
872
873         word64 W[16];
874         word64 T[8];
875     /* Copy context->state[] to working vars */
876         memcpy(T, state, sizeof(T));
877     /* 80 operations, partially loop unrolled */
878         for (unsigned int j=0; j<80; j+=16)
879         {
880                 R( 0); R( 1); R( 2); R( 3);
881                 R( 4); R( 5); R( 6); R( 7);
882                 R( 8); R( 9); R(10); R(11);
883                 R(12); R(13); R(14); R(15);
884         }
885     /* Add the working vars back into context.state[] */
886     state[0] += a(0);
887     state[1] += b(0);
888     state[2] += c(0);
889     state[3] += d(0);
890     state[4] += e(0);
891     state[5] += f(0);
892     state[6] += g(0);
893     state[7] += h(0);
894 }
895
896 NAMESPACE_END
897
898 #endif  // #ifndef CRYPTOPP_GENERATE_X64_MASM
899 #endif  // #ifndef CRYPTOPP_IMPORTS