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_snefru.h" |
24 | #include "php_hash_snefru_tables.h" |
25 | |
26 | #define round(L, C, N, SB) \ |
27 | SBE = SB[C & 0xff]; \ |
28 | L ^= SBE; \ |
29 | N ^= SBE |
30 | |
31 | #ifndef DBG_SNEFRU |
32 | #define DBG_SNEFRU 0 |
33 | #endif |
34 | |
35 | #if DBG_SNEFRU |
36 | void ph(php_hash_uint32 h[16]) |
37 | { |
38 | int i; |
39 | for (i = 0; i < 16; i++) |
40 | printf ("%08lx" , h[i]); printf("\n" ); |
41 | } |
42 | #endif |
43 | |
44 | static inline void Snefru(php_hash_uint32 input[16]) |
45 | { |
46 | static int shifts[4] = {16, 8, 16, 24}; |
47 | int b, index, rshift, lshift; |
48 | const php_hash_uint32 *t0,*t1; |
49 | php_hash_uint32 SBE,B00,B01,B02,B03,B04,B05,B06,B07,B08,B09,B10,B11,B12,B13,B14,B15; |
50 | |
51 | B00 = input[0]; |
52 | B01 = input[1]; |
53 | B02 = input[2]; |
54 | B03 = input[3]; |
55 | B04 = input[4]; |
56 | B05 = input[5]; |
57 | B06 = input[6]; |
58 | B07 = input[7]; |
59 | B08 = input[8]; |
60 | B09 = input[9]; |
61 | B10 = input[10]; |
62 | B11 = input[11]; |
63 | B12 = input[12]; |
64 | B13 = input[13]; |
65 | B14 = input[14]; |
66 | B15 = input[15]; |
67 | |
68 | for (index = 0; index < 8; index++) { |
69 | t0 = tables[2*index+0]; |
70 | t1 = tables[2*index+1]; |
71 | for (b = 0; b < 4; b++) { |
72 | round(B15, B00, B01, t0); |
73 | round(B00, B01, B02, t0); |
74 | round(B01, B02, B03, t1); |
75 | round(B02, B03, B04, t1); |
76 | round(B03, B04, B05, t0); |
77 | round(B04, B05, B06, t0); |
78 | round(B05, B06, B07, t1); |
79 | round(B06, B07, B08, t1); |
80 | round(B07, B08, B09, t0); |
81 | round(B08, B09, B10, t0); |
82 | round(B09, B10, B11, t1); |
83 | round(B10, B11, B12, t1); |
84 | round(B11, B12, B13, t0); |
85 | round(B12, B13, B14, t0); |
86 | round(B13, B14, B15, t1); |
87 | round(B14, B15, B00, t1); |
88 | |
89 | rshift = shifts[b]; |
90 | lshift = 32-rshift; |
91 | |
92 | B00 = (B00 >> rshift) | (B00 << lshift); |
93 | B01 = (B01 >> rshift) | (B01 << lshift); |
94 | B02 = (B02 >> rshift) | (B02 << lshift); |
95 | B03 = (B03 >> rshift) | (B03 << lshift); |
96 | B04 = (B04 >> rshift) | (B04 << lshift); |
97 | B05 = (B05 >> rshift) | (B05 << lshift); |
98 | B06 = (B06 >> rshift) | (B06 << lshift); |
99 | B07 = (B07 >> rshift) | (B07 << lshift); |
100 | B08 = (B08 >> rshift) | (B08 << lshift); |
101 | B09 = (B09 >> rshift) | (B09 << lshift); |
102 | B10 = (B10 >> rshift) | (B10 << lshift); |
103 | B11 = (B11 >> rshift) | (B11 << lshift); |
104 | B12 = (B12 >> rshift) | (B12 << lshift); |
105 | B13 = (B13 >> rshift) | (B13 << lshift); |
106 | B14 = (B14 >> rshift) | (B14 << lshift); |
107 | B15 = (B15 >> rshift) | (B15 << lshift); |
108 | } |
109 | } |
110 | input[0] ^= B15; |
111 | input[1] ^= B14; |
112 | input[2] ^= B13; |
113 | input[3] ^= B12; |
114 | input[4] ^= B11; |
115 | input[5] ^= B10; |
116 | input[6] ^= B09; |
117 | input[7] ^= B08; |
118 | #if DBG_SNEFRU |
119 | ph(input); |
120 | #endif |
121 | } |
122 | |
123 | static inline void SnefruTransform(PHP_SNEFRU_CTX *context, const unsigned char input[32]) |
124 | { |
125 | int i, j; |
126 | |
127 | for (i = 0, j = 0; i < 32; i += 4, ++j) { |
128 | context->state[8+j] = ((input[i] & 0xff) << 24) | ((input[i+1] & 0xff) << 16) | |
129 | ((input[i+2] & 0xff) << 8) | (input[i+3] & 0xff); |
130 | } |
131 | Snefru(context->state); |
132 | memset(&context->state[8], 0, sizeof(php_hash_uint32) * 8); |
133 | } |
134 | |
135 | PHP_HASH_API void PHP_SNEFRUInit(PHP_SNEFRU_CTX *context) |
136 | { |
137 | memset(context, 0, sizeof(*context)); |
138 | } |
139 | |
140 | static const php_hash_uint32 MAX32 = 0xffffffffLU; |
141 | |
142 | PHP_HASH_API void PHP_SNEFRUUpdate(PHP_SNEFRU_CTX *context, const unsigned char *input, size_t len) |
143 | { |
144 | if ((MAX32 - context->count[1]) < (len * 8)) { |
145 | context->count[0]++; |
146 | context->count[1] = MAX32 - context->count[1]; |
147 | context->count[1] = (len * 8) - context->count[1]; |
148 | } else { |
149 | context->count[1] += len * 8; |
150 | } |
151 | |
152 | if (context->length + len < 32) { |
153 | memcpy(&context->buffer[context->length], input, len); |
154 | context->length += len; |
155 | } else { |
156 | size_t i = 0, r = (context->length + len) % 32; |
157 | |
158 | if (context->length) { |
159 | i = 32 - context->length; |
160 | memcpy(&context->buffer[context->length], input, i); |
161 | SnefruTransform(context, context->buffer); |
162 | } |
163 | |
164 | for (; i + 32 <= len; i += 32) { |
165 | SnefruTransform(context, input + i); |
166 | } |
167 | |
168 | memcpy(context->buffer, input + i, r); |
169 | memset(&context->buffer[r], 0, 32 - r); |
170 | context->length = r; |
171 | } |
172 | } |
173 | |
174 | PHP_HASH_API void PHP_SNEFRUFinal(unsigned char digest[32], PHP_SNEFRU_CTX *context) |
175 | { |
176 | php_hash_uint32 i, j; |
177 | |
178 | if (context->length) { |
179 | SnefruTransform(context, context->buffer); |
180 | } |
181 | |
182 | context->state[14] = context->count[0]; |
183 | context->state[15] = context->count[1]; |
184 | Snefru(context->state); |
185 | |
186 | for (i = 0, j = 0; j < 32; i++, j += 4) { |
187 | digest[j] = (unsigned char) ((context->state[i] >> 24) & 0xff); |
188 | digest[j + 1] = (unsigned char) ((context->state[i] >> 16) & 0xff); |
189 | digest[j + 2] = (unsigned char) ((context->state[i] >> 8) & 0xff); |
190 | digest[j + 3] = (unsigned char) (context->state[i] & 0xff); |
191 | } |
192 | |
193 | memset(context, 0, sizeof(*context)); |
194 | } |
195 | |
196 | const php_hash_ops php_hash_snefru_ops = { |
197 | (php_hash_init_func_t) PHP_SNEFRUInit, |
198 | (php_hash_update_func_t) PHP_SNEFRUUpdate, |
199 | (php_hash_final_func_t) PHP_SNEFRUFinal, |
200 | (php_hash_copy_func_t) php_hash_copy, |
201 | 32, |
202 | 32, |
203 | sizeof(PHP_SNEFRU_CTX) |
204 | }; |
205 | |
206 | /* |
207 | * Local variables: |
208 | * tab-width: 4 |
209 | * c-basic-offset: 4 |
210 | * End: |
211 | * vim600: sw=4 ts=4 fdm=marker |
212 | * vim<600: sw=4 ts=4 |
213 | */ |
214 | |