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