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