|
26 | 26 | #include "ext/standard/file.h" |
27 | 27 | #include "ext/standard/php_var.h" |
28 | 28 |
|
| 29 | +#if defined(__APPLE__) && __has_include(<CommonCrypto/CommonKeyDerivation.h>) |
| 30 | +# include <CommonCrypto/CommonCryptoError.h> |
| 31 | +# include <CommonCrypto/CommonKeyDerivation.h> |
| 32 | +# define PHP_HASH_HAVE_COMMONCRYPTO_PBKDF2 1 |
| 33 | +#endif |
| 34 | + |
29 | 35 | /* Internal helper from hash_sha.c, not part of the public hash API. */ |
30 | 36 | void php_hash_sha256_final32_from_context(unsigned char digest[32], const PHP_SHA256_CTX *context, const unsigned char data[32]); |
31 | 37 |
|
@@ -627,6 +633,51 @@ static zend_string *php_hash_pbkdf2_sha256(const char *pass, size_t pass_len, co |
627 | 633 | return returnval; |
628 | 634 | } |
629 | 635 |
|
| 636 | +#ifdef PHP_HASH_HAVE_COMMONCRYPTO_PBKDF2 |
| 637 | +static zend_string *php_hash_pbkdf2_sha256_commoncrypto(const char *pass, size_t pass_len, const char *salt, size_t salt_len, zend_long iterations, zend_long length, bool raw_output) { |
| 638 | + zend_string *returnval; |
| 639 | + unsigned char *derived = NULL; |
| 640 | + zend_long derived_len = 0; |
| 641 | + |
| 642 | + if (iterations > UINT32_MAX) { |
| 643 | + return NULL; |
| 644 | + } |
| 645 | + |
| 646 | + if (length == 0) { |
| 647 | + length = raw_output ? 32 : 64; |
| 648 | + } |
| 649 | + |
| 650 | + derived_len = raw_output ? length : (zend_long) ceil((float) length / 2.0); |
| 651 | + if (derived_len <= 0) { |
| 652 | + return NULL; |
| 653 | + } |
| 654 | + |
| 655 | + derived = safe_emalloc(derived_len, 1, 0); |
| 656 | + if (CCKeyDerivationPBKDF( |
| 657 | + kCCPBKDF2, |
| 658 | + pass, pass_len, |
| 659 | + (const uint8_t *) salt, salt_len, |
| 660 | + kCCPRFHmacAlgSHA256, |
| 661 | + (uint32_t) iterations, |
| 662 | + derived, (size_t) derived_len) != kCCSuccess) { |
| 663 | + efree(derived); |
| 664 | + return NULL; |
| 665 | + } |
| 666 | + |
| 667 | + returnval = zend_string_alloc(length, 0); |
| 668 | + if (raw_output) { |
| 669 | + memcpy(ZSTR_VAL(returnval), derived, length); |
| 670 | + } else { |
| 671 | + php_hash_bin2hex(ZSTR_VAL(returnval), derived, derived_len); |
| 672 | + } |
| 673 | + ZSTR_VAL(returnval)[length] = 0; |
| 674 | + ZEND_SECURE_ZERO(derived, derived_len); |
| 675 | + efree(derived); |
| 676 | + |
| 677 | + return returnval; |
| 678 | +} |
| 679 | +#endif |
| 680 | + |
630 | 681 | static void php_hash_do_hash_hmac( |
631 | 682 | zval *return_value, zend_string *algo, char *data, size_t data_len, char *key, size_t key_len, bool raw_output, bool isfilename |
632 | 683 | ) /* {{{ */ { |
@@ -1155,6 +1206,12 @@ PHP_FUNCTION(hash_pbkdf2) |
1155 | 1206 | } |
1156 | 1207 |
|
1157 | 1208 | if (ops == &php_hash_sha256_ops) { |
| 1209 | +#ifdef PHP_HASH_HAVE_COMMONCRYPTO_PBKDF2 |
| 1210 | + zend_string *returnval_cc = php_hash_pbkdf2_sha256_commoncrypto(pass, pass_len, salt, salt_len, iterations, length, raw_output); |
| 1211 | + if (returnval_cc != NULL) { |
| 1212 | + RETURN_NEW_STR(returnval_cc); |
| 1213 | + } |
| 1214 | +#endif |
1158 | 1215 | RETURN_NEW_STR(php_hash_pbkdf2_sha256(pass, pass_len, salt, salt_len, iterations, length, raw_output)); |
1159 | 1216 | } |
1160 | 1217 |
|
|
0 commit comments