1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2007 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_gost.c,v 1.2.2.3.2.2 2007/01/08 22:29:25 nlopess Exp $ */
21 :
22 : #include "php_hash.h"
23 : #include "php_hash_gost.h"
24 : #include "php_hash_gost_tables.h"
25 :
26 : /* {{{ Gost()
27 : * derived from gost_compress() by Markku-Juhani Saarinen <mjos@ssh.fi>
28 : */
29 :
30 : #define round(k1, k2) \
31 : t = (k1) + r; \
32 : l ^= tables[0][t & 0xff] ^ tables[1][(t >> 8) & 0xff] ^ \
33 : tables[2][(t >> 16) & 0xff] ^ tables[3][t >> 24]; \
34 : t = (k2) + l; \
35 : r ^= tables[0][t & 0xff] ^ tables[1][(t >> 8) & 0xff] ^ \
36 : tables[2][(t >> 16) & 0xff] ^ tables[3][t >> 24];
37 :
38 : #define R(key, h, i, t, l, r) \
39 : r = h[i]; \
40 : l = h[i + 1]; \
41 : round(key[0], key[1]) \
42 : round(key[2], key[3]) \
43 : round(key[4], key[5]) \
44 : round(key[6], key[7]) \
45 : round(key[0], key[1]) \
46 : round(key[2], key[3]) \
47 : round(key[4], key[5]) \
48 : round(key[6], key[7]) \
49 : round(key[0], key[1]) \
50 : round(key[2], key[3]) \
51 : round(key[4], key[5]) \
52 : round(key[6], key[7]) \
53 : round(key[7], key[6]) \
54 : round(key[5], key[4]) \
55 : round(key[3], key[2]) \
56 : round(key[1], key[0]) \
57 : t = r; \
58 : r = l; \
59 : l = t; \
60 :
61 : #define X(w, u, v) \
62 : w[0] = u[0] ^ v[0]; \
63 : w[1] = u[1] ^ v[1]; \
64 : w[2] = u[2] ^ v[2]; \
65 : w[3] = u[3] ^ v[3]; \
66 : w[4] = u[4] ^ v[4]; \
67 : w[5] = u[5] ^ v[5]; \
68 : w[6] = u[6] ^ v[6]; \
69 : w[7] = u[7] ^ v[7];
70 :
71 : #define P(key, w) \
72 : key[0] = (w[0] & 0x000000ff) | ((w[2] & 0x000000ff) << 8) | \
73 : ((w[4] & 0x000000ff) << 16) | ((w[6] & 0x000000ff) << 24); \
74 : key[1] = ((w[0] & 0x0000ff00) >> 8) | (w[2] & 0x0000ff00) | \
75 : ((w[4] & 0x0000ff00) << 8) | ((w[6] & 0x0000ff00) << 16); \
76 : key[2] = ((w[0] & 0x00ff0000) >> 16) | ((w[2] & 0x00ff0000) >> 8) | \
77 : (w[4] & 0x00ff0000) | ((w[6] & 0x00ff0000) << 8); \
78 : key[3] = ((w[0] & 0xff000000) >> 24) | ((w[2] & 0xff000000) >> 16) | \
79 : ((w[4] & 0xff000000) >> 8) | (w[6] & 0xff000000); \
80 : key[4] = (w[1] & 0x000000ff) | ((w[3] & 0x000000ff) << 8) | \
81 : ((w[5] & 0x000000ff) << 16) | ((w[7] & 0x000000ff) << 24); \
82 : key[5] = ((w[1] & 0x0000ff00) >> 8) | (w[3] & 0x0000ff00) | \
83 : ((w[5] & 0x0000ff00) << 8) | ((w[7] & 0x0000ff00) << 16); \
84 : key[6] = ((w[1] & 0x00ff0000) >> 16) | ((w[3] & 0x00ff0000) >> 8) | \
85 : (w[5] & 0x00ff0000) | ((w[7] & 0x00ff0000) << 8); \
86 : key[7] = ((w[1] & 0xff000000) >> 24) | ((w[3] & 0xff000000) >> 16) | \
87 : ((w[5] & 0xff000000) >> 8) | (w[7] & 0xff000000);
88 :
89 : #define A(x, l, r) \
90 : l = x[0] ^ x[2]; \
91 : r = x[1] ^ x[3]; \
92 : x[0] = x[2]; \
93 : x[1] = x[3]; \
94 : x[2] = x[4]; \
95 : x[3] = x[5]; \
96 : x[4] = x[6]; \
97 : x[5] = x[7]; \
98 : x[6] = l; \
99 : x[7] = r;
100 :
101 : #define AA(x, l, r) \
102 : l = x[0]; \
103 : r = x[2]; \
104 : x[0] = x[4]; \
105 : x[2] = x[6]; \
106 : x[4] = l ^ r; \
107 : x[6] = x[0] ^ r; \
108 : l = x[1]; \
109 : r = x[3]; \
110 : x[1] = x[5]; \
111 : x[3] = x[7]; \
112 : x[5] = l ^ r; \
113 : x[7] = x[1] ^ r;
114 :
115 : #define C(x) \
116 : x[0] ^= 0xff00ff00; \
117 : x[1] ^= 0xff00ff00; \
118 : x[2] ^= 0x00ff00ff; \
119 : x[3] ^= 0x00ff00ff; \
120 : x[4] ^= 0x00ffff00; \
121 : x[5] ^= 0xff0000ff; \
122 : x[6] ^= 0x000000ff; \
123 : x[7] ^= 0xff00ffff;
124 :
125 : #define S(s, l, r) \
126 : s[i] = r; \
127 : s[i + 1] = l;
128 :
129 : #define SHIFT12(u, m, s) \
130 : u[0] = m[0] ^ s[6]; \
131 : u[1] = m[1] ^ s[7]; \
132 : u[2] = m[2] ^ (s[0] << 16) ^ (s[0] >> 16) ^ (s[0] & 0xffff) ^ \
133 : (s[1] & 0xffff) ^ (s[1] >> 16) ^ (s[2] << 16) ^ s[6] ^ (s[6] << 16) ^ \
134 : (s[7] & 0xffff0000) ^ (s[7] >> 16); \
135 : u[3] = m[3] ^ (s[0] & 0xffff) ^ (s[0] << 16) ^ (s[1] & 0xffff) ^ \
136 : (s[1] << 16) ^ (s[1] >> 16) ^ (s[2] << 16) ^ (s[2] >> 16) ^ \
137 : (s[3] << 16) ^ s[6] ^ (s[6] << 16) ^ (s[6] >> 16) ^ (s[7] & 0xffff) ^ \
138 : (s[7] << 16) ^ (s[7] >> 16); \
139 : u[4] = m[4] ^ \
140 : (s[0] & 0xffff0000) ^ (s[0] << 16) ^ (s[0] >> 16) ^ \
141 : (s[1] & 0xffff0000) ^ (s[1] >> 16) ^ (s[2] << 16) ^ (s[2] >> 16) ^ \
142 : (s[3] << 16) ^ (s[3] >> 16) ^ (s[4] << 16) ^ (s[6] << 16) ^ \
143 : (s[6] >> 16) ^(s[7] & 0xffff) ^ (s[7] << 16) ^ (s[7] >> 16); \
144 : u[5] = m[5] ^ (s[0] << 16) ^ (s[0] >> 16) ^ (s[0] & 0xffff0000) ^ \
145 : (s[1] & 0xffff) ^ s[2] ^ (s[2] >> 16) ^ (s[3] << 16) ^ (s[3] >> 16) ^ \
146 : (s[4] << 16) ^ (s[4] >> 16) ^ (s[5] << 16) ^ (s[6] << 16) ^ \
147 : (s[6] >> 16) ^ (s[7] & 0xffff0000) ^ (s[7] << 16) ^ (s[7] >> 16); \
148 : u[6] = m[6] ^ s[0] ^ (s[1] >> 16) ^ (s[2] << 16) ^ s[3] ^ (s[3] >> 16) ^ \
149 : (s[4] << 16) ^ (s[4] >> 16) ^ (s[5] << 16) ^ (s[5] >> 16) ^ s[6] ^ \
150 : (s[6] << 16) ^ (s[6] >> 16) ^ (s[7] << 16); \
151 : u[7] = m[7] ^ (s[0] & 0xffff0000) ^ (s[0] << 16) ^ (s[1] & 0xffff) ^ \
152 : (s[1] << 16) ^ (s[2] >> 16) ^ (s[3] << 16) ^ s[4] ^ (s[4] >> 16) ^ \
153 : (s[5] << 16) ^ (s[5] >> 16) ^ (s[6] >> 16) ^ (s[7] & 0xffff) ^ \
154 : (s[7] << 16) ^ (s[7] >> 16);
155 :
156 : #define SHIFT16(h, v, u) \
157 : v[0] = h[0] ^ (u[1] << 16) ^ (u[0] >> 16); \
158 : v[1] = h[1] ^ (u[2] << 16) ^ (u[1] >> 16); \
159 : v[2] = h[2] ^ (u[3] << 16) ^ (u[2] >> 16); \
160 : v[3] = h[3] ^ (u[4] << 16) ^ (u[3] >> 16); \
161 : v[4] = h[4] ^ (u[5] << 16) ^ (u[4] >> 16); \
162 : v[5] = h[5] ^ (u[6] << 16) ^ (u[5] >> 16); \
163 : v[6] = h[6] ^ (u[7] << 16) ^ (u[6] >> 16); \
164 : v[7] = h[7] ^ (u[0] & 0xffff0000) ^ (u[0] << 16) ^ (u[7] >> 16) ^ \
165 : (u[1] & 0xffff0000) ^ (u[1] << 16) ^ (u[6] << 16) ^ (u[7] & 0xffff0000);
166 :
167 : #define SHIFT61(h, v) \
168 : h[0] = (v[0] & 0xffff0000) ^ (v[0] << 16) ^ (v[0] >> 16) ^ (v[1] >> 16) ^ \
169 : (v[1] & 0xffff0000) ^ (v[2] << 16) ^ (v[3] >> 16) ^ (v[4] << 16) ^ \
170 : (v[5] >> 16) ^ v[5] ^ (v[6] >> 16) ^ (v[7] << 16) ^ (v[7] >> 16) ^ \
171 : (v[7] & 0xffff); \
172 : h[1] = (v[0] << 16) ^ (v[0] >> 16) ^ (v[0] & 0xffff0000) ^ (v[1] & 0xffff) ^ \
173 : v[2] ^ (v[2] >> 16) ^ (v[3] << 16) ^ (v[4] >> 16) ^ (v[5] << 16) ^ \
174 : (v[6] << 16) ^ v[6] ^ (v[7] & 0xffff0000) ^ (v[7] >> 16); \
175 : h[2] = (v[0] & 0xffff) ^ (v[0] << 16) ^ (v[1] << 16) ^ (v[1] >> 16) ^ \
176 : (v[1] & 0xffff0000) ^ (v[2] << 16) ^ (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^ \
177 : (v[5] >> 16) ^ v[6] ^ (v[6] >> 16) ^ (v[7] & 0xffff) ^ (v[7] << 16) ^ \
178 : (v[7] >> 16); \
179 : h[3] = (v[0] << 16) ^ (v[0] >> 16) ^ (v[0] & 0xffff0000) ^ \
180 : (v[1] & 0xffff0000) ^ (v[1] >> 16) ^ (v[2] << 16) ^ (v[2] >> 16) ^ v[2] ^ \
181 : (v[3] << 16) ^ (v[4] >> 16) ^ v[4] ^ (v[5] << 16) ^ (v[6] << 16) ^ \
182 : (v[7] & 0xffff) ^ (v[7] >> 16); \
183 : h[4] = (v[0] >> 16) ^ (v[1] << 16) ^ v[1] ^ (v[2] >> 16) ^ v[2] ^ \
184 : (v[3] << 16) ^ (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^ (v[5] >> 16) ^ \
185 : v[5] ^ (v[6] << 16) ^ (v[6] >> 16) ^ (v[7] << 16); \
186 : h[5] = (v[0] << 16) ^ (v[0] & 0xffff0000) ^ (v[1] << 16) ^ (v[1] >> 16) ^ \
187 : (v[1] & 0xffff0000) ^ (v[2] << 16) ^ v[2] ^ (v[3] >> 16) ^ v[3] ^ \
188 : (v[4] << 16) ^ (v[4] >> 16) ^ v[4] ^ (v[5] << 16) ^ (v[6] << 16) ^ \
189 : (v[6] >> 16) ^ v[6] ^ (v[7] << 16) ^ (v[7] >> 16) ^ (v[7] & 0xffff0000); \
190 : h[6] = v[0] ^ v[2] ^ (v[2] >> 16) ^ v[3] ^ (v[3] << 16) ^ v[4] ^ \
191 : (v[4] >> 16) ^ (v[5] << 16) ^ (v[5] >> 16) ^ v[5] ^ (v[6] << 16) ^ \
192 : (v[6] >> 16) ^ v[6] ^ (v[7] << 16) ^ v[7]; \
193 : h[7] = v[0] ^ (v[0] >> 16) ^ (v[1] << 16) ^ (v[1] >> 16) ^ (v[2] << 16) ^ \
194 : (v[3] >> 16) ^ v[3] ^ (v[4] << 16) ^ v[4] ^ (v[5] >> 16) ^ v[5] ^ \
195 : (v[6] << 16) ^ (v[6] >> 16) ^ (v[7] << 16) ^ v[7];
196 :
197 : #define PASS \
198 : X(w, u, v); \
199 : P(key, w); \
200 : R(key, h, i, t, l, r); \
201 : S(s, l, r); \
202 : if (i != 6) { \
203 : A(u, l, r); \
204 : if (i == 2) { \
205 : C(u); \
206 : } \
207 : AA(v, l, r); \
208 : }
209 :
210 : static inline void Gost(php_hash_uint32 state[8], php_hash_uint32 data[8])
211 0 : {
212 : int i;
213 0 : php_hash_uint32 l, r, t, key[8], u[8], v[8], w[8], s[8], *h = state, *m = data;
214 :
215 0 : memcpy(u, state, sizeof(u));
216 0 : memcpy(v, data, sizeof(v));
217 :
218 0 : for (i = 0; i < 8; i += 2) {
219 0 : PASS;
220 : }
221 0 : SHIFT12(u, m, s);
222 0 : SHIFT16(h, v, u);
223 0 : SHIFT61(h, v);
224 0 : }
225 : /* }}} */
226 :
227 : static inline void GostTransform(PHP_GOST_CTX *context, const unsigned char input[32])
228 0 : {
229 : int i, j;
230 0 : php_hash_uint32 data[8], temp = 0, save = 0;
231 :
232 0 : for (i = 0, j = 0; i < 8; ++i, j += 4) {
233 0 : data[i] = ((php_hash_uint32) input[j]) | (((php_hash_uint32) input[j + 1]) << 8) |
234 : (((php_hash_uint32) input[j + 2]) << 16) | (((php_hash_uint32) input[j + 3]) << 24);
235 0 : save = context->state[i + 8];
236 0 : context->state[i + 8] += data[i] + temp;
237 0 : temp = ((context->state[i + 8] < data[i]) || (context->state[i + 8] < save)) ? 1 : 0;
238 : }
239 :
240 0 : Gost(context->state, data);
241 0 : }
242 :
243 : PHP_HASH_API void PHP_GOSTInit(PHP_GOST_CTX *context)
244 0 : {
245 0 : memset(context, 0, sizeof(*context));
246 0 : }
247 :
248 : static const php_hash_uint32 MAX32 = 0xffffffffLU;
249 :
250 : PHP_HASH_API void PHP_GOSTUpdate(PHP_GOST_CTX *context, const unsigned char *input, size_t len)
251 0 : {
252 0 : if ((MAX32 - context->count[0]) < (len * 8)) {
253 0 : context->count[1]++;
254 0 : context->count[0] = MAX32 - context->count[0];
255 0 : context->count[0] = (len * 8) - context->count[0];
256 : } else {
257 0 : context->count[0] += len * 8;
258 : }
259 :
260 0 : if (context->length + len < 32) {
261 0 : memcpy(&context->buffer[context->length], input, len);
262 0 : context->length += len;
263 : } else {
264 0 : size_t i = 0, r = (context->length + len) % 32;
265 :
266 0 : if (context->length) {
267 0 : i = 32 - context->length;
268 0 : memcpy(&context->buffer[context->length], input, i);
269 0 : GostTransform(context, context->buffer);
270 : }
271 :
272 0 : for (; i + 32 <= len; i += 32) {
273 0 : GostTransform(context, input + i);
274 : }
275 :
276 0 : memcpy(context->buffer, input + i, r);
277 0 : memset(&context->buffer[r], 0, 32 - r);
278 0 : context->length = r;
279 : }
280 0 : }
281 :
282 : PHP_HASH_API void PHP_GOSTFinal(unsigned char digest[32], PHP_GOST_CTX *context)
283 0 : {
284 0 : php_hash_uint32 i, j, l[8] = {0};
285 :
286 0 : if (context->length) {
287 0 : GostTransform(context, context->buffer);
288 : }
289 :
290 0 : memcpy(l, context->count, sizeof(context->count));
291 0 : Gost(context->state, l);
292 0 : memcpy(l, &context->state[8], sizeof(l));
293 0 : Gost(context->state, l);
294 :
295 0 : for (i = 0, j = 0; j < 32; i++, j += 4) {
296 0 : digest[j] = (unsigned char) (context->state[i] & 0xff);
297 0 : digest[j + 1] = (unsigned char) ((context->state[i] >> 8) & 0xff);
298 0 : digest[j + 2] = (unsigned char) ((context->state[i] >> 16) & 0xff);
299 0 : digest[j + 3] = (unsigned char) ((context->state[i] >> 24) & 0xff);
300 : }
301 :
302 0 : memset(context, 0, sizeof(*context));
303 0 : }
304 :
305 : const php_hash_ops php_hash_gost_ops = {
306 : (php_hash_init_func_t) PHP_GOSTInit,
307 : (php_hash_update_func_t) PHP_GOSTUpdate,
308 : (php_hash_final_func_t) PHP_GOSTFinal,
309 : 32,
310 : 32,
311 : sizeof(PHP_GOST_CTX)
312 : };
313 :
314 : /*
315 : * Local variables:
316 : * tab-width: 4
317 : * c-basic-offset: 4
318 : * End:
319 : * vim600: sw=4 ts=4 fdm=marker
320 : * vim<600: sw=4 ts=4
321 : */
|