summaryrefslogtreecommitdiff
path: root/sha256.c
diff options
context:
space:
mode:
authorStefan Esser2015-12-17 16:35:34 +0100
committerStefan Esser2015-12-17 16:35:34 +0100
commitc4c9192839ba7842f5da58f5fd525056c77cfe54 (patch)
tree810854ddb53e03d7320570ec8d634390a849d6b2 /sha256.c
parentaee7faf18880573b60606756a61faea32a1bb89a (diff)
Continue the actual porting work on GitHub
Diffstat (limited to 'sha256.c')
-rw-r--r--sha256.c413
1 files changed, 413 insertions, 0 deletions
diff --git a/sha256.c b/sha256.c
new file mode 100644
index 0000000..bf938c4
--- /dev/null
+++ b/sha256.c
@@ -0,0 +1,413 @@
1/*
2 +----------------------------------------------------------------------+
3 | Suhosin Version 1 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2006-2007 The Hardened-PHP Project |
6 | Copyright (c) 2007-2015 SektionEins GmbH |
7 +----------------------------------------------------------------------+
8 | This source file is subject to version 3.01 of the PHP license, |
9 | that is bundled with this package in the file LICENSE, and is |
10 | available through the world-wide-web at the following url: |
11 | http://www.php.net/license/3_01.txt |
12 | If you did not receive a copy of the PHP license and are unable to |
13 | obtain it through the world-wide-web, please send a note to |
14 | license@php.net so we can mail you a copy immediately. |
15 +----------------------------------------------------------------------+
16 | Author: Stefan Esser <sesser@sektioneins.de> |
17 +----------------------------------------------------------------------+
18*/
19
20/* $Id: sha256.c $ */
21
22#include <stdio.h>
23#include "php.h"
24
25/* This code is heavily based on the PHP md5/sha1 implementations */
26
27#include "sha256.h"
28
29static void make_sha256_digest(char *sha256str, unsigned char *digest)
30{
31 int i;
32
33 for (i = 0; i < 32; i++) {
34 sprintf(sha256str, "%02x", digest[i]);
35 sha256str += 2;
36 }
37
38 *sha256str = '\0';
39}
40
41/* {{{ proto string sha256(string str [, bool raw_output])
42 Calculate the sha256 hash of a string */
43static PHP_FUNCTION(suhosin_sha256)
44{
45 char *arg;
46 int arg_len;
47 zend_bool raw_output = 0;
48 char sha256str[65];
49 suhosin_SHA256_CTX context;
50 unsigned char digest[32];
51
52 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &arg, &arg_len, &raw_output) == FAILURE) {
53 return;
54 }
55
56 sha256str[0] = '\0';
57 suhosin_SHA256Init(&context);
58 suhosin_SHA256Update(&context, (unsigned char *)arg, (unsigned int)arg_len);
59 suhosin_SHA256Final(digest, &context);
60 if (raw_output) {
61 RETURN_STRINGL((char *)digest, 32);
62 } else {
63 make_sha256_digest(sha256str, digest);
64 RETVAL_STRING(sha256str);
65 }
66
67}
68
69/* }}} */
70
71/* {{{ proto string sha256_file(string filename [, bool raw_output])
72 Calculate the sha256 hash of given filename */
73static PHP_FUNCTION(suhosin_sha256_file)
74{
75 char *arg;
76 int arg_len;
77 zend_bool raw_output = 0;
78 char sha256str[65];
79 unsigned char buf[1024];
80 unsigned char digest[32];
81 suhosin_SHA256_CTX context;
82 int n;
83 php_stream *stream;
84
85 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "p|b", &arg, &arg_len, &raw_output) == FAILURE) {
86 return;
87 }
88
89 stream = php_stream_open_wrapper(arg, "rb", REPORT_ERRORS, NULL);
90 if (!stream) {
91 RETURN_FALSE;
92 }
93
94 suhosin_SHA256Init(&context);
95
96 while ((n = php_stream_read(stream, buf, sizeof(buf))) > 0) {
97 suhosin_SHA256Update(&context, buf, n);
98 }
99
100 suhosin_SHA256Final(digest, &context);
101
102 php_stream_close(stream);
103
104 if (n<0) {
105 RETURN_FALSE;
106 }
107
108 if (raw_output) {
109 RETURN_STRINGL((char *)digest, 32);
110 } else {
111 make_sha256_digest(sha256str, digest);
112 RETVAL_STRING(sha256str);
113 }
114}
115/* }}} */
116
117
118static void SHA256Transform(php_uint32[8], const unsigned char[64]);
119static void SHA256Encode(unsigned char *, php_uint32 *, unsigned int);
120static void SHA256Decode(php_uint32 *, const unsigned char *, unsigned int);
121
122static unsigned char PADDING[64] =
123{
124 0x80, 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, 0, 0, 0, 0,
126 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
127};
128
129/* F, G, H and I are basic SHA256 functions.
130 */
131#define F(x) (ROTATE_RIGHT(x,2) ^ ROTATE_RIGHT(x,13) ^ ROTATE_RIGHT(x,22))
132#define G(x, y, z) (((x) & (y)) | ((z) & ((y) | (x))))
133#define H(x) (ROTATE_RIGHT(x,6) ^ ROTATE_RIGHT(x,11) ^ ROTATE_RIGHT(x,25))
134#define I(x, y, z) (((x) & (y)) | ((~x) & z))
135
136/* ROTATE_RIGHT rotates x right n bits.
137 */
138#define ROTATE_RIGHT(x, n) (((x) >> (n)) | ((x) << (32-(n))))
139
140/* W[i]
141 */
142#define W(i) ( tmp1=ROTATE_RIGHT(x[(i-15)&15],7)^ROTATE_RIGHT(x[(i-15)&15],18)^(x[(i-15)&15] >> 3), \
143 tmp2=ROTATE_RIGHT(x[(i-2)&15],17)^ROTATE_RIGHT(x[(i-2)&15],19)^(x[(i-2)&15] >> 10), \
144 (x[i&15]=x[i&15] + tmp1 + x[(i-7)&15] + tmp2) )
145
146/* ROUND function of sha256
147 */
148
149#define ROUND(a,b,c,d,e,f,g,h,w,k) { \
150 t1 = (h) + H((e)) + I((e), (f), (g)) + (k) + (php_uint32)(w); \
151 (h) = F((a)) + G((a), (b), (c)) + t1; \
152 (d) += t1; \
153 }
154
155
156/* {{{ suhosin_SHA256Init
157 * SHA256 initialization. Begins an SHA256 operation, writing a new context.
158 */
159void suhosin_SHA256Init(suhosin_SHA256_CTX * context)
160{
161 context->count[0] = context->count[1] = 0;
162 /* Load magic initialization constants.
163 */
164 context->state[0] = 0x6a09e667;
165 context->state[1] = 0xbb67ae85;
166 context->state[2] = 0x3c6ef372;
167 context->state[3] = 0xa54ff53a;
168 context->state[4] = 0x510e527f;
169 context->state[5] = 0x9b05688c;
170 context->state[6] = 0x1f83d9ab;
171 context->state[7] = 0x5be0cd19;
172}
173/* }}} */
174
175/* {{{ suhosin_SHA256Update
176 SHA256 block update operation. Continues an SHA256 message-digest
177 operation, processing another message block, and updating the
178 context.
179 */
180void suhosin_SHA256Update(suhosin_SHA256_CTX * context, const unsigned char *input,
181 unsigned int inputLen)
182{
183 unsigned int i, index, partLen;
184
185 /* Compute number of bytes mod 64 */
186 index = (unsigned int) ((context->count[0] >> 3) & 0x3F);
187
188 /* Update number of bits */
189 if ((context->count[0] += ((php_uint32) inputLen << 3))
190 < ((php_uint32) inputLen << 3))
191 context->count[1]++;
192 context->count[1] += ((php_uint32) inputLen >> 29);
193
194 partLen = 64 - index;
195
196 /* Transform as many times as possible.
197 */
198 if (inputLen >= partLen) {
199 memcpy
200 ((unsigned char*) & context->buffer[index], (unsigned char*) input, partLen);
201 SHA256Transform(context->state, context->buffer);
202
203 for (i = partLen; i + 63 < inputLen; i += 64)
204 SHA256Transform(context->state, &input[i]);
205
206 index = 0;
207 } else
208 i = 0;
209
210 /* Buffer remaining input */
211 memcpy
212 ((unsigned char*) & context->buffer[index], (unsigned char*) & input[i],
213 inputLen - i);
214}
215/* }}} */
216
217/* {{{ suhosin_SHA256Final
218 SHA256 finalization. Ends an SHA256 message-digest operation, writing the
219 the message digest and zeroizing the context.
220 */
221void suhosin_SHA256Final(unsigned char digest[32], suhosin_SHA256_CTX * context)
222{
223 unsigned char bits[8];
224 unsigned int index, padLen;
225
226 /* Save number of bits */
227 bits[7] = context->count[0] & 0xFF;
228 bits[6] = (context->count[0] >> 8) & 0xFF;
229 bits[5] = (context->count[0] >> 16) & 0xFF;
230 bits[4] = (context->count[0] >> 24) & 0xFF;
231 bits[3] = context->count[1] & 0xFF;
232 bits[2] = (context->count[1] >> 8) & 0xFF;
233 bits[1] = (context->count[1] >> 16) & 0xFF;
234 bits[0] = (context->count[1] >> 24) & 0xFF;
235
236 /* Pad out to 56 mod 64.
237 */
238 index = (unsigned int) ((context->count[0] >> 3) & 0x3f);
239 padLen = (index < 56) ? (56 - index) : (120 - index);
240 suhosin_SHA256Update(context, PADDING, padLen);
241
242 /* Append length (before padding) */
243 suhosin_SHA256Update(context, bits, 8);
244
245 /* Store state in digest */
246 SHA256Encode(digest, context->state, 32);
247
248 /* Zeroize sensitive information.
249 */
250 memset((unsigned char*) context, 0, sizeof(*context));
251}
252/* }}} */
253
254/* {{{ SHA256Transform
255 * SHA256 basic transformation. Transforms state based on block.
256 */
257static void SHA256Transform(state, block)
258php_uint32 state[8];
259const unsigned char block[64];
260{
261 php_uint32 a = state[0], b = state[1], c = state[2];
262 php_uint32 d = state[3], e = state[4], f = state[5];
263 php_uint32 g = state[6], h = state[7], x[16], tmp1, tmp2, t1;
264
265 SHA256Decode(x, block, 64);
266
267 ROUND(a, b, c, d, e, f, g, h, x[0], 0x428a2f98)
268 ROUND(h, a, b, c, d, e, f, g, x[1], 0x71374491)
269 ROUND(g, h, a, b, c, d, e, f, x[2], 0xb5c0fbcf)
270 ROUND(f, g, h, a, b, c, d, e, x[3], 0xe9b5dba5)
271 ROUND(e, f, g, h, a, b, c, d, x[4], 0x3956c25b)
272 ROUND(d, e, f, g, h, a, b, c, x[5], 0x59f111f1)
273 ROUND(c, d, e, f, g, h, a, b, x[6], 0x923f82a4)
274 ROUND(b, c, d, e, f, g, h, a, x[7], 0xab1c5ed5)
275 ROUND(a, b, c, d, e, f, g, h, x[8], 0xd807aa98)
276 ROUND(h, a, b, c, d, e, f, g, x[9], 0x12835b01)
277 ROUND(g, h, a, b, c, d, e, f, x[10], 0x243185be)
278 ROUND(f, g, h, a, b, c, d, e, x[11], 0x550c7dc3)
279 ROUND(e, f, g, h, a, b, c, d, x[12], 0x72be5d74)
280 ROUND(d, e, f, g, h, a, b, c, x[13], 0x80deb1fe)
281 ROUND(c, d, e, f, g, h, a, b, x[14], 0x9bdc06a7)
282 ROUND(b, c, d, e, f, g, h, a, x[15], 0xc19bf174)
283 ROUND(a, b, c, d, e, f, g, h, W(16), 0xe49b69c1)
284 ROUND(h, a, b, c, d, e, f, g, W(17), 0xefbe4786)
285 ROUND(g, h, a, b, c, d, e, f, W(18), 0x0fc19dc6)
286 ROUND(f, g, h, a, b, c, d, e, W(19), 0x240ca1cc)
287 ROUND(e, f, g, h, a, b, c, d, W(20), 0x2de92c6f)
288 ROUND(d, e, f, g, h, a, b, c, W(21), 0x4a7484aa)
289 ROUND(c, d, e, f, g, h, a, b, W(22), 0x5cb0a9dc)
290 ROUND(b, c, d, e, f, g, h, a, W(23), 0x76f988da)
291 ROUND(a, b, c, d, e, f, g, h, W(24), 0x983e5152)
292 ROUND(h, a, b, c, d, e, f, g, W(25), 0xa831c66d)
293 ROUND(g, h, a, b, c, d, e, f, W(26), 0xb00327c8)
294 ROUND(f, g, h, a, b, c, d, e, W(27), 0xbf597fc7)
295 ROUND(e, f, g, h, a, b, c, d, W(28), 0xc6e00bf3)
296 ROUND(d, e, f, g, h, a, b, c, W(29), 0xd5a79147)
297 ROUND(c, d, e, f, g, h, a, b, W(30), 0x06ca6351)
298 ROUND(b, c, d, e, f, g, h, a, W(31), 0x14292967)
299 ROUND(a, b, c, d, e, f, g, h, W(32), 0x27b70a85)
300 ROUND(h, a, b, c, d, e, f, g, W(33), 0x2e1b2138)
301 ROUND(g, h, a, b, c, d, e, f, W(34), 0x4d2c6dfc)
302 ROUND(f, g, h, a, b, c, d, e, W(35), 0x53380d13)
303 ROUND(e, f, g, h, a, b, c, d, W(36), 0x650a7354)
304 ROUND(d, e, f, g, h, a, b, c, W(37), 0x766a0abb)
305 ROUND(c, d, e, f, g, h, a, b, W(38), 0x81c2c92e)
306 ROUND(b, c, d, e, f, g, h, a, W(39), 0x92722c85)
307 ROUND(a, b, c, d, e, f, g, h, W(40), 0xa2bfe8a1)
308 ROUND(h, a, b, c, d, e, f, g, W(41), 0xa81a664b)
309 ROUND(g, h, a, b, c, d, e, f, W(42), 0xc24b8b70)
310 ROUND(f, g, h, a, b, c, d, e, W(43), 0xc76c51a3)
311 ROUND(e, f, g, h, a, b, c, d, W(44), 0xd192e819)
312 ROUND(d, e, f, g, h, a, b, c, W(45), 0xd6990624)
313 ROUND(c, d, e, f, g, h, a, b, W(46), 0xf40e3585)
314 ROUND(b, c, d, e, f, g, h, a, W(47), 0x106aa070)
315 ROUND(a, b, c, d, e, f, g, h, W(48), 0x19a4c116)
316 ROUND(h, a, b, c, d, e, f, g, W(49), 0x1e376c08)
317 ROUND(g, h, a, b, c, d, e, f, W(50), 0x2748774c)
318 ROUND(f, g, h, a, b, c, d, e, W(51), 0x34b0bcb5)
319 ROUND(e, f, g, h, a, b, c, d, W(52), 0x391c0cb3)
320 ROUND(d, e, f, g, h, a, b, c, W(53), 0x4ed8aa4a)
321 ROUND(c, d, e, f, g, h, a, b, W(54), 0x5b9cca4f)
322 ROUND(b, c, d, e, f, g, h, a, W(55), 0x682e6ff3)
323 ROUND(a, b, c, d, e, f, g, h, W(56), 0x748f82ee)
324 ROUND(h, a, b, c, d, e, f, g, W(57), 0x78a5636f)
325 ROUND(g, h, a, b, c, d, e, f, W(58), 0x84c87814)
326 ROUND(f, g, h, a, b, c, d, e, W(59), 0x8cc70208)
327 ROUND(e, f, g, h, a, b, c, d, W(60), 0x90befffa)
328 ROUND(d, e, f, g, h, a, b, c, W(61), 0xa4506ceb)
329 ROUND(c, d, e, f, g, h, a, b, W(62), 0xbef9a3f7)
330 ROUND(b, c, d, e, f, g, h, a, W(63), 0xc67178f2)
331
332 state[0] += a;
333 state[1] += b;
334 state[2] += c;
335 state[3] += d;
336 state[4] += e;
337 state[5] += f;
338 state[6] += g;
339 state[7] += h;
340
341 /* Zeroize sensitive information. */
342 memset((unsigned char*) x, 0, sizeof(x));
343}
344/* }}} */
345
346/* {{{ SHA256Encode
347 Encodes input (php_uint32) into output (unsigned char). Assumes len is
348 a multiple of 4.
349 */
350static void SHA256Encode(output, input, len)
351unsigned char *output;
352php_uint32 *input;
353unsigned int len;
354{
355 unsigned int i, j;
356
357 for (i = 0, j = 0; j < len; i++, j += 4) {
358 output[j] = (unsigned char) ((input[i] >> 24) & 0xff);
359 output[j + 1] = (unsigned char) ((input[i] >> 16) & 0xff);
360 output[j + 2] = (unsigned char) ((input[i] >> 8) & 0xff);
361 output[j + 3] = (unsigned char) (input[i] & 0xff);
362 }
363}
364/* }}} */
365
366/* {{{ SHA256Decode
367 Decodes input (unsigned char) into output (php_uint32). Assumes len is
368 a multiple of 4.
369 */
370static void SHA256Decode(output, input, len)
371php_uint32 *output;
372const unsigned char *input;
373unsigned int len;
374{
375 unsigned int i, j;
376
377 for (i = 0, j = 0; j < len; i++, j += 4)
378 output[i] = ((php_uint32) input[j + 3]) | (((php_uint32) input[j + 2]) << 8) |
379 (((php_uint32) input[j + 1]) << 16) | (((php_uint32) input[j]) << 24);
380}
381/* }}} */
382
383
384/* {{{ suhosin_sha256_functions[]
385 */
386static zend_function_entry suhosin_sha256_functions[] = {
387 PHP_NAMED_FE(sha256, PHP_FN(suhosin_sha256), NULL)
388 PHP_NAMED_FE(sha256_file, PHP_FN(suhosin_sha256_file), NULL)
389 {NULL, NULL, NULL}
390};
391/* }}} */
392
393
394void suhosin_hook_sha256(TSRMLS_D)
395{
396 /* check if we already have sha256 support */
397 if (zend_hash_str_find(CG(function_table), "sha256", sizeof("sha256"))) {
398 return;
399 }
400
401 /* add the sha256 functions */
402 zend_register_functions(NULL, suhosin_sha256_functions, NULL, MODULE_PERSISTENT TSRMLS_CC);
403}
404
405
406/*
407 * Local variables:
408 * tab-width: 4
409 * c-basic-offset: 4
410 * End:
411 * vim600: sw=4 ts=4 fdm=marker
412 * vim<600: sw=4 ts=4
413 */