Skip to content

hash: Support custom algo parameters #6400

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 12 commits into from
Closed
48 changes: 27 additions & 21 deletions ext/hash/hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ PHP_HASH_API int php_hash_unserialize(php_hashcontext_object *hash, zend_long ma
/* Userspace */

static void php_hash_do_hash(
zval *return_value, zend_string *algo, char *data, size_t data_len, zend_bool raw_output, bool isfilename
zval *return_value, zend_string *algo, char *data, size_t data_len, zend_bool raw_output, bool isfilename, HashTable *args
) /* {{{ */ {
zend_string *digest;
const php_hash_ops *ops;
Expand All @@ -374,7 +374,7 @@ static void php_hash_do_hash(
}

context = php_hash_alloc_context(ops);
ops->hash_init(context);
ops->hash_init(context, args);

if (isfilename) {
char buf[1024];
Expand Down Expand Up @@ -418,15 +418,17 @@ PHP_FUNCTION(hash)
char *data;
size_t data_len;
zend_bool raw_output = 0;
HashTable *args = NULL;

ZEND_PARSE_PARAMETERS_START(2, 3)
ZEND_PARSE_PARAMETERS_START(2, 4)
Z_PARAM_STR(algo)
Z_PARAM_STRING(data, data_len)
Z_PARAM_OPTIONAL
Z_PARAM_BOOL(raw_output)
Z_PARAM_ARRAY_HT(args)
ZEND_PARSE_PARAMETERS_END();

php_hash_do_hash(return_value, algo, data, data_len, raw_output, 0);
php_hash_do_hash(return_value, algo, data, data_len, raw_output, 0, args);
}
/* }}} */

Expand All @@ -438,15 +440,17 @@ PHP_FUNCTION(hash_file)
char *data;
size_t data_len;
zend_bool raw_output = 0;
HashTable *args = NULL;

ZEND_PARSE_PARAMETERS_START(2, 3)
Z_PARAM_STR(algo)
Z_PARAM_STRING(data, data_len)
Z_PARAM_OPTIONAL
Z_PARAM_BOOL(raw_output)
Z_PARAM_ARRAY_HT(args)
ZEND_PARSE_PARAMETERS_END();

php_hash_do_hash(return_value, algo, data, data_len, raw_output, 1);
php_hash_do_hash(return_value, algo, data, data_len, raw_output, 1, args);
}
/* }}} */

Expand All @@ -468,7 +472,7 @@ static inline void php_hash_hmac_prep_key(unsigned char *K, const php_hash_ops *
memset(K, 0, ops->block_size);
if (key_len > ops->block_size) {
/* Reduce the key first */
ops->hash_init(context);
ops->hash_init(context, NULL);
ops->hash_update(context, key, key_len);
ops->hash_final(K, context);
} else {
Expand All @@ -479,7 +483,7 @@ static inline void php_hash_hmac_prep_key(unsigned char *K, const php_hash_ops *
}

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) {
ops->hash_init(context);
ops->hash_init(context, NULL);
ops->hash_update(context, key, ops->block_size);
ops->hash_update(context, data, data_size);
ops->hash_final(final, context);
Expand Down Expand Up @@ -522,7 +526,7 @@ static void php_hash_do_hash_hmac(
if (isfilename) {
char buf[1024];
ssize_t n;
ops->hash_init(context);
ops->hash_init(context, NULL);
ops->hash_update(context, K, ops->block_size);
while ((n = php_stream_read(stream, buf, sizeof(buf))) > 0) {
ops->hash_update(context, (unsigned char *) buf, n);
Expand Down Expand Up @@ -605,8 +609,9 @@ PHP_FUNCTION(hash_init)
void *context;
const php_hash_ops *ops;
php_hashcontext_object *hash;
HashTable *args = NULL;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|lS", &algo, &options, &key) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|lSh", &algo, &options, &key, &args) == FAILURE) {
RETURN_THROWS();
}

Expand All @@ -632,7 +637,7 @@ PHP_FUNCTION(hash_init)
hash = php_hashcontext_from_object(Z_OBJ_P(return_value));

context = php_hash_alloc_context(ops);
ops->hash_init(context);
ops->hash_init(context, args);

hash->ops = ops;
hash->context = context;
Expand All @@ -650,7 +655,7 @@ PHP_FUNCTION(hash_init)
ops->hash_update(context, (unsigned char *) ZSTR_VAL(key), ZSTR_LEN(key));
ops->hash_final((unsigned char *) K, context);
/* Make the context ready to start over */
ops->hash_init(context);
ops->hash_init(context, args);
} else {
memcpy(K, ZSTR_VAL(key), ZSTR_LEN(key));
}
Expand Down Expand Up @@ -792,7 +797,7 @@ PHP_FUNCTION(hash_final)
}

/* Feed this result into the outer hash */
hash->ops->hash_init(hash->context);
hash->ops->hash_init(hash->context, NULL);
hash->ops->hash_update(hash->context, hash->key, hash->ops->block_size);
hash->ops->hash_update(hash->context, (unsigned char *) ZSTR_VAL(digest), hash->ops->digest_size);
hash->ops->hash_final((unsigned char *) ZSTR_VAL(digest), hash->context);
Expand Down Expand Up @@ -915,7 +920,7 @@ PHP_FUNCTION(hash_hkdf)
context = php_hash_alloc_context(ops);

// Extract
ops->hash_init(context);
ops->hash_init(context, NULL);
K = emalloc(ops->block_size);
php_hash_hmac_prep_key(K, ops, context,
(unsigned char *) (salt ? ZSTR_VAL(salt) : ""), salt ? ZSTR_LEN(salt) : 0);
Expand All @@ -935,7 +940,7 @@ PHP_FUNCTION(hash_hkdf)
c[0] = (i & 0xFF);

php_hash_hmac_prep_key(K, ops, context, prk, ops->digest_size);
ops->hash_init(context);
ops->hash_init(context, NULL);
ops->hash_update(context, K, ops->block_size);

if (i > 1) {
Expand Down Expand Up @@ -980,8 +985,9 @@ PHP_FUNCTION(hash_pbkdf2)
zend_bool raw_output = 0;
const php_hash_ops *ops;
void *context;
HashTable *args;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sssl|lb", &algo, &pass, &pass_len, &salt, &salt_len, &iterations, &length, &raw_output) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "Sssl|lbh", &algo, &pass, &pass_len, &salt, &salt_len, &iterations, &length, &raw_output, &args) == FAILURE) {
RETURN_THROWS();
}

Expand All @@ -1007,7 +1013,7 @@ PHP_FUNCTION(hash_pbkdf2)
}

context = php_hash_alloc_context(ops);
ops->hash_init(context);
ops->hash_init(context, args);

K1 = emalloc(ops->block_size);
K2 = emalloc(ops->block_size);
Expand Down Expand Up @@ -1212,7 +1218,7 @@ PHP_FUNCTION(mhash)
if (key) {
php_hash_do_hash_hmac(return_value, algo, data, data_len, key, key_len, 1, 0);
} else {
php_hash_do_hash(return_value, algo, data, data_len, 1, 0);
php_hash_do_hash(return_value, algo, data, data_len, 1, 0, NULL);
}

if (algo) {
Expand Down Expand Up @@ -1319,13 +1325,13 @@ PHP_FUNCTION(mhash_keygen_s2k)
}

context = php_hash_alloc_context(ops);
ops->hash_init(context);
ops->hash_init(context, NULL);

key = ecalloc(1, times * block_size);
digest = emalloc(ops->digest_size + 1);

for (i = 0; i < times; i++) {
ops->hash_init(context);
ops->hash_init(context, NULL);

for (j=0;j<i;j++) {
ops->hash_update(context, &null, 1);
Expand Down Expand Up @@ -1392,7 +1398,7 @@ static zend_object *php_hashcontext_clone(zend_object *zobj) {
newobj->ops = oldobj->ops;
newobj->options = oldobj->options;
newobj->context = php_hash_alloc_context(newobj->ops);
newobj->ops->hash_init(newobj->context);
newobj->ops->hash_init(newobj->context, NULL);

if (SUCCESS != newobj->ops->hash_copy(newobj->ops, oldobj->context, newobj->context)) {
efree(newobj->context);
Expand Down Expand Up @@ -1529,8 +1535,8 @@ PHP_METHOD(HashContext, __unserialize)

hash->ops = ops;
hash->context = php_hash_alloc_context(ops);
ops->hash_init(hash->context);
hash->options = options;
ops->hash_init(hash->context, NULL);

unserialize_result = ops->hash_unserialize(hash, magic, hash_zv);
if (unserialize_result != SUCCESS) {
Expand Down
6 changes: 3 additions & 3 deletions ext/hash/hash.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@

/** @generate-function-entries */

function hash(string $algo, string $data, bool $binary = false): string|false {}
function hash(string $algo, string $data, bool $binary = false, array $options = []): string|false {}

function hash_file(string $algo, string $filename, bool $binary = false): string|false {}
function hash_file(string $algo, string $filename, bool $binary = false, array $options = []): string|false {}

function hash_hmac(string $algo, string $data, string $key, bool $binary = false): string|false {}

function hash_hmac_file(string $algo, string $data, string $key, bool $binary = false): string|false {}

function hash_init(string $algo, int $flags = 0, string $key = ""): HashContext {}
function hash_init(string $algo, int $flags = 0, string $key = "", array $options = []): HashContext {}

function hash_update(HashContext $context, string $data): bool {}

Expand Down
2 changes: 1 addition & 1 deletion ext/hash/hash_adler32.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#include "php_hash.h"
#include "php_hash_adler32.h"

PHP_HASH_API void PHP_ADLER32Init(PHP_ADLER32_CTX *context)
PHP_HASH_API void PHP_ADLER32Init(PHP_ADLER32_CTX *context, ZEND_ATTRIBUTE_UNUSED HashTable *args)
{
context->state = 1;
}
Expand Down
5 changes: 4 additions & 1 deletion ext/hash/hash_arginfo.h
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 9352e0ac98e2ac53dc15d5024f9ef0c8092c4e9c */
* Stub hash: e8466049fca2eae179adbc19bb67e71f6486ec4e */

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_hash, 0, 2, MAY_BE_STRING|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, algo, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, data, IS_STRING, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, binary, _IS_BOOL, 0, "false")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 0, "[]")
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_hash_file, 0, 2, MAY_BE_STRING|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, algo, IS_STRING, 0)
ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, binary, _IS_BOOL, 0, "false")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 0, "[]")
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_hash_hmac, 0, 3, MAY_BE_STRING|MAY_BE_FALSE)
Expand All @@ -26,6 +28,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_hash_init, 0, 1, HashContext, 0)
ZEND_ARG_TYPE_INFO(0, algo, IS_STRING, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, flags, IS_LONG, 0, "0")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, key, IS_STRING, 0, "\"\"")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_ARRAY, 0, "[]")
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_hash_update, 0, 2, _IS_BOOL, 0)
Expand Down
2 changes: 1 addition & 1 deletion ext/hash/hash_crc32.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#include "php_hash_crc32_tables.h"
#include "ext/standard/crc32_x86.h"

PHP_HASH_API void PHP_CRC32Init(PHP_CRC32_CTX *context)
PHP_HASH_API void PHP_CRC32Init(PHP_CRC32_CTX *context, ZEND_ATTRIBUTE_UNUSED HashTable *args)
{
context->state = ~0;
}
Expand Down
4 changes: 2 additions & 2 deletions ext/hash/hash_fnv.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ const php_hash_ops php_hash_fnv1a64_ops = {
/* {{{ PHP_FNV132Init
* 32-bit FNV-1 hash initialisation
*/
PHP_HASH_API void PHP_FNV132Init(PHP_FNV132_CTX *context)
PHP_HASH_API void PHP_FNV132Init(PHP_FNV132_CTX *context, ZEND_ATTRIBUTE_UNUSED HashTable *args)
{
context->state = PHP_FNV1_32_INIT;
}
Expand Down Expand Up @@ -118,7 +118,7 @@ PHP_HASH_API void PHP_FNV132Final(unsigned char digest[4], PHP_FNV132_CTX * cont
/* {{{ PHP_FNV164Init
* 64-bit FNV-1 hash initialisation
*/
PHP_HASH_API void PHP_FNV164Init(PHP_FNV164_CTX *context)
PHP_HASH_API void PHP_FNV164Init(PHP_FNV164_CTX *context, ZEND_ATTRIBUTE_UNUSED HashTable *args)
{
context->state = PHP_FNV1_64_INIT;
}
Expand Down
6 changes: 3 additions & 3 deletions ext/hash/hash_gost.c
Original file line number Diff line number Diff line change
Expand Up @@ -235,15 +235,15 @@ static inline void GostTransform(PHP_GOST_CTX *context, const unsigned char inpu
Gost(context, data);
}

PHP_HASH_API void PHP_GOSTInit(PHP_GOST_CTX *context)
PHP_HASH_API void PHP_GOSTInit(PHP_GOST_CTX *context, ZEND_ATTRIBUTE_UNUSED HashTable *args)
{
memset(context, 0, sizeof(*context));
context->tables = &tables_test;
}

PHP_HASH_API void PHP_GOSTInitCrypto(PHP_GOST_CTX *context)
PHP_HASH_API void PHP_GOSTInitCrypto(PHP_GOST_CTX *context, ZEND_ATTRIBUTE_UNUSED HashTable *args)
{
PHP_GOSTInit(context);
PHP_GOSTInit(context, NULL);
context->tables = &tables_crypto;
}

Expand Down
2 changes: 1 addition & 1 deletion ext/hash/hash_haval.c
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ const php_hash_ops php_hash_##p##haval##b##_ops = { \
php_hash_unserialize, \
PHP_HAVAL_SPEC, \
((b) / 8), 128, sizeof(PHP_HAVAL_CTX), 1 }; \
PHP_HASH_API void PHP_##p##HAVAL##b##Init(PHP_HAVAL_CTX *context) \
PHP_HASH_API void PHP_##p##HAVAL##b##Init(PHP_HAVAL_CTX *context, ZEND_ATTRIBUTE_UNUSED HashTable *args) \
{ int i; context->count[0] = context->count[1] = 0; \
for(i = 0; i < 8; i++) context->state[i] = D0[i]; \
context->passes = p; context->output = b; \
Expand Down
2 changes: 1 addition & 1 deletion ext/hash/hash_joaat.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const php_hash_ops php_hash_joaat_ops = {
0
};

PHP_HASH_API void PHP_JOAATInit(PHP_JOAAT_CTX *context)
PHP_HASH_API void PHP_JOAATInit(PHP_JOAAT_CTX *context, ZEND_ATTRIBUTE_UNUSED HashTable *args)
{
context->state = 0;
}
Expand Down
12 changes: 6 additions & 6 deletions ext/hash/hash_md.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

const php_hash_ops php_hash_md5_ops = {
"md5",
(php_hash_init_func_t) PHP_MD5Init,
(php_hash_init_func_t) PHP_MD5InitArgs,
(php_hash_update_func_t) PHP_MD5Update,
(php_hash_final_func_t) PHP_MD5Final,
php_hash_copy,
Expand All @@ -34,7 +34,7 @@ const php_hash_ops php_hash_md5_ops = {

const php_hash_ops php_hash_md4_ops = {
"md4",
(php_hash_init_func_t) PHP_MD4Init,
(php_hash_init_func_t) PHP_MD4InitArgs,
(php_hash_update_func_t) PHP_MD4Update,
(php_hash_final_func_t) PHP_MD4Final,
php_hash_copy,
Expand All @@ -51,7 +51,7 @@ static int php_md2_unserialize(php_hashcontext_object *hash, zend_long magic, co

const php_hash_ops php_hash_md2_ops = {
"md2",
(php_hash_init_func_t) PHP_MD2Init,
(php_hash_init_func_t) PHP_MD2InitArgs,
(php_hash_update_func_t) PHP_MD2Update,
(php_hash_final_func_t) PHP_MD2Final,
php_hash_copy,
Expand Down Expand Up @@ -182,10 +182,10 @@ static void MD4Transform(uint32_t state[4], const unsigned char block[64])
state[3] += d;
}

/* {{{ PHP_MD4Init
/* {{{ PHP_MD4InitArgs
* MD4 initialization. Begins an MD4 operation, writing a new context.
*/
PHP_HASH_API void PHP_MD4Init(PHP_MD4_CTX * context)
PHP_HASH_API void PHP_MD4InitArgs(PHP_MD4_CTX * context, ZEND_ATTRIBUTE_UNUSED HashTable *args)
{
context->count[0] = context->count[1] = 0;
/* Load magic initialization constants.
Expand Down Expand Up @@ -287,7 +287,7 @@ static const unsigned char MD2_S[256] = {
242, 239, 183, 14, 102, 88, 208, 228, 166, 119, 114, 248, 235, 117, 75, 10,
49, 68, 80, 180, 143, 237, 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 };

PHP_HASH_API void PHP_MD2Init(PHP_MD2_CTX *context)
PHP_HASH_API void PHP_MD2InitArgs(PHP_MD2_CTX *context, ZEND_ATTRIBUTE_UNUSED HashTable *args)
{
memset(context, 0, sizeof(PHP_MD2_CTX));
}
Expand Down
Loading