1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 6 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 The PHP Group |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 3.01 of the PHP license, |
8 : | that is bundled with this package in the file LICENSE, and is |
9 : | available through the world-wide-web at the following url: |
10 : | http://www.php.net/license/3_01.txt |
11 : | If you did not receive a copy of the PHP license and are unable to |
12 : | obtain it through the world-wide-web, please send a note to |
13 : | license@php.net so we can mail you a copy immediately. |
14 : +----------------------------------------------------------------------+
15 : | Authors: Michael Wallner <mike@php.net> |
16 : | Sara Golemon <pollita@php.net> |
17 : +----------------------------------------------------------------------+
18 : */
19 :
20 : /* $Id: hash_tiger.c 276986 2009-03-10 23:40:06Z helly $ */
21 :
22 : #include "php_hash.h"
23 : #include "php_hash_tiger.h"
24 : #include "php_hash_tiger_tables.h"
25 :
26 : #if (defined(__APPLE__) || defined(__APPLE_CC__)) && (defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__))
27 : # if defined(__LITTLE_ENDIAN__)
28 : # undef WORDS_BIGENDIAN
29 : # else
30 : # if defined(__BIG_ENDIAN__)
31 : # define WORDS_BIGENDIAN
32 : # endif
33 : # endif
34 : #endif
35 :
36 : /* {{{ */
37 : #define save_abc \
38 : aa = a; \
39 : bb = b; \
40 : cc = c;
41 :
42 : #define round(a,b,c,x,mul) \
43 : c ^= x; \
44 : a -= t1[(unsigned char)(c)] ^ \
45 : t2[(unsigned char)(((php_hash_uint32)(c))>>(2*8))] ^ \
46 : t3[(unsigned char)((c)>>(4*8))] ^ \
47 : t4[(unsigned char)(((php_hash_uint32)((c)>>(4*8)))>>(2*8))] ; \
48 : b += t4[(unsigned char)(((php_hash_uint32)(c))>>(1*8))] ^ \
49 : t3[(unsigned char)(((php_hash_uint32)(c))>>(3*8))] ^ \
50 : t2[(unsigned char)(((php_hash_uint32)((c)>>(4*8)))>>(1*8))] ^ \
51 : t1[(unsigned char)(((php_hash_uint32)((c)>>(4*8)))>>(3*8))]; \
52 : b *= mul;
53 :
54 : #define pass(a,b,c,mul) \
55 : round(a,b,c,x0,mul) \
56 : round(b,c,a,x1,mul) \
57 : round(c,a,b,x2,mul) \
58 : round(a,b,c,x3,mul) \
59 : round(b,c,a,x4,mul) \
60 : round(c,a,b,x5,mul) \
61 : round(a,b,c,x6,mul) \
62 : round(b,c,a,x7,mul)
63 :
64 : #define key_schedule \
65 : x0 -= x7 ^ L64(0xA5A5A5A5A5A5A5A5); \
66 : x1 ^= x0; \
67 : x2 += x1; \
68 : x3 -= x2 ^ ((~x1)<<19); \
69 : x4 ^= x3; \
70 : x5 += x4; \
71 : x6 -= x5 ^ ((~x4)>>23); \
72 : x7 ^= x6; \
73 : x0 += x7; \
74 : x1 -= x0 ^ ((~x7)<<19); \
75 : x2 ^= x1; \
76 : x3 += x2; \
77 : x4 -= x3 ^ ((~x2)>>23); \
78 : x5 ^= x4; \
79 : x6 += x5; \
80 : x7 -= x6 ^ L64(0x0123456789ABCDEF);
81 :
82 : #define feedforward \
83 : a ^= aa; \
84 : b -= bb; \
85 : c += cc;
86 :
87 : #define compress(passes) \
88 : save_abc \
89 : pass(a,b,c,5) \
90 : key_schedule \
91 : pass(c,a,b,7) \
92 : key_schedule \
93 : pass(b,c,a,9) \
94 : for(pass_no=0; pass_no<passes; pass_no++) { \
95 : key_schedule \
96 : pass(a,b,c,9) \
97 : tmpa=a; a=c; c=b; b=tmpa; \
98 : } \
99 : feedforward
100 :
101 : #define split_ex(str) \
102 : x0=str[0]; x1=str[1]; x2=str[2]; x3=str[3]; \
103 : x4=str[4]; x5=str[5]; x6=str[6]; x7=str[7];
104 : #ifdef WORDS_BIGENDIAN
105 : # define split(str) \
106 : { \
107 : int i; \
108 : php_hash_uint64 tmp[8]; \
109 : \
110 : for (i = 0; i < 64; ++i) { \
111 : ((unsigned char *) tmp)[i^7] = ((unsigned char *) str)[i]; \
112 : } \
113 : split_ex(tmp); \
114 : }
115 : #else
116 : # define split split_ex
117 : #endif
118 :
119 : #define tiger_compress(passes, str, state) \
120 : { \
121 : register php_hash_uint64 a, b, c, tmpa, x0, x1, x2, x3, x4, x5, x6, x7; \
122 : php_hash_uint64 aa, bb, cc; \
123 : int pass_no; \
124 : \
125 : a = state[0]; \
126 : b = state[1]; \
127 : c = state[2]; \
128 : \
129 : split(str); \
130 : \
131 : compress(passes); \
132 : \
133 : state[0] = a; \
134 : state[1] = b; \
135 : state[2] = c; \
136 : }
137 : /* }}} */
138 :
139 : static inline void TigerFinalize(PHP_TIGER_CTX *context)
140 40 : {
141 40 : context->passed += (php_hash_uint64) context->length << 3;
142 :
143 40 : context->buffer[context->length++] = 0x1;
144 40 : if (context->length % 8) {
145 37 : memset(&context->buffer[context->length], 0, 8-context->length%8);
146 37 : context->length += 8-context->length%8;
147 : }
148 :
149 40 : if (context->length > 56) {
150 10 : memset(&context->buffer[context->length], 0, 64 - context->length);
151 10 : tiger_compress(context->passes, ((php_hash_uint64 *) context->buffer), context->state);
152 10 : memset(context->buffer, 0, 56);
153 : } else {
154 30 : memset(&context->buffer[context->length], 0, 56 - context->length);
155 : }
156 :
157 : #ifndef WORDS_BIGENDIAN
158 40 : memcpy(&context->buffer[56], &context->passed, sizeof(php_hash_uint64));
159 : #else
160 : context->buffer[56] = (unsigned char) (context->passed & 0xff);
161 : context->buffer[57] = (unsigned char) ((context->passed >> 8) & 0xff);
162 : context->buffer[58] = (unsigned char) ((context->passed >> 16) & 0xff);
163 : context->buffer[59] = (unsigned char) ((context->passed >> 24) & 0xff);
164 : context->buffer[60] = (unsigned char) ((context->passed >> 32) & 0xff);
165 : context->buffer[61] = (unsigned char) ((context->passed >> 40) & 0xff);
166 : context->buffer[62] = (unsigned char) ((context->passed >> 48) & 0xff);
167 : context->buffer[63] = (unsigned char) ((context->passed >> 56) & 0xff);
168 : #endif
169 40 : tiger_compress(context->passes, ((php_hash_uint64 *) context->buffer), context->state);
170 40 : }
171 :
172 : PHP_HASH_API void PHP_3TIGERInit(PHP_TIGER_CTX *context)
173 29 : {
174 29 : memset(context, 0, sizeof(*context));
175 29 : context->state[0] = L64(0x0123456789ABCDEF);
176 29 : context->state[1] = L64(0xFEDCBA9876543210);
177 29 : context->state[2] = L64(0xF096A5B4C3B2E187);
178 29 : }
179 :
180 : PHP_HASH_API void PHP_4TIGERInit(PHP_TIGER_CTX *context)
181 12 : {
182 12 : memset(context, 0, sizeof(*context));
183 12 : context->passes = 1;
184 12 : context->state[0] = L64(0x0123456789ABCDEF);
185 12 : context->state[1] = L64(0xFEDCBA9876543210);
186 12 : context->state[2] = L64(0xF096A5B4C3B2E187);
187 12 : }
188 :
189 : PHP_HASH_API void PHP_TIGERUpdate(PHP_TIGER_CTX *context, const unsigned char *input, size_t len)
190 53 : {
191 53 : if (context->length + len < 64) {
192 39 : memcpy(&context->buffer[context->length], input, len);
193 39 : context->length += len;
194 : } else {
195 14 : size_t i = 0, r = (context->length + len) % 64;
196 :
197 14 : if (context->length) {
198 5 : i = 64 - context->length;
199 5 : memcpy(&context->buffer[context->length], input, i);
200 5 : tiger_compress(context->passes, ((const php_hash_uint64 *) context->buffer), context->state);
201 5 : memset(context->buffer, 0, 64);
202 5 : context->passed += 512;
203 : }
204 :
205 26 : for (; i + 64 <= len; i += 64) {
206 12 : memcpy(context->buffer, &input[i], 64);
207 12 : tiger_compress(context->passes, ((const php_hash_uint64 *) context->buffer), context->state);
208 12 : context->passed += 512;
209 : }
210 14 : memset(&context->buffer[r], 0, 64-r);
211 14 : memcpy(context->buffer, &input[i], r);
212 14 : context->length = r;
213 : }
214 53 : }
215 :
216 : PHP_HASH_API void PHP_TIGER128Final(unsigned char digest[16], PHP_TIGER_CTX *context)
217 8 : {
218 8 : TigerFinalize(context);
219 :
220 8 : digest[0] = (unsigned char) ((context->state[0] >> 56) & 0xff);
221 8 : digest[1] = (unsigned char) ((context->state[0] >> 48) & 0xff);
222 8 : digest[2] = (unsigned char) ((context->state[0] >> 40) & 0xff);
223 8 : digest[3] = (unsigned char) ((context->state[0] >> 32) & 0xff);
224 8 : digest[4] = (unsigned char) ((context->state[0] >> 24) & 0xff);
225 8 : digest[5] = (unsigned char) ((context->state[0] >> 16) & 0xff);
226 8 : digest[6] = (unsigned char) ((context->state[0] >> 8) & 0xff);
227 8 : digest[7] = (unsigned char) (context->state[0] & 0xff);
228 8 : digest[8] = (unsigned char) ((context->state[1] >> 56) & 0xff);
229 8 : digest[9] = (unsigned char) ((context->state[1] >> 48) & 0xff);
230 8 : digest[10] = (unsigned char) ((context->state[1] >> 40) & 0xff);
231 8 : digest[11] = (unsigned char) ((context->state[1] >> 32) & 0xff);
232 8 : digest[12] = (unsigned char) ((context->state[1] >> 24) & 0xff);
233 8 : digest[13] = (unsigned char) ((context->state[1] >> 16) & 0xff);
234 8 : digest[14] = (unsigned char) ((context->state[1] >> 8) & 0xff);
235 8 : digest[15] = (unsigned char) (context->state[1] & 0xff);
236 :
237 8 : memset(context, 0, sizeof(*context));
238 8 : }
239 :
240 : PHP_HASH_API void PHP_TIGER160Final(unsigned char digest[20], PHP_TIGER_CTX *context)
241 8 : {
242 8 : TigerFinalize(context);
243 :
244 8 : digest[0] = (unsigned char) ((context->state[0] >> 56) & 0xff);
245 8 : digest[1] = (unsigned char) ((context->state[0] >> 48) & 0xff);
246 8 : digest[2] = (unsigned char) ((context->state[0] >> 40) & 0xff);
247 8 : digest[3] = (unsigned char) ((context->state[0] >> 32) & 0xff);
248 8 : digest[4] = (unsigned char) ((context->state[0] >> 24) & 0xff);
249 8 : digest[5] = (unsigned char) ((context->state[0] >> 16) & 0xff);
250 8 : digest[6] = (unsigned char) ((context->state[0] >> 8) & 0xff);
251 8 : digest[7] = (unsigned char) (context->state[0] & 0xff);
252 8 : digest[8] = (unsigned char) ((context->state[1] >> 56) & 0xff);
253 8 : digest[9] = (unsigned char) ((context->state[1] >> 48) & 0xff);
254 8 : digest[10] = (unsigned char) ((context->state[1] >> 40) & 0xff);
255 8 : digest[11] = (unsigned char) ((context->state[1] >> 32) & 0xff);
256 8 : digest[12] = (unsigned char) ((context->state[1] >> 24) & 0xff);
257 8 : digest[13] = (unsigned char) ((context->state[1] >> 16) & 0xff);
258 8 : digest[14] = (unsigned char) ((context->state[1] >> 8) & 0xff);
259 8 : digest[15] = (unsigned char) (context->state[1] & 0xff);
260 8 : digest[16] = (unsigned char) ((context->state[2] >> 56) & 0xff);
261 8 : digest[17] = (unsigned char) ((context->state[2] >> 48) & 0xff);
262 8 : digest[18] = (unsigned char) ((context->state[2] >> 40) & 0xff);
263 8 : digest[19] = (unsigned char) ((context->state[2] >> 32) & 0xff);
264 :
265 8 : memset(context, 0, sizeof(*context));
266 8 : }
267 :
268 : PHP_HASH_API void PHP_TIGER192Final(unsigned char digest[24], PHP_TIGER_CTX *context)
269 24 : {
270 24 : TigerFinalize(context);
271 :
272 24 : digest[0] = (unsigned char) ((context->state[0] >> 56) & 0xff);
273 24 : digest[1] = (unsigned char) ((context->state[0] >> 48) & 0xff);
274 24 : digest[2] = (unsigned char) ((context->state[0] >> 40) & 0xff);
275 24 : digest[3] = (unsigned char) ((context->state[0] >> 32) & 0xff);
276 24 : digest[4] = (unsigned char) ((context->state[0] >> 24) & 0xff);
277 24 : digest[5] = (unsigned char) ((context->state[0] >> 16) & 0xff);
278 24 : digest[6] = (unsigned char) ((context->state[0] >> 8) & 0xff);
279 24 : digest[7] = (unsigned char) (context->state[0] & 0xff);
280 24 : digest[8] = (unsigned char) ((context->state[1] >> 56) & 0xff);
281 24 : digest[9] = (unsigned char) ((context->state[1] >> 48) & 0xff);
282 24 : digest[10] = (unsigned char) ((context->state[1] >> 40) & 0xff);
283 24 : digest[11] = (unsigned char) ((context->state[1] >> 32) & 0xff);
284 24 : digest[12] = (unsigned char) ((context->state[1] >> 24) & 0xff);
285 24 : digest[13] = (unsigned char) ((context->state[1] >> 16) & 0xff);
286 24 : digest[14] = (unsigned char) ((context->state[1] >> 8) & 0xff);
287 24 : digest[15] = (unsigned char) (context->state[1] & 0xff);
288 24 : digest[16] = (unsigned char) ((context->state[2] >> 56) & 0xff);
289 24 : digest[17] = (unsigned char) ((context->state[2] >> 48) & 0xff);
290 24 : digest[18] = (unsigned char) ((context->state[2] >> 40) & 0xff);
291 24 : digest[19] = (unsigned char) ((context->state[2] >> 32) & 0xff);
292 24 : digest[20] = (unsigned char) ((context->state[2] >> 24) & 0xff);
293 24 : digest[21] = (unsigned char) ((context->state[2] >> 16) & 0xff);
294 24 : digest[22] = (unsigned char) ((context->state[2] >> 8) & 0xff);
295 24 : digest[23] = (unsigned char) (context->state[2] & 0xff);
296 :
297 24 : memset(context, 0, sizeof(*context));
298 24 : }
299 :
300 : #define PHP_HASH_TIGER_OPS(p, b) \
301 : const php_hash_ops php_hash_##p##tiger##b##_ops = { \
302 : (php_hash_init_func_t) PHP_##p##TIGERInit, \
303 : (php_hash_update_func_t) PHP_TIGERUpdate, \
304 : (php_hash_final_func_t) PHP_TIGER##b##Final, \
305 : (php_hash_copy_func_t) php_hash_copy, \
306 : b/8, \
307 : 64, \
308 : sizeof(PHP_TIGER_CTX) \
309 : }
310 :
311 : PHP_HASH_TIGER_OPS(3, 128);
312 : PHP_HASH_TIGER_OPS(3, 160);
313 : PHP_HASH_TIGER_OPS(3, 192);
314 : PHP_HASH_TIGER_OPS(4, 128);
315 : PHP_HASH_TIGER_OPS(4, 160);
316 : PHP_HASH_TIGER_OPS(4, 192);
317 :
318 : /*
319 : * Local variables:
320 : * tab-width: 4
321 : * c-basic-offset: 4
322 : * End:
323 : * vim600: sw=4 ts=4 fdm=marker
324 : * vim<600: sw=4 ts=4
325 : */
|