1 | /* |
2 | +----------------------------------------------------------------------+ |
3 | | PHP Version 5 | |
4 | +----------------------------------------------------------------------+ |
5 | | Copyright (c) 1997-2015 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$ */ |
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 | unsigned 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 | { |
141 | context->passed += (php_hash_uint64) context->length << 3; |
142 | |
143 | context->buffer[context->length++] = 0x1; |
144 | if (context->length % 8) { |
145 | memset(&context->buffer[context->length], 0, 8-context->length%8); |
146 | context->length += 8-context->length%8; |
147 | } |
148 | |
149 | if (context->length > 56) { |
150 | memset(&context->buffer[context->length], 0, 64 - context->length); |
151 | tiger_compress(context->passes, ((php_hash_uint64 *) context->buffer), context->state); |
152 | memset(context->buffer, 0, 56); |
153 | } else { |
154 | memset(&context->buffer[context->length], 0, 56 - context->length); |
155 | } |
156 | |
157 | #ifndef WORDS_BIGENDIAN |
158 | 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 | tiger_compress(context->passes, ((php_hash_uint64 *) context->buffer), context->state); |
170 | } |
171 | |
172 | static inline void TigerDigest(unsigned char *digest_str, unsigned int digest_len, PHP_TIGER_CTX *context) |
173 | { |
174 | unsigned int i; |
175 | |
176 | for (i = 0; i < digest_len; ++i) { |
177 | digest_str[i] = (unsigned char) ((context->state[i/8] >> (8 * (i%8))) & 0xff); |
178 | } |
179 | } |
180 | |
181 | PHP_HASH_API void PHP_3TIGERInit(PHP_TIGER_CTX *context) |
182 | { |
183 | memset(context, 0, sizeof(*context)); |
184 | context->state[0] = L64(0x0123456789ABCDEF); |
185 | context->state[1] = L64(0xFEDCBA9876543210); |
186 | context->state[2] = L64(0xF096A5B4C3B2E187); |
187 | } |
188 | |
189 | PHP_HASH_API void PHP_4TIGERInit(PHP_TIGER_CTX *context) |
190 | { |
191 | memset(context, 0, sizeof(*context)); |
192 | context->passes = 1; |
193 | context->state[0] = L64(0x0123456789ABCDEF); |
194 | context->state[1] = L64(0xFEDCBA9876543210); |
195 | context->state[2] = L64(0xF096A5B4C3B2E187); |
196 | } |
197 | |
198 | PHP_HASH_API void PHP_TIGERUpdate(PHP_TIGER_CTX *context, const unsigned char *input, size_t len) |
199 | { |
200 | if (context->length + len < 64) { |
201 | memcpy(&context->buffer[context->length], input, len); |
202 | context->length += len; |
203 | } else { |
204 | size_t i = 0, r = (context->length + len) % 64; |
205 | |
206 | if (context->length) { |
207 | i = 64 - context->length; |
208 | memcpy(&context->buffer[context->length], input, i); |
209 | tiger_compress(context->passes, ((const php_hash_uint64 *) context->buffer), context->state); |
210 | memset(context->buffer, 0, 64); |
211 | context->passed += 512; |
212 | } |
213 | |
214 | for (; i + 64 <= len; i += 64) { |
215 | memcpy(context->buffer, &input[i], 64); |
216 | tiger_compress(context->passes, ((const php_hash_uint64 *) context->buffer), context->state); |
217 | context->passed += 512; |
218 | } |
219 | memset(&context->buffer[r], 0, 64-r); |
220 | memcpy(context->buffer, &input[i], r); |
221 | context->length = r; |
222 | } |
223 | } |
224 | |
225 | PHP_HASH_API void PHP_TIGER128Final(unsigned char digest[16], PHP_TIGER_CTX *context) |
226 | { |
227 | TigerFinalize(context); |
228 | TigerDigest(digest, 16, context); |
229 | memset(context, 0, sizeof(*context)); |
230 | } |
231 | |
232 | PHP_HASH_API void PHP_TIGER160Final(unsigned char digest[20], PHP_TIGER_CTX *context) |
233 | { |
234 | TigerFinalize(context); |
235 | TigerDigest(digest, 20, context); |
236 | memset(context, 0, sizeof(*context)); |
237 | } |
238 | |
239 | PHP_HASH_API void PHP_TIGER192Final(unsigned char digest[24], PHP_TIGER_CTX *context) |
240 | { |
241 | TigerFinalize(context); |
242 | TigerDigest(digest, 24, context); |
243 | memset(context, 0, sizeof(*context)); |
244 | } |
245 | |
246 | #define PHP_HASH_TIGER_OPS(p, b) \ |
247 | const php_hash_ops php_hash_##p##tiger##b##_ops = { \ |
248 | (php_hash_init_func_t) PHP_##p##TIGERInit, \ |
249 | (php_hash_update_func_t) PHP_TIGERUpdate, \ |
250 | (php_hash_final_func_t) PHP_TIGER##b##Final, \ |
251 | (php_hash_copy_func_t) php_hash_copy, \ |
252 | b/8, \ |
253 | 64, \ |
254 | sizeof(PHP_TIGER_CTX) \ |
255 | } |
256 | |
257 | PHP_HASH_TIGER_OPS(3, 128); |
258 | PHP_HASH_TIGER_OPS(3, 160); |
259 | PHP_HASH_TIGER_OPS(3, 192); |
260 | PHP_HASH_TIGER_OPS(4, 128); |
261 | PHP_HASH_TIGER_OPS(4, 160); |
262 | PHP_HASH_TIGER_OPS(4, 192); |
263 | |
264 | /* |
265 | * Local variables: |
266 | * tab-width: 4 |
267 | * c-basic-offset: 4 |
268 | * End: |
269 | * vim600: sw=4 ts=4 fdm=marker |
270 | * vim<600: sw=4 ts=4 |
271 | */ |
272 | |