1 /* 2 +----------------------------------------------------------------------+ 3 | PHP Version 7 | 4 +----------------------------------------------------------------------+ 5 | Copyright (c) 1997-2018 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 #ifdef HAVE_CONFIG_H 21 #include "config.h" 22 #endif 23 24 #include <math.h> 25 #include "php_hash.h" 26 #include "ext/standard/info.h" 27 #include "ext/standard/file.h" 28 29 #include "zend_interfaces.h" 30 #include "zend_exceptions.h" 31 32 HashTable php_hash_hashtable; 33 zend_class_entry *php_hashcontext_ce; 34 static zend_object_handlers php_hashcontext_handlers; 35 36 #ifdef PHP_MHASH_BC 37 struct mhash_bc_entry { 38 char *mhash_name; 39 char *hash_name; 40 int value; 41 }; 42 43 #define MHASH_NUM_ALGOS 34 44 45 static struct mhash_bc_entry mhash_to_hash[MHASH_NUM_ALGOS] = { 46 {"CRC32", "crc32", 0}, 47 {"MD5", "md5", 1}, 48 {"SHA1", "sha1", 2}, 49 {"HAVAL256", "haval256,3", 3}, 50 {NULL, NULL, 4}, 51 {"RIPEMD160", "ripemd160", 5}, 52 {NULL, NULL, 6}, 53 {"TIGER", "tiger192,3", 7}, 54 {"GOST", "gost", 8}, 55 {"CRC32B", "crc32b", 9}, 56 {"HAVAL224", "haval224,3", 10}, 57 {"HAVAL192", "haval192,3", 11}, 58 {"HAVAL160", "haval160,3", 12}, 59 {"HAVAL128", "haval128,3", 13}, 60 {"TIGER128", "tiger128,3", 14}, 61 {"TIGER160", "tiger160,3", 15}, 62 {"MD4", "md4", 16}, 63 {"SHA256", "sha256", 17}, 64 {"ADLER32", "adler32", 18}, 65 {"SHA224", "sha224", 19}, 66 {"SHA512", "sha512", 20}, 67 {"SHA384", "sha384", 21}, 68 {"WHIRLPOOL", "whirlpool", 22}, 69 {"RIPEMD128", "ripemd128", 23}, 70 {"RIPEMD256", "ripemd256", 24}, 71 {"RIPEMD320", "ripemd320", 25}, 72 {NULL, NULL, 26}, /* support needs to be added for snefru 128 */ 73 {"SNEFRU256", "snefru256", 27}, 74 {"MD2", "md2", 28}, 75 {"FNV132", "fnv132", 29}, 76 {"FNV1A32", "fnv1a32", 30}, 77 {"FNV164", "fnv164", 31}, 78 {"FNV1A64", "fnv1a64", 32}, 79 {"JOAAT", "joaat", 33}, 80 }; 81 #endif 82 83 /* Hash Registry Access */ 84 85 PHP_HASH_API const php_hash_ops *php_hash_fetch_ops(const char *algo, size_t algo_len) /* {{{ */ 86 { 87 char *lower = zend_str_tolower_dup(algo, algo_len); 88 php_hash_ops *ops = zend_hash_str_find_ptr(&php_hash_hashtable, lower, algo_len); 89 efree(lower); 90 91 return ops; 92 } 93 /* }}} */ 94 95 PHP_HASH_API void php_hash_register_algo(const char *algo, const php_hash_ops *ops) /* {{{ */ 96 { 97 size_t algo_len = strlen(algo); 98 char *lower = zend_str_tolower_dup(algo, algo_len); 99 zend_hash_add_ptr(&php_hash_hashtable, zend_string_init_interned(lower, algo_len, 1), (void *) ops); 100 efree(lower); 101 } 102 /* }}} */ 103 104 PHP_HASH_API int php_hash_copy(const void *ops, void *orig_context, void *dest_context) /* {{{ */ 105 { 106 php_hash_ops *hash_ops = (php_hash_ops *)ops; 107 108 memcpy(dest_context, orig_context, hash_ops->context_size); 109 return SUCCESS; 110 } 111 /* }}} */ 112 113 /* Userspace */ 114 115 static void php_hash_do_hash(INTERNAL_FUNCTION_PARAMETERS, int isfilename, zend_bool raw_output_default) /* {{{ */ 116 { 117 zend_string *digest; 118 char *algo, *data; 119 size_t algo_len, data_len; 120 zend_bool raw_output = raw_output_default; 121 const php_hash_ops *ops; 122 void *context; 123 php_stream *stream = NULL; 124 125 if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|b", &algo, &algo_len, &data, &data_len, &raw_output) == FAILURE) { 126 return; 127 } 128 129 ops = php_hash_fetch_ops(algo, algo_len); 130 if (!ops) { 131 php_error_docref(NULL, E_WARNING, "Unknown hashing algorithm: %s", algo); 132 RETURN_FALSE; 133 } 134 if (isfilename) { 135 if (CHECK_NULL_PATH(data, data_len)) { 136 php_error_docref(NULL, E_WARNING, "Invalid path"); 137 RETURN_FALSE; 138 } 139 stream = php_stream_open_wrapper_ex(data, "rb", REPORT_ERRORS, NULL, FG(default_context)); 140 if (!stream) { 141 /* Stream will report errors opening file */ 142 RETURN_FALSE; 143 } 144 } 145 146 context = emalloc(ops->context_size); 147 ops->hash_init(context); 148 149 if (isfilename) { 150 char buf[1024]; 151 size_t n; 152 153 while ((n = php_stream_read(stream, buf, sizeof(buf))) > 0) { 154 ops->hash_update(context, (unsigned char *) buf, n); 155 } 156 php_stream_close(stream); 157 } else { 158 ops->hash_update(context, (unsigned char *) data, data_len); 159 } 160 161 digest = zend_string_alloc(ops->digest_size, 0); 162 ops->hash_final((unsigned char *) ZSTR_VAL(digest), context); 163 efree(context); 164 165 if (raw_output) { 166 ZSTR_VAL(digest)[ops->digest_size] = 0; 167 RETURN_NEW_STR(digest); 168 } else { 169 zend_string *hex_digest = zend_string_safe_alloc(ops->digest_size, 2, 0, 0); 170 171 php_hash_bin2hex(ZSTR_VAL(hex_digest), (unsigned char *) ZSTR_VAL(digest), ops->digest_size); 172 ZSTR_VAL(hex_digest)[2 * ops->digest_size] = 0; 173 zend_string_release_ex(digest, 0); 174 RETURN_NEW_STR(hex_digest); 175 } 176 } 177 /* }}} */ 178 179 /* {{{ proto string hash(string algo, string data[, bool raw_output = false]) 180 Generate a hash of a given input string 181 Returns lowercase hexits by default */ 182 PHP_FUNCTION(hash) 183 { 184 php_hash_do_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0); 185 } 186 /* }}} */ 187 188 /* {{{ proto string hash_file(string algo, string filename[, bool raw_output = false]) 189 Generate a hash of a given file 190 Returns lowercase hexits by default */ 191 PHP_FUNCTION(hash_file) 192 { 193 php_hash_do_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 0); 194 } 195 /* }}} */ 196 197 static inline void php_hash_string_xor_char(unsigned char *out, const unsigned char *in, const unsigned char xor_with, const int length) { 198 int i; 199 for (i=0; i < length; i++) { 200 out[i] = in[i] ^ xor_with; 201 } 202 } 203 204 static inline void php_hash_string_xor(unsigned char *out, const unsigned char *in, const unsigned char *xor_with, const int length) { 205 int i; 206 for (i=0; i < length; i++) { 207 out[i] = in[i] ^ xor_with[i]; 208 } 209 } 210 211 static inline void php_hash_hmac_prep_key(unsigned char *K, const php_hash_ops *ops, void *context, const unsigned char *key, const size_t key_len) { 212 memset(K, 0, ops->block_size); 213 if (key_len > (size_t)ops->block_size) { 214 /* Reduce the key first */ 215 ops->hash_init(context); 216 ops->hash_update(context, key, key_len); 217 ops->hash_final(K, context); 218 } else { 219 memcpy(K, key, key_len); 220 } 221 /* XOR the key with 0x36 to get the ipad) */ 222 php_hash_string_xor_char(K, K, 0x36, ops->block_size); 223 } 224 225 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 zend_long data_size) { 226 ops->hash_init(context); 227 ops->hash_update(context, key, ops->block_size); 228 ops->hash_update(context, data, data_size); 229 ops->hash_final(final, context); 230 } 231 232 static void php_hash_do_hash_hmac(INTERNAL_FUNCTION_PARAMETERS, int isfilename, zend_bool raw_output_default) /* {{{ */ 233 { 234 zend_string *digest; 235 char *algo, *data, *key; 236 unsigned char *K; 237 size_t algo_len, data_len, key_len; 238 zend_bool raw_output = raw_output_default; 239 const php_hash_ops *ops; 240 void *context; 241 php_stream *stream = NULL; 242 243 if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|b", &algo, &algo_len, &data, &data_len, 244 &key, &key_len, &raw_output) == FAILURE) { 245 return; 246 } 247 248 ops = php_hash_fetch_ops(algo, algo_len); 249 if (!ops) { 250 php_error_docref(NULL, E_WARNING, "Unknown hashing algorithm: %s", algo); 251 RETURN_FALSE; 252 } 253 else if (!ops->is_crypto) { 254 php_error_docref(NULL, E_WARNING, "Non-cryptographic hashing algorithm: %s", algo); 255 RETURN_FALSE; 256 } 257 258 if (isfilename) { 259 if (CHECK_NULL_PATH(data, data_len)) { 260 php_error_docref(NULL, E_WARNING, "Invalid path"); 261 RETURN_FALSE; 262 } 263 stream = php_stream_open_wrapper_ex(data, "rb", REPORT_ERRORS, NULL, FG(default_context)); 264 if (!stream) { 265 /* Stream will report errors opening file */ 266 RETURN_FALSE; 267 } 268 } 269 270 context = emalloc(ops->context_size); 271 272 K = emalloc(ops->block_size); 273 digest = zend_string_alloc(ops->digest_size, 0); 274 275 php_hash_hmac_prep_key(K, ops, context, (unsigned char *) key, key_len); 276 277 if (isfilename) { 278 char buf[1024]; 279 int n; 280 ops->hash_init(context); 281 ops->hash_update(context, K, ops->block_size); 282 while ((n = php_stream_read(stream, buf, sizeof(buf))) > 0) { 283 ops->hash_update(context, (unsigned char *) buf, n); 284 } 285 php_stream_close(stream); 286 ops->hash_final((unsigned char *) ZSTR_VAL(digest), context); 287 } else { 288 php_hash_hmac_round((unsigned char *) ZSTR_VAL(digest), ops, context, K, (unsigned char *) data, data_len); 289 } 290 291 php_hash_string_xor_char(K, K, 0x6A, ops->block_size); 292 293 php_hash_hmac_round((unsigned char *) ZSTR_VAL(digest), ops, context, K, (unsigned char *) ZSTR_VAL(digest), ops->digest_size); 294 295 /* Zero the key */ 296 ZEND_SECURE_ZERO(K, ops->block_size); 297 efree(K); 298 efree(context); 299 300 if (raw_output) { 301 ZSTR_VAL(digest)[ops->digest_size] = 0; 302 RETURN_NEW_STR(digest); 303 } else { 304 zend_string *hex_digest = zend_string_safe_alloc(ops->digest_size, 2, 0, 0); 305 306 php_hash_bin2hex(ZSTR_VAL(hex_digest), (unsigned char *) ZSTR_VAL(digest), ops->digest_size); 307 ZSTR_VAL(hex_digest)[2 * ops->digest_size] = 0; 308 zend_string_release_ex(digest, 0); 309 RETURN_NEW_STR(hex_digest); 310 } 311 } 312 /* }}} */ 313 314 /* {{{ proto string hash_hmac(string algo, string data, string key[, bool raw_output = false]) 315 Generate a hash of a given input string with a key using HMAC 316 Returns lowercase hexits by default */ 317 PHP_FUNCTION(hash_hmac) 318 { 319 php_hash_do_hash_hmac(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 0); 320 } 321 /* }}} */ 322 323 /* {{{ proto string hash_hmac_file(string algo, string filename, string key[, bool raw_output = false]) 324 Generate a hash of a given file with a key using HMAC 325 Returns lowercase hexits by default */ 326 PHP_FUNCTION(hash_hmac_file) 327 { 328 php_hash_do_hash_hmac(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1, 0); 329 } 330 /* }}} */ 331 332 static void php_hashcontext_ctor(INTERNAL_FUNCTION_PARAMETERS, zval *objval) { 333 zend_string *algo, *key = NULL; 334 zend_long options = 0; 335 int argc = ZEND_NUM_ARGS(); 336 void *context; 337 const php_hash_ops *ops; 338 php_hashcontext_object *hash = php_hashcontext_from_object(Z_OBJ_P(objval)); 339 340 if (zend_parse_parameters(argc, "S|lS", &algo, &options, &key) == FAILURE) { 341 zval_ptr_dtor(return_value); 342 RETURN_NULL(); 343 } 344 345 ops = php_hash_fetch_ops(ZSTR_VAL(algo), ZSTR_LEN(algo)); 346 if (!ops) { 347 php_error_docref(NULL, E_WARNING, "Unknown hashing algorithm: %s", ZSTR_VAL(algo)); 348 zval_ptr_dtor(return_value); 349 RETURN_FALSE; 350 } 351 352 if (options & PHP_HASH_HMAC) { 353 if (!ops->is_crypto) { 354 php_error_docref(NULL, E_WARNING, "HMAC requested with a non-cryptographic hashing algorithm: %s", ZSTR_VAL(algo)); 355 zval_ptr_dtor(return_value); 356 RETURN_FALSE; 357 } 358 if (!key || (ZSTR_LEN(key) == 0)) { 359 /* Note: a zero length key is no key at all */ 360 php_error_docref(NULL, E_WARNING, "HMAC requested without a key"); 361 zval_ptr_dtor(return_value); 362 RETURN_FALSE; 363 } 364 } 365 366 context = emalloc(ops->context_size); 367 ops->hash_init(context); 368 369 hash->ops = ops; 370 hash->context = context; 371 hash->options = options; 372 hash->key = NULL; 373 374 if (options & PHP_HASH_HMAC) { 375 char *K = emalloc(ops->block_size); 376 int i, block_size; 377 378 memset(K, 0, ops->block_size); 379 380 if (ZSTR_LEN(key) > (size_t)ops->block_size) { 381 /* Reduce the key first */ 382 ops->hash_update(context, (unsigned char *) ZSTR_VAL(key), ZSTR_LEN(key)); 383 ops->hash_final((unsigned char *) K, context); 384 /* Make the context ready to start over */ 385 ops->hash_init(context); 386 } else { 387 memcpy(K, ZSTR_VAL(key), ZSTR_LEN(key)); 388 } 389 390 /* XOR ipad */ 391 block_size = ops->block_size; 392 for(i=0; i < block_size; i++) { 393 K[i] ^= 0x36; 394 } 395 ops->hash_update(context, (unsigned char *) K, ops->block_size); 396 hash->key = (unsigned char *) K; 397 } 398 } 399 400 /* {{{ proto HashContext hash_init(string algo[, int options, string key]) 401 Initialize a hashing context */ 402 PHP_FUNCTION(hash_init) 403 { 404 object_init_ex(return_value, php_hashcontext_ce); 405 php_hashcontext_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, return_value); 406 } 407 /* }}} */ 408 409 #define PHP_HASHCONTEXT_VERIFY(func, hash) { \ 410 if (!hash->context) { \ 411 php_error(E_WARNING, "%s(): supplied resource is not a valid Hash Context resource", func); \ 412 RETURN_NULL(); \ 413 } \ 414 } 415 416 /* {{{ proto bool hash_update(HashContext context, string data) 417 Pump data into the hashing algorithm */ 418 PHP_FUNCTION(hash_update) 419 { 420 zval *zhash; 421 php_hashcontext_object *hash; 422 zend_string *data; 423 424 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OS", &zhash, php_hashcontext_ce, &data) == FAILURE) { 425 return; 426 } 427 428 hash = php_hashcontext_from_object(Z_OBJ_P(zhash)); 429 PHP_HASHCONTEXT_VERIFY("hash_update", hash); 430 hash->ops->hash_update(hash->context, (unsigned char *) ZSTR_VAL(data), ZSTR_LEN(data)); 431 432 RETURN_TRUE; 433 } 434 /* }}} */ 435 436 /* {{{ proto int hash_update_stream(HashContext context, resource handle[, int length]) 437 Pump data into the hashing algorithm from an open stream */ 438 PHP_FUNCTION(hash_update_stream) 439 { 440 zval *zhash, *zstream; 441 php_hashcontext_object *hash; 442 php_stream *stream = NULL; 443 zend_long length = -1, didread = 0; 444 445 if (zend_parse_parameters(ZEND_NUM_ARGS(), "Or|l", &zhash, php_hashcontext_ce, &zstream, &length) == FAILURE) { 446 return; 447 } 448 449 hash = php_hashcontext_from_object(Z_OBJ_P(zhash)); 450 PHP_HASHCONTEXT_VERIFY("hash_update_stream", hash); 451 php_stream_from_zval(stream, zstream); 452 453 while (length) { 454 char buf[1024]; 455 zend_long n, toread = 1024; 456 457 if (length > 0 && toread > length) { 458 toread = length; 459 } 460 461 if ((n = php_stream_read(stream, buf, toread)) <= 0) { 462 /* Nada mas */ 463 RETURN_LONG(didread); 464 } 465 hash->ops->hash_update(hash->context, (unsigned char *) buf, n); 466 length -= n; 467 didread += n; 468 } 469 470 RETURN_LONG(didread); 471 } 472 /* }}} */ 473 474 /* {{{ proto bool hash_update_file(HashContext context, string filename[, resource context]) 475 Pump data into the hashing algorithm from a file */ 476 PHP_FUNCTION(hash_update_file) 477 { 478 zval *zhash, *zcontext = NULL; 479 php_hashcontext_object *hash; 480 php_stream_context *context; 481 php_stream *stream; 482 zend_string *filename; 483 char buf[1024]; 484 size_t n; 485 486 if (zend_parse_parameters(ZEND_NUM_ARGS(), "OP|r", &zhash, php_hashcontext_ce, &filename, &zcontext) == FAILURE) { 487 return; 488 } 489 490 hash = php_hashcontext_from_object(Z_OBJ_P(zhash)); 491 PHP_HASHCONTEXT_VERIFY("hash_update_file", hash); 492 context = php_stream_context_from_zval(zcontext, 0); 493 494 stream = php_stream_open_wrapper_ex(ZSTR_VAL(filename), "rb", REPORT_ERRORS, NULL, context); 495 if (!stream) { 496 /* Stream will report errors opening file */ 497 RETURN_FALSE; 498 } 499 500 while ((n = php_stream_read(stream, buf, sizeof(buf))) > 0) { 501 hash->ops->hash_update(hash->context, (unsigned char *) buf, n); 502 } 503 php_stream_close(stream); 504 505 RETURN_TRUE; 506 } 507 /* }}} */ 508 509 /* {{{ proto string hash_final(HashContext context[, bool raw_output=false]) 510 Output resulting digest */ 511 PHP_FUNCTION(hash_final) 512 { 513 zval *zhash; 514 php_hashcontext_object *hash; 515 zend_bool raw_output = 0; 516 zend_string *digest; 517 int digest_len; 518 519 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|b", &zhash, php_hashcontext_ce, &raw_output) == FAILURE) { 520 return; 521 } 522 523 hash = php_hashcontext_from_object(Z_OBJ_P(zhash)); 524 PHP_HASHCONTEXT_VERIFY("hash_final", hash); 525 526 digest_len = hash->ops->digest_size; 527 digest = zend_string_alloc(digest_len, 0); 528 hash->ops->hash_final((unsigned char *) ZSTR_VAL(digest), hash->context); 529 if (hash->options & PHP_HASH_HMAC) { 530 int i, block_size; 531 532 /* Convert K to opad -- 0x6A = 0x36 ^ 0x5C */ 533 block_size = hash->ops->block_size; 534 for(i=0; i < block_size; i++) { 535 hash->key[i] ^= 0x6A; 536 } 537 538 /* Feed this result into the outter hash */ 539 hash->ops->hash_init(hash->context); 540 hash->ops->hash_update(hash->context, hash->key, hash->ops->block_size); 541 hash->ops->hash_update(hash->context, (unsigned char *) ZSTR_VAL(digest), hash->ops->digest_size); 542 hash->ops->hash_final((unsigned char *) ZSTR_VAL(digest), hash->context); 543 544 /* Zero the key */ 545 ZEND_SECURE_ZERO(hash->key, hash->ops->block_size); 546 efree(hash->key); 547 hash->key = NULL; 548 } 549 ZSTR_VAL(digest)[digest_len] = 0; 550 551 /* Invalidate the object from further use */ 552 efree(hash->context); 553 hash->context = NULL; 554 555 if (raw_output) { 556 RETURN_NEW_STR(digest); 557 } else { 558 zend_string *hex_digest = zend_string_safe_alloc(digest_len, 2, 0, 0); 559 560 php_hash_bin2hex(ZSTR_VAL(hex_digest), (unsigned char *) ZSTR_VAL(digest), digest_len); 561 ZSTR_VAL(hex_digest)[2 * digest_len] = 0; 562 zend_string_release_ex(digest, 0); 563 RETURN_NEW_STR(hex_digest); 564 } 565 } 566 /* }}} */ 567 568 /* {{{ proto HashContext hash_copy(HashContext context) 569 Copy hash object */ 570 PHP_FUNCTION(hash_copy) 571 { 572 zval *zhash; 573 574 if (zend_parse_parameters(ZEND_NUM_ARGS(), "O", &zhash, php_hashcontext_ce) == FAILURE) { 575 return; 576 } 577 578 RETVAL_OBJ(Z_OBJ_HANDLER_P(zhash, clone_obj)(zhash)); 579 580 if (php_hashcontext_from_object(Z_OBJ_P(return_value))->context == NULL) { 581 zval_ptr_dtor(return_value); 582 RETURN_FALSE; 583 } 584 } 585 /* }}} */ 586 587 /* {{{ proto array hash_algos(void) 588 Return a list of registered hashing algorithms */ 589 PHP_FUNCTION(hash_algos) 590 { 591 zend_string *str; 592 593 array_init(return_value); 594 ZEND_HASH_FOREACH_STR_KEY(&php_hash_hashtable, str) { 595 add_next_index_str(return_value, zend_string_copy(str)); 596 } ZEND_HASH_FOREACH_END(); 597 } 598 /* }}} */ 599 600 /* {{{ proto array hash_hmac_algos(void) 601 Return a list of registered hashing algorithms suitable for hash_hmac() */ 602 PHP_FUNCTION(hash_hmac_algos) 603 { 604 zend_string *str; 605 const php_hash_ops *ops; 606 607 array_init(return_value); 608 ZEND_HASH_FOREACH_STR_KEY_PTR(&php_hash_hashtable, str, ops) { 609 if (ops->is_crypto) { 610 add_next_index_str(return_value, zend_string_copy(str)); 611 } 612 } ZEND_HASH_FOREACH_END(); 613 } 614 /* }}} */ 615 616 /* {{{ proto string hash_hkdf(string algo, string ikm [, int length = 0, string info = '', string salt = '']) 617 RFC5869 HMAC-based key derivation function */ 618 PHP_FUNCTION(hash_hkdf) 619 { 620 zend_string *returnval, *ikm, *algo, *info = NULL, *salt = NULL; 621 zend_long length = 0; 622 unsigned char *prk, *digest, *K; 623 int i, rounds; 624 const php_hash_ops *ops; 625 void *context; 626 627 if (zend_parse_parameters(ZEND_NUM_ARGS(), "SS|lSS", &algo, &ikm, &length, &info, &salt) == FAILURE) { 628 return; 629 } 630 631 ops = php_hash_fetch_ops(ZSTR_VAL(algo), ZSTR_LEN(algo)); 632 if (!ops) { 633 php_error_docref(NULL, E_WARNING, "Unknown hashing algorithm: %s", ZSTR_VAL(algo)); 634 RETURN_FALSE; 635 } 636 637 if (!ops->is_crypto) { 638 php_error_docref(NULL, E_WARNING, "Non-cryptographic hashing algorithm: %s", ZSTR_VAL(algo)); 639 RETURN_FALSE; 640 } 641 642 if (ZSTR_LEN(ikm) == 0) { 643 php_error_docref(NULL, E_WARNING, "Input keying material cannot be empty"); 644 RETURN_FALSE; 645 } 646 647 if (length < 0) { 648 php_error_docref(NULL, E_WARNING, "Length must be greater than or equal to 0: " ZEND_LONG_FMT, length); 649 RETURN_FALSE; 650 } else if (length == 0) { 651 length = ops->digest_size; 652 } else if (length > ops->digest_size * 255) { 653 php_error_docref(NULL, E_WARNING, "Length must be less than or equal to %d: " ZEND_LONG_FMT, ops->digest_size * 255, length); 654 RETURN_FALSE; 655 } 656 657 context = emalloc(ops->context_size); 658 659 // Extract 660 ops->hash_init(context); 661 K = emalloc(ops->block_size); 662 php_hash_hmac_prep_key(K, ops, context, 663 (unsigned char *) (salt ? ZSTR_VAL(salt) : ""), salt ? ZSTR_LEN(salt) : 0); 664 665 prk = emalloc(ops->digest_size); 666 php_hash_hmac_round(prk, ops, context, K, (unsigned char *) ZSTR_VAL(ikm), ZSTR_LEN(ikm)); 667 php_hash_string_xor_char(K, K, 0x6A, ops->block_size); 668 php_hash_hmac_round(prk, ops, context, K, prk, ops->digest_size); 669 ZEND_SECURE_ZERO(K, ops->block_size); 670 671 // Expand 672 returnval = zend_string_alloc(length, 0); 673 digest = emalloc(ops->digest_size); 674 for (i = 1, rounds = (length - 1) / ops->digest_size + 1; i <= rounds; i++) { 675 // chr(i) 676 unsigned char c[1]; 677 c[0] = (i & 0xFF); 678 679 php_hash_hmac_prep_key(K, ops, context, prk, ops->digest_size); 680 ops->hash_init(context); 681 ops->hash_update(context, K, ops->block_size); 682 683 if (i > 1) { 684 ops->hash_update(context, digest, ops->digest_size); 685 } 686 687 if (info != NULL && ZSTR_LEN(info) > 0) { 688 ops->hash_update(context, (unsigned char *) ZSTR_VAL(info), ZSTR_LEN(info)); 689 } 690 691 ops->hash_update(context, c, 1); 692 ops->hash_final(digest, context); 693 php_hash_string_xor_char(K, K, 0x6A, ops->block_size); 694 php_hash_hmac_round(digest, ops, context, K, digest, ops->digest_size); 695 memcpy( 696 ZSTR_VAL(returnval) + ((i - 1) * ops->digest_size), 697 digest, 698 (i == rounds ? length - ((i - 1) * ops->digest_size) : ops->digest_size) 699 ); 700 } 701 702 ZEND_SECURE_ZERO(K, ops->block_size); 703 ZEND_SECURE_ZERO(digest, ops->digest_size); 704 ZEND_SECURE_ZERO(prk, ops->digest_size); 705 efree(K); 706 efree(context); 707 efree(prk); 708 efree(digest); 709 ZSTR_VAL(returnval)[length] = 0; 710 RETURN_STR(returnval); 711 } 712 713 /* {{{ proto string hash_pbkdf2(string algo, string password, string salt, int iterations [, int length = 0, bool raw_output = false]) 714 Generate a PBKDF2 hash of the given password and salt 715 Returns lowercase hexits by default */ 716 PHP_FUNCTION(hash_pbkdf2) 717 { 718 zend_string *returnval; 719 char *algo, *salt, *pass = NULL; 720 unsigned char *computed_salt, *digest, *temp, *result, *K1, *K2 = NULL; 721 zend_long loops, i, j, iterations, digest_length = 0, length = 0; 722 size_t algo_len, pass_len, salt_len = 0; 723 zend_bool raw_output = 0; 724 const php_hash_ops *ops; 725 void *context; 726 727 if (zend_parse_parameters(ZEND_NUM_ARGS(), "sssl|lb", &algo, &algo_len, &pass, &pass_len, &salt, &salt_len, &iterations, &length, &raw_output) == FAILURE) { 728 return; 729 } 730 731 ops = php_hash_fetch_ops(algo, algo_len); 732 if (!ops) { 733 php_error_docref(NULL, E_WARNING, "Unknown hashing algorithm: %s", algo); 734 RETURN_FALSE; 735 } 736 else if (!ops->is_crypto) { 737 php_error_docref(NULL, E_WARNING, "Non-cryptographic hashing algorithm: %s", algo); 738 RETURN_FALSE; 739 } 740 741 if (iterations <= 0) { 742 php_error_docref(NULL, E_WARNING, "Iterations must be a positive integer: " ZEND_LONG_FMT, iterations); 743 RETURN_FALSE; 744 } 745 746 if (length < 0) { 747 php_error_docref(NULL, E_WARNING, "Length must be greater than or equal to 0: " ZEND_LONG_FMT, length); 748 RETURN_FALSE; 749 } 750 751 if (salt_len > INT_MAX - 4) { 752 php_error_docref(NULL, E_WARNING, "Supplied salt is too long, max of INT_MAX - 4 bytes: %zd supplied", salt_len); 753 RETURN_FALSE; 754 } 755 756 context = emalloc(ops->context_size); 757 ops->hash_init(context); 758 759 K1 = emalloc(ops->block_size); 760 K2 = emalloc(ops->block_size); 761 digest = emalloc(ops->digest_size); 762 temp = emalloc(ops->digest_size); 763 764 /* Setup Keys that will be used for all hmac rounds */ 765 php_hash_hmac_prep_key(K1, ops, context, (unsigned char *) pass, pass_len); 766 /* Convert K1 to opad -- 0x6A = 0x36 ^ 0x5C */ 767 php_hash_string_xor_char(K2, K1, 0x6A, ops->block_size); 768 769 /* Setup Main Loop to build a long enough result */ 770 if (length == 0) { 771 length = ops->digest_size; 772 if (!raw_output) { 773 length = length * 2; 774 } 775 } 776 digest_length = length; 777 if (!raw_output) { 778 digest_length = (zend_long) ceil((float) length / 2.0); 779 } 780 781 loops = (zend_long) ceil((float) digest_length / (float) ops->digest_size); 782 783 result = safe_emalloc(loops, ops->digest_size, 0); 784 785 computed_salt = safe_emalloc(salt_len, 1, 4); 786 memcpy(computed_salt, (unsigned char *) salt, salt_len); 787 788 for (i = 1; i <= loops; i++) { 789 /* digest = hash_hmac(salt + pack('N', i), password) { */ 790 791 /* pack("N", i) */ 792 computed_salt[salt_len] = (unsigned char) (i >> 24); 793 computed_salt[salt_len + 1] = (unsigned char) ((i & 0xFF0000) >> 16); 794 computed_salt[salt_len + 2] = (unsigned char) ((i & 0xFF00) >> 8); 795 computed_salt[salt_len + 3] = (unsigned char) (i & 0xFF); 796 797 php_hash_hmac_round(digest, ops, context, K1, computed_salt, (zend_long) salt_len + 4); 798 php_hash_hmac_round(digest, ops, context, K2, digest, ops->digest_size); 799 /* } */ 800 801 /* temp = digest */ 802 memcpy(temp, digest, ops->digest_size); 803 804 /* 805 * Note that the loop starting at 1 is intentional, since we've already done 806 * the first round of the algorithm. 807 */ 808 for (j = 1; j < iterations; j++) { 809 /* digest = hash_hmac(digest, password) { */ 810 php_hash_hmac_round(digest, ops, context, K1, digest, ops->digest_size); 811 php_hash_hmac_round(digest, ops, context, K2, digest, ops->digest_size); 812 /* } */ 813 /* temp ^= digest */ 814 php_hash_string_xor(temp, temp, digest, ops->digest_size); 815 } 816 /* result += temp */ 817 memcpy(result + ((i - 1) * ops->digest_size), temp, ops->digest_size); 818 } 819 /* Zero potentially sensitive variables */ 820 ZEND_SECURE_ZERO(K1, ops->block_size); 821 ZEND_SECURE_ZERO(K2, ops->block_size); 822 ZEND_SECURE_ZERO(computed_salt, salt_len + 4); 823 efree(K1); 824 efree(K2); 825 efree(computed_salt); 826 efree(context); 827 efree(digest); 828 efree(temp); 829 830 returnval = zend_string_alloc(length, 0); 831 if (raw_output) { 832 memcpy(ZSTR_VAL(returnval), result, length); 833 } else { 834 php_hash_bin2hex(ZSTR_VAL(returnval), result, digest_length); 835 } 836 ZSTR_VAL(returnval)[length] = 0; 837 efree(result); 838 RETURN_NEW_STR(returnval); 839 } 840 /* }}} */ 841 842 /* {{{ proto bool hash_equals(string known_string, string user_string) 843 Compares two strings using the same time whether they're equal or not. 844 A difference in length will leak */ 845 PHP_FUNCTION(hash_equals) 846 { 847 zval *known_zval, *user_zval; 848 char *known_str, *user_str; 849 int result = 0; 850 size_t j; 851 852 if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &known_zval, &user_zval) == FAILURE) { 853 return; 854 } 855 856 /* We only allow comparing string to prevent unexpected results. */ 857 if (Z_TYPE_P(known_zval) != IS_STRING) { 858 php_error_docref(NULL, E_WARNING, "Expected known_string to be a string, %s given", zend_zval_type_name(known_zval)); 859 RETURN_FALSE; 860 } 861 862 if (Z_TYPE_P(user_zval) != IS_STRING) { 863 php_error_docref(NULL, E_WARNING, "Expected user_string to be a string, %s given", zend_zval_type_name(user_zval)); 864 RETURN_FALSE; 865 } 866 867 if (Z_STRLEN_P(known_zval) != Z_STRLEN_P(user_zval)) { 868 RETURN_FALSE; 869 } 870 871 known_str = Z_STRVAL_P(known_zval); 872 user_str = Z_STRVAL_P(user_zval); 873 874 /* This is security sensitive code. Do not optimize this for speed. */ 875 for (j = 0; j < Z_STRLEN_P(known_zval); j++) { 876 result |= known_str[j] ^ user_str[j]; 877 } 878 879 RETURN_BOOL(0 == result); 880 } 881 /* }}} */ 882 883 /* {{{ proto HashContext::__construct() */ 884 static PHP_METHOD(HashContext, __construct) { 885 /* Normally unreachable as private/final */ 886 zend_throw_exception(zend_ce_error, "Illegal call to private/final constructor", 0); 887 } 888 /* }}} */ 889 890 static const zend_function_entry php_hashcontext_methods[] = { 891 PHP_ME(HashContext, __construct, NULL, ZEND_ACC_PRIVATE | ZEND_ACC_CTOR) 892 PHP_FE_END 893 }; 894 895 /* Module Housekeeping */ 896 897 #define PHP_HASH_HAVAL_REGISTER(p,b) php_hash_register_algo("haval" #b "," #p , &php_hash_##p##haval##b##_ops); 898 899 #ifdef PHP_MHASH_BC 900 901 #if 0 902 /* See #69823, we should not insert module into module_registry while doing startup */ 903 904 PHP_MINFO_FUNCTION(mhash) 905 { 906 php_info_print_table_start(); 907 php_info_print_table_row(2, "MHASH support", "Enabled"); 908 php_info_print_table_row(2, "MHASH API Version", "Emulated Support"); 909 php_info_print_table_end(); 910 } 911 912 zend_module_entry mhash_module_entry = { 913 STANDARD_MODULE_HEADER, 914 "mhash", 915 NULL, 916 NULL, 917 NULL, 918 NULL, 919 NULL, 920 PHP_MINFO(mhash), 921 PHP_MHASH_VERSION, 922 STANDARD_MODULE_PROPERTIES, 923 }; 924 #endif 925 926 static void mhash_init(INIT_FUNC_ARGS) 927 { 928 char buf[128]; 929 int len; 930 int algo_number = 0; 931 932 for (algo_number = 0; algo_number < MHASH_NUM_ALGOS; algo_number++) { 933 struct mhash_bc_entry algorithm = mhash_to_hash[algo_number]; 934 if (algorithm.mhash_name == NULL) { 935 continue; 936 } 937 938 len = slprintf(buf, 127, "MHASH_%s", algorithm.mhash_name); 939 zend_register_long_constant(buf, len, algorithm.value, CONST_CS | CONST_PERSISTENT, module_number); 940 } 941 942 /* TODO: this cause #69823 zend_register_internal_module(&mhash_module_entry); */ 943 } 944 945 /* {{{ proto string mhash(int hash, string data [, string key]) 946 Hash data with hash */ 947 PHP_FUNCTION(mhash) 948 { 949 zval *z_algorithm; 950 zend_long algorithm; 951 952 if (zend_parse_parameters(1, "z", &z_algorithm) == FAILURE) { 953 return; 954 } 955 956 algorithm = zval_get_long(z_algorithm); 957 958 /* need to convert the first parameter from int constant to string algorithm name */ 959 if (algorithm >= 0 && algorithm < MHASH_NUM_ALGOS) { 960 struct mhash_bc_entry algorithm_lookup = mhash_to_hash[algorithm]; 961 if (algorithm_lookup.hash_name) { 962 ZVAL_STRING(z_algorithm, algorithm_lookup.hash_name); 963 } 964 } 965 966 if (ZEND_NUM_ARGS() == 3) { 967 php_hash_do_hash_hmac(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1); 968 } else if (ZEND_NUM_ARGS() == 2) { 969 php_hash_do_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0, 1); 970 } else { 971 WRONG_PARAM_COUNT; 972 } 973 } 974 /* }}} */ 975 976 /* {{{ proto string mhash_get_hash_name(int hash) 977 Gets the name of hash */ 978 PHP_FUNCTION(mhash_get_hash_name) 979 { 980 zend_long algorithm; 981 982 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &algorithm) == FAILURE) { 983 return; 984 } 985 986 if (algorithm >= 0 && algorithm < MHASH_NUM_ALGOS) { 987 struct mhash_bc_entry algorithm_lookup = mhash_to_hash[algorithm]; 988 if (algorithm_lookup.mhash_name) { 989 RETURN_STRING(algorithm_lookup.mhash_name); 990 } 991 } 992 RETURN_FALSE; 993 } 994 /* }}} */ 995 996 /* {{{ proto int mhash_count(void) 997 Gets the number of available hashes */ 998 PHP_FUNCTION(mhash_count) 999 { 1000 if (zend_parse_parameters_none() == FAILURE) { 1001 return; 1002 } 1003 RETURN_LONG(MHASH_NUM_ALGOS - 1); 1004 } 1005 /* }}} */ 1006 1007 /* {{{ proto int mhash_get_block_size(int hash) 1008 Gets the block size of hash */ 1009 PHP_FUNCTION(mhash_get_block_size) 1010 { 1011 zend_long algorithm; 1012 1013 if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &algorithm) == FAILURE) { 1014 return; 1015 } 1016 RETVAL_FALSE; 1017 1018 if (algorithm >= 0 && algorithm < MHASH_NUM_ALGOS) { 1019 struct mhash_bc_entry algorithm_lookup = mhash_to_hash[algorithm]; 1020 if (algorithm_lookup.mhash_name) { 1021 const php_hash_ops *ops = php_hash_fetch_ops(algorithm_lookup.hash_name, strlen(algorithm_lookup.hash_name)); 1022 if (ops) { 1023 RETVAL_LONG(ops->digest_size); 1024 } 1025 } 1026 } 1027 } 1028 /* }}} */ 1029 1030 #define SALT_SIZE 8 1031 1032 /* {{{ proto string mhash_keygen_s2k(int hash, string input_password, string salt, int bytes) 1033 Generates a key using hash functions */ 1034 PHP_FUNCTION(mhash_keygen_s2k) 1035 { 1036 zend_long algorithm, l_bytes; 1037 int bytes; 1038 char *password, *salt; 1039 size_t password_len, salt_len; 1040 char padded_salt[SALT_SIZE]; 1041 1042 if (zend_parse_parameters(ZEND_NUM_ARGS(), "lssl", &algorithm, &password, &password_len, &salt, &salt_len, &l_bytes) == FAILURE) { 1043 return; 1044 } 1045 1046 bytes = (int)l_bytes; 1047 if (bytes <= 0){ 1048 php_error_docref(NULL, E_WARNING, "the byte parameter must be greater than 0"); 1049 RETURN_FALSE; 1050 } 1051 1052 salt_len = MIN(salt_len, SALT_SIZE); 1053 1054 memcpy(padded_salt, salt, salt_len); 1055 if (salt_len < SALT_SIZE) { 1056 memset(padded_salt + salt_len, 0, SALT_SIZE - salt_len); 1057 } 1058 salt_len = SALT_SIZE; 1059 1060 RETVAL_FALSE; 1061 if (algorithm >= 0 && algorithm < MHASH_NUM_ALGOS) { 1062 struct mhash_bc_entry algorithm_lookup = mhash_to_hash[algorithm]; 1063 if (algorithm_lookup.mhash_name) { 1064 const php_hash_ops *ops = php_hash_fetch_ops(algorithm_lookup.hash_name, strlen(algorithm_lookup.hash_name)); 1065 if (ops) { 1066 unsigned char null = '\0'; 1067 void *context; 1068 char *key, *digest; 1069 int i = 0, j = 0; 1070 int block_size = ops->digest_size; 1071 int times = bytes / block_size; 1072 if (bytes % block_size != 0) times++; 1073 1074 context = emalloc(ops->context_size); 1075 ops->hash_init(context); 1076 1077 key = ecalloc(1, times * block_size); 1078 digest = emalloc(ops->digest_size + 1); 1079 1080 for (i = 0; i < times; i++) { 1081 ops->hash_init(context); 1082 1083 for (j=0;j<i;j++) { 1084 ops->hash_update(context, &null, 1); 1085 } 1086 ops->hash_update(context, (unsigned char *)padded_salt, salt_len); 1087 ops->hash_update(context, (unsigned char *)password, password_len); 1088 ops->hash_final((unsigned char *)digest, context); 1089 memcpy( &key[i*block_size], digest, block_size); 1090 } 1091 1092 RETVAL_STRINGL(key, bytes); 1093 ZEND_SECURE_ZERO(key, bytes); 1094 efree(digest); 1095 efree(context); 1096 efree(key); 1097 } 1098 } 1099 } 1100 } 1101 /* }}} */ 1102 1103 #endif 1104 1105 /* ----------------------------------------------------------------------- */ 1106 1107 /* {{{ php_hashcontext_create */ 1108 static zend_object* php_hashcontext_create(zend_class_entry *ce) { 1109 php_hashcontext_object *objval = zend_object_alloc(sizeof(php_hashcontext_object), ce); 1110 zend_object *zobj = &objval->std; 1111 1112 zend_object_std_init(zobj, ce); 1113 object_properties_init(zobj, ce); 1114 zobj->handlers = &php_hashcontext_handlers; 1115 1116 return zobj; 1117 } 1118 /* }}} */ 1119 1120 /* {{{ php_hashcontext_dtor */ 1121 static void php_hashcontext_dtor(zend_object *obj) { 1122 php_hashcontext_object *hash = php_hashcontext_from_object(obj); 1123 1124 /* Just in case the algo has internally allocated resources */ 1125 if (hash->context) { 1126 unsigned char *dummy = emalloc(hash->ops->digest_size); 1127 hash->ops->hash_final(dummy, hash->context); 1128 efree(dummy); 1129 efree(hash->context); 1130 hash->context = NULL; 1131 } 1132 1133 if (hash->key) { 1134 ZEND_SECURE_ZERO(hash->key, hash->ops->block_size); 1135 efree(hash->key); 1136 hash->key = NULL; 1137 } 1138 } 1139 /* }}} */ 1140 1141 /* {{{ php_hashcontext_clone */ 1142 static zend_object *php_hashcontext_clone(zval *pzv) { 1143 php_hashcontext_object *oldobj = php_hashcontext_from_object(Z_OBJ_P(pzv)); 1144 zend_object *znew = php_hashcontext_create(Z_OBJCE_P(pzv)); 1145 php_hashcontext_object *newobj = php_hashcontext_from_object(znew); 1146 1147 zend_objects_clone_members(znew, Z_OBJ_P(pzv)); 1148 1149 newobj->ops = oldobj->ops; 1150 newobj->options = oldobj->options; 1151 newobj->context = emalloc(newobj->ops->context_size); 1152 newobj->ops->hash_init(newobj->context); 1153 1154 if (SUCCESS != newobj->ops->hash_copy(newobj->ops, oldobj->context, newobj->context)) { 1155 efree(newobj->context); 1156 newobj->context = NULL; 1157 return znew; 1158 } 1159 1160 newobj->key = ecalloc(1, newobj->ops->block_size); 1161 if (oldobj->key) { 1162 memcpy(newobj->key, oldobj->key, newobj->ops->block_size); 1163 } 1164 1165 return znew; 1166 } 1167 /* }}} */ 1168 1169 /* {{{ PHP_MINIT_FUNCTION 1170 */ 1171 PHP_MINIT_FUNCTION(hash) 1172 { 1173 zend_class_entry ce; 1174 1175 zend_hash_init(&php_hash_hashtable, 35, NULL, NULL, 1); 1176 1177 php_hash_register_algo("md2", &php_hash_md2_ops); 1178 php_hash_register_algo("md4", &php_hash_md4_ops); 1179 php_hash_register_algo("md5", &php_hash_md5_ops); 1180 php_hash_register_algo("sha1", &php_hash_sha1_ops); 1181 php_hash_register_algo("sha224", &php_hash_sha224_ops); 1182 php_hash_register_algo("sha256", &php_hash_sha256_ops); 1183 php_hash_register_algo("sha384", &php_hash_sha384_ops); 1184 php_hash_register_algo("sha512/224", &php_hash_sha512_224_ops); 1185 php_hash_register_algo("sha512/256", &php_hash_sha512_256_ops); 1186 php_hash_register_algo("sha512", &php_hash_sha512_ops); 1187 php_hash_register_algo("sha3-224", &php_hash_sha3_224_ops); 1188 php_hash_register_algo("sha3-256", &php_hash_sha3_256_ops); 1189 php_hash_register_algo("sha3-384", &php_hash_sha3_384_ops); 1190 php_hash_register_algo("sha3-512", &php_hash_sha3_512_ops); 1191 php_hash_register_algo("ripemd128", &php_hash_ripemd128_ops); 1192 php_hash_register_algo("ripemd160", &php_hash_ripemd160_ops); 1193 php_hash_register_algo("ripemd256", &php_hash_ripemd256_ops); 1194 php_hash_register_algo("ripemd320", &php_hash_ripemd320_ops); 1195 php_hash_register_algo("whirlpool", &php_hash_whirlpool_ops); 1196 php_hash_register_algo("tiger128,3", &php_hash_3tiger128_ops); 1197 php_hash_register_algo("tiger160,3", &php_hash_3tiger160_ops); 1198 php_hash_register_algo("tiger192,3", &php_hash_3tiger192_ops); 1199 php_hash_register_algo("tiger128,4", &php_hash_4tiger128_ops); 1200 php_hash_register_algo("tiger160,4", &php_hash_4tiger160_ops); 1201 php_hash_register_algo("tiger192,4", &php_hash_4tiger192_ops); 1202 php_hash_register_algo("snefru", &php_hash_snefru_ops); 1203 php_hash_register_algo("snefru256", &php_hash_snefru_ops); 1204 php_hash_register_algo("gost", &php_hash_gost_ops); 1205 php_hash_register_algo("gost-crypto", &php_hash_gost_crypto_ops); 1206 php_hash_register_algo("adler32", &php_hash_adler32_ops); 1207 php_hash_register_algo("crc32", &php_hash_crc32_ops); 1208 php_hash_register_algo("crc32b", &php_hash_crc32b_ops); 1209 php_hash_register_algo("fnv132", &php_hash_fnv132_ops); 1210 php_hash_register_algo("fnv1a32", &php_hash_fnv1a32_ops); 1211 php_hash_register_algo("fnv164", &php_hash_fnv164_ops); 1212 php_hash_register_algo("fnv1a64", &php_hash_fnv1a64_ops); 1213 php_hash_register_algo("joaat", &php_hash_joaat_ops); 1214 1215 PHP_HASH_HAVAL_REGISTER(3,128); 1216 PHP_HASH_HAVAL_REGISTER(3,160); 1217 PHP_HASH_HAVAL_REGISTER(3,192); 1218 PHP_HASH_HAVAL_REGISTER(3,224); 1219 PHP_HASH_HAVAL_REGISTER(3,256); 1220 1221 PHP_HASH_HAVAL_REGISTER(4,128); 1222 PHP_HASH_HAVAL_REGISTER(4,160); 1223 PHP_HASH_HAVAL_REGISTER(4,192); 1224 PHP_HASH_HAVAL_REGISTER(4,224); 1225 PHP_HASH_HAVAL_REGISTER(4,256); 1226 1227 PHP_HASH_HAVAL_REGISTER(5,128); 1228 PHP_HASH_HAVAL_REGISTER(5,160); 1229 PHP_HASH_HAVAL_REGISTER(5,192); 1230 PHP_HASH_HAVAL_REGISTER(5,224); 1231 PHP_HASH_HAVAL_REGISTER(5,256); 1232 1233 REGISTER_LONG_CONSTANT("HASH_HMAC", PHP_HASH_HMAC, CONST_CS | CONST_PERSISTENT); 1234 1235 INIT_CLASS_ENTRY(ce, "HashContext", php_hashcontext_methods); 1236 php_hashcontext_ce = zend_register_internal_class(&ce); 1237 php_hashcontext_ce->ce_flags |= ZEND_ACC_FINAL; 1238 php_hashcontext_ce->create_object = php_hashcontext_create; 1239 php_hashcontext_ce->serialize = zend_class_serialize_deny; 1240 php_hashcontext_ce->unserialize = zend_class_unserialize_deny; 1241 1242 memcpy(&php_hashcontext_handlers, &std_object_handlers, 1243 sizeof(zend_object_handlers)); 1244 php_hashcontext_handlers.offset = XtOffsetOf(php_hashcontext_object, std); 1245 php_hashcontext_handlers.dtor_obj = php_hashcontext_dtor; 1246 php_hashcontext_handlers.clone_obj = php_hashcontext_clone; 1247 1248 #ifdef PHP_MHASH_BC 1249 mhash_init(INIT_FUNC_ARGS_PASSTHRU); 1250 #endif 1251 1252 return SUCCESS; 1253 } 1254 /* }}} */ 1255 1256 /* {{{ PHP_MSHUTDOWN_FUNCTION 1257 */ 1258 PHP_MSHUTDOWN_FUNCTION(hash) 1259 { 1260 zend_hash_destroy(&php_hash_hashtable); 1261 1262 return SUCCESS; 1263 } 1264 /* }}} */ 1265 1266 /* {{{ PHP_MINFO_FUNCTION 1267 */ 1268 PHP_MINFO_FUNCTION(hash) 1269 { 1270 char buffer[2048]; 1271 zend_string *str; 1272 char *s = buffer, *e = s + sizeof(buffer); 1273 1274 ZEND_HASH_FOREACH_STR_KEY(&php_hash_hashtable, str) { 1275 s += slprintf(s, e - s, "%s ", ZSTR_VAL(str)); 1276 } ZEND_HASH_FOREACH_END(); 1277 *s = 0; 1278 1279 php_info_print_table_start(); 1280 php_info_print_table_row(2, "hash support", "enabled"); 1281 php_info_print_table_row(2, "Hashing Engines", buffer); 1282 php_info_print_table_end(); 1283 1284 #ifdef PHP_MHASH_BC 1285 php_info_print_table_start(); 1286 php_info_print_table_row(2, "MHASH support", "Enabled"); 1287 php_info_print_table_row(2, "MHASH API Version", "Emulated Support"); 1288 php_info_print_table_end(); 1289 #endif 1290 1291 } 1292 /* }}} */ 1293 1294 /* {{{ arginfo */ 1295 #ifdef PHP_HASH_MD5_NOT_IN_CORE 1296 ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_md5, 0, 0, 1) 1297 ZEND_ARG_INFO(0, str) 1298 ZEND_ARG_INFO(0, raw_output) 1299 ZEND_END_ARG_INFO() 1300 1301 ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_md5_file, 0, 0, 1) 1302 ZEND_ARG_INFO(0, filename) 1303 ZEND_ARG_INFO(0, raw_output) 1304 ZEND_END_ARG_INFO() 1305 #endif 1306 1307 #ifdef PHP_HASH_SHA1_NOT_IN_CORE 1308 ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_sha1, 0, 0, 1) 1309 ZEND_ARG_INFO(0, str) 1310 ZEND_ARG_INFO(0, raw_output) 1311 ZEND_END_ARG_INFO() 1312 1313 ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_sha1_file, 0, 0, 1) 1314 ZEND_ARG_INFO(0, filename) 1315 ZEND_ARG_INFO(0, raw_output) 1316 ZEND_END_ARG_INFO() 1317 #endif 1318 1319 ZEND_BEGIN_ARG_INFO_EX(arginfo_hash, 0, 0, 2) 1320 ZEND_ARG_INFO(0, algo) 1321 ZEND_ARG_INFO(0, data) 1322 ZEND_ARG_INFO(0, raw_output) 1323 ZEND_END_ARG_INFO() 1324 1325 ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_file, 0, 0, 2) 1326 ZEND_ARG_INFO(0, algo) 1327 ZEND_ARG_INFO(0, filename) 1328 ZEND_ARG_INFO(0, raw_output) 1329 ZEND_END_ARG_INFO() 1330 1331 ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_hmac, 0, 0, 3) 1332 ZEND_ARG_INFO(0, algo) 1333 ZEND_ARG_INFO(0, data) 1334 ZEND_ARG_INFO(0, key) 1335 ZEND_ARG_INFO(0, raw_output) 1336 ZEND_END_ARG_INFO() 1337 1338 ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_hmac_file, 0, 0, 3) 1339 ZEND_ARG_INFO(0, algo) 1340 ZEND_ARG_INFO(0, filename) 1341 ZEND_ARG_INFO(0, key) 1342 ZEND_ARG_INFO(0, raw_output) 1343 ZEND_END_ARG_INFO() 1344 1345 ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_init, 0, 0, 1) 1346 ZEND_ARG_INFO(0, algo) 1347 ZEND_ARG_INFO(0, options) 1348 ZEND_ARG_INFO(0, key) 1349 ZEND_END_ARG_INFO() 1350 1351 ZEND_BEGIN_ARG_INFO(arginfo_hash_update, 0) 1352 ZEND_ARG_INFO(0, context) 1353 ZEND_ARG_INFO(0, data) 1354 ZEND_END_ARG_INFO() 1355 1356 ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_update_stream, 0, 0, 2) 1357 ZEND_ARG_INFO(0, context) 1358 ZEND_ARG_INFO(0, handle) 1359 ZEND_ARG_INFO(0, length) 1360 ZEND_END_ARG_INFO() 1361 1362 ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_update_file, 0, 0, 2) 1363 ZEND_ARG_INFO(0, context) 1364 ZEND_ARG_INFO(0, filename) 1365 ZEND_ARG_INFO(0, stream_context) 1366 ZEND_END_ARG_INFO() 1367 1368 ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_final, 0, 0, 1) 1369 ZEND_ARG_INFO(0, context) 1370 ZEND_ARG_INFO(0, raw_output) 1371 ZEND_END_ARG_INFO() 1372 1373 ZEND_BEGIN_ARG_INFO(arginfo_hash_copy, 0) 1374 ZEND_ARG_INFO(0, context) 1375 ZEND_END_ARG_INFO() 1376 1377 ZEND_BEGIN_ARG_INFO(arginfo_hash_algos, 0) 1378 ZEND_END_ARG_INFO() 1379 1380 ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_pbkdf2, 0, 0, 4) 1381 ZEND_ARG_INFO(0, algo) 1382 ZEND_ARG_INFO(0, password) 1383 ZEND_ARG_INFO(0, salt) 1384 ZEND_ARG_INFO(0, iterations) 1385 ZEND_ARG_INFO(0, length) 1386 ZEND_ARG_INFO(0, raw_output) 1387 ZEND_END_ARG_INFO() 1388 1389 ZEND_BEGIN_ARG_INFO(arginfo_hash_equals, 0) 1390 ZEND_ARG_INFO(0, known_string) 1391 ZEND_ARG_INFO(0, user_string) 1392 ZEND_END_ARG_INFO() 1393 1394 ZEND_BEGIN_ARG_INFO_EX(arginfo_hash_hkdf, 0, 0, 2) 1395 ZEND_ARG_INFO(0, ikm) 1396 ZEND_ARG_INFO(0, algo) 1397 ZEND_ARG_INFO(0, length) 1398 ZEND_ARG_INFO(0, string) 1399 ZEND_ARG_INFO(0, salt) 1400 ZEND_END_ARG_INFO() 1401 1402 /* BC Land */ 1403 #ifdef PHP_MHASH_BC 1404 ZEND_BEGIN_ARG_INFO(arginfo_mhash_get_block_size, 0) 1405 ZEND_ARG_INFO(0, hash) 1406 ZEND_END_ARG_INFO() 1407 1408 ZEND_BEGIN_ARG_INFO(arginfo_mhash_get_hash_name, 0) 1409 ZEND_ARG_INFO(0, hash) 1410 ZEND_END_ARG_INFO() 1411 1412 ZEND_BEGIN_ARG_INFO(arginfo_mhash_keygen_s2k, 0) 1413 ZEND_ARG_INFO(0, hash) 1414 ZEND_ARG_INFO(0, input_password) 1415 ZEND_ARG_INFO(0, salt) 1416 ZEND_ARG_INFO(0, bytes) 1417 ZEND_END_ARG_INFO() 1418 1419 ZEND_BEGIN_ARG_INFO(arginfo_mhash_count, 0) 1420 ZEND_END_ARG_INFO() 1421 1422 ZEND_BEGIN_ARG_INFO_EX(arginfo_mhash, 0, 0, 2) 1423 ZEND_ARG_INFO(0, hash) 1424 ZEND_ARG_INFO(0, data) 1425 ZEND_ARG_INFO(0, key) 1426 ZEND_END_ARG_INFO() 1427 #endif 1428 1429 /* }}} */ 1430 1431 /* {{{ hash_functions[] 1432 */ 1433 static const zend_function_entry hash_functions[] = { 1434 PHP_FE(hash, arginfo_hash) 1435 PHP_FE(hash_file, arginfo_hash_file) 1436 1437 PHP_FE(hash_hmac, arginfo_hash_hmac) 1438 PHP_FE(hash_hmac_file, arginfo_hash_hmac_file) 1439 1440 PHP_FE(hash_init, arginfo_hash_init) 1441 PHP_FE(hash_update, arginfo_hash_update) 1442 PHP_FE(hash_update_stream, arginfo_hash_update_stream) 1443 PHP_FE(hash_update_file, arginfo_hash_update_file) 1444 PHP_FE(hash_final, arginfo_hash_final) 1445 PHP_FE(hash_copy, arginfo_hash_copy) 1446 1447 PHP_FE(hash_algos, arginfo_hash_algos) 1448 PHP_FE(hash_hmac_algos, arginfo_hash_algos) 1449 PHP_FE(hash_pbkdf2, arginfo_hash_pbkdf2) 1450 PHP_FE(hash_equals, arginfo_hash_equals) 1451 PHP_FE(hash_hkdf, arginfo_hash_hkdf) 1452 1453 /* BC Land */ 1454 #ifdef PHP_HASH_MD5_NOT_IN_CORE 1455 PHP_NAMED_FE(md5, php_if_md5, arginfo_hash_md5) 1456 PHP_NAMED_FE(md5_file, php_if_md5_file, arginfo_hash_md5_file) 1457 #endif /* PHP_HASH_MD5_NOT_IN_CORE */ 1458 1459 #ifdef PHP_HASH_SHA1_NOT_IN_CORE 1460 PHP_NAMED_FE(sha1, php_if_sha1, arginfo_hash_sha1) 1461 PHP_NAMED_FE(sha1_file, php_if_sha1_file, arginfo_hash_sha1_file) 1462 #endif /* PHP_HASH_SHA1_NOT_IN_CORE */ 1463 1464 #ifdef PHP_MHASH_BC 1465 PHP_FE(mhash_keygen_s2k, arginfo_mhash_keygen_s2k) 1466 PHP_FE(mhash_get_block_size, arginfo_mhash_get_block_size) 1467 PHP_FE(mhash_get_hash_name, arginfo_mhash_get_hash_name) 1468 PHP_FE(mhash_count, arginfo_mhash_count) 1469 PHP_FE(mhash, arginfo_mhash) 1470 #endif 1471 1472 PHP_FE_END 1473 }; 1474 /* }}} */ 1475 1476 /* {{{ hash_module_entry 1477 */ 1478 zend_module_entry hash_module_entry = { 1479 STANDARD_MODULE_HEADER, 1480 PHP_HASH_EXTNAME, 1481 hash_functions, 1482 PHP_MINIT(hash), 1483 PHP_MSHUTDOWN(hash), 1484 NULL, /* RINIT */ 1485 NULL, /* RSHUTDOWN */ 1486 PHP_MINFO(hash), 1487 PHP_HASH_VERSION, 1488 STANDARD_MODULE_PROPERTIES 1489 }; 1490 /* }}} */ 1491 1492 #ifdef COMPILE_DL_HASH 1493 ZEND_GET_MODULE(hash) 1494 #endif 1495 1496 /* 1497 * Local variables: 1498 * tab-width: 4 1499 * c-basic-offset: 4 1500 * End: 1501 * vim600: noet sw=4 ts=4 fdm=marker 1502 * vim<600: noet sw=4 ts=4 1503 */ 1504