1 | // tiger.cpp - written and placed in the public domain by Wei Dai |
---|
2 | |
---|
3 | #include "pch.h" |
---|
4 | #include "config.h" |
---|
5 | |
---|
6 | #include "tiger.h" |
---|
7 | #include "misc.h" |
---|
8 | #include "cpu.h" |
---|
9 | |
---|
10 | #if defined(CRYPTOPP_DISABLE_TIGER_ASM) |
---|
11 | # undef CRYPTOPP_X86_ASM_AVAILABLE |
---|
12 | # undef CRYPTOPP_X32_ASM_AVAILABLE |
---|
13 | # undef CRYPTOPP_X64_ASM_AVAILABLE |
---|
14 | # undef CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE |
---|
15 | #endif |
---|
16 | |
---|
17 | NAMESPACE_BEGIN(CryptoPP) |
---|
18 | |
---|
19 | void Tiger::InitState(HashWordType *state) |
---|
20 | { |
---|
21 | state[0] = W64LIT(0x0123456789ABCDEF); |
---|
22 | state[1] = W64LIT(0xFEDCBA9876543210); |
---|
23 | state[2] = W64LIT(0xF096A5B4C3B2E187); |
---|
24 | } |
---|
25 | |
---|
26 | void Tiger::TruncatedFinal(byte *hash, size_t size) |
---|
27 | { |
---|
28 | ThrowIfInvalidTruncatedSize(size); |
---|
29 | |
---|
30 | PadLastBlock(56, 0x01); |
---|
31 | CorrectEndianess(m_data, m_data, 56); |
---|
32 | |
---|
33 | m_data[7] = GetBitCountLo(); |
---|
34 | |
---|
35 | Transform(m_state, m_data); |
---|
36 | CorrectEndianess(m_state, m_state, DigestSize()); |
---|
37 | memcpy(hash, m_state, size); |
---|
38 | |
---|
39 | Restart(); // reinit for next use |
---|
40 | } |
---|
41 | |
---|
42 | void Tiger::Transform (word64 *digest, const word64 *X) |
---|
43 | { |
---|
44 | #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32) |
---|
45 | if (HasSSE2()) |
---|
46 | { |
---|
47 | #ifdef __GNUC__ |
---|
48 | __asm__ __volatile__ |
---|
49 | ( |
---|
50 | INTEL_NOPREFIX |
---|
51 | AS_PUSH_IF86(bx) |
---|
52 | #else |
---|
53 | #if _MSC_VER < 1300 |
---|
54 | const word64 *t = table; |
---|
55 | AS2( mov edx, t) |
---|
56 | #else |
---|
57 | AS2( lea edx, [table]) |
---|
58 | #endif |
---|
59 | AS2( mov eax, digest) |
---|
60 | AS2( mov esi, X) |
---|
61 | #endif |
---|
62 | AS2( movq mm0, [eax]) |
---|
63 | AS2( movq mm1, [eax+1*8]) |
---|
64 | AS2( movq mm5, mm1) |
---|
65 | AS2( movq mm2, [eax+2*8]) |
---|
66 | AS2( movq mm7, [edx+4*2048+0*8]) |
---|
67 | AS2( movq mm6, [edx+4*2048+1*8]) |
---|
68 | AS2( mov ecx, esp) |
---|
69 | AS2( and esp, 0xfffffff0) |
---|
70 | AS2( sub esp, 8*8) |
---|
71 | AS_PUSH_IF86(cx) |
---|
72 | |
---|
73 | #define SSE2_round(a,b,c,x,mul) \ |
---|
74 | AS2( pxor c, [x])\ |
---|
75 | AS2( movd ecx, c)\ |
---|
76 | AS2( movzx edi, cl)\ |
---|
77 | AS2( movq mm3, [edx+0*2048+edi*8])\ |
---|
78 | AS2( movzx edi, ch)\ |
---|
79 | AS2( movq mm4, [edx+3*2048+edi*8])\ |
---|
80 | AS2( shr ecx, 16)\ |
---|
81 | AS2( movzx edi, cl)\ |
---|
82 | AS2( pxor mm3, [edx+1*2048+edi*8])\ |
---|
83 | AS2( movzx edi, ch)\ |
---|
84 | AS2( pxor mm4, [edx+2*2048+edi*8])\ |
---|
85 | AS3( pextrw ecx, c, 2)\ |
---|
86 | AS2( movzx edi, cl)\ |
---|
87 | AS2( pxor mm3, [edx+2*2048+edi*8])\ |
---|
88 | AS2( movzx edi, ch)\ |
---|
89 | AS2( pxor mm4, [edx+1*2048+edi*8])\ |
---|
90 | AS3( pextrw ecx, c, 3)\ |
---|
91 | AS2( movzx edi, cl)\ |
---|
92 | AS2( pxor mm3, [edx+3*2048+edi*8])\ |
---|
93 | AS2( psubq a, mm3)\ |
---|
94 | AS2( movzx edi, ch)\ |
---|
95 | AS2( pxor mm4, [edx+0*2048+edi*8])\ |
---|
96 | AS2( paddq b, mm4)\ |
---|
97 | SSE2_mul_##mul(b) |
---|
98 | |
---|
99 | #define SSE2_mul_5(b) \ |
---|
100 | AS2( movq mm3, b)\ |
---|
101 | AS2( psllq b, 2)\ |
---|
102 | AS2( paddq b, mm3) |
---|
103 | |
---|
104 | #define SSE2_mul_7(b) \ |
---|
105 | AS2( movq mm3, b)\ |
---|
106 | AS2( psllq b, 3)\ |
---|
107 | AS2( psubq b, mm3) |
---|
108 | |
---|
109 | #define SSE2_mul_9(b) \ |
---|
110 | AS2( movq mm3, b)\ |
---|
111 | AS2( psllq b, 3)\ |
---|
112 | AS2( paddq b, mm3) |
---|
113 | |
---|
114 | #define label2_5 1 |
---|
115 | #define label2_7 2 |
---|
116 | #define label2_9 3 |
---|
117 | |
---|
118 | #define SSE2_pass(A,B,C,mul,X) \ |
---|
119 | AS2( xor ebx, ebx)\ |
---|
120 | ASL(mul)\ |
---|
121 | SSE2_round(A,B,C,X+0*8+ebx,mul)\ |
---|
122 | SSE2_round(B,C,A,X+1*8+ebx,mul)\ |
---|
123 | AS2( cmp ebx, 6*8)\ |
---|
124 | ASJ( je, label2_##mul, f)\ |
---|
125 | SSE2_round(C,A,B,X+2*8+ebx,mul)\ |
---|
126 | AS2( add ebx, 3*8)\ |
---|
127 | ASJ( jmp, mul, b)\ |
---|
128 | ASL(label2_##mul) |
---|
129 | |
---|
130 | #define SSE2_key_schedule(Y,X) \ |
---|
131 | AS2( movq mm3, [X+7*8])\ |
---|
132 | AS2( pxor mm3, mm6)\ |
---|
133 | AS2( movq mm4, [X+0*8])\ |
---|
134 | AS2( psubq mm4, mm3)\ |
---|
135 | AS2( movq [Y+0*8], mm4)\ |
---|
136 | AS2( pxor mm4, [X+1*8])\ |
---|
137 | AS2( movq mm3, mm4)\ |
---|
138 | AS2( movq [Y+1*8], mm4)\ |
---|
139 | AS2( paddq mm4, [X+2*8])\ |
---|
140 | AS2( pxor mm3, mm7)\ |
---|
141 | AS2( psllq mm3, 19)\ |
---|
142 | AS2( movq [Y+2*8], mm4)\ |
---|
143 | AS2( pxor mm3, mm4)\ |
---|
144 | AS2( movq mm4, [X+3*8])\ |
---|
145 | AS2( psubq mm4, mm3)\ |
---|
146 | AS2( movq [Y+3*8], mm4)\ |
---|
147 | AS2( pxor mm4, [X+4*8])\ |
---|
148 | AS2( movq mm3, mm4)\ |
---|
149 | AS2( movq [Y+4*8], mm4)\ |
---|
150 | AS2( paddq mm4, [X+5*8])\ |
---|
151 | AS2( pxor mm3, mm7)\ |
---|
152 | AS2( psrlq mm3, 23)\ |
---|
153 | AS2( movq [Y+5*8], mm4)\ |
---|
154 | AS2( pxor mm3, mm4)\ |
---|
155 | AS2( movq mm4, [X+6*8])\ |
---|
156 | AS2( psubq mm4, mm3)\ |
---|
157 | AS2( movq [Y+6*8], mm4)\ |
---|
158 | AS2( pxor mm4, [X+7*8])\ |
---|
159 | AS2( movq mm3, mm4)\ |
---|
160 | AS2( movq [Y+7*8], mm4)\ |
---|
161 | AS2( paddq mm4, [Y+0*8])\ |
---|
162 | AS2( pxor mm3, mm7)\ |
---|
163 | AS2( psllq mm3, 19)\ |
---|
164 | AS2( movq [Y+0*8], mm4)\ |
---|
165 | AS2( pxor mm3, mm4)\ |
---|
166 | AS2( movq mm4, [Y+1*8])\ |
---|
167 | AS2( psubq mm4, mm3)\ |
---|
168 | AS2( movq [Y+1*8], mm4)\ |
---|
169 | AS2( pxor mm4, [Y+2*8])\ |
---|
170 | AS2( movq mm3, mm4)\ |
---|
171 | AS2( movq [Y+2*8], mm4)\ |
---|
172 | AS2( paddq mm4, [Y+3*8])\ |
---|
173 | AS2( pxor mm3, mm7)\ |
---|
174 | AS2( psrlq mm3, 23)\ |
---|
175 | AS2( movq [Y+3*8], mm4)\ |
---|
176 | AS2( pxor mm3, mm4)\ |
---|
177 | AS2( movq mm4, [Y+4*8])\ |
---|
178 | AS2( psubq mm4, mm3)\ |
---|
179 | AS2( movq [Y+4*8], mm4)\ |
---|
180 | AS2( pxor mm4, [Y+5*8])\ |
---|
181 | AS2( movq [Y+5*8], mm4)\ |
---|
182 | AS2( paddq mm4, [Y+6*8])\ |
---|
183 | AS2( movq [Y+6*8], mm4)\ |
---|
184 | AS2( pxor mm4, [edx+4*2048+2*8])\ |
---|
185 | AS2( movq mm3, [Y+7*8])\ |
---|
186 | AS2( psubq mm3, mm4)\ |
---|
187 | AS2( movq [Y+7*8], mm3) |
---|
188 | |
---|
189 | #if CRYPTOPP_BOOL_X32 |
---|
190 | SSE2_pass(mm0, mm1, mm2, 5, esi) |
---|
191 | SSE2_key_schedule(esp+8, esi) |
---|
192 | SSE2_pass(mm2, mm0, mm1, 7, esp+8) |
---|
193 | SSE2_key_schedule(esp+8, esp+8) |
---|
194 | SSE2_pass(mm1, mm2, mm0, 9, esp+8) |
---|
195 | #else |
---|
196 | SSE2_pass(mm0, mm1, mm2, 5, esi) |
---|
197 | SSE2_key_schedule(esp+4, esi) |
---|
198 | SSE2_pass(mm2, mm0, mm1, 7, esp+4) |
---|
199 | SSE2_key_schedule(esp+4, esp+4) |
---|
200 | SSE2_pass(mm1, mm2, mm0, 9, esp+4) |
---|
201 | #endif |
---|
202 | |
---|
203 | AS2( pxor mm0, [eax+0*8]) |
---|
204 | AS2( movq [eax+0*8], mm0) |
---|
205 | AS2( psubq mm1, mm5) |
---|
206 | AS2( movq [eax+1*8], mm1) |
---|
207 | AS2( paddq mm2, [eax+2*8]) |
---|
208 | AS2( movq [eax+2*8], mm2) |
---|
209 | |
---|
210 | AS_POP_IF86(sp) |
---|
211 | AS1( emms) |
---|
212 | |
---|
213 | #ifdef __GNUC__ |
---|
214 | AS_POP_IF86(bx) |
---|
215 | ATT_PREFIX |
---|
216 | : |
---|
217 | : "a" (digest), "S" (X), "d" (table) |
---|
218 | : "%ecx", "%edi", "memory", "cc" |
---|
219 | ); |
---|
220 | #endif |
---|
221 | } |
---|
222 | else |
---|
223 | #endif |
---|
224 | { |
---|
225 | word64 a = digest[0]; |
---|
226 | word64 b = digest[1]; |
---|
227 | word64 c = digest[2]; |
---|
228 | word64 Y[8]; |
---|
229 | |
---|
230 | #define t1 (table) |
---|
231 | #define t2 (table+256) |
---|
232 | #define t3 (table+256*2) |
---|
233 | #define t4 (table+256*3) |
---|
234 | |
---|
235 | #define round(a,b,c,x,mul) \ |
---|
236 | c ^= x; \ |
---|
237 | a -= t1[GETBYTE(c,0)] ^ t2[GETBYTE(c,2)] ^ t3[GETBYTE(c,4)] ^ t4[GETBYTE(c,6)]; \ |
---|
238 | b += t4[GETBYTE(c,1)] ^ t3[GETBYTE(c,3)] ^ t2[GETBYTE(c,5)] ^ t1[GETBYTE(c,7)]; \ |
---|
239 | b *= mul |
---|
240 | |
---|
241 | #define pass(a,b,c,mul,X) {\ |
---|
242 | int i=0;\ |
---|
243 | while (true)\ |
---|
244 | {\ |
---|
245 | round(a,b,c,X[i+0],mul); \ |
---|
246 | round(b,c,a,X[i+1],mul); \ |
---|
247 | if (i==6)\ |
---|
248 | break;\ |
---|
249 | round(c,a,b,X[i+2],mul); \ |
---|
250 | i+=3;\ |
---|
251 | }} |
---|
252 | |
---|
253 | #define key_schedule(Y,X) \ |
---|
254 | Y[0] = X[0] - (X[7]^W64LIT(0xA5A5A5A5A5A5A5A5)); \ |
---|
255 | Y[1] = X[1] ^ Y[0]; \ |
---|
256 | Y[2] = X[2] + Y[1]; \ |
---|
257 | Y[3] = X[3] - (Y[2] ^ ((~Y[1])<<19)); \ |
---|
258 | Y[4] = X[4] ^ Y[3]; \ |
---|
259 | Y[5] = X[5] + Y[4]; \ |
---|
260 | Y[6] = X[6] - (Y[5] ^ ((~Y[4])>>23)); \ |
---|
261 | Y[7] = X[7] ^ Y[6]; \ |
---|
262 | Y[0] += Y[7]; \ |
---|
263 | Y[1] -= Y[0] ^ ((~Y[7])<<19); \ |
---|
264 | Y[2] ^= Y[1]; \ |
---|
265 | Y[3] += Y[2]; \ |
---|
266 | Y[4] -= Y[3] ^ ((~Y[2])>>23); \ |
---|
267 | Y[5] ^= Y[4]; \ |
---|
268 | Y[6] += Y[5]; \ |
---|
269 | Y[7] -= Y[6] ^ W64LIT(0x0123456789ABCDEF) |
---|
270 | |
---|
271 | pass(a,b,c,5,X); |
---|
272 | key_schedule(Y,X); |
---|
273 | pass(c,a,b,7,Y); |
---|
274 | key_schedule(Y,Y); |
---|
275 | pass(b,c,a,9,Y); |
---|
276 | |
---|
277 | digest[0] = a ^ digest[0]; |
---|
278 | digest[1] = b - digest[1]; |
---|
279 | digest[2] = c + digest[2]; |
---|
280 | } |
---|
281 | } |
---|
282 | |
---|
283 | NAMESPACE_END |
---|