From 0413024cdd8be3baa60f0f3ce6f4861aacf59b55 Mon Sep 17 00:00:00 2001 From: Greg Harmon <9166584+gregharmon@users.noreply.github.com> Date: Mon, 9 Feb 2026 17:09:14 -0500 Subject: [PATCH 1/5] Optimize PBKDF2 by reusing HMAC base contexts --- ext/hash/hash.c | 64 ++++++++++++++++++++++++-------------- ext/hash/tests/gh9604.phpt | 33 ++++++++++++++++++++ 2 files changed, 74 insertions(+), 23 deletions(-) create mode 100644 ext/hash/tests/gh9604.phpt diff --git a/ext/hash/hash.c b/ext/hash/hash.c index d255711efbed9..59f29ffdad4af 100644 --- a/ext/hash/hash.c +++ b/ext/hash/hash.c @@ -492,6 +492,16 @@ static inline void php_hash_hmac_round(unsigned char *final, const php_hash_ops ops->hash_final(final, context); } +static inline void php_hash_hmac_round_with_copy(unsigned char *final, const php_hash_ops *ops, const void *base_context, void *context, const unsigned char *data, const zend_long data_size) { + if (EXPECTED(ops->hash_copy == php_hash_copy)) { + memcpy(context, base_context, ops->context_size); + } else { + ops->hash_copy(ops, base_context, context); + } + ops->hash_update(context, data, data_size); + ops->hash_final(final, context); +} + static void php_hash_do_hash_hmac( zval *return_value, zend_string *algo, char *data, size_t data_len, char *key, size_t key_len, bool raw_output, bool isfilename ) /* {{{ */ { @@ -986,12 +996,12 @@ PHP_FUNCTION(hash_pbkdf2) { zend_string *returnval, *algo; char *salt, *pass = NULL; - unsigned char *computed_salt, *digest, *temp, *result, *K1, *K2 = NULL; + unsigned char *computed_salt, *digest, *result, *K = NULL; zend_long loops, i, j, iterations, digest_length = 0, length = 0; size_t pass_len, salt_len = 0; bool raw_output = false; const php_hash_ops *ops; - void *context; + void *context, *inner_context, *outer_context; HashTable *args = NULL; if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sssl|lbh", &algo, &pass, &pass_len, &salt, &salt_len, &iterations, &length, &raw_output, &args) == FAILURE) { @@ -1019,18 +1029,25 @@ PHP_FUNCTION(hash_pbkdf2) RETURN_THROWS(); } + inner_context = php_hash_alloc_context(ops); + outer_context = php_hash_alloc_context(ops); context = php_hash_alloc_context(ops); ops->hash_init(context, args); - K1 = emalloc(ops->block_size); - K2 = emalloc(ops->block_size); + K = emalloc(ops->block_size); digest = emalloc(ops->digest_size); - temp = emalloc(ops->digest_size); /* Setup Keys that will be used for all hmac rounds */ - php_hash_hmac_prep_key(K1, ops, context, (unsigned char *) pass, pass_len); - /* Convert K1 to opad -- 0x6A = 0x36 ^ 0x5C */ - php_hash_string_xor_char(K2, K1, 0x6A, ops->block_size); + php_hash_hmac_prep_key(K, ops, context, (unsigned char *) pass, pass_len); + + ops->hash_init(inner_context, NULL); + ops->hash_update(inner_context, K, ops->block_size); + + /* Convert K from ipad to opad -- 0x6A = 0x36 ^ 0x5C */ + php_hash_string_xor_char(K, K, 0x6A, ops->block_size); + + ops->hash_init(outer_context, NULL); + ops->hash_update(outer_context, K, ops->block_size); /* Setup Main Loop to build a long enough result */ if (length == 0) { @@ -1052,6 +1069,8 @@ PHP_FUNCTION(hash_pbkdf2) memcpy(computed_salt, (unsigned char *) salt, salt_len); for (i = 1; i <= loops; i++) { + unsigned char *result_block = result + ((i - 1) * ops->digest_size); + /* digest = hash_hmac(salt + pack('N', i), password) { */ /* pack("N", i) */ @@ -1060,12 +1079,11 @@ PHP_FUNCTION(hash_pbkdf2) computed_salt[salt_len + 2] = (unsigned char) ((i & 0xFF00) >> 8); computed_salt[salt_len + 3] = (unsigned char) (i & 0xFF); - php_hash_hmac_round(digest, ops, context, K1, computed_salt, (zend_long) salt_len + 4); - php_hash_hmac_round(digest, ops, context, K2, digest, ops->digest_size); + php_hash_hmac_round_with_copy(digest, ops, inner_context, context, computed_salt, (zend_long) salt_len + 4); + php_hash_hmac_round_with_copy(digest, ops, outer_context, context, digest, ops->digest_size); /* } */ - /* temp = digest */ - memcpy(temp, digest, ops->digest_size); + memcpy(result_block, digest, ops->digest_size); /* * Note that the loop starting at 1 is intentional, since we've already done @@ -1073,25 +1091,25 @@ PHP_FUNCTION(hash_pbkdf2) */ for (j = 1; j < iterations; j++) { /* digest = hash_hmac(digest, password) { */ - php_hash_hmac_round(digest, ops, context, K1, digest, ops->digest_size); - php_hash_hmac_round(digest, ops, context, K2, digest, ops->digest_size); + php_hash_hmac_round_with_copy(digest, ops, inner_context, context, digest, ops->digest_size); + php_hash_hmac_round_with_copy(digest, ops, outer_context, context, digest, ops->digest_size); /* } */ - /* temp ^= digest */ - php_hash_string_xor(temp, temp, digest, ops->digest_size); + /* result block ^= digest */ + php_hash_string_xor(result_block, result_block, digest, ops->digest_size); } - /* result += temp */ - memcpy(result + ((i - 1) * ops->digest_size), temp, ops->digest_size); } /* Zero potentially sensitive variables */ - ZEND_SECURE_ZERO(K1, ops->block_size); - ZEND_SECURE_ZERO(K2, ops->block_size); + ZEND_SECURE_ZERO(K, ops->block_size); ZEND_SECURE_ZERO(computed_salt, salt_len + 4); - efree(K1); - efree(K2); + ZEND_SECURE_ZERO(inner_context, ops->context_size); + ZEND_SECURE_ZERO(outer_context, ops->context_size); + ZEND_SECURE_ZERO(context, ops->context_size); + efree(K); efree(computed_salt); + efree(inner_context); + efree(outer_context); efree(context); efree(digest); - efree(temp); returnval = zend_string_alloc(length, 0); if (raw_output) { diff --git a/ext/hash/tests/gh9604.phpt b/ext/hash/tests/gh9604.phpt new file mode 100644 index 0000000000000..d4fb073695b64 --- /dev/null +++ b/ext/hash/tests/gh9604.phpt @@ -0,0 +1,33 @@ +--TEST-- +Hash: PBKDF2 context reuse regression (GH-9604) +--FILE-- + +--EXPECT-- +*** Testing hash_pbkdf2() GH-9604 vectors *** +sha1_hex: ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957 +sha1_raw_hex: ea6c014dc72d6f8ccd1ed92ace1d41f0d8de8957 +sha1_match: yes +sha256_hex: ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43 +sha256_raw_hex: ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43 +sha256_match: yes +sha256_raw_hex_64: ae4d0c95af6b46d32d0adff928f06dd02a303f8ef3c251dfd6e2d85a95474c43830651afcb5c862f0b249bd031f7a67520d136470f5ec271ece91c07773253d9 From 8378d8eb059ea998b64105e2ac8dbe7e11082a53 Mon Sep 17 00:00:00 2001 From: Greg Harmon <9166584+gregharmon@users.noreply.github.com> Date: Mon, 9 Feb 2026 17:09:18 -0500 Subject: [PATCH 2/5] Add SHA-256-specific PBKDF2 fast path --- ext/hash/hash.c | 129 ++++++++++++++++++++++++++++++++++++++++++++ ext/hash/hash_sha.c | 23 ++++++++ 2 files changed, 152 insertions(+) diff --git a/ext/hash/hash.c b/ext/hash/hash.c index 59f29ffdad4af..226c28cea38c0 100644 --- a/ext/hash/hash.c +++ b/ext/hash/hash.c @@ -21,10 +21,14 @@ #include #include "php_hash.h" +#include "php_hash_sha.h" #include "ext/standard/info.h" #include "ext/standard/file.h" #include "ext/standard/php_var.h" +/* Internal helper from hash_sha.c, not part of the public hash API. */ +void php_hash_sha256_final32_from_context(unsigned char digest[32], const PHP_SHA256_CTX *context, const unsigned char data[32]); + #include "zend_attributes.h" #include "zend_exceptions.h" #include "zend_interfaces.h" @@ -502,6 +506,127 @@ static inline void php_hash_hmac_round_with_copy(unsigned char *final, const php ops->hash_final(final, context); } +static const unsigned char php_hash_sha_padding[128] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static inline void php_hash_sha256_encode(unsigned char digest[32], const uint32_t state[8]) { + for (size_t i = 0; i < 8; i++) { + digest[i * 4] = (unsigned char) ((state[i] >> 24) & 0xff); + digest[(i * 4) + 1] = (unsigned char) ((state[i] >> 16) & 0xff); + digest[(i * 4) + 2] = (unsigned char) ((state[i] >> 8) & 0xff); + digest[(i * 4) + 3] = (unsigned char) (state[i] & 0xff); + } +} + +static inline void php_hash_sha256_final_no_zero(unsigned char digest[32], PHP_SHA256_CTX *context) { + unsigned char bits[8]; + unsigned int index, pad_len; + + bits[7] = (unsigned char) (context->count[0] & 0xFF); + bits[6] = (unsigned char) ((context->count[0] >> 8) & 0xFF); + bits[5] = (unsigned char) ((context->count[0] >> 16) & 0xFF); + bits[4] = (unsigned char) ((context->count[0] >> 24) & 0xFF); + bits[3] = (unsigned char) (context->count[1] & 0xFF); + bits[2] = (unsigned char) ((context->count[1] >> 8) & 0xFF); + bits[1] = (unsigned char) ((context->count[1] >> 16) & 0xFF); + bits[0] = (unsigned char) ((context->count[1] >> 24) & 0xFF); + + index = (unsigned int) ((context->count[0] >> 3) & 0x3f); + pad_len = (index < 56) ? (56 - index) : (120 - index); + PHP_SHA256Update(context, php_hash_sha_padding, pad_len); + PHP_SHA256Update(context, bits, 8); + + php_hash_sha256_encode(digest, context->state); +} + +static zend_string *php_hash_pbkdf2_sha256(const char *pass, size_t pass_len, const char *salt, size_t salt_len, zend_long iterations, zend_long length, bool raw_output) { + zend_string *returnval; + unsigned char *digest, *result, *K = NULL, counter[4]; + zend_long loops, i, j, digest_length = 0; + const size_t digest_size = 32; + const size_t block_size = 64; + PHP_SHA256_CTX inner_context, outer_context, context; + + memset(&context, 0, sizeof(PHP_SHA256_CTX)); + K = emalloc(block_size); + digest = emalloc(digest_size); + + php_hash_hmac_prep_key(K, &php_hash_sha256_ops, &context, (const unsigned char *) pass, pass_len); + + PHP_SHA256Init(&inner_context); + PHP_SHA256Update(&inner_context, K, block_size); + + php_hash_string_xor_char(K, K, 0x6A, block_size); + PHP_SHA256Init(&outer_context); + PHP_SHA256Update(&outer_context, K, block_size); + + if (length == 0) { + length = digest_size; + if (!raw_output) { + length = length * 2; + } + } + digest_length = length; + if (!raw_output) { + digest_length = (zend_long) ceil((float) length / 2.0); + } + + loops = (zend_long) ceil((float) digest_length / (float) digest_size); + + result = safe_emalloc(loops, digest_size, 0); + + for (i = 1; i <= loops; i++) { + unsigned char *result_block = result + ((i - 1) * digest_size); + + counter[0] = (unsigned char) (i >> 24); + counter[1] = (unsigned char) ((i & 0xFF0000) >> 16); + counter[2] = (unsigned char) ((i & 0xFF00) >> 8); + counter[3] = (unsigned char) (i & 0xFF); + + context = inner_context; + PHP_SHA256Update(&context, (const unsigned char *) salt, salt_len); + PHP_SHA256Update(&context, counter, sizeof(counter)); + php_hash_sha256_final_no_zero(digest, &context); + + php_hash_sha256_final32_from_context(digest, &outer_context, digest); + memcpy(result_block, digest, digest_size); + + for (j = 1; j < iterations; j++) { + php_hash_sha256_final32_from_context(digest, &inner_context, digest); + php_hash_sha256_final32_from_context(digest, &outer_context, digest); + + php_hash_string_xor(result_block, result_block, digest, digest_size); + } + } + + ZEND_SECURE_ZERO(K, block_size); + ZEND_SECURE_ZERO(digest, digest_size); + ZEND_SECURE_ZERO(&inner_context, sizeof(PHP_SHA256_CTX)); + ZEND_SECURE_ZERO(&outer_context, sizeof(PHP_SHA256_CTX)); + ZEND_SECURE_ZERO(&context, sizeof(PHP_SHA256_CTX)); + efree(K); + efree(digest); + + returnval = zend_string_alloc(length, 0); + if (raw_output) { + memcpy(ZSTR_VAL(returnval), result, length); + } else { + php_hash_bin2hex(ZSTR_VAL(returnval), result, digest_length); + } + ZSTR_VAL(returnval)[length] = 0; + efree(result); + + return returnval; +} + static void php_hash_do_hash_hmac( zval *return_value, zend_string *algo, char *data, size_t data_len, char *key, size_t key_len, bool raw_output, bool isfilename ) /* {{{ */ { @@ -1029,6 +1154,10 @@ PHP_FUNCTION(hash_pbkdf2) RETURN_THROWS(); } + if (ops == &php_hash_sha256_ops) { + RETURN_NEW_STR(php_hash_pbkdf2_sha256(pass, pass_len, salt, salt_len, iterations, length, raw_output)); + } + inner_context = php_hash_alloc_context(ops); outer_context = php_hash_alloc_context(ops); context = php_hash_alloc_context(ops); diff --git a/ext/hash/hash_sha.c b/ext/hash/hash_sha.c index 3129446fcde40..c1a74ed3e675d 100644 --- a/ext/hash/hash_sha.c +++ b/ext/hash/hash_sha.c @@ -390,6 +390,29 @@ PHP_HASH_API void PHP_SHA256Final(unsigned char digest[32], PHP_SHA256_CTX * con } /* }}} */ +/* {{{ php_hash_sha256_final32_from_context + Compute SHA256(base_ctx || data[32]) where base_ctx already hashed one full 64-byte block. + */ +void php_hash_sha256_final32_from_context(unsigned char digest[32], const PHP_SHA256_CTX *context, const unsigned char data[32]) +{ + uint32_t state[8]; + unsigned char block[64]; + + ZEND_ASSERT(context->count[1] == 0); + ZEND_ASSERT(context->count[0] == 512); + + memcpy(state, context->state, sizeof(state)); + memcpy(block, data, 32); + block[32] = 0x80; + memset(block + 33, 0, 23); + memset(block + 56, 0, 8); + block[62] = 0x03; + + SHA256Transform(state, block); + SHAEncode32(digest, state, 32); +} +/* }}} */ + /* sha384/sha512 */ /* Ch */ From 2cf96e4b3968b811cea8a936d15d4658de816c70 Mon Sep 17 00:00:00 2001 From: Greg Harmon <9166584+gregharmon@users.noreply.github.com> Date: Mon, 9 Feb 2026 17:09:23 -0500 Subject: [PATCH 3/5] Use CommonCrypto for PBKDF2-HMAC-SHA256 on Apple --- ext/hash/hash.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/ext/hash/hash.c b/ext/hash/hash.c index 226c28cea38c0..b3288ea441530 100644 --- a/ext/hash/hash.c +++ b/ext/hash/hash.c @@ -26,6 +26,12 @@ #include "ext/standard/file.h" #include "ext/standard/php_var.h" +#if defined(__APPLE__) && __has_include() +# include +# include +# define PHP_HASH_HAVE_COMMONCRYPTO_PBKDF2 1 +#endif + /* Internal helper from hash_sha.c, not part of the public hash API. */ void php_hash_sha256_final32_from_context(unsigned char digest[32], const PHP_SHA256_CTX *context, const unsigned char data[32]); @@ -627,6 +633,51 @@ static zend_string *php_hash_pbkdf2_sha256(const char *pass, size_t pass_len, co return returnval; } +#ifdef PHP_HASH_HAVE_COMMONCRYPTO_PBKDF2 +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) { + zend_string *returnval; + unsigned char *derived = NULL; + zend_long derived_len = 0; + + if (iterations > UINT32_MAX) { + return NULL; + } + + if (length == 0) { + length = raw_output ? 32 : 64; + } + + derived_len = raw_output ? length : (zend_long) ceil((float) length / 2.0); + if (derived_len <= 0) { + return NULL; + } + + derived = safe_emalloc(derived_len, 1, 0); + if (CCKeyDerivationPBKDF( + kCCPBKDF2, + pass, pass_len, + (const uint8_t *) salt, salt_len, + kCCPRFHmacAlgSHA256, + (uint32_t) iterations, + derived, (size_t) derived_len) != kCCSuccess) { + efree(derived); + return NULL; + } + + returnval = zend_string_alloc(length, 0); + if (raw_output) { + memcpy(ZSTR_VAL(returnval), derived, length); + } else { + php_hash_bin2hex(ZSTR_VAL(returnval), derived, derived_len); + } + ZSTR_VAL(returnval)[length] = 0; + ZEND_SECURE_ZERO(derived, derived_len); + efree(derived); + + return returnval; +} +#endif + static void php_hash_do_hash_hmac( zval *return_value, zend_string *algo, char *data, size_t data_len, char *key, size_t key_len, bool raw_output, bool isfilename ) /* {{{ */ { @@ -1155,6 +1206,12 @@ PHP_FUNCTION(hash_pbkdf2) } if (ops == &php_hash_sha256_ops) { +#ifdef PHP_HASH_HAVE_COMMONCRYPTO_PBKDF2 + zend_string *returnval_cc = php_hash_pbkdf2_sha256_commoncrypto(pass, pass_len, salt, salt_len, iterations, length, raw_output); + if (returnval_cc != NULL) { + RETURN_NEW_STR(returnval_cc); + } +#endif RETURN_NEW_STR(php_hash_pbkdf2_sha256(pass, pass_len, salt, salt_len, iterations, length, raw_output)); } From 1e94d0ba9282da0b9b953f38f7766ede4aad5c89 Mon Sep 17 00:00:00 2001 From: Greg Harmon <9166584+gregharmon@users.noreply.github.com> Date: Mon, 9 Feb 2026 17:09:28 -0500 Subject: [PATCH 4/5] Use integer arithmetic for PBKDF2 length calculations --- ext/hash/hash.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/ext/hash/hash.c b/ext/hash/hash.c index b3288ea441530..4684475064f9d 100644 --- a/ext/hash/hash.c +++ b/ext/hash/hash.c @@ -19,7 +19,6 @@ #include #endif -#include #include "php_hash.h" #include "php_hash_sha.h" #include "ext/standard/info.h" @@ -582,10 +581,10 @@ static zend_string *php_hash_pbkdf2_sha256(const char *pass, size_t pass_len, co } digest_length = length; if (!raw_output) { - digest_length = (zend_long) ceil((float) length / 2.0); + digest_length = (length / 2) + (length % 2); } - loops = (zend_long) ceil((float) digest_length / (float) digest_size); + loops = (digest_length / digest_size) + ((digest_length % digest_size) ? 1 : 0); result = safe_emalloc(loops, digest_size, 0); @@ -647,7 +646,7 @@ static zend_string *php_hash_pbkdf2_sha256_commoncrypto(const char *pass, size_t length = raw_output ? 32 : 64; } - derived_len = raw_output ? length : (zend_long) ceil((float) length / 2.0); + derived_len = raw_output ? length : (length / 2) + (length % 2); if (derived_len <= 0) { return NULL; } @@ -1244,10 +1243,10 @@ PHP_FUNCTION(hash_pbkdf2) } digest_length = length; if (!raw_output) { - digest_length = (zend_long) ceil((float) length / 2.0); + digest_length = (length / 2) + (length % 2); } - loops = (zend_long) ceil((float) digest_length / (float) ops->digest_size); + loops = (digest_length / ops->digest_size) + ((digest_length % ops->digest_size) ? 1 : 0); result = safe_emalloc(loops, ops->digest_size, 0); From 5eb7bf8bf8deb5617e27c52a6c2a41207690ba77 Mon Sep 17 00:00:00 2001 From: Greg Harmon <9166584+gregharmon@users.noreply.github.com> Date: Tue, 10 Feb 2026 21:56:52 -0500 Subject: [PATCH 5/5] Address PBKDF2 SHA-256 review followups --- ext/hash/hash.c | 32 +++++++++++++++++--------------- ext/hash/hash_sha.c | 23 ----------------------- 2 files changed, 17 insertions(+), 38 deletions(-) diff --git a/ext/hash/hash.c b/ext/hash/hash.c index 4684475064f9d..eebfead06d277 100644 --- a/ext/hash/hash.c +++ b/ext/hash/hash.c @@ -31,9 +31,6 @@ # define PHP_HASH_HAVE_COMMONCRYPTO_PBKDF2 1 #endif -/* Internal helper from hash_sha.c, not part of the public hash API. */ -void php_hash_sha256_final32_from_context(unsigned char digest[32], const PHP_SHA256_CTX *context, const unsigned char data[32]); - #include "zend_attributes.h" #include "zend_exceptions.h" #include "zend_interfaces.h" @@ -524,10 +521,10 @@ static const unsigned char php_hash_sha_padding[128] = { static inline void php_hash_sha256_encode(unsigned char digest[32], const uint32_t state[8]) { for (size_t i = 0; i < 8; i++) { - digest[i * 4] = (unsigned char) ((state[i] >> 24) & 0xff); + digest[(i * 4) + 0] = (unsigned char) ((state[i] >> 24) & 0xff); digest[(i * 4) + 1] = (unsigned char) ((state[i] >> 16) & 0xff); digest[(i * 4) + 2] = (unsigned char) ((state[i] >> 8) & 0xff); - digest[(i * 4) + 3] = (unsigned char) (state[i] & 0xff); + digest[(i * 4) + 3] = (unsigned char) ((state[i] >> 0) & 0xff); } } @@ -552,10 +549,17 @@ static inline void php_hash_sha256_final_no_zero(unsigned char digest[32], PHP_S php_hash_sha256_encode(digest, context->state); } +static inline void php_hash_sha256_final32_from_context(unsigned char digest[32], const PHP_SHA256_CTX *base_context, const unsigned char data[32]) { + PHP_SHA256_CTX context = *base_context; + + PHP_SHA256Update(&context, data, 32); + php_hash_sha256_final_no_zero(digest, &context); + ZEND_SECURE_ZERO(&context, sizeof(context)); +} + static zend_string *php_hash_pbkdf2_sha256(const char *pass, size_t pass_len, const char *salt, size_t salt_len, zend_long iterations, zend_long length, bool raw_output) { - zend_string *returnval; unsigned char *digest, *result, *K = NULL, counter[4]; - zend_long loops, i, j, digest_length = 0; + zend_long digest_length; const size_t digest_size = 32; const size_t block_size = 64; PHP_SHA256_CTX inner_context, outer_context, context; @@ -584,11 +588,10 @@ static zend_string *php_hash_pbkdf2_sha256(const char *pass, size_t pass_len, co digest_length = (length / 2) + (length % 2); } - loops = (digest_length / digest_size) + ((digest_length % digest_size) ? 1 : 0); - + const zend_long loops = (digest_length / digest_size) + ((digest_length % digest_size) ? 1 : 0); result = safe_emalloc(loops, digest_size, 0); - for (i = 1; i <= loops; i++) { + for (zend_long i = 1; i <= loops; i++) { unsigned char *result_block = result + ((i - 1) * digest_size); counter[0] = (unsigned char) (i >> 24); @@ -604,7 +607,7 @@ static zend_string *php_hash_pbkdf2_sha256(const char *pass, size_t pass_len, co php_hash_sha256_final32_from_context(digest, &outer_context, digest); memcpy(result_block, digest, digest_size); - for (j = 1; j < iterations; j++) { + for (zend_long j = 1; j < iterations; j++) { php_hash_sha256_final32_from_context(digest, &inner_context, digest); php_hash_sha256_final32_from_context(digest, &outer_context, digest); @@ -620,7 +623,7 @@ static zend_string *php_hash_pbkdf2_sha256(const char *pass, size_t pass_len, co efree(K); efree(digest); - returnval = zend_string_alloc(length, 0); + zend_string *returnval = zend_string_alloc(length, 0); if (raw_output) { memcpy(ZSTR_VAL(returnval), result, length); } else { @@ -634,9 +637,8 @@ static zend_string *php_hash_pbkdf2_sha256(const char *pass, size_t pass_len, co #ifdef PHP_HASH_HAVE_COMMONCRYPTO_PBKDF2 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) { - zend_string *returnval; unsigned char *derived = NULL; - zend_long derived_len = 0; + zend_long derived_len; if (iterations > UINT32_MAX) { return NULL; @@ -663,7 +665,7 @@ static zend_string *php_hash_pbkdf2_sha256_commoncrypto(const char *pass, size_t return NULL; } - returnval = zend_string_alloc(length, 0); + zend_string *returnval = zend_string_alloc(length, 0); if (raw_output) { memcpy(ZSTR_VAL(returnval), derived, length); } else { diff --git a/ext/hash/hash_sha.c b/ext/hash/hash_sha.c index c1a74ed3e675d..3129446fcde40 100644 --- a/ext/hash/hash_sha.c +++ b/ext/hash/hash_sha.c @@ -390,29 +390,6 @@ PHP_HASH_API void PHP_SHA256Final(unsigned char digest[32], PHP_SHA256_CTX * con } /* }}} */ -/* {{{ php_hash_sha256_final32_from_context - Compute SHA256(base_ctx || data[32]) where base_ctx already hashed one full 64-byte block. - */ -void php_hash_sha256_final32_from_context(unsigned char digest[32], const PHP_SHA256_CTX *context, const unsigned char data[32]) -{ - uint32_t state[8]; - unsigned char block[64]; - - ZEND_ASSERT(context->count[1] == 0); - ZEND_ASSERT(context->count[0] == 512); - - memcpy(state, context->state, sizeof(state)); - memcpy(block, data, 32); - block[32] = 0x80; - memset(block + 33, 0, 23); - memset(block + 56, 0, 8); - block[62] = 0x03; - - SHA256Transform(state, block); - SHAEncode32(digest, state, 32); -} -/* }}} */ - /* sha384/sha512 */ /* Ch */