diff options
| author | Ben Fuhrmannek | 2021-11-19 14:57:01 +0100 |
|---|---|---|
| committer | Ben Fuhrmannek | 2021-11-19 14:57:01 +0100 |
| commit | c447df6ce8964b2863a50f0f8027d9b234b7507f (patch) | |
| tree | f3a6633d09f628bcd4efd409d92c8b44efe07868 /src/sp_unserialize.c | |
| parent | a34055a8fb6aa421a13da698ea0fe514bb27952e (diff) | |
replaced call_user_func with C level call
Diffstat (limited to 'src/sp_unserialize.c')
| -rw-r--r-- | src/sp_unserialize.c | 77 |
1 files changed, 49 insertions, 28 deletions
diff --git a/src/sp_unserialize.c b/src/sp_unserialize.c index 5ede015..4a9f565 100644 --- a/src/sp_unserialize.c +++ b/src/sp_unserialize.c | |||
| @@ -1,5 +1,40 @@ | |||
| 1 | #include "php_snuffleupagus.h" | 1 | #include "php_snuffleupagus.h" |
| 2 | 2 | ||
| 3 | // condensed version of PHP's php_hash_do_hash_hmac() in ext/hash/hash.c | ||
| 4 | static zend_string *sp_do_hash_hmac_sha256(char *data, size_t data_len, char *key, size_t key_len) | ||
| 5 | { | ||
| 6 | zend_string *algo = zend_string_init(ZEND_STRL("sha256"), 0); | ||
| 7 | const php_hash_ops *ops = php_hash_fetch_ops(algo); | ||
| 8 | zend_string_release_ex(algo, 0); | ||
| 9 | |||
| 10 | if (!ops || !ops->is_crypto) { | ||
| 11 | sp_log_err("unsupported hash algorithm for hmac: %s", ZSTR_VAL(algo)); | ||
| 12 | return NULL; | ||
| 13 | } | ||
| 14 | |||
| 15 | void *context = php_hash_alloc_context(ops); | ||
| 16 | |||
| 17 | unsigned char *K = emalloc(ops->block_size); | ||
| 18 | zend_string *digest = zend_string_alloc(ops->digest_size, 0); | ||
| 19 | |||
| 20 | php_hash_hmac_prep_key(K, ops, context, (unsigned char *) key, key_len); | ||
| 21 | php_hash_hmac_round((unsigned char *) ZSTR_VAL(digest), ops, context, K, (unsigned char *) data, data_len); | ||
| 22 | php_hash_string_xor_char(K, K, 0x6A, ops->block_size); | ||
| 23 | php_hash_hmac_round((unsigned char *) ZSTR_VAL(digest), ops, context, K, (unsigned char *) ZSTR_VAL(digest), ops->digest_size); | ||
| 24 | |||
| 25 | /* Zero the key */ | ||
| 26 | ZEND_SECURE_ZERO(K, ops->block_size); | ||
| 27 | efree(K); | ||
| 28 | efree(context); | ||
| 29 | |||
| 30 | zend_string *hex_digest = zend_string_safe_alloc(ops->digest_size, 2, 0, 0); | ||
| 31 | |||
| 32 | php_hash_bin2hex(ZSTR_VAL(hex_digest), (unsigned char *) ZSTR_VAL(digest), ops->digest_size); | ||
| 33 | ZSTR_VAL(hex_digest)[2 * ops->digest_size] = 0; | ||
| 34 | zend_string_release_ex(digest, 0); | ||
| 35 | return hex_digest; | ||
| 36 | } | ||
| 37 | |||
| 3 | PHP_FUNCTION(sp_serialize) { | 38 | PHP_FUNCTION(sp_serialize) { |
| 4 | zif_handler orig_handler; | 39 | zif_handler orig_handler; |
| 5 | 40 | ||
| @@ -10,19 +45,13 @@ PHP_FUNCTION(sp_serialize) { | |||
| 10 | } | 45 | } |
| 11 | 46 | ||
| 12 | /* Compute the HMAC of the textual representation of the serialized data*/ | 47 | /* Compute the HMAC of the textual representation of the serialized data*/ |
| 13 | zval func_name; | 48 | zend_string *hmac = sp_do_hash_hmac_sha256(Z_STRVAL_P(return_value), Z_STRLEN_P(return_value), ZSTR_VAL(SPCFG(encryption_key)), ZSTR_LEN(SPCFG(encryption_key))); |
| 14 | zval hmac; | ||
| 15 | zval params[3] = {0}; | ||
| 16 | 49 | ||
| 17 | ZVAL_STRING(&func_name, "hash_hmac"); | 50 | if (!hmac) { |
| 18 | ZVAL_STRING(¶ms[0], "sha256"); | 51 | zend_bailout(); |
| 19 | params[1] = *return_value; | 52 | } |
| 20 | ZVAL_STRING( | ||
| 21 | ¶ms[2], | ||
| 22 | ZSTR_VAL(SPCFG(encryption_key))); | ||
| 23 | call_user_function(CG(function_table), NULL, &func_name, &hmac, 3, params); | ||
| 24 | 53 | ||
| 25 | size_t len = Z_STRLEN_P(return_value) + Z_STRLEN(hmac); | 54 | size_t len = Z_STRLEN_P(return_value) + ZSTR_LEN(hmac); |
| 26 | if (len < Z_STRLEN_P(return_value)) { | 55 | if (len < Z_STRLEN_P(return_value)) { |
| 27 | // LCOV_EXCL_START | 56 | // LCOV_EXCL_START |
| 28 | sp_log_err("overflow_error", | 57 | sp_log_err("overflow_error", |
| @@ -32,8 +61,9 @@ PHP_FUNCTION(sp_serialize) { | |||
| 32 | } | 61 | } |
| 33 | 62 | ||
| 34 | /* Append the computed HMAC to the serialized data. */ | 63 | /* Append the computed HMAC to the serialized data. */ |
| 35 | return_value->value.str = zend_string_concat2(Z_STRVAL_P(return_value), Z_STRLEN_P(return_value), Z_STRVAL(hmac), Z_STRLEN(hmac)); | 64 | zend_string *orig_ret_str = return_value->value.str; |
| 36 | return; | 65 | RETVAL_NEW_STR(zend_string_concat2(Z_STRVAL_P(return_value), Z_STRLEN_P(return_value), ZSTR_VAL(hmac), ZSTR_LEN(hmac))); |
| 66 | zend_string_free(orig_ret_str); | ||
| 37 | } | 67 | } |
| 38 | 68 | ||
| 39 | PHP_FUNCTION(sp_unserialize) { | 69 | PHP_FUNCTION(sp_unserialize) { |
| @@ -42,7 +72,6 @@ PHP_FUNCTION(sp_unserialize) { | |||
| 42 | char *buf = NULL; | 72 | char *buf = NULL; |
| 43 | char *serialized_str = NULL; | 73 | char *serialized_str = NULL; |
| 44 | char *hmac = NULL; | 74 | char *hmac = NULL; |
| 45 | zval expected_hmac; | ||
| 46 | size_t buf_len = 0; | 75 | size_t buf_len = 0; |
| 47 | zval *opts = NULL; | 76 | zval *opts = NULL; |
| 48 | 77 | ||
| @@ -62,22 +91,14 @@ PHP_FUNCTION(sp_unserialize) { | |||
| 62 | serialized_str = ecalloc(buf_len - 64 + 1, 1); | 91 | serialized_str = ecalloc(buf_len - 64 + 1, 1); |
| 63 | memcpy(serialized_str, buf, buf_len - 64); | 92 | memcpy(serialized_str, buf, buf_len - 64); |
| 64 | 93 | ||
| 65 | zval func_name; | 94 | zend_string *expected_hmac = sp_do_hash_hmac_sha256(serialized_str, strlen(serialized_str), ZSTR_VAL(SPCFG(encryption_key)), ZSTR_LEN(SPCFG(encryption_key))); |
| 66 | ZVAL_STRING(&func_name, "hash_hmac"); | ||
| 67 | |||
| 68 | zval params[3] = {0}; | ||
| 69 | ZVAL_STRING(¶ms[0], "sha256"); | ||
| 70 | ZVAL_STRING(¶ms[1], serialized_str); | ||
| 71 | ZVAL_STRING( | ||
| 72 | ¶ms[2], | ||
| 73 | ZSTR_VAL(SPCFG(encryption_key))); | ||
| 74 | call_user_function(CG(function_table), NULL, &func_name, &expected_hmac, 3, | ||
| 75 | params); | ||
| 76 | 95 | ||
| 77 | unsigned int status = 0; | 96 | unsigned int status = 0; |
| 78 | for (uint8_t i = 0; i < 64; i++) { | 97 | if (expected_hmac) { |
| 79 | status |= (hmac[i] ^ (Z_STRVAL(expected_hmac))[i]); | 98 | for (uint8_t i = 0; i < 64; i++) { |
| 80 | } | 99 | status |= (hmac[i] ^ (ZSTR_VAL(expected_hmac))[i]); |
| 100 | } | ||
| 101 | } else { status = 1; } | ||
| 81 | 102 | ||
| 82 | if (0 == status) { | 103 | if (0 == status) { |
| 83 | if ((orig_handler = zend_hash_str_find_ptr(SPG(sp_internal_functions_hook), ZEND_STRL("unserialize")))) { | 104 | if ((orig_handler = zend_hash_str_find_ptr(SPG(sp_internal_functions_hook), ZEND_STRL("unserialize")))) { |
