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