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 : | Author: Stefan Esser <sesser@php.net> |
16 : +----------------------------------------------------------------------+
17 : */
18 :
19 : /* $Id: sha1.c 276986 2009-03-10 23:40:06Z helly $ */
20 :
21 : #include "php.h"
22 : #include "ext/standard/file.h"
23 :
24 : /* This code is heavily based on the PHP md5 implementation */
25 :
26 : #include "sha1.h"
27 : #include "md5.h"
28 :
29 : PHPAPI void make_sha1_digest(char *sha1str, unsigned char *digest) /* {{{ */
30 0 : {
31 0 : make_digest_ex(sha1str, digest, 20);
32 0 : }
33 : /* }}} */
34 :
35 : /* {{{ proto string sha1(string str [, bool raw_output]) U
36 : Calculate the sha1 hash of a string */
37 : PHP_FUNCTION(sha1)
38 92 : {
39 : char *arg;
40 : int arg_len;
41 : zend_uchar arg_type;
42 92 : zend_bool raw_output = 0;
43 : char sha1str[41];
44 : PHP_SHA1_CTX context;
45 : unsigned char digest[20];
46 :
47 92 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t|b", &arg, &arg_len, &arg_type, &raw_output) == FAILURE) {
48 15 : return;
49 : }
50 :
51 77 : if (arg_type == IS_UNICODE) {
52 56 : arg = zend_unicode_to_ascii((UChar*)arg, arg_len TSRMLS_CC);
53 56 : if (!arg) {
54 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Binary or ASCII-Unicode string expected, non-ASCII-Unicode string received");
55 0 : RETURN_FALSE;
56 : }
57 : }
58 :
59 77 : sha1str[0] = '\0';
60 77 : PHP_SHA1Init(&context);
61 77 : PHP_SHA1Update(&context, (unsigned char*)arg, arg_len);
62 77 : PHP_SHA1Final(digest, &context);
63 77 : if (raw_output) {
64 24 : RETVAL_STRINGL((char*)digest, 20, 1);
65 : } else {
66 53 : make_digest_ex(sha1str, digest, 20);
67 53 : RETVAL_ASCII_STRING(sha1str, ZSTR_DUPLICATE);
68 : }
69 :
70 77 : if (arg_type == IS_UNICODE) {
71 56 : efree(arg);
72 : }
73 : }
74 :
75 : /* }}} */
76 :
77 : /* {{{ proto string sha1_file(string filename [, bool raw_output]) U
78 : Calculate the sha1 hash of given filename */
79 : PHP_FUNCTION(sha1_file)
80 17 : {
81 : char *arg;
82 : int arg_len;
83 : zend_uchar arg_type;
84 17 : zend_bool raw_output = 0;
85 : char sha1str[41];
86 : unsigned char buf[1024];
87 : unsigned char digest[20];
88 : PHP_SHA1_CTX context;
89 : int n;
90 : php_stream *stream;
91 :
92 17 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t|b", &arg, &arg_len, &arg_type, &raw_output) == FAILURE) {
93 2 : return;
94 : }
95 :
96 15 : if (arg_type == IS_UNICODE) {
97 15 : if (php_stream_path_encode(NULL, &arg, &arg_len, (UChar*)arg, arg_len, REPORT_ERRORS, FG(default_context)) == FAILURE) {
98 0 : RETURN_FALSE;
99 : }
100 : }
101 :
102 15 : stream = php_stream_open_wrapper(arg, "rb", REPORT_ERRORS, NULL);
103 15 : if (arg_type == IS_UNICODE) {
104 15 : efree(arg);
105 : }
106 15 : if (!stream) {
107 5 : RETURN_FALSE;
108 : }
109 :
110 10 : PHP_SHA1Init(&context);
111 :
112 26 : while ((n = php_stream_read(stream, (char*)buf, sizeof(buf))) > 0) {
113 6 : PHP_SHA1Update(&context, buf, n);
114 : }
115 :
116 10 : PHP_SHA1Final(digest, &context);
117 :
118 10 : php_stream_close(stream);
119 :
120 10 : if (n<0) {
121 0 : RETURN_FALSE;
122 : }
123 :
124 10 : if (raw_output) {
125 3 : RETURN_STRINGL((char*)digest, 20, 1);
126 : } else {
127 7 : make_digest_ex(sha1str, digest, 20);
128 7 : RETVAL_ASCII_STRING(sha1str, ZSTR_DUPLICATE);
129 : }
130 : }
131 : /* }}} */
132 :
133 : static void SHA1Transform(php_uint32[5], const unsigned char[64]);
134 : static void SHA1Encode(unsigned char *, php_uint32 *, unsigned int);
135 : static void SHA1Decode(php_uint32 *, const unsigned char *, unsigned int);
136 :
137 : static unsigned char PADDING[64] =
138 : {
139 : 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
140 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
141 : 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
142 : };
143 :
144 : /* F, G, H and I are basic SHA1 functions.
145 : */
146 : #define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
147 : #define G(x, y, z) ((x) ^ (y) ^ (z))
148 : #define H(x, y, z) (((x) & (y)) | ((z) & ((x) | (y))))
149 : #define I(x, y, z) ((x) ^ (y) ^ (z))
150 :
151 : /* ROTATE_LEFT rotates x left n bits.
152 : */
153 : #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
154 :
155 : /* W[i]
156 : */
157 : #define W(i) ( tmp=x[(i-3)&15]^x[(i-8)&15]^x[(i-14)&15]^x[i&15], \
158 : (x[i&15]=ROTATE_LEFT(tmp, 1)) )
159 :
160 : /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
161 : */
162 : #define FF(a, b, c, d, e, w) { \
163 : (e) += F ((b), (c), (d)) + (w) + (php_uint32)(0x5A827999); \
164 : (e) += ROTATE_LEFT ((a), 5); \
165 : (b) = ROTATE_LEFT((b), 30); \
166 : }
167 : #define GG(a, b, c, d, e, w) { \
168 : (e) += G ((b), (c), (d)) + (w) + (php_uint32)(0x6ED9EBA1); \
169 : (e) += ROTATE_LEFT ((a), 5); \
170 : (b) = ROTATE_LEFT((b), 30); \
171 : }
172 : #define HH(a, b, c, d, e, w) { \
173 : (e) += H ((b), (c), (d)) + (w) + (php_uint32)(0x8F1BBCDC); \
174 : (e) += ROTATE_LEFT ((a), 5); \
175 : (b) = ROTATE_LEFT((b), 30); \
176 : }
177 : #define II(a, b, c, d, e, w) { \
178 : (e) += I ((b), (c), (d)) + (w) + (php_uint32)(0xCA62C1D6); \
179 : (e) += ROTATE_LEFT ((a), 5); \
180 : (b) = ROTATE_LEFT((b), 30); \
181 : }
182 :
183 :
184 : /* {{{ PHP_SHA1Init
185 : * SHA1 initialization. Begins an SHA1 operation, writing a new context.
186 : */
187 : PHPAPI void PHP_SHA1Init(PHP_SHA1_CTX * context)
188 10083 : {
189 10083 : context->count[0] = context->count[1] = 0;
190 : /* Load magic initialization constants.
191 : */
192 10083 : context->state[0] = 0x67452301;
193 10083 : context->state[1] = 0xefcdab89;
194 10083 : context->state[2] = 0x98badcfe;
195 10083 : context->state[3] = 0x10325476;
196 10083 : context->state[4] = 0xc3d2e1f0;
197 10083 : }
198 : /* }}} */
199 :
200 : /* {{{ PHP_SHA1Update
201 : SHA1 block update operation. Continues an SHA1 message-digest
202 : operation, processing another message block, and updating the
203 : context.
204 : */
205 : PHPAPI void PHP_SHA1Update(PHP_SHA1_CTX * context, const unsigned char *input,
206 : unsigned int inputLen)
207 59674 : {
208 : unsigned int i, index, partLen;
209 :
210 : /* Compute number of bytes mod 64 */
211 59674 : index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
212 :
213 : /* Update number of bits */
214 59674 : if ((context->count[0] += ((php_uint32) inputLen << 3))
215 : < ((php_uint32) inputLen << 3))
216 0 : context->count[1]++;
217 59674 : context->count[1] += ((php_uint32) inputLen >> 29);
218 :
219 59674 : partLen = 64 - index;
220 :
221 : /* Transform as many times as possible.
222 : */
223 59674 : if (inputLen >= partLen) {
224 42856 : memcpy
225 : ((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen);
226 42856 : SHA1Transform(context->state, context->buffer);
227 :
228 518427 : for (i = partLen; i + 63 < inputLen; i += 64)
229 475571 : SHA1Transform(context->state, &input[i]);
230 :
231 42856 : index = 0;
232 : } else
233 16818 : i = 0;
234 :
235 : /* Buffer remaining input */
236 59674 : memcpy
237 : ((unsigned char*) & context->buffer[index], (unsigned char*) & input[i],
238 : inputLen - i);
239 59674 : }
240 : /* }}} */
241 :
242 : /* {{{ PHP_SHA1Final
243 : SHA1 finalization. Ends an SHA1 message-digest operation, writing the
244 : the message digest and zeroizing the context.
245 : */
246 : PHPAPI void PHP_SHA1Final(unsigned char digest[20], PHP_SHA1_CTX * context)
247 10082 : {
248 : unsigned char bits[8];
249 : unsigned int index, padLen;
250 :
251 : /* Save number of bits */
252 10082 : bits[7] = context->count[0] & 0xFF;
253 10082 : bits[6] = (context->count[0] >> 8) & 0xFF;
254 10082 : bits[5] = (context->count[0] >> 16) & 0xFF;
255 10082 : bits[4] = (context->count[0] >> 24) & 0xFF;
256 10082 : bits[3] = context->count[1] & 0xFF;
257 10082 : bits[2] = (context->count[1] >> 8) & 0xFF;
258 10082 : bits[1] = (context->count[1] >> 16) & 0xFF;
259 10082 : bits[0] = (context->count[1] >> 24) & 0xFF;
260 :
261 : /* Pad out to 56 mod 64.
262 : */
263 10082 : index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
264 10082 : padLen = (index < 56) ? (56 - index) : (120 - index);
265 10082 : PHP_SHA1Update(context, PADDING, padLen);
266 :
267 : /* Append length (before padding) */
268 10082 : PHP_SHA1Update(context, bits, 8);
269 :
270 : /* Store state in digest */
271 10082 : SHA1Encode(digest, context->state, 20);
272 :
273 : /* Zeroize sensitive information.
274 : */
275 10082 : memset((unsigned char*) context, 0, sizeof(*context));
276 10082 : }
277 : /* }}} */
278 :
279 : /* {{{ SHA1Transform
280 : * SHA1 basic transformation. Transforms state based on block.
281 : */
282 : static void SHA1Transform(state, block)
283 : php_uint32 state[5];
284 : const unsigned char block[64];
285 518427 : {
286 518427 : php_uint32 a = state[0], b = state[1], c = state[2];
287 518427 : php_uint32 d = state[3], e = state[4], x[16], tmp;
288 :
289 518427 : SHA1Decode(x, block, 64);
290 :
291 : /* Round 1 */
292 518427 : FF(a, b, c, d, e, x[0]); /* 1 */
293 518427 : FF(e, a, b, c, d, x[1]); /* 2 */
294 518427 : FF(d, e, a, b, c, x[2]); /* 3 */
295 518427 : FF(c, d, e, a, b, x[3]); /* 4 */
296 518427 : FF(b, c, d, e, a, x[4]); /* 5 */
297 518427 : FF(a, b, c, d, e, x[5]); /* 6 */
298 518427 : FF(e, a, b, c, d, x[6]); /* 7 */
299 518427 : FF(d, e, a, b, c, x[7]); /* 8 */
300 518427 : FF(c, d, e, a, b, x[8]); /* 9 */
301 518427 : FF(b, c, d, e, a, x[9]); /* 10 */
302 518427 : FF(a, b, c, d, e, x[10]); /* 11 */
303 518427 : FF(e, a, b, c, d, x[11]); /* 12 */
304 518427 : FF(d, e, a, b, c, x[12]); /* 13 */
305 518427 : FF(c, d, e, a, b, x[13]); /* 14 */
306 518427 : FF(b, c, d, e, a, x[14]); /* 15 */
307 518427 : FF(a, b, c, d, e, x[15]); /* 16 */
308 518427 : FF(e, a, b, c, d, W(16)); /* 17 */
309 518427 : FF(d, e, a, b, c, W(17)); /* 18 */
310 518427 : FF(c, d, e, a, b, W(18)); /* 19 */
311 518427 : FF(b, c, d, e, a, W(19)); /* 20 */
312 :
313 : /* Round 2 */
314 518427 : GG(a, b, c, d, e, W(20)); /* 21 */
315 518427 : GG(e, a, b, c, d, W(21)); /* 22 */
316 518427 : GG(d, e, a, b, c, W(22)); /* 23 */
317 518427 : GG(c, d, e, a, b, W(23)); /* 24 */
318 518427 : GG(b, c, d, e, a, W(24)); /* 25 */
319 518427 : GG(a, b, c, d, e, W(25)); /* 26 */
320 518427 : GG(e, a, b, c, d, W(26)); /* 27 */
321 518427 : GG(d, e, a, b, c, W(27)); /* 28 */
322 518427 : GG(c, d, e, a, b, W(28)); /* 29 */
323 518427 : GG(b, c, d, e, a, W(29)); /* 30 */
324 518427 : GG(a, b, c, d, e, W(30)); /* 31 */
325 518427 : GG(e, a, b, c, d, W(31)); /* 32 */
326 518427 : GG(d, e, a, b, c, W(32)); /* 33 */
327 518427 : GG(c, d, e, a, b, W(33)); /* 34 */
328 518427 : GG(b, c, d, e, a, W(34)); /* 35 */
329 518427 : GG(a, b, c, d, e, W(35)); /* 36 */
330 518427 : GG(e, a, b, c, d, W(36)); /* 37 */
331 518427 : GG(d, e, a, b, c, W(37)); /* 38 */
332 518427 : GG(c, d, e, a, b, W(38)); /* 39 */
333 518427 : GG(b, c, d, e, a, W(39)); /* 40 */
334 :
335 : /* Round 3 */
336 518427 : HH(a, b, c, d, e, W(40)); /* 41 */
337 518427 : HH(e, a, b, c, d, W(41)); /* 42 */
338 518427 : HH(d, e, a, b, c, W(42)); /* 43 */
339 518427 : HH(c, d, e, a, b, W(43)); /* 44 */
340 518427 : HH(b, c, d, e, a, W(44)); /* 45 */
341 518427 : HH(a, b, c, d, e, W(45)); /* 46 */
342 518427 : HH(e, a, b, c, d, W(46)); /* 47 */
343 518427 : HH(d, e, a, b, c, W(47)); /* 48 */
344 518427 : HH(c, d, e, a, b, W(48)); /* 49 */
345 518427 : HH(b, c, d, e, a, W(49)); /* 50 */
346 518427 : HH(a, b, c, d, e, W(50)); /* 51 */
347 518427 : HH(e, a, b, c, d, W(51)); /* 52 */
348 518427 : HH(d, e, a, b, c, W(52)); /* 53 */
349 518427 : HH(c, d, e, a, b, W(53)); /* 54 */
350 518427 : HH(b, c, d, e, a, W(54)); /* 55 */
351 518427 : HH(a, b, c, d, e, W(55)); /* 56 */
352 518427 : HH(e, a, b, c, d, W(56)); /* 57 */
353 518427 : HH(d, e, a, b, c, W(57)); /* 58 */
354 518427 : HH(c, d, e, a, b, W(58)); /* 59 */
355 518427 : HH(b, c, d, e, a, W(59)); /* 60 */
356 :
357 : /* Round 4 */
358 518427 : II(a, b, c, d, e, W(60)); /* 61 */
359 518427 : II(e, a, b, c, d, W(61)); /* 62 */
360 518427 : II(d, e, a, b, c, W(62)); /* 63 */
361 518427 : II(c, d, e, a, b, W(63)); /* 64 */
362 518427 : II(b, c, d, e, a, W(64)); /* 65 */
363 518427 : II(a, b, c, d, e, W(65)); /* 66 */
364 518427 : II(e, a, b, c, d, W(66)); /* 67 */
365 518427 : II(d, e, a, b, c, W(67)); /* 68 */
366 518427 : II(c, d, e, a, b, W(68)); /* 69 */
367 518427 : II(b, c, d, e, a, W(69)); /* 70 */
368 518427 : II(a, b, c, d, e, W(70)); /* 71 */
369 518427 : II(e, a, b, c, d, W(71)); /* 72 */
370 518427 : II(d, e, a, b, c, W(72)); /* 73 */
371 518427 : II(c, d, e, a, b, W(73)); /* 74 */
372 518427 : II(b, c, d, e, a, W(74)); /* 75 */
373 518427 : II(a, b, c, d, e, W(75)); /* 76 */
374 518427 : II(e, a, b, c, d, W(76)); /* 77 */
375 518427 : II(d, e, a, b, c, W(77)); /* 78 */
376 518427 : II(c, d, e, a, b, W(78)); /* 79 */
377 518427 : II(b, c, d, e, a, W(79)); /* 80 */
378 :
379 518427 : state[0] += a;
380 518427 : state[1] += b;
381 518427 : state[2] += c;
382 518427 : state[3] += d;
383 518427 : state[4] += e;
384 :
385 : /* Zeroize sensitive information. */
386 518427 : memset((unsigned char*) x, 0, sizeof(x));
387 518427 : }
388 : /* }}} */
389 :
390 : /* {{{ SHA1Encode
391 : Encodes input (php_uint32) into output (unsigned char). Assumes len is
392 : a multiple of 4.
393 : */
394 : static void SHA1Encode(output, input, len)
395 : unsigned char *output;
396 : php_uint32 *input;
397 : unsigned int len;
398 10082 : {
399 : unsigned int i, j;
400 :
401 60492 : for (i = 0, j = 0; j < len; i++, j += 4) {
402 50410 : output[j] = (unsigned char) ((input[i] >> 24) & 0xff);
403 50410 : output[j + 1] = (unsigned char) ((input[i] >> 16) & 0xff);
404 50410 : output[j + 2] = (unsigned char) ((input[i] >> 8) & 0xff);
405 50410 : output[j + 3] = (unsigned char) (input[i] & 0xff);
406 : }
407 10082 : }
408 : /* }}} */
409 :
410 : /* {{{ SHA1Decode
411 : Decodes input (unsigned char) into output (php_uint32). Assumes len is
412 : a multiple of 4.
413 : */
414 : static void SHA1Decode(output, input, len)
415 : php_uint32 *output;
416 : const unsigned char *input;
417 : unsigned int len;
418 518427 : {
419 : unsigned int i, j;
420 :
421 8813259 : for (i = 0, j = 0; j < len; i++, j += 4)
422 8294832 : output[i] = ((php_uint32) input[j + 3]) | (((php_uint32) input[j + 2]) << 8) |
423 : (((php_uint32) input[j + 1]) << 16) | (((php_uint32) input[j]) << 24);
424 518427 : }
425 : /* }}} */
426 :
427 : /*
428 : * Local variables:
429 : * tab-width: 4
430 : * c-basic-offset: 4
431 : * End:
432 : * vim600: sw=4 ts=4 fdm=marker
433 : * vim<600: sw=4 ts=4
434 : */
|