xref: /PHP-5.5/ext/hash/hash.c (revision 4435b914)
1 /*
2   +----------------------------------------------------------------------+
3   | PHP Version 5                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2015 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: Sara Golemon <pollita@php.net>                               |
16   |         Scott MacVicar <scottmac@php.net>                            |
17   +----------------------------------------------------------------------+
18 */
19 
20 /* $Id$ */
21 
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
25 
26 #include <math.h>
27 #include "php_hash.h"
28 #include "ext/standard/info.h"
29 #include "ext/standard/file.h"
30 
31 static int php_hash_le_hash;
32 HashTable php_hash_hashtable;
33 
34 #if (PHP_MAJOR_VERSION >= 5)
35 # define DEFAULT_CONTEXT FG(default_context)
36 #else
37 # define DEFAULT_CONTEXT NULL
38 #endif
39 
40 #ifdef PHP_MHASH_BC
41 struct mhash_bc_entry {
42 	char *mhash_name;
43 	char *hash_name;
44 	int value;
45 };
46 
47 #define MHASH_NUM_ALGOS 34
48 
49 static struct mhash_bc_entry mhash_to_hash[MHASH_NUM_ALGOS] = {
50 	{"CRC32", "crc32", 0},
51 	{"MD5", "md5", 1},
52 	{"SHA1", "sha1", 2},
53 	{"HAVAL256", "haval256,3", 3},
54 	{NULL, NULL, 4},
55 	{"RIPEMD160", "ripemd160", 5},
56 	{NULL, NULL, 6},
57 	{"TIGER", "tiger192,3", 7},
58 	{"GOST", "gost", 8},
59 	{"CRC32B", "crc32b", 9},
60 	{"HAVAL224", "haval224,3", 10},
61 	{"HAVAL192", "haval192,3", 11},
62 	{"HAVAL160", "haval160,3", 12},
63 	{"HAVAL128", "haval128,3", 13},
64 	{"TIGER128", "tiger128,3", 14},
65 	{"TIGER160", "tiger160,3", 15},
66 	{"MD4", "md4", 16},
67 	{"SHA256", "sha256", 17},
68 	{"ADLER32", "adler32", 18},
69 	{"SHA224", "sha224", 19},
70 	{"SHA512", "sha512", 20},
71 	{"SHA384", "sha384", 21},
72 	{"WHIRLPOOL", "whirlpool", 22},
73 	{"RIPEMD128", "ripemd128", 23},
74 	{"RIPEMD256", "ripemd256", 24},
75 	{"RIPEMD320", "ripemd320", 25},
76 	{NULL, NULL, 26}, /* support needs to be added for snefru 128 */
77 	{"SNEFRU256", "snefru256", 27},
78 	{"MD2", "md2", 28},
79 	{"FNV132", "fnv132", 29},
80 	{"FNV1A32", "fnv1a32", 30},
81 	{"FNV164", "fnv164", 31},
82 	{"FNV1A64", "fnv1a64", 32},
83 	{"JOAAT", "joaat", 33},
84 };
85 #endif
86 
87 /* Hash Registry Access */
88 
php_hash_fetch_ops(const char * algo,int algo_len)89 PHP_HASH_API const php_hash_ops *php_hash_fetch_ops(const char *algo, int algo_len) /* {{{ */
90 {
91 	php_hash_ops *ops;
92 	char *lower = estrndup(algo, algo_len);
93 
94 	zend_str_tolower(lower, algo_len);
95 	if (SUCCESS != zend_hash_find(&php_hash_hashtable, lower, algo_len + 1, (void*)&ops)) {
96 		ops = NULL;
97 	}
98 	efree(lower);
99 
100 	return ops;
101 }
102 /* }}} */
103 
php_hash_register_algo(const char * algo,const php_hash_ops * ops)104 PHP_HASH_API void php_hash_register_algo(const char *algo, const php_hash_ops *ops) /* {{{ */
105 {
106 	int algo_len = strlen(algo);
107 	char *lower = estrndup(algo, algo_len);
108 
109 	zend_str_tolower(lower, algo_len);
110 	zend_hash_add(&php_hash_hashtable, lower, algo_len + 1, (void*)ops, sizeof(php_hash_ops), NULL);
111 	efree(lower);
112 }
113 /* }}} */
114 
php_hash_copy(const void * ops,void * orig_context,void * dest_context)115 PHP_HASH_API int php_hash_copy(const void *ops, void *orig_context, void *dest_context) /* {{{ */
116 {
117 	php_hash_ops *hash_ops = (php_hash_ops *)ops;
118 
119 	memcpy(dest_context, orig_context, hash_ops->context_size);
120 	return SUCCESS;
121 }
122 /* }}} */
123 
124 /* Userspace */
125 
php_hash_do_hash(INTERNAL_FUNCTION_PARAMETERS,int isfilename,zend_bool raw_output_default)126 static void php_hash_do_hash(INTERNAL_FUNCTION_PARAMETERS, int isfilename, zend_bool raw_output_default) /* {{{ */
127 {
128 	char *algo, *data, *digest;
129 	int algo_len, data_len;
130 	zend_bool raw_output = raw_output_default;
131 	const php_hash_ops *ops;
132 	void *context;
133 	php_stream *stream = NULL;
134 
135 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|b", &algo, &algo_len, &data, &data_len, &raw_output) == FAILURE) {
136 		return;
137 	}
138 
139 	ops = php_hash_fetch_ops(algo, algo_len);
140 	if (!ops) {
141 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown hashing algorithm: %s", algo);
142 		RETURN_FALSE;
143 	}
144 	if (isfilename) {
145 		if (CHECK_NULL_PATH(data, data_len)) {
146 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid path");
147 			RETURN_FALSE;
148 		}
149 		stream = php_stream_open_wrapper_ex(data, "rb", REPORT_ERRORS, NULL, DEFAULT_CONTEXT);
150 		if (!stream) {
151 			/* Stream will report errors opening file */
152 			RETURN_FALSE;
153 		}
154 	}
155 
156 	context = emalloc(ops->context_size);
157 	ops->hash_init(context);
158 
159 	if (isfilename) {
160 		char buf[1024];
161 		int n;
162 
163 		while ((n = php_stream_read(stream, buf, sizeof(buf))) > 0) {
164 			ops->hash_update(context, (unsigned char *) buf, n);
165 		}
166 		php_stream_close(stream);
167 	} else {
168 		ops->hash_update(context, (unsigned char *) data, data_len);
169 	}
170 
171 	digest = emalloc(ops->digest_size + 1);
172 	ops->hash_final((unsigned char *) digest, context);
173 	efree(context);
174 
175 	if (raw_output) {
176 		digest[ops->digest_size] = 0;
177 		RETURN_STRINGL(digest, ops->digest_size, 0);
178 	} else {
179 		char *hex_digest = safe_emalloc(ops->digest_size, 2, 1);
180 
181 		php_hash_bin2hex(hex_digest, (unsigned char *) digest, ops->digest_size);
182 		hex_digest[2 * ops->digest_size] = 0;
183 		efree(digest);
184 		RETURN_STRINGL(hex_digest, 2 * ops->digest_size, 0);
185 	}
186 }
187 /* }}} */
188 
189 /* {{{ proto string hash(string algo, string data[, bool raw_output = false])
190 Generate a hash of a given input string
191 Returns lowercase hexits by default */
PHP_FUNCTION(hash)192 PHP_FUNCTION(hash)
193 {
194 	php_hash_do_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0);
195 }
196 /* }}} */
197 
198 /* {{{ proto string hash_file(string algo, string filename[, bool raw_output = false])
199 Generate a hash of a given file
200 Returns lowercase hexits by default */
PHP_FUNCTION(hash_file)201 PHP_FUNCTION(hash_file)
202 {
203 	php_hash_do_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 0);
204 }
205 /* }}} */
206 
php_hash_string_xor_char(unsigned char * out,const unsigned char * in,const unsigned char xor_with,const int length)207 static inline void php_hash_string_xor_char(unsigned char *out, const unsigned char *in, const unsigned char xor_with, const int length) {
208 	int i;
209 	for (i=0; i < length; i++) {
210 		out[i] = in[i] ^ xor_with;
211 	}
212 }
213 
php_hash_string_xor(unsigned char * out,const unsigned char * in,const unsigned char * xor_with,const int length)214 static inline void php_hash_string_xor(unsigned char *out, const unsigned char *in, const unsigned char *xor_with, const int length) {
215 	int i;
216 	for (i=0; i < length; i++) {
217 		out[i] = in[i] ^ xor_with[i];
218 	}
219 }
220 
php_hash_hmac_prep_key(unsigned char * K,const php_hash_ops * ops,void * context,const unsigned char * key,const int key_len)221 static inline void php_hash_hmac_prep_key(unsigned char *K, const php_hash_ops *ops, void *context, const unsigned char *key, const int key_len) {
222 	memset(K, 0, ops->block_size);
223 	if (key_len > ops->block_size) {
224 		/* Reduce the key first */
225 		ops->hash_init(context);
226 		ops->hash_update(context, key, key_len);
227 		ops->hash_final(K, context);
228 	} else {
229 		memcpy(K, key, key_len);
230 	}
231 	/* XOR the key with 0x36 to get the ipad) */
232 	php_hash_string_xor_char(K, K, 0x36, ops->block_size);
233 }
234 
php_hash_hmac_round(unsigned char * final,const php_hash_ops * ops,void * context,const unsigned char * key,const unsigned char * data,const long data_size)235 static inline void php_hash_hmac_round(unsigned char *final, const php_hash_ops *ops, void *context, const unsigned char *key, const unsigned char *data, const long data_size) {
236 	ops->hash_init(context);
237 	ops->hash_update(context, key, ops->block_size);
238 	ops->hash_update(context, data, data_size);
239 	ops->hash_final(final, context);
240 }
241 
php_hash_do_hash_hmac(INTERNAL_FUNCTION_PARAMETERS,int isfilename,zend_bool raw_output_default)242 static void php_hash_do_hash_hmac(INTERNAL_FUNCTION_PARAMETERS, int isfilename, zend_bool raw_output_default) /* {{{ */
243 {
244 	char *algo, *data, *digest, *key, *K;
245 	int algo_len, data_len, key_len;
246 	zend_bool raw_output = raw_output_default;
247 	const php_hash_ops *ops;
248 	void *context;
249 	php_stream *stream = NULL;
250 
251 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|b", &algo, &algo_len, &data, &data_len,
252 																  &key, &key_len, &raw_output) == FAILURE) {
253 		return;
254 	}
255 
256 	ops = php_hash_fetch_ops(algo, algo_len);
257 	if (!ops) {
258 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown hashing algorithm: %s", algo);
259 		RETURN_FALSE;
260 	}
261 	if (isfilename) {
262 		if (CHECK_NULL_PATH(data, data_len)) {
263 			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid path");
264 			RETURN_FALSE;
265 		}
266 		stream = php_stream_open_wrapper_ex(data, "rb", REPORT_ERRORS, NULL, DEFAULT_CONTEXT);
267 		if (!stream) {
268 			/* Stream will report errors opening file */
269 			RETURN_FALSE;
270 		}
271 	}
272 
273 	context = emalloc(ops->context_size);
274 
275 	K = emalloc(ops->block_size);
276 	digest = emalloc(ops->digest_size + 1);
277 
278 	php_hash_hmac_prep_key((unsigned char *) K, ops, context, (unsigned char *) key, key_len);
279 
280 	if (isfilename) {
281 		char buf[1024];
282 		int n;
283 		ops->hash_init(context);
284 		ops->hash_update(context, (unsigned char *) K, ops->block_size);
285 		while ((n = php_stream_read(stream, buf, sizeof(buf))) > 0) {
286 			ops->hash_update(context, (unsigned char *) buf, n);
287 		}
288 		php_stream_close(stream);
289 		ops->hash_final((unsigned char *) digest, context);
290 	} else {
291 		php_hash_hmac_round((unsigned char *) digest, ops, context, (unsigned char *) K, (unsigned char *) data, data_len);
292 	}
293 
294 	php_hash_string_xor_char((unsigned char *) K, (unsigned char *) K, 0x6A, ops->block_size);
295 
296 	php_hash_hmac_round((unsigned char *) digest, ops, context, (unsigned char *) K, (unsigned char *) digest, ops->digest_size);
297 
298 	/* Zero the key */
299 	memset(K, 0, ops->block_size);
300 	efree(K);
301 	efree(context);
302 
303 	if (raw_output) {
304 		digest[ops->digest_size] = 0;
305 		RETURN_STRINGL(digest, ops->digest_size, 0);
306 	} else {
307 		char *hex_digest = safe_emalloc(ops->digest_size, 2, 1);
308 
309 		php_hash_bin2hex(hex_digest, (unsigned char *) digest, ops->digest_size);
310 		hex_digest[2 * ops->digest_size] = 0;
311 		efree(digest);
312 		RETURN_STRINGL(hex_digest, 2 * ops->digest_size, 0);
313 	}
314 }
315 /* }}} */
316 
317 /* {{{ proto string hash_hmac(string algo, string data, string key[, bool raw_output = false])
318 Generate a hash of a given input string with a key using HMAC
319 Returns lowercase hexits by default */
PHP_FUNCTION(hash_hmac)320 PHP_FUNCTION(hash_hmac)
321 {
322 	php_hash_do_hash_hmac(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0);
323 }
324 /* }}} */
325 
326 /* {{{ proto string hash_hmac_file(string algo, string filename, string key[, bool raw_output = false])
327 Generate a hash of a given file with a key using HMAC
328 Returns lowercase hexits by default */
PHP_FUNCTION(hash_hmac_file)329 PHP_FUNCTION(hash_hmac_file)
330 {
331 	php_hash_do_hash_hmac(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 0);
332 }
333 /* }}} */
334 
335 
336 /* {{{ proto resource hash_init(string algo[, int options, string key])
337 Initialize a hashing context */
PHP_FUNCTION(hash_init)338 PHP_FUNCTION(hash_init)
339 {
340 	char *algo, *key = NULL;
341 	int algo_len, key_len = 0, argc = ZEND_NUM_ARGS();
342 	long options = 0;
343 	void *context;
344 	const php_hash_ops *ops;
345 	php_hash_data *hash;
346 
347 	if (zend_parse_parameters(argc TSRMLS_CC, "s|ls", &algo, &algo_len, &options, &key, &key_len) == FAILURE) {
348 		return;
349 	}
350 
351 	ops = php_hash_fetch_ops(algo, algo_len);
352 	if (!ops) {
353 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown hashing algorithm: %s", algo);
354 		RETURN_FALSE;
355 	}
356 
357 	if (options & PHP_HASH_HMAC &&
358 		key_len <= 0) {
359 		/* Note: a zero length key is no key at all */
360 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "HMAC requested without a key");
361 		RETURN_FALSE;
362 	}
363 
364 	context = emalloc(ops->context_size);
365 	ops->hash_init(context);
366 
367 	hash = emalloc(sizeof(php_hash_data));
368 	hash->ops = ops;
369 	hash->context = context;
370 	hash->options = options;
371 	hash->key = NULL;
372 
373 	if (options & PHP_HASH_HMAC) {
374 		char *K = emalloc(ops->block_size);
375 		int i;
376 
377 		memset(K, 0, ops->block_size);
378 
379 		if (key_len > ops->block_size) {
380 			/* Reduce the key first */
381 			ops->hash_update(context, (unsigned char *) key, key_len);
382 			ops->hash_final((unsigned char *) K, context);
383 			/* Make the context ready to start over */
384 			ops->hash_init(context);
385 		} else {
386 			memcpy(K, key, key_len);
387 		}
388 
389 		/* XOR ipad */
390 		for(i=0; i < ops->block_size; i++) {
391 			K[i] ^= 0x36;
392 		}
393 		ops->hash_update(context, (unsigned char *) K, ops->block_size);
394 		hash->key = (unsigned char *) K;
395 	}
396 
397 	ZEND_REGISTER_RESOURCE(return_value, hash, php_hash_le_hash);
398 }
399 /* }}} */
400 
401 /* {{{ proto bool hash_update(resource context, string data)
402 Pump data into the hashing algorithm */
PHP_FUNCTION(hash_update)403 PHP_FUNCTION(hash_update)
404 {
405 	zval *zhash;
406 	php_hash_data *hash;
407 	char *data;
408 	int data_len;
409 
410 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs", &zhash, &data, &data_len) == FAILURE) {
411 		return;
412 	}
413 
414 	ZEND_FETCH_RESOURCE(hash, php_hash_data*, &zhash, -1, PHP_HASH_RESNAME, php_hash_le_hash);
415 
416 	hash->ops->hash_update(hash->context, (unsigned char *) data, data_len);
417 
418 	RETURN_TRUE;
419 }
420 /* }}} */
421 
422 /* {{{ proto int hash_update_stream(resource context, resource handle[, integer length])
423 Pump data into the hashing algorithm from an open stream */
PHP_FUNCTION(hash_update_stream)424 PHP_FUNCTION(hash_update_stream)
425 {
426 	zval *zhash, *zstream;
427 	php_hash_data *hash;
428 	php_stream *stream = NULL;
429 	long length = -1, didread = 0;
430 
431 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rr|l", &zhash, &zstream, &length) == FAILURE) {
432 		return;
433 	}
434 
435 	ZEND_FETCH_RESOURCE(hash, php_hash_data*, &zhash, -1, PHP_HASH_RESNAME, php_hash_le_hash);
436 	php_stream_from_zval(stream, &zstream);
437 
438 	while (length) {
439 		char buf[1024];
440 		long n, toread = 1024;
441 
442 		if (length > 0 && toread > length) {
443 			toread = length;
444 		}
445 
446 		if ((n = php_stream_read(stream, buf, toread)) <= 0) {
447 			/* Nada mas */
448 			RETURN_LONG(didread);
449 		}
450 		hash->ops->hash_update(hash->context, (unsigned char *) buf, n);
451 		length -= n;
452 		didread += n;
453 	}
454 
455 	RETURN_LONG(didread);
456 }
457 /* }}} */
458 
459 /* {{{ proto bool hash_update_file(resource context, string filename[, resource context])
460 Pump data into the hashing algorithm from a file */
PHP_FUNCTION(hash_update_file)461 PHP_FUNCTION(hash_update_file)
462 {
463 	zval *zhash, *zcontext = NULL;
464 	php_hash_data *hash;
465 	php_stream_context *context;
466 	php_stream *stream;
467 	char *filename, buf[1024];
468 	int filename_len, n;
469 
470 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rp|r", &zhash, &filename, &filename_len, &zcontext) == FAILURE) {
471 		return;
472 	}
473 
474 	ZEND_FETCH_RESOURCE(hash, php_hash_data*, &zhash, -1, PHP_HASH_RESNAME, php_hash_le_hash);
475 	context = php_stream_context_from_zval(zcontext, 0);
476 
477 	stream = php_stream_open_wrapper_ex(filename, "rb", REPORT_ERRORS, NULL, context);
478 	if (!stream) {
479 		/* Stream will report errors opening file */
480 		RETURN_FALSE;
481 	}
482 
483 	while ((n = php_stream_read(stream, buf, sizeof(buf))) > 0) {
484 		hash->ops->hash_update(hash->context, (unsigned char *) buf, n);
485 	}
486 	php_stream_close(stream);
487 
488 	RETURN_TRUE;
489 }
490 /* }}} */
491 
492 /* {{{ proto string hash_final(resource context[, bool raw_output=false])
493 Output resulting digest */
PHP_FUNCTION(hash_final)494 PHP_FUNCTION(hash_final)
495 {
496 	zval *zhash;
497 	php_hash_data *hash;
498 	zend_bool raw_output = 0;
499 	zend_rsrc_list_entry *le;
500 	char *digest;
501 	int digest_len;
502 
503 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|b", &zhash, &raw_output) == FAILURE) {
504 		return;
505 	}
506 
507 	ZEND_FETCH_RESOURCE(hash, php_hash_data*, &zhash, -1, PHP_HASH_RESNAME, php_hash_le_hash);
508 
509 	digest_len = hash->ops->digest_size;
510 	digest = emalloc(digest_len + 1);
511 	hash->ops->hash_final((unsigned char *) digest, hash->context);
512 	if (hash->options & PHP_HASH_HMAC) {
513 		int i;
514 
515 		/* Convert K to opad -- 0x6A = 0x36 ^ 0x5C */
516 		for(i=0; i < hash->ops->block_size; i++) {
517 			hash->key[i] ^= 0x6A;
518 		}
519 
520 		/* Feed this result into the outter hash */
521 		hash->ops->hash_init(hash->context);
522 		hash->ops->hash_update(hash->context, (unsigned char *) hash->key, hash->ops->block_size);
523 		hash->ops->hash_update(hash->context, (unsigned char *) digest, hash->ops->digest_size);
524 		hash->ops->hash_final((unsigned char *) digest, hash->context);
525 
526 		/* Zero the key */
527 		memset(hash->key, 0, hash->ops->block_size);
528 		efree(hash->key);
529 		hash->key = NULL;
530 	}
531 	digest[digest_len] = 0;
532 	efree(hash->context);
533 	hash->context = NULL;
534 
535 	/* zend_list_REAL_delete() */
536 	if (zend_hash_index_find(&EG(regular_list), Z_RESVAL_P(zhash), (void *) &le)==SUCCESS) {
537 		/* This is a hack to avoid letting the resource hide elsewhere (like in separated vars)
538 			FETCH_RESOURCE is intelligent enough to handle dealing with any issues this causes */
539 		le->refcount = 1;
540 	} /* FAILURE is not an option */
541 	zend_list_delete(Z_RESVAL_P(zhash));
542 
543 	if (raw_output) {
544 		RETURN_STRINGL(digest, digest_len, 0);
545 	} else {
546 		char *hex_digest = safe_emalloc(digest_len,2,1);
547 
548 		php_hash_bin2hex(hex_digest, (unsigned char *) digest, digest_len);
549 		hex_digest[2 * digest_len] = 0;
550 		efree(digest);
551 		RETURN_STRINGL(hex_digest, 2 * digest_len, 0);
552 	}
553 }
554 /* }}} */
555 
556 /* {{{ proto resource hash_copy(resource context)
557 Copy hash resource */
PHP_FUNCTION(hash_copy)558 PHP_FUNCTION(hash_copy)
559 {
560 	zval *zhash;
561 	php_hash_data *hash, *copy_hash;
562 	void *context;
563 	int res;
564 
565 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zhash) == FAILURE) {
566 		return;
567 	}
568 
569 	ZEND_FETCH_RESOURCE(hash, php_hash_data*, &zhash, -1, PHP_HASH_RESNAME, php_hash_le_hash);
570 
571 
572 	context = emalloc(hash->ops->context_size);
573 	hash->ops->hash_init(context);
574 
575 	res = hash->ops->hash_copy(hash->ops, hash->context, context);
576 	if (res != SUCCESS) {
577 		efree(context);
578 		RETURN_FALSE;
579 	}
580 
581 	copy_hash = emalloc(sizeof(php_hash_data));
582 	copy_hash->ops = hash->ops;
583 	copy_hash->context = context;
584 	copy_hash->options = hash->options;
585 	copy_hash->key = ecalloc(1, hash->ops->block_size);
586 	if (hash->key) {
587 		memcpy(copy_hash->key, hash->key, hash->ops->block_size);
588 	}
589 	ZEND_REGISTER_RESOURCE(return_value, copy_hash, php_hash_le_hash);
590 }
591 /* }}} */
592 
593 /* {{{ proto array hash_algos(void)
594 Return a list of registered hashing algorithms */
PHP_FUNCTION(hash_algos)595 PHP_FUNCTION(hash_algos)
596 {
597 	HashPosition pos;
598 	char *str;
599 	uint str_len;
600 	long type;
601 	ulong idx;
602 
603 	array_init(return_value);
604 	for(zend_hash_internal_pointer_reset_ex(&php_hash_hashtable, &pos);
605 		(type = zend_hash_get_current_key_ex(&php_hash_hashtable, &str, &str_len, &idx, 0, &pos)) != HASH_KEY_NON_EXISTENT;
606 		zend_hash_move_forward_ex(&php_hash_hashtable, &pos)) {
607 		add_next_index_stringl(return_value, str, str_len-1, 1);
608 	}
609 }
610 /* }}} */
611 
612 /* {{{ proto string hash_pbkdf2(string algo, string password, string salt, int iterations [, int length = 0, bool raw_output = false])
613 Generate a PBKDF2 hash of the given password and salt
614 Returns lowercase hexits by default */
PHP_FUNCTION(hash_pbkdf2)615 PHP_FUNCTION(hash_pbkdf2)
616 {
617 	char *returnval, *algo, *salt, *pass;
618 	unsigned char *computed_salt, *digest, *temp, *result, *K1, *K2;
619 	long loops, i, j, iterations, length = 0, digest_length;
620 	int algo_len, pass_len, salt_len;
621 	zend_bool raw_output = 0;
622 	const php_hash_ops *ops;
623 	void *context;
624 
625 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sssl|lb", &algo, &algo_len, &pass, &pass_len, &salt, &salt_len, &iterations, &length, &raw_output) == FAILURE) {
626 		return;
627 	}
628 
629 	ops = php_hash_fetch_ops(algo, algo_len);
630 	if (!ops) {
631 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown hashing algorithm: %s", algo);
632 		RETURN_FALSE;
633 	}
634 
635 	if (iterations <= 0) {
636 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Iterations must be a positive integer: %ld", iterations);
637 		RETURN_FALSE;
638 	}
639 
640 	if (length < 0) {
641 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length must be greater than or equal to 0: %ld", length);
642 		RETURN_FALSE;
643 	}
644 
645 	if (salt_len > INT_MAX - 4) {
646 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Supplied salt is too long, max of INT_MAX - 4 bytes: %d supplied", salt_len);
647 		RETURN_FALSE;
648 	}
649 
650 	context = emalloc(ops->context_size);
651 	ops->hash_init(context);
652 
653 	K1 = emalloc(ops->block_size);
654 	K2 = emalloc(ops->block_size);
655 	digest = emalloc(ops->digest_size);
656 	temp = emalloc(ops->digest_size);
657 
658 	/* Setup Keys that will be used for all hmac rounds */
659 	php_hash_hmac_prep_key(K1, ops, context, (unsigned char *) pass, pass_len);
660 	/* Convert K1 to opad -- 0x6A = 0x36 ^ 0x5C */
661 	php_hash_string_xor_char(K2, K1, 0x6A, ops->block_size);
662 
663 	/* Setup Main Loop to build a long enough result */
664 	if (length == 0) {
665 		length = ops->digest_size;
666 		if (!raw_output) {
667 			length = length * 2;
668 		}
669 	}
670 	digest_length = length;
671 	if (!raw_output) {
672 		digest_length = (long) ceil((float) length / 2.0);
673 	}
674 
675 	loops = (long) ceil((float) digest_length / (float) ops->digest_size);
676 
677 	result = safe_emalloc(loops, ops->digest_size, 0);
678 
679 	computed_salt = safe_emalloc(salt_len, 1, 4);
680 	memcpy(computed_salt, (unsigned char *) salt, salt_len);
681 
682 	for (i = 1; i <= loops; i++) {
683 		/* digest = hash_hmac(salt + pack('N', i), password) { */
684 
685 		/* pack("N", i) */
686 		computed_salt[salt_len] = (unsigned char) (i >> 24);
687 		computed_salt[salt_len + 1] = (unsigned char) ((i & 0xFF0000) >> 16);
688 		computed_salt[salt_len + 2] = (unsigned char) ((i & 0xFF00) >> 8);
689 		computed_salt[salt_len + 3] = (unsigned char) (i & 0xFF);
690 
691 		php_hash_hmac_round(digest, ops, context, K1, computed_salt, (long) salt_len + 4);
692 		php_hash_hmac_round(digest, ops, context, K2, digest, ops->digest_size);
693 		/* } */
694 
695 		/* temp = digest */
696 		memcpy(temp, digest, ops->digest_size);
697 
698 		/*
699 		 * Note that the loop starting at 1 is intentional, since we've already done
700 		 * the first round of the algorithm.
701 		 */
702 		for (j = 1; j < iterations; j++) {
703 			/* digest = hash_hmac(digest, password) { */
704 			php_hash_hmac_round(digest, ops, context, K1, digest, ops->digest_size);
705 			php_hash_hmac_round(digest, ops, context, K2, digest, ops->digest_size);
706 			/* } */
707 			/* temp ^= digest */
708 			php_hash_string_xor(temp, temp, digest, ops->digest_size);
709 		}
710 		/* result += temp */
711 		memcpy(result + ((i - 1) * ops->digest_size), temp, ops->digest_size);
712 	}
713 	/* Zero potentially sensitive variables */
714 	memset(K1, 0, ops->block_size);
715 	memset(K2, 0, ops->block_size);
716 	memset(computed_salt, 0, salt_len + 4);
717 	efree(K1);
718 	efree(K2);
719 	efree(computed_salt);
720 	efree(context);
721 	efree(digest);
722 	efree(temp);
723 
724 	returnval = safe_emalloc(length, 1, 1);
725 	if (raw_output) {
726 		memcpy(returnval, result, length);
727 	} else {
728 		php_hash_bin2hex(returnval, result, digest_length);
729 	}
730 	returnval[length] = 0;
731 	efree(result);
732 	RETURN_STRINGL(returnval, length, 0);
733 }
734 /* }}} */
735 
736 /* Module Housekeeping */
737 
php_hash_dtor(zend_rsrc_list_entry * rsrc TSRMLS_DC)738 static void php_hash_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC) /* {{{ */
739 {
740 	php_hash_data *hash = (php_hash_data*)rsrc->ptr;
741 
742 	/* Just in case the algo has internally allocated resources */
743 	if (hash->context) {
744 		unsigned char *dummy = emalloc(hash->ops->digest_size);
745 		hash->ops->hash_final(dummy, hash->context);
746 		efree(dummy);
747 		efree(hash->context);
748 	}
749 
750 	if (hash->key) {
751 		memset(hash->key, 0, hash->ops->block_size);
752 		efree(hash->key);
753 	}
754 	efree(hash);
755 }
756 /* }}} */
757 
758 #define PHP_HASH_HAVAL_REGISTER(p,b)	php_hash_register_algo("haval" #b "," #p , &php_hash_##p##haval##b##_ops);
759 
760 #ifdef PHP_MHASH_BC
761 
PHP_MINFO_FUNCTION(mhash)762 PHP_MINFO_FUNCTION(mhash)
763 {
764 	php_info_print_table_start();
765 	php_info_print_table_row(2, "MHASH support", "Enabled");
766 	php_info_print_table_row(2, "MHASH API Version", "Emulated Support");
767 	php_info_print_table_end();
768 }
769 
770 zend_module_entry mhash_module_entry = {
771 	STANDARD_MODULE_HEADER,
772 	"mhash",
773 	NULL,
774 	NULL,
775 	NULL,
776 	NULL,
777 	NULL,
778 	PHP_MINFO(mhash),
779 	NO_VERSION_YET,
780 	STANDARD_MODULE_PROPERTIES,
781 };
782 
mhash_init(INIT_FUNC_ARGS)783 static void mhash_init(INIT_FUNC_ARGS)
784 {
785 	char buf[128];
786 	int len;
787 	int algo_number = 0;
788 
789 	for (algo_number = 0; algo_number < MHASH_NUM_ALGOS; algo_number++) {
790 		struct mhash_bc_entry algorithm = mhash_to_hash[algo_number];
791 		if (algorithm.mhash_name == NULL) {
792 			continue;
793 		}
794 
795 		len = slprintf(buf, 127, "MHASH_%s", algorithm.mhash_name, strlen(algorithm.mhash_name));
796 		zend_register_long_constant(buf, len + 1, algorithm.value, CONST_CS | CONST_PERSISTENT, module_number TSRMLS_CC);
797 	}
798 	zend_register_internal_module(&mhash_module_entry TSRMLS_CC);
799 }
800 
801 /* {{{ proto string mhash(int hash, string data [, string key])
802    Hash data with hash */
PHP_FUNCTION(mhash)803 PHP_FUNCTION(mhash)
804 {
805 	zval **z_algorithm;
806 	long algorithm;
807 
808 	if (zend_parse_parameters(1 TSRMLS_CC, "Z", &z_algorithm) == FAILURE) {
809 		return;
810 	}
811 
812 	SEPARATE_ZVAL(z_algorithm);
813 	convert_to_long_ex(z_algorithm);
814 	algorithm = Z_LVAL_PP(z_algorithm);
815 
816 	/* need to convert the first parameter from int constant to string algorithm name */
817 	if (algorithm >= 0 && algorithm < MHASH_NUM_ALGOS) {
818 		struct mhash_bc_entry algorithm_lookup = mhash_to_hash[algorithm];
819 		if (algorithm_lookup.hash_name) {
820 			ZVAL_STRING(*z_algorithm, algorithm_lookup.hash_name, 1);
821 		}
822 	}
823 
824 	if (ZEND_NUM_ARGS() == 3) {
825 		php_hash_do_hash_hmac(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1);
826 	} else if (ZEND_NUM_ARGS() == 2) {
827 		php_hash_do_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1);
828 	} else {
829 		WRONG_PARAM_COUNT;
830 	}
831 }
832 /* }}} */
833 
834 /* {{{ proto string mhash_get_hash_name(int hash)
835    Gets the name of hash */
PHP_FUNCTION(mhash_get_hash_name)836 PHP_FUNCTION(mhash_get_hash_name)
837 {
838 	long algorithm;
839 
840 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &algorithm) == FAILURE) {
841 		return;
842 	}
843 
844 	if (algorithm >= 0 && algorithm  < MHASH_NUM_ALGOS) {
845 		struct mhash_bc_entry algorithm_lookup = mhash_to_hash[algorithm];
846 		if (algorithm_lookup.mhash_name) {
847 			RETURN_STRING(algorithm_lookup.mhash_name, 1);
848 		}
849 	}
850 	RETURN_FALSE;
851 }
852 /* }}} */
853 
854 /* {{{ proto int mhash_count(void)
855    Gets the number of available hashes */
PHP_FUNCTION(mhash_count)856 PHP_FUNCTION(mhash_count)
857 {
858 	if (zend_parse_parameters_none() == FAILURE) {
859 		return;
860 	}
861 	RETURN_LONG(MHASH_NUM_ALGOS - 1);
862 }
863 /* }}} */
864 
865 /* {{{ proto int mhash_get_block_size(int hash)
866    Gets the block size of hash */
PHP_FUNCTION(mhash_get_block_size)867 PHP_FUNCTION(mhash_get_block_size)
868 {
869 	long algorithm;
870 
871 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &algorithm) == FAILURE) {
872 		return;
873 	}
874 	RETVAL_FALSE;
875 
876 	if (algorithm >= 0 && algorithm  < MHASH_NUM_ALGOS) {
877 		struct mhash_bc_entry algorithm_lookup = mhash_to_hash[algorithm];
878 		if (algorithm_lookup.mhash_name) {
879 			const php_hash_ops *ops = php_hash_fetch_ops(algorithm_lookup.hash_name, strlen(algorithm_lookup.hash_name));
880 			if (ops) {
881 				RETVAL_LONG(ops->digest_size);
882 			}
883 		}
884 	}
885 }
886 /* }}} */
887 
888 #define SALT_SIZE 8
889 
890 /* {{{ proto string mhash_keygen_s2k(int hash, string input_password, string salt, int bytes)
891    Generates a key using hash functions */
PHP_FUNCTION(mhash_keygen_s2k)892 PHP_FUNCTION(mhash_keygen_s2k)
893 {
894 	long algorithm, l_bytes;
895 	int bytes;
896 	char *password, *salt;
897 	int password_len, salt_len;
898 	char padded_salt[SALT_SIZE];
899 
900 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lssl", &algorithm, &password, &password_len, &salt, &salt_len, &l_bytes) == FAILURE) {
901 		return;
902 	}
903 
904 	bytes = (int)l_bytes;
905 	if (bytes <= 0){
906 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "the byte parameter must be greater than 0");
907 		RETURN_FALSE;
908 	}
909 
910 	salt_len = MIN(salt_len, SALT_SIZE);
911 
912 	memcpy(padded_salt, salt, salt_len);
913 	if (salt_len < SALT_SIZE) {
914 		memset(padded_salt + salt_len, 0, SALT_SIZE - salt_len);
915 	}
916 	salt_len = SALT_SIZE;
917 
918 	RETVAL_FALSE;
919 	if (algorithm >= 0 && algorithm < MHASH_NUM_ALGOS) {
920 		struct mhash_bc_entry algorithm_lookup = mhash_to_hash[algorithm];
921 		if (algorithm_lookup.mhash_name) {
922 			const php_hash_ops *ops = php_hash_fetch_ops(algorithm_lookup.hash_name, strlen(algorithm_lookup.hash_name));
923 			if (ops) {
924 				unsigned char null = '\0';
925 				void *context;
926 				char *key, *digest;
927 				int i = 0, j = 0;
928 				int block_size = ops->digest_size;
929 				int times = bytes / block_size;
930 				if (bytes % block_size  != 0) times++;
931 
932 				context = emalloc(ops->context_size);
933 				ops->hash_init(context);
934 
935 				key = ecalloc(1, times * block_size);
936 				digest = emalloc(ops->digest_size + 1);
937 
938 				for (i = 0; i < times; i++) {
939 					ops->hash_init(context);
940 
941 					for (j=0;j<i;j++) {
942 						ops->hash_update(context, &null, 1);
943 					}
944 					ops->hash_update(context, (unsigned char *)padded_salt, salt_len);
945 					ops->hash_update(context, (unsigned char *)password, password_len);
946 					ops->hash_final((unsigned char *)digest, context);
947 					memcpy( &key[i*block_size], digest, block_size);
948 				}
949 
950 				RETVAL_STRINGL(key, bytes, 1);
951 				memset(key, 0, bytes);
952 				efree(digest);
953 				efree(context);
954 				efree(key);
955 			}
956 		}
957 	}
958 }
959 /* }}} */
960 
961 #endif
962 
963 /* {{{ PHP_MINIT_FUNCTION
964  */
PHP_MINIT_FUNCTION(hash)965 PHP_MINIT_FUNCTION(hash)
966 {
967 	php_hash_le_hash = zend_register_list_destructors_ex(php_hash_dtor, NULL, PHP_HASH_RESNAME, module_number);
968 
969 	zend_hash_init(&php_hash_hashtable, 35, NULL, NULL, 1);
970 
971 	php_hash_register_algo("md2",			&php_hash_md2_ops);
972 	php_hash_register_algo("md4",			&php_hash_md4_ops);
973 	php_hash_register_algo("md5",			&php_hash_md5_ops);
974 	php_hash_register_algo("sha1",			&php_hash_sha1_ops);
975 	php_hash_register_algo("sha224",		&php_hash_sha224_ops);
976 	php_hash_register_algo("sha256",		&php_hash_sha256_ops);
977 	php_hash_register_algo("sha384",		&php_hash_sha384_ops);
978 	php_hash_register_algo("sha512",		&php_hash_sha512_ops);
979 	php_hash_register_algo("ripemd128",		&php_hash_ripemd128_ops);
980 	php_hash_register_algo("ripemd160",		&php_hash_ripemd160_ops);
981 	php_hash_register_algo("ripemd256",		&php_hash_ripemd256_ops);
982 	php_hash_register_algo("ripemd320",		&php_hash_ripemd320_ops);
983 	php_hash_register_algo("whirlpool",		&php_hash_whirlpool_ops);
984 	php_hash_register_algo("tiger128,3",	&php_hash_3tiger128_ops);
985 	php_hash_register_algo("tiger160,3",	&php_hash_3tiger160_ops);
986 	php_hash_register_algo("tiger192,3",	&php_hash_3tiger192_ops);
987 	php_hash_register_algo("tiger128,4",	&php_hash_4tiger128_ops);
988 	php_hash_register_algo("tiger160,4",	&php_hash_4tiger160_ops);
989 	php_hash_register_algo("tiger192,4",	&php_hash_4tiger192_ops);
990 	php_hash_register_algo("snefru",		&php_hash_snefru_ops);
991 	php_hash_register_algo("snefru256",		&php_hash_snefru_ops);
992 	php_hash_register_algo("gost",			&php_hash_gost_ops);
993 	php_hash_register_algo("adler32",		&php_hash_adler32_ops);
994 	php_hash_register_algo("crc32",			&php_hash_crc32_ops);
995 	php_hash_register_algo("crc32b",		&php_hash_crc32b_ops);
996 	php_hash_register_algo("fnv132",		&php_hash_fnv132_ops);
997 	php_hash_register_algo("fnv164",		&php_hash_fnv164_ops);
998 	php_hash_register_algo("joaat",			&php_hash_joaat_ops);
999 
1000 	PHP_HASH_HAVAL_REGISTER(3,128);
1001 	PHP_HASH_HAVAL_REGISTER(3,160);
1002 	PHP_HASH_HAVAL_REGISTER(3,192);
1003 	PHP_HASH_HAVAL_REGISTER(3,224);
1004 	PHP_HASH_HAVAL_REGISTER(3,256);
1005 
1006 	PHP_HASH_HAVAL_REGISTER(4,128);
1007 	PHP_HASH_HAVAL_REGISTER(4,160);
1008 	PHP_HASH_HAVAL_REGISTER(4,192);
1009 	PHP_HASH_HAVAL_REGISTER(4,224);
1010 	PHP_HASH_HAVAL_REGISTER(4,256);
1011 
1012 	PHP_HASH_HAVAL_REGISTER(5,128);
1013 	PHP_HASH_HAVAL_REGISTER(5,160);
1014 	PHP_HASH_HAVAL_REGISTER(5,192);
1015 	PHP_HASH_HAVAL_REGISTER(5,224);
1016 	PHP_HASH_HAVAL_REGISTER(5,256);
1017 
1018 	REGISTER_LONG_CONSTANT("HASH_HMAC",		PHP_HASH_HMAC,	CONST_CS | CONST_PERSISTENT);
1019 
1020 #ifdef PHP_MHASH_BC
1021 	mhash_init(INIT_FUNC_ARGS_PASSTHRU);
1022 #endif
1023 
1024 	return SUCCESS;
1025 }
1026 /* }}} */
1027 
1028 /* {{{ PHP_MSHUTDOWN_FUNCTION
1029  */
PHP_MSHUTDOWN_FUNCTION(hash)1030 PHP_MSHUTDOWN_FUNCTION(hash)
1031 {
1032 	zend_hash_destroy(&php_hash_hashtable);
1033 
1034 	return SUCCESS;
1035 }
1036 /* }}} */
1037 
1038 /* {{{ PHP_MINFO_FUNCTION
1039  */
PHP_MINFO_FUNCTION(hash)1040 PHP_MINFO_FUNCTION(hash)
1041 {
1042 	HashPosition pos;
1043 	char buffer[2048];
1044 	char *s = buffer, *e = s + sizeof(buffer), *str;
1045 	ulong idx;
1046 	long type;
1047 
1048 	for(zend_hash_internal_pointer_reset_ex(&php_hash_hashtable, &pos);
1049 		(type = zend_hash_get_current_key_ex(&php_hash_hashtable, &str, NULL, &idx, 0, &pos)) != HASH_KEY_NON_EXISTENT;
1050 		zend_hash_move_forward_ex(&php_hash_hashtable, &pos)) {
1051 		s += slprintf(s, e - s, "%s ", str);
1052 	}
1053 	*s = 0;
1054 
1055 	php_info_print_table_start();
1056 	php_info_print_table_row(2, "hash support", "enabled");
1057 	php_info_print_table_row(2, "Hashing Engines", buffer);
1058 	php_info_print_table_end();
1059 }
1060 /* }}} */
1061 
1062 /* {{{ arginfo */
1063 #ifdef PHP_HASH_MD5_NOT_IN_CORE
1064 ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_md5, 0, 0, 1)
1065 	ZEND_ARG_INFO(0, str)
1066 	ZEND_ARG_INFO(0, raw_output)
1067 ZEND_END_ARG_INFO()
1068 
1069 ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_md5_file, 0, 0, 1)
1070 	ZEND_ARG_INFO(0, filename)
1071 	ZEND_ARG_INFO(0, raw_output)
1072 ZEND_END_ARG_INFO()
1073 #endif
1074 
1075 #ifdef PHP_HASH_SHA1_NOT_IN_CORE
1076 ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_sha1, 0, 0, 1)
1077 	ZEND_ARG_INFO(0, str)
1078 	ZEND_ARG_INFO(0, raw_output)
1079 ZEND_END_ARG_INFO()
1080 
1081 ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_sha1_file, 0, 0, 1)
1082 	ZEND_ARG_INFO(0, filename)
1083 	ZEND_ARG_INFO(0, raw_output)
1084 ZEND_END_ARG_INFO()
1085 #endif
1086 
1087 ZEND_BEGIN_ARG_INFO_EX(arginfo_hash, 0, 0, 2)
1088 	ZEND_ARG_INFO(0, algo)
1089 	ZEND_ARG_INFO(0, data)
1090 	ZEND_ARG_INFO(0, raw_output)
1091 ZEND_END_ARG_INFO()
1092 
1093 ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_file, 0, 0, 2)
1094 	ZEND_ARG_INFO(0, algo)
1095 	ZEND_ARG_INFO(0, filename)
1096 	ZEND_ARG_INFO(0, raw_output)
1097 ZEND_END_ARG_INFO()
1098 
1099 ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_hmac, 0, 0, 3)
1100 	ZEND_ARG_INFO(0, algo)
1101 	ZEND_ARG_INFO(0, data)
1102 	ZEND_ARG_INFO(0, key)
1103 	ZEND_ARG_INFO(0, raw_output)
1104 ZEND_END_ARG_INFO()
1105 
1106 ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_hmac_file, 0, 0, 3)
1107 	ZEND_ARG_INFO(0, algo)
1108 	ZEND_ARG_INFO(0, filename)
1109 	ZEND_ARG_INFO(0, key)
1110 	ZEND_ARG_INFO(0, raw_output)
1111 ZEND_END_ARG_INFO()
1112 
1113 ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_init, 0, 0, 1)
1114 	ZEND_ARG_INFO(0, algo)
1115 	ZEND_ARG_INFO(0, options)
1116 	ZEND_ARG_INFO(0, key)
1117 ZEND_END_ARG_INFO()
1118 
1119 ZEND_BEGIN_ARG_INFO(arginfo_hash_update, 0)
1120 	ZEND_ARG_INFO(0, context)
1121 	ZEND_ARG_INFO(0, data)
1122 ZEND_END_ARG_INFO()
1123 
1124 ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_update_stream, 0, 0, 2)
1125 	ZEND_ARG_INFO(0, context)
1126 	ZEND_ARG_INFO(0, handle)
1127 	ZEND_ARG_INFO(0, length)
1128 ZEND_END_ARG_INFO()
1129 
1130 ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_update_file, 0, 0, 2)
1131 	ZEND_ARG_INFO(0, context)
1132 	ZEND_ARG_INFO(0, filename)
1133 	ZEND_ARG_INFO(0, context)
1134 ZEND_END_ARG_INFO()
1135 
1136 ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_final, 0, 0, 1)
1137 	ZEND_ARG_INFO(0, context)
1138 	ZEND_ARG_INFO(0, raw_output)
1139 ZEND_END_ARG_INFO()
1140 
1141 ZEND_BEGIN_ARG_INFO(arginfo_hash_copy, 0)
1142 	ZEND_ARG_INFO(0, context)
1143 ZEND_END_ARG_INFO()
1144 
1145 ZEND_BEGIN_ARG_INFO(arginfo_hash_algos, 0)
1146 ZEND_END_ARG_INFO()
1147 
1148 ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_pbkdf2, 0, 0, 4)
1149 	ZEND_ARG_INFO(0, algo)
1150 	ZEND_ARG_INFO(0, password)
1151 	ZEND_ARG_INFO(0, salt)
1152 	ZEND_ARG_INFO(0, iterations)
1153 	ZEND_ARG_INFO(0, length)
1154 	ZEND_ARG_INFO(0, raw_output)
1155 ZEND_END_ARG_INFO()
1156 
1157 /* BC Land */
1158 #ifdef PHP_MHASH_BC
1159 ZEND_BEGIN_ARG_INFO(arginfo_mhash_get_block_size, 0)
1160 	ZEND_ARG_INFO(0, hash)
1161 ZEND_END_ARG_INFO()
1162 
1163 ZEND_BEGIN_ARG_INFO(arginfo_mhash_get_hash_name, 0)
1164 	ZEND_ARG_INFO(0, hash)
1165 ZEND_END_ARG_INFO()
1166 
1167 ZEND_BEGIN_ARG_INFO(arginfo_mhash_keygen_s2k, 0)
1168 	ZEND_ARG_INFO(0, hash)
1169 	ZEND_ARG_INFO(0, input_password)
1170 	ZEND_ARG_INFO(0, salt)
1171 	ZEND_ARG_INFO(0, bytes)
1172 ZEND_END_ARG_INFO()
1173 
1174 ZEND_BEGIN_ARG_INFO(arginfo_mhash_count, 0)
1175 ZEND_END_ARG_INFO()
1176 
1177 ZEND_BEGIN_ARG_INFO_EX(arginfo_mhash, 0, 0, 2)
1178 	ZEND_ARG_INFO(0, hash)
1179 	ZEND_ARG_INFO(0, data)
1180 	ZEND_ARG_INFO(0, key)
1181 ZEND_END_ARG_INFO()
1182 #endif
1183 
1184 /* }}} */
1185 
1186 /* {{{ hash_functions[]
1187  */
1188 const zend_function_entry hash_functions[] = {
1189 	PHP_FE(hash,									arginfo_hash)
1190 	PHP_FE(hash_file,								arginfo_hash_file)
1191 
1192 	PHP_FE(hash_hmac,								arginfo_hash_hmac)
1193 	PHP_FE(hash_hmac_file,							arginfo_hash_hmac_file)
1194 
1195 	PHP_FE(hash_init,								arginfo_hash_init)
1196 	PHP_FE(hash_update,								arginfo_hash_update)
1197 	PHP_FE(hash_update_stream,						arginfo_hash_update_stream)
1198 	PHP_FE(hash_update_file,						arginfo_hash_update_file)
1199 	PHP_FE(hash_final,								arginfo_hash_final)
1200 	PHP_FE(hash_copy,								arginfo_hash_copy)
1201 
1202 	PHP_FE(hash_algos,								arginfo_hash_algos)
1203 	PHP_FE(hash_pbkdf2,								arginfo_hash_pbkdf2)
1204 
1205 	/* BC Land */
1206 #ifdef PHP_HASH_MD5_NOT_IN_CORE
1207 	PHP_NAMED_FE(md5, php_if_md5,					arginfo_hash_md5)
1208 	PHP_NAMED_FE(md5_file, php_if_md5_file,			arginfo_hash_md5_file)
1209 #endif /* PHP_HASH_MD5_NOT_IN_CORE */
1210 
1211 #ifdef PHP_HASH_SHA1_NOT_IN_CORE
1212 	PHP_NAMED_FE(sha1, php_if_sha1,					arginfo_hash_sha1)
1213 	PHP_NAMED_FE(sha1_file, php_if_sha1_file,		arginfo_hash_sha1_file)
1214 #endif /* PHP_HASH_SHA1_NOT_IN_CORE */
1215 
1216 #ifdef PHP_MHASH_BC
1217 	PHP_FE(mhash_keygen_s2k, arginfo_mhash_keygen_s2k)
1218 	PHP_FE(mhash_get_block_size, arginfo_mhash_get_block_size)
1219 	PHP_FE(mhash_get_hash_name, arginfo_mhash_get_hash_name)
1220 	PHP_FE(mhash_count, arginfo_mhash_count)
1221 	PHP_FE(mhash, arginfo_mhash)
1222 #endif
1223 
1224 	PHP_FE_END
1225 };
1226 /* }}} */
1227 
1228 /* {{{ hash_module_entry
1229  */
1230 zend_module_entry hash_module_entry = {
1231 #if ZEND_MODULE_API_NO >= 20010901
1232 	STANDARD_MODULE_HEADER,
1233 #endif
1234 	PHP_HASH_EXTNAME,
1235 	hash_functions,
1236 	PHP_MINIT(hash),
1237 	PHP_MSHUTDOWN(hash),
1238 	NULL, /* RINIT */
1239 	NULL, /* RSHUTDOWN */
1240 	PHP_MINFO(hash),
1241 #if ZEND_MODULE_API_NO >= 20010901
1242 	PHP_HASH_EXTVER, /* Replace with version number for your extension */
1243 #endif
1244 	STANDARD_MODULE_PROPERTIES
1245 };
1246 /* }}} */
1247 
1248 #ifdef COMPILE_DL_HASH
1249 ZEND_GET_MODULE(hash)
1250 #endif
1251 
1252 /*
1253  * Local variables:
1254  * tab-width: 4
1255  * c-basic-offset: 4
1256  * End:
1257  * vim600: noet sw=4 ts=4 fdm=marker
1258  * vim<600: noet sw=4 ts=4
1259  */
1260 
1261