summaryrefslogtreecommitdiff
path: root/src/sp_unserialize.c
diff options
context:
space:
mode:
authorBen Fuhrmannek2021-11-19 14:57:01 +0100
committerBen Fuhrmannek2021-11-19 14:57:01 +0100
commitc447df6ce8964b2863a50f0f8027d9b234b7507f (patch)
treef3a6633d09f628bcd4efd409d92c8b44efe07868 /src/sp_unserialize.c
parenta34055a8fb6aa421a13da698ea0fe514bb27952e (diff)
replaced call_user_func with C level call
Diffstat (limited to 'src/sp_unserialize.c')
-rw-r--r--src/sp_unserialize.c77
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
4static 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
3PHP_FUNCTION(sp_serialize) { 38PHP_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(&params[0], "sha256"); 51 zend_bailout();
19 params[1] = *return_value; 52 }
20 ZVAL_STRING(
21 &params[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
39PHP_FUNCTION(sp_unserialize) { 69PHP_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(&params[0], "sha256");
70 ZVAL_STRING(&params[1], serialized_str);
71 ZVAL_STRING(
72 &params[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")))) {