1 | /* Do not include ANY system headers here. The implementation is */
|
---|
2 | /* somehow flawed - maybe something gets overlayed by definitions */
|
---|
3 | /* in the system headers. Results will become incorrect. */
|
---|
4 |
|
---|
5 | #include "config_xor.h"
|
---|
6 |
|
---|
7 |
|
---|
8 | #if !defined(HAVE_LONG_64) && !defined(HAVE_LONG_LONG_64)
|
---|
9 |
|
---|
10 | /* Tiger: A Fast New Hash Function
|
---|
11 | *
|
---|
12 | * Ross Anderson and Eli Biham
|
---|
13 | *
|
---|
14 | * From the homepage (http://www.cs.technion.ac.il/~biham/Reports/Tiger/):
|
---|
15 | *
|
---|
16 | * Tiger has no usage restrictions nor patents. It can be used freely,
|
---|
17 | * with the reference implementation, with other implementations or with
|
---|
18 | * a modification to the reference implementation (as long as it still
|
---|
19 | * implements Tiger). We only ask you to let us know about your
|
---|
20 | * implementation and to cite the origin of Tiger and of the reference
|
---|
21 | * implementation.
|
---|
22 | *
|
---|
23 | *
|
---|
24 | * The authors' home pages can be found both in
|
---|
25 | * http://www.cs.technion.ac.il/~biham/ and in
|
---|
26 | * http://www.cl.cam.ac.uk/users/rja14/.
|
---|
27 | * The authors' email addresses are biham@cs.technion.ac.il
|
---|
28 | * and rja14@cl.cam.ac.uk.
|
---|
29 | */
|
---|
30 |
|
---|
31 |
|
---|
32 | #if defined(HAVE_INT_32)
|
---|
33 | typedef unsigned int sh_word32;
|
---|
34 | #elif defined(HAVE_LONG_32)
|
---|
35 | typedef unsigned long sh_word32;
|
---|
36 | #elif defined(HAVE_SHORT_32)
|
---|
37 | typedef unsigned short sh_word32;
|
---|
38 | #else
|
---|
39 | #error No 32 byte type found !
|
---|
40 | #endif
|
---|
41 |
|
---|
42 | typedef unsigned char sh_byte;
|
---|
43 |
|
---|
44 | /* Big endian: */
|
---|
45 | #ifdef WORDS_BIGENDIAN
|
---|
46 | #define BIG_ENDIAN
|
---|
47 | #endif
|
---|
48 |
|
---|
49 | /* NOTE that this code is NOT FULLY OPTIMIZED for any */
|
---|
50 | /* machine. Assembly code might be much faster on some */
|
---|
51 | /* machines, especially if the code is compiled with */
|
---|
52 | /* gcc. */
|
---|
53 |
|
---|
54 | /* The number of passes of the hash function. */
|
---|
55 | /* Three passes are recommended. */
|
---|
56 | /* Use four passes when you need extra security. */
|
---|
57 | /* Must be at least three. */
|
---|
58 | #define PASSES 3
|
---|
59 |
|
---|
60 | extern sh_word32 tiger_table[4*256][2];
|
---|
61 |
|
---|
62 | #define t1 (tiger_table)
|
---|
63 | #define t2 (tiger_table+256)
|
---|
64 | #define t3 (tiger_table+256*2)
|
---|
65 | #define t4 (tiger_table+256*3)
|
---|
66 |
|
---|
67 | #define sh_sub64(s0, s1, p0, p1) \
|
---|
68 | temps0 = (p0); \
|
---|
69 | tcarry = s0 < temps0; \
|
---|
70 | s0 -= temps0; \
|
---|
71 | s1 -= (p1) + tcarry;
|
---|
72 |
|
---|
73 | #define sh_add64(s0, s1, p0, p1) \
|
---|
74 | temps0 = (p0); \
|
---|
75 | s0 += temps0; \
|
---|
76 | tcarry = s0 < temps0; \
|
---|
77 | s1 += (p1) + tcarry;
|
---|
78 |
|
---|
79 | #define sh_xor64(s0, s1, p0, p1) \
|
---|
80 | s0 ^= (p0); \
|
---|
81 | s1 ^= (p1);
|
---|
82 |
|
---|
83 | #define sh_mul5(s0, s1) \
|
---|
84 | tempt0 = s0<<2; \
|
---|
85 | tempt1 = (s1<<2)|(s0>>30); \
|
---|
86 | sh_add64(s0, s1, tempt0, tempt1);
|
---|
87 |
|
---|
88 | #define sh_mul7(s0, s1) \
|
---|
89 | tempt0 = s0<<3; \
|
---|
90 | tempt1 = (s1<<3)|(s0>>29); \
|
---|
91 | sh_sub64(tempt0, tempt1, s0, s1); \
|
---|
92 | s0 = tempt0; \
|
---|
93 | s1 = tempt1;
|
---|
94 |
|
---|
95 | #define sh_mul9(s0, s1) \
|
---|
96 | tempt0 = s0<<3; \
|
---|
97 | tempt1 = (s1<<3)|(s0>>29); \
|
---|
98 | sh_add64(s0, s1, tempt0, tempt1);
|
---|
99 |
|
---|
100 | #define sh_save_abc \
|
---|
101 | aa0 = a0; \
|
---|
102 | aa1 = a1; \
|
---|
103 | bb0 = b0; \
|
---|
104 | bb1 = b1; \
|
---|
105 | cc0 = c0; \
|
---|
106 | cc1 = c1;
|
---|
107 |
|
---|
108 | #define sh_round(a0,a1,b0,b1,c0,c1,x0,x1,mul) \
|
---|
109 | sh_xor64(c0, c1, x0, x1); \
|
---|
110 | temp0 = t1[((c0)>>(0*8))&0xFF][0] ; \
|
---|
111 | temp1 = t1[((c0)>>(0*8))&0xFF][1] ; \
|
---|
112 | temp0 ^= t2[((c0)>>(2*8))&0xFF][0] ; \
|
---|
113 | temp1 ^= t2[((c0)>>(2*8))&0xFF][1] ; \
|
---|
114 | temp0 ^= t3[((c1)>>(0*8))&0xFF][0] ; \
|
---|
115 | temp1 ^= t3[((c1)>>(0*8))&0xFF][1] ; \
|
---|
116 | temp0 ^= t4[((c1)>>(2*8))&0xFF][0] ; \
|
---|
117 | temp1 ^= t4[((c1)>>(2*8))&0xFF][1] ; \
|
---|
118 | sh_sub64(a0, a1, temp0, temp1); \
|
---|
119 | temp0 = t4[((c0)>>(1*8))&0xFF][0] ; \
|
---|
120 | temp1 = t4[((c0)>>(1*8))&0xFF][1] ; \
|
---|
121 | temp0 ^= t3[((c0)>>(3*8))&0xFF][0] ; \
|
---|
122 | temp1 ^= t3[((c0)>>(3*8))&0xFF][1] ; \
|
---|
123 | temp0 ^= t2[((c1)>>(1*8))&0xFF][0] ; \
|
---|
124 | temp1 ^= t2[((c1)>>(1*8))&0xFF][1] ; \
|
---|
125 | temp0 ^= t1[((c1)>>(3*8))&0xFF][0] ; \
|
---|
126 | temp1 ^= t1[((c1)>>(3*8))&0xFF][1] ; \
|
---|
127 | sh_add64(b0, b1, temp0, temp1); \
|
---|
128 | if((mul)==5) \
|
---|
129 | {sh_mul5(b0, b1);} \
|
---|
130 | else \
|
---|
131 | if((mul)==7) \
|
---|
132 | {sh_mul7(b0, b1);} \
|
---|
133 | else \
|
---|
134 | {sh_mul9(b0, b1)};
|
---|
135 |
|
---|
136 | #define sh_pass(a0,a1,b0,b1,c0,c1,mul) \
|
---|
137 | sh_round(a0,a1,b0,b1,c0,c1,x00,x01,mul); \
|
---|
138 | sh_round(b0,b1,c0,c1,a0,a1,x10,x11,mul); \
|
---|
139 | sh_round(c0,c1,a0,a1,b0,b1,x20,x21,mul); \
|
---|
140 | sh_round(a0,a1,b0,b1,c0,c1,x30,x31,mul); \
|
---|
141 | sh_round(b0,b1,c0,c1,a0,a1,x40,x41,mul); \
|
---|
142 | sh_round(c0,c1,a0,a1,b0,b1,x50,x51,mul); \
|
---|
143 | sh_round(a0,a1,b0,b1,c0,c1,x60,x61,mul); \
|
---|
144 | sh_round(b0,b1,c0,c1,a0,a1,x70,x71,mul);
|
---|
145 |
|
---|
146 | #define sh_key_schedule \
|
---|
147 | sh_sub64(x00, x01, x70^0xA5A5A5A5, x71^0xA5A5A5A5); \
|
---|
148 | sh_xor64(x10, x11, x00, x01); \
|
---|
149 | sh_add64(x20, x21, x10, x11); \
|
---|
150 | sh_sub64(x30, x31, x20^((~x10)<<19), ~x21^(((x11)<<19)|((x10)>>13))); \
|
---|
151 | sh_xor64(x40, x41, x30, x31); \
|
---|
152 | sh_add64(x50, x51, x40, x41); \
|
---|
153 | sh_sub64(x60, x61, ~x50^(((x40)>>23)|((x41)<<9)), x51^((~x41)>>23)); \
|
---|
154 | sh_xor64(x70, x71, x60, x61); \
|
---|
155 | sh_add64(x00, x01, x70, x71); \
|
---|
156 | sh_sub64(x10, x11, x00^((~x70)<<19), ~x01^(((x71)<<19)|((x70)>>13))); \
|
---|
157 | sh_xor64(x20, x21, x10, x11); \
|
---|
158 | sh_add64(x30, x31, x20, x21); \
|
---|
159 | sh_sub64(x40, x41, ~x30^(((x20)>>23)|((x21)<<9)), x31^((~x21)>>23)); \
|
---|
160 | sh_xor64(x50, x51, x40, x41); \
|
---|
161 | sh_add64(x60, x61, x50, x51); \
|
---|
162 | sh_sub64(x70, x71, x60^0x89ABCDEF, x61^0x01234567);
|
---|
163 |
|
---|
164 | #define sh_feedforward \
|
---|
165 | sh_xor64(a0, a1, aa0, aa1); \
|
---|
166 | sh_sub64(b0, b1, bb0, bb1); \
|
---|
167 | sh_add64(c0, c1, cc0, cc1);
|
---|
168 |
|
---|
169 | #ifdef UNROLL_COMPRESS
|
---|
170 | #define sh_compress \
|
---|
171 | sh_save_abc \
|
---|
172 | sh_pass(a0,a1,b0,b1,c0,c1,5); \
|
---|
173 | sh_key_schedule; \
|
---|
174 | sh_pass(c0,c1,a0,a1,b0,b1,7); \
|
---|
175 | sh_key_schedule; \
|
---|
176 | sh_pass(b0,b1,c0,c1,a0,a1,9); \
|
---|
177 | for(pass_no=3; pass_no<PASSES; pass_no++) { \
|
---|
178 | sh_key_schedule \
|
---|
179 | sh_pass(a0,a1,b0,b1,c0,c1,9); \
|
---|
180 | tmpa=a0; a0=c0; c0=b0; b0=tmpa; \
|
---|
181 | tmpa=a1; a1=c1; c1=b1; b1=tmpa;} \
|
---|
182 | sh_feedforward
|
---|
183 | #else
|
---|
184 | #define sh_compress \
|
---|
185 | sh_save_abc \
|
---|
186 | for(pass_no=0; pass_no<PASSES; pass_no++) { \
|
---|
187 | if(pass_no != 0) {sh_key_schedule} \
|
---|
188 | sh_pass(a0,a1,b0,b1,c0,c1,(pass_no==0?5:pass_no==1?7:9)) \
|
---|
189 | tmpa=a0; a0=c0; c0=b0; b0=tmpa; \
|
---|
190 | tmpa=a1; a1=c1; c1=b1; b1=tmpa;} \
|
---|
191 | sh_feedforward
|
---|
192 | #endif
|
---|
193 |
|
---|
194 | #define tiger_compress_macro(str, state) \
|
---|
195 | { \
|
---|
196 | register sh_word32 a0, a1, b0, b1, c0, c1, tmpa; \
|
---|
197 | sh_word32 aa0, aa1, bb0, bb1, cc0, cc1; \
|
---|
198 | sh_word32 x00, x01, x10, x11, x20, x21, x30, x31, \
|
---|
199 | x40, x41, x50, x51, x60, x61, x70, x71; \
|
---|
200 | register sh_word32 temp0, temp1, tempt0, tempt1, temps0, tcarry; \
|
---|
201 | int pass_no; \
|
---|
202 | \
|
---|
203 | a0 = state[0]; \
|
---|
204 | a1 = state[1]; \
|
---|
205 | b0 = state[2]; \
|
---|
206 | b1 = state[3]; \
|
---|
207 | c0 = state[4]; \
|
---|
208 | c1 = state[5]; \
|
---|
209 | \
|
---|
210 | x00=str[0*2]; x01=str[0*2+1]; x10=str[1*2]; x11=str[1*2+1]; \
|
---|
211 | x20=str[2*2]; x21=str[2*2+1]; x30=str[3*2]; x31=str[3*2+1]; \
|
---|
212 | x40=str[4*2]; x41=str[4*2+1]; x50=str[5*2]; x51=str[5*2+1]; \
|
---|
213 | x60=str[6*2]; x61=str[6*2+1]; x70=str[7*2]; x71=str[7*2+1]; \
|
---|
214 | \
|
---|
215 | sh_compress; \
|
---|
216 | \
|
---|
217 | state[0] = a0; \
|
---|
218 | state[1] = a1; \
|
---|
219 | state[2] = b0; \
|
---|
220 | state[3] = b1; \
|
---|
221 | state[4] = c0; \
|
---|
222 | state[5] = c1; \
|
---|
223 | }
|
---|
224 |
|
---|
225 | #ifdef UNROLL_COMPRESS
|
---|
226 | /* The compress function is inlined */
|
---|
227 | #define tiger_compress(str, state) \
|
---|
228 | tiger_compress_macro(((sh_word32*)str), ((sh_word32*)state))
|
---|
229 | #else
|
---|
230 | /* The compress function is a function */
|
---|
231 | void
|
---|
232 | tiger_compress(sh_word32 *str, sh_word32 state[6])
|
---|
233 | {
|
---|
234 | tiger_compress_macro(((sh_word32*)str), ((sh_word32*)state));
|
---|
235 | }
|
---|
236 | #endif
|
---|
237 |
|
---|
238 | void
|
---|
239 | tiger_t(sh_word32 *str, sh_word32 length, sh_word32 res[6])
|
---|
240 | {
|
---|
241 | register sh_word32 i;
|
---|
242 | #ifdef BIG_ENDIAN
|
---|
243 | register sh_word32 j;
|
---|
244 | sh_byte temp[64];
|
---|
245 | #endif
|
---|
246 |
|
---|
247 | for(i=length; i>=64; i-=64)
|
---|
248 | {
|
---|
249 | #ifdef BIG_ENDIAN
|
---|
250 | for(j=0; j<64; j++)
|
---|
251 | temp[j^3] = ((sh_byte*)str)[j];
|
---|
252 | tiger_compress(((sh_word32*)temp), res);
|
---|
253 | #else
|
---|
254 | tiger_compress(str, res);
|
---|
255 | #endif
|
---|
256 | str += 16;
|
---|
257 | }
|
---|
258 | }
|
---|
259 |
|
---|
260 | void
|
---|
261 | tiger(sh_word32 *str, sh_word32 length, sh_word32 res[6])
|
---|
262 | {
|
---|
263 | register sh_word32 i, j;
|
---|
264 | sh_byte temp[64];
|
---|
265 |
|
---|
266 | for(i=length; i>=64; i-=64)
|
---|
267 | {
|
---|
268 | #ifdef BIG_ENDIAN
|
---|
269 | for(j=0; j<64; j++)
|
---|
270 | temp[j^3] = ((sh_byte*)str)[j];
|
---|
271 | tiger_compress(((sh_word32*)temp), res);
|
---|
272 | #else
|
---|
273 | tiger_compress(str, res);
|
---|
274 | #endif
|
---|
275 | str += 16;
|
---|
276 | }
|
---|
277 |
|
---|
278 | #ifdef BIG_ENDIAN
|
---|
279 | for(j=0; j<i; j++)
|
---|
280 | temp[j^3] = ((sh_byte*)str)[j];
|
---|
281 |
|
---|
282 | temp[j^3] = 0x01;
|
---|
283 | j++;
|
---|
284 | for(; j&7; j++)
|
---|
285 | temp[j^3] = 0;
|
---|
286 | #else
|
---|
287 | for(j=0; j<i; j++)
|
---|
288 | temp[j] = ((sh_byte*)str)[j];
|
---|
289 |
|
---|
290 | temp[j++] = 0x01;
|
---|
291 | for(; j&7; j++)
|
---|
292 | temp[j] = 0;
|
---|
293 | #endif
|
---|
294 | if(j>56)
|
---|
295 | {
|
---|
296 | for(; j<64; j++)
|
---|
297 | temp[j] = 0;
|
---|
298 | tiger_compress(((sh_word32*)temp), res);
|
---|
299 | j=0;
|
---|
300 | }
|
---|
301 |
|
---|
302 | for(; j<56; j++)
|
---|
303 | temp[j] = 0;
|
---|
304 | ((sh_word32*)(&(temp[56])))[0] = ((sh_word32)length)<<3;
|
---|
305 | ((sh_word32*)(&(temp[56])))[1] = 0;
|
---|
306 | tiger_compress(((sh_word32*)temp), res);
|
---|
307 | }
|
---|
308 |
|
---|
309 | #else
|
---|
310 | void dummy_1 (int a)
|
---|
311 | {
|
---|
312 | (void) a;
|
---|
313 | return;
|
---|
314 | }
|
---|
315 | #endif
|
---|
316 |
|
---|
317 |
|
---|
318 |
|
---|
319 |
|
---|
320 |
|
---|
321 |
|
---|
322 |
|
---|
323 |
|
---|
324 |
|
---|