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