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
NAMESPACE_BEGIN(CryptoPP)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
TruncatedFinal(byte * hash,size_t size)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
Transform(word64 * digest,const word64 * X)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 AS2( lea edx, [table])
54 AS2( mov eax, digest)
55 AS2( mov esi, X)
56 #endif
57 AS2( movq mm0, [eax])
58 AS2( movq mm1, [eax+1*8])
59 AS2( movq mm5, mm1)
60 AS2( movq mm2, [eax+2*8])
61 AS2( movq mm7, [edx+4*2048+0*8])
62 AS2( movq mm6, [edx+4*2048+1*8])
63 AS2( mov ecx, esp)
64 AS2( and esp, 0xfffffff0)
65 AS2( sub esp, 8*8)
66 AS_PUSH_IF86(cx)
67
68 #define SSE2_round(a,b,c,x,mul) \
69 AS2( pxor c, [x])\
70 AS2( movd ecx, c)\
71 AS2( movzx edi, cl)\
72 AS2( movq mm3, [edx+0*2048+edi*8])\
73 AS2( movzx edi, ch)\
74 AS2( movq mm4, [edx+3*2048+edi*8])\
75 AS2( shr ecx, 16)\
76 AS2( movzx edi, cl)\
77 AS2( pxor mm3, [edx+1*2048+edi*8])\
78 AS2( movzx edi, ch)\
79 AS2( pxor mm4, [edx+2*2048+edi*8])\
80 AS3( pextrw ecx, c, 2)\
81 AS2( movzx edi, cl)\
82 AS2( pxor mm3, [edx+2*2048+edi*8])\
83 AS2( movzx edi, ch)\
84 AS2( pxor mm4, [edx+1*2048+edi*8])\
85 AS3( pextrw ecx, c, 3)\
86 AS2( movzx edi, cl)\
87 AS2( pxor mm3, [edx+3*2048+edi*8])\
88 AS2( psubq a, mm3)\
89 AS2( movzx edi, ch)\
90 AS2( pxor mm4, [edx+0*2048+edi*8])\
91 AS2( paddq b, mm4)\
92 SSE2_mul_##mul(b)
93
94 #define SSE2_mul_5(b) \
95 AS2( movq mm3, b)\
96 AS2( psllq b, 2)\
97 AS2( paddq b, mm3)
98
99 #define SSE2_mul_7(b) \
100 AS2( movq mm3, b)\
101 AS2( psllq b, 3)\
102 AS2( psubq b, mm3)
103
104 #define SSE2_mul_9(b) \
105 AS2( movq mm3, b)\
106 AS2( psllq b, 3)\
107 AS2( paddq b, mm3)
108
109 #define label2_5 1
110 #define label2_7 2
111 #define label2_9 3
112
113 #define SSE2_pass(A,B,C,mul,X) \
114 AS2( xor ebx, ebx)\
115 ASL(mul)\
116 SSE2_round(A,B,C,X+0*8+ebx,mul)\
117 SSE2_round(B,C,A,X+1*8+ebx,mul)\
118 AS2( cmp ebx, 6*8)\
119 ASJ( je, label2_##mul, f)\
120 SSE2_round(C,A,B,X+2*8+ebx,mul)\
121 AS2( add ebx, 3*8)\
122 ASJ( jmp, mul, b)\
123 ASL(label2_##mul)
124
125 #define SSE2_key_schedule(Y,X) \
126 AS2( movq mm3, [X+7*8])\
127 AS2( pxor mm3, mm6)\
128 AS2( movq mm4, [X+0*8])\
129 AS2( psubq mm4, mm3)\
130 AS2( movq [Y+0*8], mm4)\
131 AS2( pxor mm4, [X+1*8])\
132 AS2( movq mm3, mm4)\
133 AS2( movq [Y+1*8], mm4)\
134 AS2( paddq mm4, [X+2*8])\
135 AS2( pxor mm3, mm7)\
136 AS2( psllq mm3, 19)\
137 AS2( movq [Y+2*8], mm4)\
138 AS2( pxor mm3, mm4)\
139 AS2( movq mm4, [X+3*8])\
140 AS2( psubq mm4, mm3)\
141 AS2( movq [Y+3*8], mm4)\
142 AS2( pxor mm4, [X+4*8])\
143 AS2( movq mm3, mm4)\
144 AS2( movq [Y+4*8], mm4)\
145 AS2( paddq mm4, [X+5*8])\
146 AS2( pxor mm3, mm7)\
147 AS2( psrlq mm3, 23)\
148 AS2( movq [Y+5*8], mm4)\
149 AS2( pxor mm3, mm4)\
150 AS2( movq mm4, [X+6*8])\
151 AS2( psubq mm4, mm3)\
152 AS2( movq [Y+6*8], mm4)\
153 AS2( pxor mm4, [X+7*8])\
154 AS2( movq mm3, mm4)\
155 AS2( movq [Y+7*8], mm4)\
156 AS2( paddq mm4, [Y+0*8])\
157 AS2( pxor mm3, mm7)\
158 AS2( psllq mm3, 19)\
159 AS2( movq [Y+0*8], mm4)\
160 AS2( pxor mm3, mm4)\
161 AS2( movq mm4, [Y+1*8])\
162 AS2( psubq mm4, mm3)\
163 AS2( movq [Y+1*8], mm4)\
164 AS2( pxor mm4, [Y+2*8])\
165 AS2( movq mm3, mm4)\
166 AS2( movq [Y+2*8], mm4)\
167 AS2( paddq mm4, [Y+3*8])\
168 AS2( pxor mm3, mm7)\
169 AS2( psrlq mm3, 23)\
170 AS2( movq [Y+3*8], mm4)\
171 AS2( pxor mm3, mm4)\
172 AS2( movq mm4, [Y+4*8])\
173 AS2( psubq mm4, mm3)\
174 AS2( movq [Y+4*8], mm4)\
175 AS2( pxor mm4, [Y+5*8])\
176 AS2( movq [Y+5*8], mm4)\
177 AS2( paddq mm4, [Y+6*8])\
178 AS2( movq [Y+6*8], mm4)\
179 AS2( pxor mm4, [edx+4*2048+2*8])\
180 AS2( movq mm3, [Y+7*8])\
181 AS2( psubq mm3, mm4)\
182 AS2( movq [Y+7*8], mm3)
183
184 #if CRYPTOPP_BOOL_X32
185 SSE2_pass(mm0, mm1, mm2, 5, esi)
186 SSE2_key_schedule(esp+8, esi)
187 SSE2_pass(mm2, mm0, mm1, 7, esp+8)
188 SSE2_key_schedule(esp+8, esp+8)
189 SSE2_pass(mm1, mm2, mm0, 9, esp+8)
190 #else
191 SSE2_pass(mm0, mm1, mm2, 5, esi)
192 SSE2_key_schedule(esp+4, esi)
193 SSE2_pass(mm2, mm0, mm1, 7, esp+4)
194 SSE2_key_schedule(esp+4, esp+4)
195 SSE2_pass(mm1, mm2, mm0, 9, esp+4)
196 #endif
197
198 AS2( pxor mm0, [eax+0*8])
199 AS2( movq [eax+0*8], mm0)
200 AS2( psubq mm1, mm5)
201 AS2( movq [eax+1*8], mm1)
202 AS2( paddq mm2, [eax+2*8])
203 AS2( movq [eax+2*8], mm2)
204
205 AS_POP_IF86(sp)
206 AS1( emms)
207
208 #ifdef __GNUC__
209 AS_POP_IF86(bx)
210 ATT_PREFIX
211 :
212 : "a" (digest), "S" (X), "d" (table)
213 : "%ecx", "%edi", "memory", "cc"
214 );
215 #endif
216 }
217 else
218 #endif
219 {
220 word64 a = digest[0];
221 word64 b = digest[1];
222 word64 c = digest[2];
223 word64 Y[8];
224
225 #define t1 (table)
226 #define t2 (table+256)
227 #define t3 (table+256*2)
228 #define t4 (table+256*3)
229
230 #define round(a,b,c,x,mul) \
231 c ^= x; \
232 a -= t1[GETBYTE(c,0)] ^ t2[GETBYTE(c,2)] ^ t3[GETBYTE(c,4)] ^ t4[GETBYTE(c,6)]; \
233 b += t4[GETBYTE(c,1)] ^ t3[GETBYTE(c,3)] ^ t2[GETBYTE(c,5)] ^ t1[GETBYTE(c,7)]; \
234 b *= mul
235
236 #define pass(a,b,c,mul,X) {\
237 int i=0;\
238 while (true)\
239 {\
240 round(a,b,c,X[i+0],mul); \
241 round(b,c,a,X[i+1],mul); \
242 if (i==6)\
243 break;\
244 round(c,a,b,X[i+2],mul); \
245 i+=3;\
246 }}
247
248 #define key_schedule(Y,X) \
249 Y[0] = X[0] - (X[7]^W64LIT(0xA5A5A5A5A5A5A5A5)); \
250 Y[1] = X[1] ^ Y[0]; \
251 Y[2] = X[2] + Y[1]; \
252 Y[3] = X[3] - (Y[2] ^ ((~Y[1])<<19)); \
253 Y[4] = X[4] ^ Y[3]; \
254 Y[5] = X[5] + Y[4]; \
255 Y[6] = X[6] - (Y[5] ^ ((~Y[4])>>23)); \
256 Y[7] = X[7] ^ Y[6]; \
257 Y[0] += Y[7]; \
258 Y[1] -= Y[0] ^ ((~Y[7])<<19); \
259 Y[2] ^= Y[1]; \
260 Y[3] += Y[2]; \
261 Y[4] -= Y[3] ^ ((~Y[2])>>23); \
262 Y[5] ^= Y[4]; \
263 Y[6] += Y[5]; \
264 Y[7] -= Y[6] ^ W64LIT(0x0123456789ABCDEF)
265
266 pass(a,b,c,5,X);
267 key_schedule(Y,X);
268 pass(c,a,b,7,Y);
269 key_schedule(Y,Y);
270 pass(b,c,a,9,Y);
271
272 digest[0] = a ^ digest[0];
273 digest[1] = b - digest[1];
274 digest[2] = c + digest[2];
275 }
276 }
277
278 NAMESPACE_END
279