From ada776c84cad810e69c0d9764cbef1628744cdd4 Mon Sep 17 00:00:00 2001 From: Eddie Kohler Date: Mon, 8 Jun 2020 08:29:42 -0400 Subject: [PATCH] Make HashContexts serializable. * Modify php_hash_ops to contain the algorithm name and serialize and unserialize methods. * Implement __serialize and __unserialize magic methods on HashContext. Note that serialized HashContexts are not necessarily portable between PHP versions or from architecture to architecture. (Most are, though Keccak and slow SHA3s are not.) An exception is thrown when an unsupported serialization is attempted. Because of security concerns, HASH_HMAC contexts are not currently serializable; attempting to serialize one throws an exception. Serialization exposes the state of HashContext memory, so ensure that memory is zeroed before use by allocating it with a new php_hash_alloc_context function. Performance impact is negligible. Some hash internal states have logical pointers into a buffer, or sponge, that absorbs input provided in bytes rather than chunks. The unserialize functions for these hash functions must validate that the logical pointers are all within bounds, lest future hash operations cause out-of-bounds memory accesses. * Adler32, CRC32, FNV, joaat: simple state, no buffer positions * Gost, MD2, SHA3, Snefru, Tiger, Whirlpool: buffer positions must be validated * MD4, MD5, SHA1, SHA2, haval, ripemd: buffer positions encoded bitwise, forced to within bounds on use; no need to validate --- UPGRADING | 10 +- ext/hash/hash.c | 386 ++++++++++++++++++++++++- ext/hash/hash.stub.php | 4 + ext/hash/hash_adler32.c | 4 + ext/hash/hash_arginfo.h | 10 + ext/hash/hash_crc32.c | 12 + ext/hash/hash_fnv.c | 28 +- ext/hash/hash_gost.c | 25 +- ext/hash/hash_haval.c | 6 +- ext/hash/hash_joaat.c | 6 +- ext/hash/hash_md.c | 33 ++- ext/hash/hash_ripemd.c | 24 +- ext/hash/hash_sha.c | 42 ++- ext/hash/hash_sha3.c | 78 +++++ ext/hash/hash_snefru.c | 19 +- ext/hash/hash_tiger.c | 19 +- ext/hash/hash_whirlpool.c | 22 +- ext/hash/php_hash.h | 23 +- ext/hash/php_hash_adler32.h | 1 + ext/hash/php_hash_crc32.h | 1 + ext/hash/php_hash_fnv.h | 2 + ext/hash/php_hash_gost.h | 1 + ext/hash/php_hash_haval.h | 1 + ext/hash/php_hash_joaat.h | 1 + ext/hash/php_hash_md.h | 4 +- ext/hash/php_hash_ripemd.h | 4 + ext/hash/php_hash_sha.h | 4 + ext/hash/php_hash_sha3.h | 3 + ext/hash/php_hash_snefru.h | 1 + ext/hash/php_hash_tiger.h | 3 +- ext/hash/php_hash_whirlpool.h | 1 + ext/hash/sha3/generic32lc/KeccakHash.h | 2 + ext/hash/sha3/generic64lc/KeccakHash.h | 2 + ext/hash/tests/hash_serialize_001.phpt | 361 +++++++++++++++++++++++ ext/hash/tests/hash_serialize_002.phpt | 116 ++++++++ ext/hash/tests/hash_serialize_003.phpt | 261 +++++++++++++++++ ext/hash/tests/hash_serialize_004.phpt | 45 +++ ext/hash/tests/serialize-context.phpt | 13 - ext/standard/md5.h | 1 + ext/standard/sha1.h | 1 + 40 files changed, 1524 insertions(+), 56 deletions(-) create mode 100644 ext/hash/tests/hash_serialize_001.phpt create mode 100644 ext/hash/tests/hash_serialize_002.phpt create mode 100644 ext/hash/tests/hash_serialize_003.phpt create mode 100644 ext/hash/tests/hash_serialize_004.phpt delete mode 100644 ext/hash/tests/serialize-context.phpt diff --git a/UPGRADING b/UPGRADING index de0eebd055..f662a6625a 100644 --- a/UPGRADING +++ b/UPGRADING @@ -568,14 +568,18 @@ PHP 8.0 UPGRADE NOTES . Added DateTime::createFromInterface() and DateTimeImmutable::createFromInterface(). +- Dom: + . Introduce DOMParentNode and DOMChildNode with new traversal and + manipulation APIs. + RFC: https://wiki.php.net/rfc/dom_living_standard_api + - Enchant: . enchant_dict_add() . enchant_dict_is_added() . LIBENCHANT_VERSION macro -- dom: - . Introduce DOMParentNode and DOMChildNode with new traversal and manipulation APIs - RFC: https://wiki.php.net/rfc/dom_living_standard_api +- Hash: + . HashContext objects can now be serialized. - Opcache: . If the opcache.record_warnings ini setting is enabled, opcache will record diff --git a/ext/hash/hash.c b/ext/hash/hash.c index 2d356b6133..469d91e34b 100644 --- a/ext/hash/hash.c +++ b/ext/hash/hash.c @@ -23,12 +23,24 @@ #include "php_hash.h" #include "ext/standard/info.h" #include "ext/standard/file.h" +#include "ext/standard/php_var.h" +#include "ext/spl/spl_exceptions.h" #include "zend_interfaces.h" #include "zend_exceptions.h" +#include "zend_smart_str.h" #include "hash_arginfo.h" +#ifdef PHP_WIN32 +# define __alignof__ __alignof +#else +# ifndef HAVE_ALIGNOF +# include +# define __alignof__(type) offsetof (struct { char c; type member;}, member) +# endif +#endif + HashTable php_hash_hashtable; zend_class_entry *php_hashcontext_ce; static zend_object_handlers php_hashcontext_handlers; @@ -111,6 +123,226 @@ PHP_HASH_API int php_hash_copy(const void *ops, void *orig_context, void *dest_c } /* }}} */ + +static inline size_t align_to(size_t pos, size_t alignment) { + size_t offset = pos & (alignment - 1); + return pos + (offset ? alignment - offset : 0); +} + +static size_t parse_serialize_spec( + const char **specp, size_t *pos, size_t *sz, size_t *max_alignment) { + size_t count, alignment; + const char *spec = *specp; + /* parse size */ + if (*spec == 's' || *spec == 'S') { + *sz = 2; + alignment = __alignof__(uint16_t); /* usually 2 */ + } else if (*spec == 'l' || *spec == 'L') { + *sz = 4; + alignment = __alignof__(uint32_t); /* usually 4 */ + } else if (*spec == 'q' || *spec == 'Q') { + *sz = 8; + alignment = __alignof__(uint64_t); /* usually 8 */ + } else if (*spec == 'i' || *spec == 'I') { + *sz = sizeof(int); + alignment = __alignof__(int); /* usually 4 */ + } else { + ZEND_ASSERT(*spec == 'b' || *spec == 'B'); + *sz = 1; + alignment = 1; + } + /* process alignment */ + *pos = align_to(*pos, alignment); + *max_alignment = *max_alignment < alignment ? alignment : *max_alignment; + /* parse count */ + ++spec; + if (isdigit((unsigned char) *spec)) { + count = 0; + while (isdigit((unsigned char) *spec)) { + count = 10 * count + *spec - '0'; + ++spec; + } + } else { + count = 1; + } + *specp = spec; + return count; +} + +static uint64_t one_from_buffer(size_t sz, const unsigned char *buf) { + if (sz == 2) { + const uint16_t *x = (const uint16_t *) buf; + return *x; + } else if (sz == 4) { + const uint32_t *x = (const uint32_t *) buf; + return *x; + } else if (sz == 8) { + const uint64_t *x = (const uint64_t *) buf; + return *x; + } else { + ZEND_ASSERT(sz == 1); + return *buf; + } +} + +static void one_to_buffer(size_t sz, unsigned char *buf, uint64_t val) { + if (sz == 2) { + uint16_t *x = (uint16_t *) buf; + *x = val; + } else if (sz == 4) { + uint32_t *x = (uint32_t *) buf; + *x = val; + } else if (sz == 8) { + uint64_t *x = (uint64_t *) buf; + *x = val; + } else { + ZEND_ASSERT(sz == 1); + *buf = val; + } +} + +/* Serialize a hash context according to a `spec` string. + Spec contents: + b[COUNT] -- serialize COUNT bytes + s[COUNT] -- serialize COUNT 16-bit integers + l[COUNT] -- serialize COUNT 32-bit integers + q[COUNT] -- serialize COUNT 64-bit integers + i[COUNT] -- serialize COUNT `int`s + B[COUNT] -- skip COUNT bytes + S[COUNT], L[COUNT], etc. -- uppercase versions skip instead of read + . (must be last character) -- assert that the hash context has exactly + this size + Example: "llllllb64l16." is the spec for an MD5 context: 6 32-bit + integers, followed by 64 bytes, then 16 32-bit integers, and that's + exactly the size of the context. + + The serialization result is an array. Each integer is serialized as a + 32-bit integer, except that a run of 2 or more bytes is encoded as a + string, and each 64-bit integer is serialized as two 32-bit integers, least + significant bits first. This allows 32-bit and 64-bit architectures to + interchange serialized HashContexts. */ + +PHP_HASH_API int php_hash_serialize_spec(const php_hashcontext_object *hash, zval *zv, const char *spec) /* {{{ */ +{ + size_t pos = 0, max_alignment = 1; + unsigned char *buf = (unsigned char *) hash->context; + zval tmp; + array_init(zv); + while (*spec != '\0' && *spec != '.') { + char spec_ch = *spec; + size_t sz, count = parse_serialize_spec(&spec, &pos, &sz, &max_alignment); + if (pos + count * sz > hash->ops->context_size) { + return FAILURE; + } + if (isupper((unsigned char) spec_ch)) { + pos += count * sz; + } else if (sz == 1 && count > 1) { + ZVAL_STRINGL(&tmp, (char *) buf + pos, count); + zend_hash_next_index_insert(Z_ARRVAL_P(zv), &tmp); + pos += count; + } else { + while (count > 0) { + uint64_t val = one_from_buffer(sz, buf + pos); + pos += sz; + ZVAL_LONG(&tmp, (int32_t) val); + zend_hash_next_index_insert(Z_ARRVAL_P(zv), &tmp); + if (sz == 8) { + ZVAL_LONG(&tmp, (int32_t) (val >> 32)); + zend_hash_next_index_insert(Z_ARRVAL_P(zv), &tmp); + } + --count; + } + } + } + if (*spec == '.' && align_to(pos, max_alignment) != hash->ops->context_size) { + return FAILURE; + } + return SUCCESS; +} +/* }}} */ + +/* Unserialize a hash context serialized by `php_hash_serialize_spec` with `spec`. + Returns SUCCESS on success and a negative error code on failure. + Codes: FAILURE (-1) == generic failure + -999 == spec wrong size for context + -1000 - POS == problem at byte offset POS */ + +PHP_HASH_API int php_hash_unserialize_spec(php_hashcontext_object *hash, const zval *zv, const char *spec) /* {{{ */ +{ + size_t pos = 0, max_alignment = 1, j = 0; + unsigned char *buf = (unsigned char *) hash->context; + zval *elt; + if (Z_TYPE_P(zv) != IS_ARRAY) { + return FAILURE; + } + while (*spec != '\0' && *spec != '.') { + char spec_ch = *spec; + size_t sz, count = parse_serialize_spec(&spec, &pos, &sz, &max_alignment); + if (pos + count * sz > hash->ops->context_size) { + return -999; + } + if (isupper((unsigned char) spec_ch)) { + pos += count * sz; + } else if (sz == 1 && count > 1) { + elt = zend_hash_index_find(Z_ARRVAL_P(zv), j); + if (!elt || Z_TYPE_P(elt) != IS_STRING || Z_STRLEN_P(elt) != count) { + return -1000 - pos; + } + ++j; + memcpy(buf + pos, Z_STRVAL_P(elt), count); + pos += count; + } else { + while (count > 0) { + uint64_t val; + elt = zend_hash_index_find(Z_ARRVAL_P(zv), j); + if (!elt || Z_TYPE_P(elt) != IS_LONG) { + return -1000 - pos; + } + ++j; + val = (uint32_t) Z_LVAL_P(elt); + if (sz == 8) { + elt = zend_hash_index_find(Z_ARRVAL_P(zv), j); + if (!elt || Z_TYPE_P(elt) != IS_LONG) { + return -1000 - pos; + } + ++j; + val += ((uint64_t) Z_LVAL_P(elt)) << 32; + } + one_to_buffer(sz, buf + pos, val); + pos += sz; + --count; + } + } + } + if (*spec == '.' && align_to(pos, max_alignment) != hash->ops->context_size) { + return -999; + } + return SUCCESS; +} +/* }}} */ + +PHP_HASH_API int php_hash_serialize(const php_hashcontext_object *hash, zend_long *magic, zval *zv) /* {{{ */ +{ + if (hash->ops->serialize_spec) { + *magic = PHP_HASH_SERIALIZE_MAGIC_SPEC; + return php_hash_serialize_spec(hash, zv, hash->ops->serialize_spec); + } else { + return FAILURE; + } +} +/* }}} */ + +PHP_HASH_API int php_hash_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) /* {{{ */ +{ + if (hash->ops->serialize_spec + && magic == PHP_HASH_SERIALIZE_MAGIC_SPEC) { + return php_hash_unserialize_spec(hash, zv, hash->ops->serialize_spec); + } else { + return FAILURE; + } +} +/* }}} */ + /* Userspace */ static void php_hash_do_hash(INTERNAL_FUNCTION_PARAMETERS, int isfilename, zend_bool raw_output_default) /* {{{ */ @@ -147,7 +379,7 @@ static void php_hash_do_hash(INTERNAL_FUNCTION_PARAMETERS, int isfilename, zend_ } } - context = emalloc(ops->context_size); + context = php_hash_alloc_context(ops); ops->hash_init(context); if (isfilename) { @@ -271,7 +503,7 @@ static void php_hash_do_hash_hmac(INTERNAL_FUNCTION_PARAMETERS, int isfilename, } } - context = emalloc(ops->context_size); + context = php_hash_alloc_context(ops); K = emalloc(ops->block_size); digest = zend_string_alloc(ops->digest_size, 0); @@ -375,7 +607,7 @@ PHP_FUNCTION(hash_init) object_init_ex(return_value, php_hashcontext_ce); hash = php_hashcontext_from_object(Z_OBJ_P(return_value)); - context = emalloc(ops->context_size); + context = php_hash_alloc_context(ops); ops->hash_init(context); hash->ops = ops; @@ -664,7 +896,7 @@ PHP_FUNCTION(hash_hkdf) RETURN_THROWS(); } - context = emalloc(ops->context_size); + context = php_hash_alloc_context(ops); // Extract ops->hash_init(context); @@ -759,7 +991,7 @@ PHP_FUNCTION(hash_pbkdf2) RETURN_THROWS(); } - context = emalloc(ops->context_size); + context = php_hash_alloc_context(ops); ops->hash_init(context); K1 = emalloc(ops->block_size); @@ -1075,7 +1307,7 @@ PHP_FUNCTION(mhash_keygen_s2k) times++; } - context = emalloc(ops->context_size); + context = php_hash_alloc_context(ops); ops->hash_init(context); key = ecalloc(1, times * block_size); @@ -1148,7 +1380,7 @@ static zend_object *php_hashcontext_clone(zend_object *zobj) { newobj->ops = oldobj->ops; newobj->options = oldobj->options; - newobj->context = emalloc(newobj->ops->context_size); + newobj->context = php_hash_alloc_context(newobj->ops); newobj->ops->hash_init(newobj->context); if (SUCCESS != newobj->ops->hash_copy(newobj->ops, oldobj->context, newobj->context)) { @@ -1166,6 +1398,144 @@ static zend_object *php_hashcontext_clone(zend_object *zobj) { } /* }}} */ +/* Serialization format: 5-element array + Index 0: hash algorithm (string) + Index 1: options (long, 0) + Index 2: hash-determined serialization of context state (usually array) + Index 3: magic number defining layout of context state (long, usually 2) + Index 4: properties (array) + + HashContext serializations are not necessarily portable between architectures or + PHP versions. If the format of a serialized hash context changes, that should + be reflected in either a different value of `magic` or a different format of + the serialized context state. Most context states are unparsed and parsed using + a spec string, such as "llb128.", using the format defined by + `php_hash_serialize_spec`/`php_hash_unserialize_spec`. Some hash algorithms must + also check the unserialized state for validity, to ensure that using an + unserialized context is safe from memory errors. + + Currently HASH_HMAC contexts cannot be serialized, because serializing them + would require serializing the HMAC key in plaintext. */ + +/* {{{ proto array HashContext::__serialize() + Serialize the object */ +PHP_METHOD(HashContext, __serialize) +{ + zval *object = ZEND_THIS; + php_hashcontext_object *hash = php_hashcontext_from_object(Z_OBJ_P(object)); + zend_long magic = 0; + zval tmp; + + if (zend_parse_parameters_none() == FAILURE) { + RETURN_THROWS(); + } + + array_init(return_value); + + if (!hash->ops->hash_serialize) { + goto serialize_failure; + } else if (hash->options & PHP_HASH_HMAC) { + zend_throw_exception(NULL, "HashContext with HASH_HMAC option cannot be serialized", 0); + RETURN_THROWS(); + } + + ZVAL_STRING(&tmp, hash->ops->algo); + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp); + + ZVAL_LONG(&tmp, hash->options); + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp); + + if (hash->ops->hash_serialize(hash, &magic, &tmp) != SUCCESS) { + goto serialize_failure; + } + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp); + + ZVAL_LONG(&tmp, magic); + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp); + + /* members */ + ZVAL_ARR(&tmp, zend_std_get_properties(&hash->std)); + Z_TRY_ADDREF(tmp); + zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp); + + return; + +serialize_failure: + zend_throw_exception_ex(NULL, 0, "HashContext for algorithm \"%s\" cannot be serialized", hash->ops->algo); + RETURN_THROWS(); +} +/* }}} */ + +/* {{{ proto void HashContext::__unserialize(array serialized) + * unserialize the object + */ +PHP_METHOD(HashContext, __unserialize) +{ + zval *object = ZEND_THIS; + php_hashcontext_object *hash = php_hashcontext_from_object(Z_OBJ_P(object)); + HashTable *data; + zval *algo_zv, *magic_zv, *options_zv, *hash_zv, *members_zv; + zend_long magic, options; + int unserialize_result; + const php_hash_ops *ops; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "h", &data) == FAILURE) { + RETURN_THROWS(); + } + + if (hash->context) { + zend_throw_exception(NULL, "HashContext::__unserialize called on initialized object", 0); + RETURN_THROWS(); + } + + algo_zv = zend_hash_index_find(data, 0); + options_zv = zend_hash_index_find(data, 1); + hash_zv = zend_hash_index_find(data, 2); + magic_zv = zend_hash_index_find(data, 3); + members_zv = zend_hash_index_find(data, 4); + + if (!algo_zv || Z_TYPE_P(algo_zv) != IS_STRING + || !magic_zv || Z_TYPE_P(magic_zv) != IS_LONG + || !options_zv || Z_TYPE_P(options_zv) != IS_LONG + || !hash_zv + || !members_zv || Z_TYPE_P(members_zv) != IS_ARRAY) { + zend_throw_exception(NULL, "Incomplete or ill-formed serialization data", 0); + RETURN_THROWS(); + } + + magic = Z_LVAL_P(magic_zv); + options = Z_LVAL_P(options_zv); + if (options & PHP_HASH_HMAC) { + zend_throw_exception(NULL, "HashContext with HASH_HMAC option cannot be serialized", 0); + RETURN_THROWS(); + } + + ops = php_hash_fetch_ops(Z_STR_P(algo_zv)); + if (!ops) { + zend_throw_exception(NULL, "Unknown hash algorithm", 0); + RETURN_THROWS(); + } else if (!ops->hash_unserialize) { + zend_throw_exception_ex(NULL, 0, "Hash algorithm \"%s\" cannot be unserialized", ops->algo); + RETURN_THROWS(); + } + + hash->ops = ops; + hash->context = php_hash_alloc_context(ops); + ops->hash_init(hash->context); + hash->options = options; + + unserialize_result = ops->hash_unserialize(hash, magic, hash_zv); + if (unserialize_result != SUCCESS) { + zend_throw_exception_ex(NULL, 0, "Incomplete or ill-formed serialization data (\"%s\" code %d)", ops->algo, unserialize_result); + /* free context */ + php_hashcontext_dtor(Z_OBJ_P(object)); + RETURN_THROWS(); + } + + object_properties_load(&hash->std, Z_ARRVAL_P(members_zv)); +} +/* }}} */ + /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(hash) @@ -1237,8 +1607,6 @@ PHP_MINIT_FUNCTION(hash) php_hashcontext_ce = zend_register_internal_class(&ce); php_hashcontext_ce->ce_flags |= ZEND_ACC_FINAL; php_hashcontext_ce->create_object = php_hashcontext_create; - php_hashcontext_ce->serialize = zend_class_serialize_deny; - php_hashcontext_ce->unserialize = zend_class_unserialize_deny; memcpy(&php_hashcontext_handlers, &std_object_handlers, sizeof(zend_object_handlers)); diff --git a/ext/hash/hash.stub.php b/ext/hash/hash.stub.php index 32465415fc..f8788ed61e 100644 --- a/ext/hash/hash.stub.php +++ b/ext/hash/hash.stub.php @@ -53,4 +53,8 @@ function mhash(int $hash, string $data, string $key = UNKNOWN): string|false {} final class HashContext { private function __construct() {} + + public function __serialize(): array {} + + public function __unserialize(array $serialized): void {} } diff --git a/ext/hash/hash_adler32.c b/ext/hash/hash_adler32.c index 8d2d2fcb93..d45012f8e6 100644 --- a/ext/hash/hash_adler32.c +++ b/ext/hash/hash_adler32.c @@ -59,10 +59,14 @@ PHP_HASH_API int PHP_ADLER32Copy(const php_hash_ops *ops, PHP_ADLER32_CTX *orig_ } const php_hash_ops php_hash_adler32_ops = { + "adler32", (php_hash_init_func_t) PHP_ADLER32Init, (php_hash_update_func_t) PHP_ADLER32Update, (php_hash_final_func_t) PHP_ADLER32Final, (php_hash_copy_func_t) PHP_ADLER32Copy, + php_hash_serialize, + php_hash_unserialize, + PHP_ADLER32_SPEC, 4, /* what to say here? */ 4, sizeof(PHP_ADLER32_CTX), diff --git a/ext/hash/hash_arginfo.h b/ext/hash/hash_arginfo.h index c09fd12001..7ba3fca9d7 100644 --- a/ext/hash/hash_arginfo.h +++ b/ext/hash/hash_arginfo.h @@ -118,6 +118,12 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_HashContext___construct, 0, 0, 0) ZEND_END_ARG_INFO() +#define arginfo_class_HashContext___serialize arginfo_hash_algos + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_HashContext___unserialize, 0, 1, IS_VOID, 0) + ZEND_ARG_TYPE_INFO(0, serialized, IS_ARRAY, 0) +ZEND_END_ARG_INFO() + ZEND_FUNCTION(hash); ZEND_FUNCTION(hash_file); @@ -150,6 +156,8 @@ ZEND_FUNCTION(mhash_count); ZEND_FUNCTION(mhash); #endif ZEND_METHOD(HashContext, __construct); +ZEND_METHOD(HashContext, __serialize); +ZEND_METHOD(HashContext, __unserialize); static const zend_function_entry ext_functions[] = { @@ -189,5 +197,7 @@ static const zend_function_entry ext_functions[] = { static const zend_function_entry class_HashContext_methods[] = { ZEND_ME(HashContext, __construct, arginfo_class_HashContext___construct, ZEND_ACC_PRIVATE) + ZEND_ME(HashContext, __serialize, arginfo_class_HashContext___serialize, ZEND_ACC_PUBLIC) + ZEND_ME(HashContext, __unserialize, arginfo_class_HashContext___unserialize, ZEND_ACC_PUBLIC) ZEND_FE_END }; diff --git a/ext/hash/hash_crc32.c b/ext/hash/hash_crc32.c index 52c67717ff..de270522d7 100644 --- a/ext/hash/hash_crc32.c +++ b/ext/hash/hash_crc32.c @@ -78,10 +78,14 @@ PHP_HASH_API int PHP_CRC32Copy(const php_hash_ops *ops, PHP_CRC32_CTX *orig_cont } const php_hash_ops php_hash_crc32_ops = { + "crc32", (php_hash_init_func_t) PHP_CRC32Init, (php_hash_update_func_t) PHP_CRC32Update, (php_hash_final_func_t) PHP_CRC32LEFinal, (php_hash_copy_func_t) PHP_CRC32Copy, + php_hash_serialize, + php_hash_unserialize, + PHP_CRC32_SPEC, 4, /* what to say here? */ 4, sizeof(PHP_CRC32_CTX), @@ -89,10 +93,14 @@ const php_hash_ops php_hash_crc32_ops = { }; const php_hash_ops php_hash_crc32b_ops = { + "crc32b", (php_hash_init_func_t) PHP_CRC32Init, (php_hash_update_func_t) PHP_CRC32BUpdate, (php_hash_final_func_t) PHP_CRC32BEFinal, (php_hash_copy_func_t) PHP_CRC32Copy, + php_hash_serialize, + php_hash_unserialize, + PHP_CRC32_SPEC, 4, /* what to say here? */ 4, sizeof(PHP_CRC32_CTX), @@ -100,10 +108,14 @@ const php_hash_ops php_hash_crc32b_ops = { }; const php_hash_ops php_hash_crc32c_ops = { + "crc32c", (php_hash_init_func_t) PHP_CRC32Init, (php_hash_update_func_t) PHP_CRC32CUpdate, (php_hash_final_func_t) PHP_CRC32BEFinal, (php_hash_copy_func_t) PHP_CRC32Copy, + php_hash_serialize, + php_hash_unserialize, + PHP_CRC32_SPEC, 4, /* what to say here? */ 4, sizeof(PHP_CRC32_CTX), diff --git a/ext/hash/hash_fnv.c b/ext/hash/hash_fnv.c index 976c53b527..2ee81b9c86 100644 --- a/ext/hash/hash_fnv.c +++ b/ext/hash/hash_fnv.c @@ -21,10 +21,14 @@ #include "php_hash_fnv.h" const php_hash_ops php_hash_fnv132_ops = { + "fnv132", (php_hash_init_func_t) PHP_FNV132Init, (php_hash_update_func_t) PHP_FNV132Update, (php_hash_final_func_t) PHP_FNV132Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_FNV132_SPEC, 4, 4, sizeof(PHP_FNV132_CTX), @@ -32,10 +36,14 @@ const php_hash_ops php_hash_fnv132_ops = { }; const php_hash_ops php_hash_fnv1a32_ops = { + "fnv1a32", (php_hash_init_func_t) PHP_FNV132Init, (php_hash_update_func_t) PHP_FNV1a32Update, - (php_hash_final_func_t) PHP_FNV132Final, - (php_hash_copy_func_t) php_hash_copy, + (php_hash_final_func_t) PHP_FNV132Final, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_FNV132_SPEC, 4, 4, sizeof(PHP_FNV132_CTX), @@ -43,10 +51,14 @@ const php_hash_ops php_hash_fnv1a32_ops = { }; const php_hash_ops php_hash_fnv164_ops = { + "fnv164", (php_hash_init_func_t) PHP_FNV164Init, (php_hash_update_func_t) PHP_FNV164Update, (php_hash_final_func_t) PHP_FNV164Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_FNV164_SPEC, 8, 4, sizeof(PHP_FNV164_CTX), @@ -54,10 +66,14 @@ const php_hash_ops php_hash_fnv164_ops = { }; const php_hash_ops php_hash_fnv1a64_ops = { + "fnv1a64", (php_hash_init_func_t) PHP_FNV164Init, (php_hash_update_func_t) PHP_FNV1a64Update, - (php_hash_final_func_t) PHP_FNV164Final, - (php_hash_copy_func_t) php_hash_copy, + (php_hash_final_func_t) PHP_FNV164Final, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_FNV164_SPEC, 8, 4, sizeof(PHP_FNV164_CTX), diff --git a/ext/hash/hash_gost.c b/ext/hash/hash_gost.c index a9e689de16..46ea032c32 100644 --- a/ext/hash/hash_gost.c +++ b/ext/hash/hash_gost.c @@ -304,11 +304,28 @@ PHP_HASH_API void PHP_GOSTFinal(unsigned char digest[32], PHP_GOST_CTX *context) ZEND_SECURE_ZERO(context, sizeof(*context)); } +static int php_gost_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) +{ + PHP_GOST_CTX *ctx = (PHP_GOST_CTX *) hash->context; + int r = FAILURE; + if (magic == PHP_HASH_SERIALIZE_MAGIC_SPEC + && (r = php_hash_unserialize_spec(hash, zv, PHP_GOST_SPEC)) == SUCCESS + && ctx->length < sizeof(ctx->buffer)) { + return SUCCESS; + } else { + return r != SUCCESS ? r : -2000; + } +} + const php_hash_ops php_hash_gost_ops = { + "gost", (php_hash_init_func_t) PHP_GOSTInit, (php_hash_update_func_t) PHP_GOSTUpdate, (php_hash_final_func_t) PHP_GOSTFinal, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_gost_unserialize, + PHP_GOST_SPEC, 32, 32, sizeof(PHP_GOST_CTX), @@ -316,10 +333,14 @@ const php_hash_ops php_hash_gost_ops = { }; const php_hash_ops php_hash_gost_crypto_ops = { + "gost-crypto", (php_hash_init_func_t) PHP_GOSTInitCrypto, (php_hash_update_func_t) PHP_GOSTUpdate, (php_hash_final_func_t) PHP_GOSTFinal, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_gost_unserialize, + PHP_GOST_SPEC, 32, 32, sizeof(PHP_GOST_CTX), diff --git a/ext/hash/hash_haval.c b/ext/hash/hash_haval.c index 62f63cbee1..34210a8992 100644 --- a/ext/hash/hash_haval.c +++ b/ext/hash/hash_haval.c @@ -247,10 +247,14 @@ static void PHP_5HAVALTransform(uint32_t state[8], const unsigned char block[128 #define PHP_HASH_HAVAL_INIT(p,b) \ const php_hash_ops php_hash_##p##haval##b##_ops = { \ + "haval" #b "," #p, \ (php_hash_init_func_t) PHP_##p##HAVAL##b##Init, \ (php_hash_update_func_t) PHP_HAVALUpdate, \ (php_hash_final_func_t) PHP_HAVAL##b##Final, \ - (php_hash_copy_func_t) php_hash_copy, \ + php_hash_copy, \ + php_hash_serialize, \ + 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) \ { int i; context->count[0] = context->count[1] = 0; \ diff --git a/ext/hash/hash_joaat.c b/ext/hash/hash_joaat.c index 10c3ca2748..5d5a2e53b9 100644 --- a/ext/hash/hash_joaat.c +++ b/ext/hash/hash_joaat.c @@ -22,10 +22,14 @@ #include "php_hash_joaat.h" const php_hash_ops php_hash_joaat_ops = { + "joaat", (php_hash_init_func_t) PHP_JOAATInit, (php_hash_update_func_t) PHP_JOAATUpdate, (php_hash_final_func_t) PHP_JOAATFinal, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_JOAAT_SPEC, 4, 4, sizeof(PHP_JOAAT_CTX), diff --git a/ext/hash/hash_md.c b/ext/hash/hash_md.c index e5cbb49b01..94fafbbf79 100644 --- a/ext/hash/hash_md.c +++ b/ext/hash/hash_md.c @@ -18,10 +18,14 @@ #include "php_hash_md.h" const php_hash_ops php_hash_md5_ops = { + "md5", (php_hash_init_func_t) PHP_MD5Init, (php_hash_update_func_t) PHP_MD5Update, (php_hash_final_func_t) PHP_MD5Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_MD5_SPEC, 16, 64, sizeof(PHP_MD5_CTX), @@ -29,21 +33,31 @@ 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_update_func_t) PHP_MD4Update, (php_hash_final_func_t) PHP_MD4Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_MD4_SPEC, 16, 64, sizeof(PHP_MD4_CTX), 1 }; +static int php_md2_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv); + const php_hash_ops php_hash_md2_ops = { + "md2", (php_hash_init_func_t) PHP_MD2Init, (php_hash_update_func_t) PHP_MD2Update, (php_hash_final_func_t) PHP_MD2Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_md2_unserialize, + PHP_MD2_SPEC, 16, 16, sizeof(PHP_MD2_CTX), @@ -340,3 +354,16 @@ PHP_HASH_API void PHP_MD2Final(unsigned char output[16], PHP_MD2_CTX *context) memcpy(output, context->state, 16); } + +static int php_md2_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) +{ + PHP_MD2_CTX *ctx = (PHP_MD2_CTX *) hash->context; + int r = FAILURE; + if (magic == PHP_HASH_SERIALIZE_MAGIC_SPEC + && (r = php_hash_unserialize_spec(hash, zv, PHP_MD2_SPEC)) == SUCCESS + && (unsigned char) ctx->in_buffer < sizeof(ctx->buffer)) { + return SUCCESS; + } else { + return r != SUCCESS ? r : -2000; + } +} diff --git a/ext/hash/hash_ripemd.c b/ext/hash/hash_ripemd.c index 84a29f6486..db1d1dc02b 100644 --- a/ext/hash/hash_ripemd.c +++ b/ext/hash/hash_ripemd.c @@ -22,10 +22,14 @@ #include "php_hash_ripemd.h" const php_hash_ops php_hash_ripemd128_ops = { + "ripemd128", (php_hash_init_func_t) PHP_RIPEMD128Init, (php_hash_update_func_t) PHP_RIPEMD128Update, (php_hash_final_func_t) PHP_RIPEMD128Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_RIPEMD128_SPEC, 16, 64, sizeof(PHP_RIPEMD128_CTX), @@ -33,10 +37,14 @@ const php_hash_ops php_hash_ripemd128_ops = { }; const php_hash_ops php_hash_ripemd160_ops = { + "ripemd160", (php_hash_init_func_t) PHP_RIPEMD160Init, (php_hash_update_func_t) PHP_RIPEMD160Update, (php_hash_final_func_t) PHP_RIPEMD160Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_RIPEMD160_SPEC, 20, 64, sizeof(PHP_RIPEMD160_CTX), @@ -44,10 +52,14 @@ const php_hash_ops php_hash_ripemd160_ops = { }; const php_hash_ops php_hash_ripemd256_ops = { + "ripemd256", (php_hash_init_func_t) PHP_RIPEMD256Init, (php_hash_update_func_t) PHP_RIPEMD256Update, (php_hash_final_func_t) PHP_RIPEMD256Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_RIPEMD256_SPEC, 32, 64, sizeof(PHP_RIPEMD256_CTX), @@ -55,10 +67,14 @@ const php_hash_ops php_hash_ripemd256_ops = { }; const php_hash_ops php_hash_ripemd320_ops = { + "ripemd320", (php_hash_init_func_t) PHP_RIPEMD320Init, (php_hash_update_func_t) PHP_RIPEMD320Update, (php_hash_final_func_t) PHP_RIPEMD320Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_RIPEMD320_SPEC, 40, 64, sizeof(PHP_RIPEMD320_CTX), diff --git a/ext/hash/hash_sha.c b/ext/hash/hash_sha.c index 30ab0d22ad..4ea5b768d7 100644 --- a/ext/hash/hash_sha.c +++ b/ext/hash/hash_sha.c @@ -63,10 +63,14 @@ static void SHADecode32(uint32_t *output, const unsigned char *input, unsigned i /* }}} */ const php_hash_ops php_hash_sha1_ops = { + "sha1", (php_hash_init_func_t) PHP_SHA1Init, (php_hash_update_func_t) PHP_SHA1Update, (php_hash_final_func_t) PHP_SHA1Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_SHA1_SPEC, 20, 64, sizeof(PHP_SHA1_CTX), @@ -76,10 +80,14 @@ const php_hash_ops php_hash_sha1_ops = { /* sha224/sha256 */ const php_hash_ops php_hash_sha256_ops = { + "sha256", (php_hash_init_func_t) PHP_SHA256Init, (php_hash_update_func_t) PHP_SHA256Update, (php_hash_final_func_t) PHP_SHA256Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_SHA256_SPEC, 32, 64, sizeof(PHP_SHA256_CTX), @@ -87,10 +95,14 @@ const php_hash_ops php_hash_sha256_ops = { }; const php_hash_ops php_hash_sha224_ops = { + "sha224", (php_hash_init_func_t) PHP_SHA224Init, (php_hash_update_func_t) PHP_SHA224Update, (php_hash_final_func_t) PHP_SHA224Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_SHA224_SPEC, 28, 64, sizeof(PHP_SHA224_CTX), @@ -578,10 +590,14 @@ PHP_HASH_API void PHP_SHA384Final(unsigned char digest[48], PHP_SHA384_CTX * con /* }}} */ const php_hash_ops php_hash_sha384_ops = { + "sha384", (php_hash_init_func_t) PHP_SHA384Init, (php_hash_update_func_t) PHP_SHA384Update, (php_hash_final_func_t) PHP_SHA384Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_SHA384_SPEC, 48, 128, sizeof(PHP_SHA384_CTX), @@ -751,10 +767,14 @@ PHP_HASH_API void PHP_SHA512_224Final(unsigned char digest[28], PHP_SHA512_CTX * /* }}} */ const php_hash_ops php_hash_sha512_ops = { + "sha512", (php_hash_init_func_t) PHP_SHA512Init, (php_hash_update_func_t) PHP_SHA512Update, (php_hash_final_func_t) PHP_SHA512Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_SHA512_SPEC, 64, 128, sizeof(PHP_SHA512_CTX), @@ -762,10 +782,14 @@ const php_hash_ops php_hash_sha512_ops = { }; const php_hash_ops php_hash_sha512_256_ops = { + "sha512/256", (php_hash_init_func_t) PHP_SHA512_256Init, (php_hash_update_func_t) PHP_SHA512_256Update, (php_hash_final_func_t) PHP_SHA512_256Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_SHA512_SPEC, 32, 128, sizeof(PHP_SHA512_CTX), @@ -773,10 +797,14 @@ const php_hash_ops php_hash_sha512_256_ops = { }; const php_hash_ops php_hash_sha512_224_ops = { + "sha512/224", (php_hash_init_func_t) PHP_SHA512_224Init, (php_hash_update_func_t) PHP_SHA512_224Update, (php_hash_final_func_t) PHP_SHA512_224Final, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_hash_unserialize, + PHP_SHA512_SPEC, 28, 128, sizeof(PHP_SHA512_CTX), diff --git a/ext/hash/hash_sha3.c b/ext/hash/hash_sha3.c index 32621514a8..52bd495f9d 100644 --- a/ext/hash/hash_sha3.c +++ b/ext/hash/hash_sha3.c @@ -201,6 +201,22 @@ static void PHP_SHA3_Final(unsigned char* digest, ZEND_SECURE_ZERO(ctx, sizeof(PHP_SHA3_CTX)); } +static int php_sha3_unserialize(php_hashcontext_object *hash, + zend_long magic, + const zval *zv, + size_t block_size) +{ + PHP_SHA3_CTX *ctx = (PHP_SHA3_CTX *) hash->context; + int r = FAILURE; + if (magic == PHP_HASH_SERIALIZE_MAGIC_SPEC + && (r = php_hash_unserialize_spec(hash, zv, PHP_SHA3_SPEC)) == SUCCESS + && ctx->pos < block_size) { + return SUCCESS; + } else { + return r != SUCCESS ? r : -2000; + } +} + // ========================================================================== #define DECLARE_SHA3_OPS(bits) \ @@ -219,11 +235,20 @@ void PHP_SHA3##bits##Final(unsigned char* digest, \ (1600 - (2 * bits)) >> 3, \ bits >> 3); \ } \ +static int php_sha3##bits##_unserialize(php_hashcontext_object *hash, \ + zend_long magic, \ + const zval *zv) { \ + return php_sha3_unserialize(hash, magic, zv, (1600 - (2 * bits)) >> 3); \ +} \ const php_hash_ops php_hash_sha3_##bits##_ops = { \ + "sha3-" #bits, \ (php_hash_init_func_t) PHP_SHA3##bits##Init, \ (php_hash_update_func_t) PHP_SHA3##bits##Update, \ (php_hash_final_func_t) PHP_SHA3##bits##Final, \ php_hash_copy, \ + php_hash_serialize, \ + php_sha3##bits##_unserialize, \ + PHP_SHA3_SPEC, \ bits >> 3, \ (1600 - (2 * bits)) >> 3, \ sizeof(PHP_SHA3_##bits##_CTX), \ @@ -237,6 +262,55 @@ const php_hash_ops php_hash_sha3_##bits##_ops = { \ #define SUCCESS SHA3_SUCCESS /* Avoid conflict between KeccacHash.h and zend_types.h */ #include "KeccakHash.h" +/* KECCAK SERIALIZATION + + Keccak_HashInstance consists of: + KeccakWidth1600_SpongeInstance { + unsigned char state[200]; + unsigned int rate; -- fixed for digest size + unsigned int byteIOIndex; -- in range [0, rate/8) + int squeezing; -- 0 normally, 1 only during finalize + } sponge; + unsigned int fixedOutputLength; -- fixed for digest size + unsigned char delimitedSuffix; -- fixed for digest size + + NB If the external sha3/ library is updated, the serialization code + may need to be updated. + + The simpler SHA3 code's serialization states are not interchangeable with + Keccak. Furthermore, the Keccak sponge state is sensitive to architecture + -- 32-bit and 64-bit implementations produce different states. It does not + appear that the state is sensitive to endianness. */ + +#if Keccak_HashInstance_ImplType == 64 +/* corresponds to sha3/generic64lc */ +# define PHP_HASH_SERIALIZE_MAGIC_KECCAK 100 +#elif Keccak_HashInstance_ImplType == 32 +/* corresponds to sha3/generic32lc */ +# define PHP_HASH_SERIALIZE_MAGIC_KECCAK 101 +#else +# error "Unknown Keccak_HashInstance_ImplType" +#endif +#define PHP_KECCAK_SPEC "b200IiIIB" + +static int php_keccak_serialize(const php_hashcontext_object *hash, zend_long *magic, zval *zv) +{ + *magic = PHP_HASH_SERIALIZE_MAGIC_KECCAK; + return php_hash_serialize_spec(hash, zv, PHP_KECCAK_SPEC); +} + +static int php_keccak_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) +{ + Keccak_HashInstance *ctx = (Keccak_HashInstance *) hash->context; + int r = FAILURE; + if (magic == PHP_HASH_SERIALIZE_MAGIC_KECCAK + && (r = php_hash_unserialize_spec(hash, zv, PHP_KECCAK_SPEC)) == SUCCESS + && ctx->sponge.byteIOIndex < ctx->sponge.rate / 8) { + return SUCCESS; + } else { + return r != SUCCESS ? r : -2000; + } +} // ========================================================================== @@ -255,10 +329,14 @@ void PHP_SHA3##bits##Final(unsigned char* digest, \ Keccak_HashFinal((Keccak_HashInstance *)ctx, digest); \ } \ const php_hash_ops php_hash_sha3_##bits##_ops = { \ + "sha3-" #bits, \ (php_hash_init_func_t) PHP_SHA3##bits##Init, \ (php_hash_update_func_t) PHP_SHA3##bits##Update, \ (php_hash_final_func_t) PHP_SHA3##bits##Final, \ php_hash_copy, \ + php_keccak_serialize, \ + php_keccak_unserialize, \ + PHP_KECCAK_SPEC, \ bits >> 3, \ (1600 - (2 * bits)) >> 3, \ sizeof(PHP_SHA3_CTX), \ diff --git a/ext/hash/hash_snefru.c b/ext/hash/hash_snefru.c index fae767f2fe..292bfef2cb 100644 --- a/ext/hash/hash_snefru.c +++ b/ext/hash/hash_snefru.c @@ -189,11 +189,28 @@ PHP_HASH_API void PHP_SNEFRUFinal(unsigned char digest[32], PHP_SNEFRU_CTX *cont ZEND_SECURE_ZERO(context, sizeof(*context)); } +static int php_snefru_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) +{ + PHP_SNEFRU_CTX *ctx = (PHP_SNEFRU_CTX *) hash->context; + int r = FAILURE; + if (magic == PHP_HASH_SERIALIZE_MAGIC_SPEC + && (r = php_hash_unserialize_spec(hash, zv, PHP_SNEFRU_SPEC)) == SUCCESS + && ctx->length < sizeof(ctx->buffer)) { + return SUCCESS; + } else { + return r != SUCCESS ? r : -2000; + } +} + const php_hash_ops php_hash_snefru_ops = { + "snefru", (php_hash_init_func_t) PHP_SNEFRUInit, (php_hash_update_func_t) PHP_SNEFRUUpdate, (php_hash_final_func_t) PHP_SNEFRUFinal, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_snefru_unserialize, + PHP_SNEFRU_SPEC, 32, 32, sizeof(PHP_SNEFRU_CTX), diff --git a/ext/hash/hash_tiger.c b/ext/hash/hash_tiger.c index 399e95af0e..8e0f365dc4 100644 --- a/ext/hash/hash_tiger.c +++ b/ext/hash/hash_tiger.c @@ -239,12 +239,29 @@ PHP_HASH_API void PHP_TIGER192Final(unsigned char digest[24], PHP_TIGER_CTX *con ZEND_SECURE_ZERO(context, sizeof(*context)); } +static int php_tiger_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) +{ + PHP_TIGER_CTX *ctx = (PHP_TIGER_CTX *) hash->context; + int r = FAILURE; + if (magic == PHP_HASH_SERIALIZE_MAGIC_SPEC + && (r = php_hash_unserialize_spec(hash, zv, PHP_TIGER_SPEC)) == SUCCESS + && ctx->length < sizeof(ctx->buffer)) { + return SUCCESS; + } else { + return r != SUCCESS ? r : -2000; + } +} + #define PHP_HASH_TIGER_OPS(p, b) \ const php_hash_ops php_hash_##p##tiger##b##_ops = { \ + "tiger" #b "," #p, \ (php_hash_init_func_t) PHP_##p##TIGERInit, \ (php_hash_update_func_t) PHP_TIGERUpdate, \ (php_hash_final_func_t) PHP_TIGER##b##Final, \ - (php_hash_copy_func_t) php_hash_copy, \ + php_hash_copy, \ + php_hash_serialize, \ + php_tiger_unserialize, \ + PHP_TIGER_SPEC, \ b/8, \ 64, \ sizeof(PHP_TIGER_CTX), \ diff --git a/ext/hash/hash_whirlpool.c b/ext/hash/hash_whirlpool.c index 5be7f80eea..8d5cbb7737 100644 --- a/ext/hash/hash_whirlpool.c +++ b/ext/hash/hash_whirlpool.c @@ -429,11 +429,31 @@ PHP_HASH_API void PHP_WHIRLPOOLFinal(unsigned char digest[64], PHP_WHIRLPOOL_CTX ZEND_SECURE_ZERO(context, sizeof(*context)); } +static int php_whirlpool_unserialize(php_hashcontext_object *hash, zend_long magic, const zval *zv) +{ + PHP_WHIRLPOOL_CTX *ctx = (PHP_WHIRLPOOL_CTX *) hash->context; + int r = FAILURE; + if (magic == PHP_HASH_SERIALIZE_MAGIC_SPEC + && (r = php_hash_unserialize_spec(hash, zv, PHP_WHIRLPOOL_SPEC)) == SUCCESS + && ctx->buffer.pos >= 0 + && ctx->buffer.pos < (int) sizeof(ctx->buffer.data) + && ctx->buffer.bits >= ctx->buffer.pos * 8 + && ctx->buffer.bits < ctx->buffer.pos * 8 + 8) { + return SUCCESS; + } else { + return r != SUCCESS ? r : -2000; + } +} + const php_hash_ops php_hash_whirlpool_ops = { + "whirlpool", (php_hash_init_func_t) PHP_WHIRLPOOLInit, (php_hash_update_func_t) PHP_WHIRLPOOLUpdate, (php_hash_final_func_t) PHP_WHIRLPOOLFinal, - (php_hash_copy_func_t) php_hash_copy, + php_hash_copy, + php_hash_serialize, + php_whirlpool_unserialize, + PHP_WHIRLPOOL_SPEC, 64, 64, sizeof(PHP_WHIRLPOOL_CTX), diff --git a/ext/hash/php_hash.h b/ext/hash/php_hash.h index 79bbc066d6..33cc6a473a 100644 --- a/ext/hash/php_hash.h +++ b/ext/hash/php_hash.h @@ -25,18 +25,28 @@ #define PHP_HASH_HMAC 0x0001 +#define PHP_HASH_SERIALIZE_MAGIC_SPEC 2 + #define L64 INT64_C +typedef struct _php_hashcontext_object php_hashcontext_object; + typedef void (*php_hash_init_func_t)(void *context); typedef void (*php_hash_update_func_t)(void *context, const unsigned char *buf, size_t count); typedef void (*php_hash_final_func_t)(unsigned char *digest, void *context); typedef int (*php_hash_copy_func_t)(const void *ops, void *orig_context, void *dest_context); +typedef int (*php_hash_serialize_func_t)(const php_hashcontext_object *hash, zend_long *magic, zval *zv); +typedef int (*php_hash_unserialize_func_t)(php_hashcontext_object *hash, zend_long magic, const zval *zv); typedef struct _php_hash_ops { + const char *algo; php_hash_init_func_t hash_init; php_hash_update_func_t hash_update; php_hash_final_func_t hash_final; php_hash_copy_func_t hash_copy; + php_hash_serialize_func_t hash_serialize; + php_hash_unserialize_func_t hash_unserialize; + const char *serialize_spec; size_t digest_size; size_t block_size; @@ -44,7 +54,7 @@ typedef struct _php_hash_ops { unsigned is_crypto: 1; } php_hash_ops; -typedef struct _php_hashcontext_object { +struct _php_hashcontext_object { const php_hash_ops *ops; void *context; @@ -52,7 +62,7 @@ typedef struct _php_hashcontext_object { unsigned char *key; zend_object std; -} php_hashcontext_object; +}; static inline php_hashcontext_object *php_hashcontext_from_object(zend_object *obj) { return ((php_hashcontext_object*)(obj + 1)) - 1; @@ -131,6 +141,15 @@ extern PHP_HASH_API zend_class_entry *php_hashcontext_ce; PHP_HASH_API const php_hash_ops *php_hash_fetch_ops(zend_string *algo); PHP_HASH_API void php_hash_register_algo(const char *algo, const php_hash_ops *ops); PHP_HASH_API int php_hash_copy(const void *ops, void *orig_context, void *dest_context); +PHP_HASH_API int php_hash_serialize(const php_hashcontext_object *context, zend_long *magic, zval *zv); +PHP_HASH_API int php_hash_unserialize(php_hashcontext_object *context, zend_long magic, const zval *zv); +PHP_HASH_API int php_hash_serialize_spec(const php_hashcontext_object *context, zval *zv, const char *spec); +PHP_HASH_API int php_hash_unserialize_spec(php_hashcontext_object *hash, const zval *zv, const char *spec); + +static inline void *php_hash_alloc_context(const php_hash_ops *ops) { + /* Zero out context memory so serialization doesn't expose internals */ + return ecalloc(1, ops->context_size); +} static inline void php_hash_bin2hex(char *out, const unsigned char *in, size_t in_len) { diff --git a/ext/hash/php_hash_adler32.h b/ext/hash/php_hash_adler32.h index 184091c971..049f16b28e 100644 --- a/ext/hash/php_hash_adler32.h +++ b/ext/hash/php_hash_adler32.h @@ -22,6 +22,7 @@ typedef struct { uint32_t state; } PHP_ADLER32_CTX; +#define PHP_ADLER32_SPEC "l." PHP_HASH_API void PHP_ADLER32Init(PHP_ADLER32_CTX *context); PHP_HASH_API void PHP_ADLER32Update(PHP_ADLER32_CTX *context, const unsigned char *input, size_t len); diff --git a/ext/hash/php_hash_crc32.h b/ext/hash/php_hash_crc32.h index 346011e417..4c1b0fedc9 100644 --- a/ext/hash/php_hash_crc32.h +++ b/ext/hash/php_hash_crc32.h @@ -22,6 +22,7 @@ typedef struct { uint32_t state; } PHP_CRC32_CTX; +#define PHP_CRC32_SPEC "l." PHP_HASH_API void PHP_CRC32Init(PHP_CRC32_CTX *context); PHP_HASH_API void PHP_CRC32Update(PHP_CRC32_CTX *context, const unsigned char *input, size_t len); diff --git a/ext/hash/php_hash_fnv.h b/ext/hash/php_hash_fnv.h index 1cb8c78d29..6728b2e902 100644 --- a/ext/hash/php_hash_fnv.h +++ b/ext/hash/php_hash_fnv.h @@ -44,10 +44,12 @@ enum php_fnv_type { typedef struct { uint32_t state; } PHP_FNV132_CTX; +#define PHP_FNV132_SPEC "l." typedef struct { uint64_t state; } PHP_FNV164_CTX; +#define PHP_FNV164_SPEC "q." PHP_HASH_API void PHP_FNV132Init(PHP_FNV132_CTX *context); diff --git a/ext/hash/php_hash_gost.h b/ext/hash/php_hash_gost.h index 987eb655cb..eb9441faa6 100644 --- a/ext/hash/php_hash_gost.h +++ b/ext/hash/php_hash_gost.h @@ -27,6 +27,7 @@ typedef struct { unsigned char buffer[32]; const uint32_t (*tables)[4][256]; } PHP_GOST_CTX; +#define PHP_GOST_SPEC "l16l2bb32" PHP_HASH_API void PHP_GOSTInit(PHP_GOST_CTX *); PHP_HASH_API void PHP_GOSTUpdate(PHP_GOST_CTX *, const unsigned char *, size_t); diff --git a/ext/hash/php_hash_haval.h b/ext/hash/php_hash_haval.h index 8eaaf2d2b7..43802b4183 100644 --- a/ext/hash/php_hash_haval.h +++ b/ext/hash/php_hash_haval.h @@ -28,6 +28,7 @@ typedef struct { short output; void (*Transform)(uint32_t state[8], const unsigned char block[128]); } PHP_HAVAL_CTX; +#define PHP_HAVAL_SPEC "l8l2b128" #define PHP_HASH_HAVAL_INIT_DECL(p,b) PHP_HASH_API void PHP_##p##HAVAL##b##Init(PHP_HAVAL_CTX *); \ PHP_HASH_API void PHP_HAVAL##b##Final(unsigned char*, PHP_HAVAL_CTX *); diff --git a/ext/hash/php_hash_joaat.h b/ext/hash/php_hash_joaat.h index ede108f1bb..b0df8a67b3 100644 --- a/ext/hash/php_hash_joaat.h +++ b/ext/hash/php_hash_joaat.h @@ -20,6 +20,7 @@ typedef struct { uint32_t state; } PHP_JOAAT_CTX; +#define PHP_JOAAT_SPEC "l." PHP_HASH_API void PHP_JOAATInit(PHP_JOAAT_CTX *context); PHP_HASH_API void PHP_JOAATUpdate(PHP_JOAAT_CTX *context, const unsigned char *input, size_t inputLen); diff --git a/ext/hash/php_hash_md.h b/ext/hash/php_hash_md.h index aed999261e..2a677fe54d 100644 --- a/ext/hash/php_hash_md.h +++ b/ext/hash/php_hash_md.h @@ -26,6 +26,7 @@ typedef struct { uint32_t count[2]; unsigned char buffer[64]; } PHP_MD4_CTX; +#define PHP_MD4_SPEC "l4l2b64." PHP_HASH_API void PHP_MD4Init(PHP_MD4_CTX *); PHP_HASH_API void PHP_MD4Update(PHP_MD4_CTX *context, const unsigned char *, size_t); @@ -36,8 +37,9 @@ typedef struct { unsigned char state[48]; unsigned char checksum[16]; unsigned char buffer[16]; - char in_buffer; + unsigned char in_buffer; } PHP_MD2_CTX; +#define PHP_MD2_SPEC "b48b16b16b." PHP_HASH_API void PHP_MD2Init(PHP_MD2_CTX *context); PHP_HASH_API void PHP_MD2Update(PHP_MD2_CTX *context, const unsigned char *, size_t); diff --git a/ext/hash/php_hash_ripemd.h b/ext/hash/php_hash_ripemd.h index 131dd0ad8f..dd9913b85b 100644 --- a/ext/hash/php_hash_ripemd.h +++ b/ext/hash/php_hash_ripemd.h @@ -24,24 +24,28 @@ typedef struct { uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } PHP_RIPEMD128_CTX; +#define PHP_RIPEMD128_SPEC "l4l2b64." typedef struct { uint32_t state[5]; /* state (ABCD) */ uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } PHP_RIPEMD160_CTX; +#define PHP_RIPEMD160_SPEC "l5l2b64." typedef struct { uint32_t state[8]; /* state (ABCD) */ uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } PHP_RIPEMD256_CTX; +#define PHP_RIPEMD256_SPEC "l8l2b64." typedef struct { uint32_t state[10]; /* state (ABCD) */ uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } PHP_RIPEMD320_CTX; +#define PHP_RIPEMD320_SPEC "l10l2b64." PHP_HASH_API void PHP_RIPEMD128Init(PHP_RIPEMD128_CTX *); PHP_HASH_API void PHP_RIPEMD128Update(PHP_RIPEMD128_CTX *, const unsigned char *, size_t); diff --git a/ext/hash/php_hash_sha.h b/ext/hash/php_hash_sha.h index 95471e7398..16da927363 100644 --- a/ext/hash/php_hash_sha.h +++ b/ext/hash/php_hash_sha.h @@ -27,6 +27,7 @@ typedef struct { uint32_t count[2]; /* number of bits, modulo 2^64 */ unsigned char buffer[64]; /* input buffer */ } PHP_SHA224_CTX; +#define PHP_SHA224_SPEC "l8l2b64." PHP_HASH_API void PHP_SHA224Init(PHP_SHA224_CTX *); PHP_HASH_API void PHP_SHA224Update(PHP_SHA224_CTX *, const unsigned char *, size_t); @@ -38,6 +39,7 @@ typedef struct { uint32_t count[2]; /* number of bits, modulo 2^64 */ unsigned char buffer[64]; /* input buffer */ } PHP_SHA256_CTX; +#define PHP_SHA256_SPEC "l8l2b64." PHP_HASH_API void PHP_SHA256Init(PHP_SHA256_CTX *); PHP_HASH_API void PHP_SHA256Update(PHP_SHA256_CTX *, const unsigned char *, size_t); @@ -49,6 +51,7 @@ typedef struct { uint64_t count[2]; /* number of bits, modulo 2^128 */ unsigned char buffer[128]; /* input buffer */ } PHP_SHA384_CTX; +#define PHP_SHA384_SPEC "q8q2b128." PHP_HASH_API void PHP_SHA384Init(PHP_SHA384_CTX *); PHP_HASH_API void PHP_SHA384Update(PHP_SHA384_CTX *, const unsigned char *, size_t); @@ -60,6 +63,7 @@ typedef struct { uint64_t count[2]; /* number of bits, modulo 2^128 */ unsigned char buffer[128]; /* input buffer */ } PHP_SHA512_CTX; +#define PHP_SHA512_SPEC "q8q2b128." PHP_HASH_API void PHP_SHA512Init(PHP_SHA512_CTX *); PHP_HASH_API void PHP_SHA512Update(PHP_SHA512_CTX *, const unsigned char *, size_t); diff --git a/ext/hash/php_hash_sha3.h b/ext/hash/php_hash_sha3.h index bb392c0ab0..f75191f339 100644 --- a/ext/hash/php_hash_sha3.h +++ b/ext/hash/php_hash_sha3.h @@ -27,6 +27,9 @@ typedef struct { unsigned char state[224]; // this must fit a Keccak_HashInstance #endif } PHP_SHA3_CTX; +#ifdef HAVE_SLOW_HASH3 +#define PHP_SHA3_SPEC "b200l." +#endif typedef PHP_SHA3_CTX PHP_SHA3_224_CTX; typedef PHP_SHA3_CTX PHP_SHA3_256_CTX; diff --git a/ext/hash/php_hash_snefru.h b/ext/hash/php_hash_snefru.h index 25ba1183e3..0f339e9309 100644 --- a/ext/hash/php_hash_snefru.h +++ b/ext/hash/php_hash_snefru.h @@ -30,6 +30,7 @@ typedef struct { unsigned char length; unsigned char buffer[32]; } PHP_SNEFRU_CTX; +#define PHP_SNEFRU_SPEC "l16l2bb32" PHP_HASH_API void PHP_SNEFRUInit(PHP_SNEFRU_CTX *); PHP_HASH_API void PHP_SNEFRUUpdate(PHP_SNEFRU_CTX *, const unsigned char *, size_t); diff --git a/ext/hash/php_hash_tiger.h b/ext/hash/php_hash_tiger.h index 4476639040..d30276ddea 100644 --- a/ext/hash/php_hash_tiger.h +++ b/ext/hash/php_hash_tiger.h @@ -22,9 +22,10 @@ typedef struct { uint64_t state[3]; uint64_t passed; unsigned char buffer[64]; + uint32_t length; unsigned int passes:1; - size_t length; } PHP_TIGER_CTX; +#define PHP_TIGER_SPEC "q3qb64l" PHP_HASH_API void PHP_3TIGERInit(PHP_TIGER_CTX *context); PHP_HASH_API void PHP_4TIGERInit(PHP_TIGER_CTX *context); diff --git a/ext/hash/php_hash_whirlpool.h b/ext/hash/php_hash_whirlpool.h index f96da414a5..fbd5948a48 100644 --- a/ext/hash/php_hash_whirlpool.h +++ b/ext/hash/php_hash_whirlpool.h @@ -27,6 +27,7 @@ typedef struct { unsigned char data[64]; } buffer; } PHP_WHIRLPOOL_CTX; +#define PHP_WHIRLPOOL_SPEC "q8b32iib64." PHP_HASH_API void PHP_WHIRLPOOLInit(PHP_WHIRLPOOL_CTX *); PHP_HASH_API void PHP_WHIRLPOOLUpdate(PHP_WHIRLPOOL_CTX *, const unsigned char *, size_t); diff --git a/ext/hash/sha3/generic32lc/KeccakHash.h b/ext/hash/sha3/generic32lc/KeccakHash.h index ec35d3dab2..d53ac1c587 100644 --- a/ext/hash/sha3/generic32lc/KeccakHash.h +++ b/ext/hash/sha3/generic32lc/KeccakHash.h @@ -108,6 +108,8 @@ HashReturn Keccak_HashFinal(Keccak_HashInstance *hashInstance, BitSequence *hash */ HashReturn Keccak_HashSqueeze(Keccak_HashInstance *hashInstance, BitSequence *data, DataLength databitlen); +#define Keccak_HashInstance_ImplType 32 + #endif #endif diff --git a/ext/hash/sha3/generic64lc/KeccakHash.h b/ext/hash/sha3/generic64lc/KeccakHash.h index ec35d3dab2..6afe6c8c9a 100644 --- a/ext/hash/sha3/generic64lc/KeccakHash.h +++ b/ext/hash/sha3/generic64lc/KeccakHash.h @@ -108,6 +108,8 @@ HashReturn Keccak_HashFinal(Keccak_HashInstance *hashInstance, BitSequence *hash */ HashReturn Keccak_HashSqueeze(Keccak_HashInstance *hashInstance, BitSequence *data, DataLength databitlen); +#define Keccak_HashInstance_ImplType 64 + #endif #endif diff --git a/ext/hash/tests/hash_serialize_001.phpt b/ext/hash/tests/hash_serialize_001.phpt new file mode 100644 index 0000000000..d515d2c5c5 --- /dev/null +++ b/ext/hash/tests/hash_serialize_001.phpt @@ -0,0 +1,361 @@ +--TEST-- +Hash: serialize()/unserialize() +--FILE-- + +--EXPECT-- +string(3) "md2" +string(32) "d5ac4ffd08f6a57b9bd402b8068392ff" +string(32) "d5ac4ffd08f6a57b9bd402b8068392ff" +string(3) "md4" +string(32) "302c45586b53a984bd3a1237cb81c15f" +string(32) "302c45586b53a984bd3a1237cb81c15f" +string(3) "md5" +string(32) "e35759f6ea35db254e415b5332269435" +string(32) "e35759f6ea35db254e415b5332269435" +string(4) "sha1" +string(40) "29f62a228f726cd728efa7a0ac6a2aba318baf15" +string(40) "29f62a228f726cd728efa7a0ac6a2aba318baf15" +string(6) "sha224" +string(56) "51fd0aa76a00b4a86103895cad5c7c2651ec7da9f4fc1e50c43ede29" +string(56) "51fd0aa76a00b4a86103895cad5c7c2651ec7da9f4fc1e50c43ede29" +string(6) "sha256" +string(64) "d3a13cf52af8e9390caed78b77b6b1e06e102204e3555d111dfd149bc5d54dba" +string(64) "d3a13cf52af8e9390caed78b77b6b1e06e102204e3555d111dfd149bc5d54dba" +string(6) "sha384" +string(96) "6950d861ace4102b803ab8b3779d2f471968233010d2608974ab89804cef6f76162b4433d6e554e11e40a7cdcf510ea3" +string(96) "6950d861ace4102b803ab8b3779d2f471968233010d2608974ab89804cef6f76162b4433d6e554e11e40a7cdcf510ea3" +string(10) "sha512/224" +string(56) "a2573d0e3f6c3e2d174c935a35a8ea31032f04e9e83499ac3ceda568" +string(56) "a2573d0e3f6c3e2d174c935a35a8ea31032f04e9e83499ac3ceda568" +string(10) "sha512/256" +string(64) "fddacab80b3a610ba024c9d75a5fe0cafe5ae7c789f829b3c5fbea8ef11ccc1a" +string(64) "fddacab80b3a610ba024c9d75a5fe0cafe5ae7c789f829b3c5fbea8ef11ccc1a" +string(6) "sha512" +string(128) "caced3db8e9e3a5543d5b933bcbe9e7834e6667545c3f5d4087b58ec8d78b4c8a4a5500c9b88f65f7368810ba9905e51f1cff3b25a5dccf76634108fb4e7ce13" +string(128) "caced3db8e9e3a5543d5b933bcbe9e7834e6667545c3f5d4087b58ec8d78b4c8a4a5500c9b88f65f7368810ba9905e51f1cff3b25a5dccf76634108fb4e7ce13" +string(8) "sha3-224" +string(56) "7e1126cffee98e5c4b0e9dd5c6efabd5c9356d668e9a2d3cfab724d4" +string(56) "7e1126cffee98e5c4b0e9dd5c6efabd5c9356d668e9a2d3cfab724d4" +string(8) "sha3-256" +string(64) "834abfed9197af09cbe66b7748c65a050a3755ef7a556d6764eb6eabc93b4c7a" +string(64) "834abfed9197af09cbe66b7748c65a050a3755ef7a556d6764eb6eabc93b4c7a" +string(8) "sha3-384" +string(96) "c9016992586f7a8663c5379ed892349c1140ad258f7c44ee82f61f0b8cb75c675012ea94dc1314e06699be2d1465f67b" +string(96) "c9016992586f7a8663c5379ed892349c1140ad258f7c44ee82f61f0b8cb75c675012ea94dc1314e06699be2d1465f67b" +string(8) "sha3-512" +string(128) "5f85341bc9c6621406bf1841c4ce01727ea8759fdf2927106c3e70a75ad9fffd095b87f995aeee844e1a2c287e1195ce809b9bdb1c31258f7fc098175b6de0b4" +string(128) "5f85341bc9c6621406bf1841c4ce01727ea8759fdf2927106c3e70a75ad9fffd095b87f995aeee844e1a2c287e1195ce809b9bdb1c31258f7fc098175b6de0b4" +string(9) "ripemd128" +string(32) "5f1bc5f5aeaf747574dd34a6535cd94a" +string(32) "5f1bc5f5aeaf747574dd34a6535cd94a" +string(9) "ripemd160" +string(40) "02a2a535ee10404c6b5cf9acb178a04fbed67269" +string(40) "02a2a535ee10404c6b5cf9acb178a04fbed67269" +string(9) "ripemd256" +string(64) "547d2ed85ca0a0e3208b5ecf4fc6a7fc1e64db8ff13493e4beaf11e4d71648e2" +string(64) "547d2ed85ca0a0e3208b5ecf4fc6a7fc1e64db8ff13493e4beaf11e4d71648e2" +string(9) "ripemd320" +string(80) "785a7df56858f550966cddfd59ce14b13bf4b18e7892c4c1ad91bf23bf67639bd2c96749ba29cfa6" +string(80) "785a7df56858f550966cddfd59ce14b13bf4b18e7892c4c1ad91bf23bf67639bd2c96749ba29cfa6" +string(9) "whirlpool" +string(128) "6e60597340640e621e25f975cef2b000b0c4c09a7af7d240a52d193002b0a8426fa7da7acc5b37ed9608016d4f396db834a0ea2f2c35f900461c9ac7e5604082" +string(128) "6e60597340640e621e25f975cef2b000b0c4c09a7af7d240a52d193002b0a8426fa7da7acc5b37ed9608016d4f396db834a0ea2f2c35f900461c9ac7e5604082" +string(10) "tiger128,3" +string(32) "8d68e78bc5e62ba925a67aa48595cfc6" +string(32) "8d68e78bc5e62ba925a67aa48595cfc6" +string(10) "tiger160,3" +string(40) "8d68e78bc5e62ba925a67aa48595cfc62cd1e5e0" +string(40) "8d68e78bc5e62ba925a67aa48595cfc62cd1e5e0" +string(10) "tiger192,3" +string(48) "8d68e78bc5e62ba925a67aa48595cfc62cd1e5e08224fc35" +string(48) "8d68e78bc5e62ba925a67aa48595cfc62cd1e5e08224fc35" +string(10) "tiger128,4" +string(32) "a26ca3f58e74fb32ee44b099cb1b5122" +string(32) "a26ca3f58e74fb32ee44b099cb1b5122" +string(10) "tiger160,4" +string(40) "a26ca3f58e74fb32ee44b099cb1b512203375900" +string(40) "a26ca3f58e74fb32ee44b099cb1b512203375900" +string(10) "tiger192,4" +string(48) "a26ca3f58e74fb32ee44b099cb1b512203375900f30b741d" +string(48) "a26ca3f58e74fb32ee44b099cb1b512203375900f30b741d" +string(6) "snefru" +string(64) "fbe88daa74c89b9e29468fa3cd3a657d31845e21bb58dd3f8d806f5179a85c26" +string(64) "fbe88daa74c89b9e29468fa3cd3a657d31845e21bb58dd3f8d806f5179a85c26" +string(9) "snefru256" +string(64) "fbe88daa74c89b9e29468fa3cd3a657d31845e21bb58dd3f8d806f5179a85c26" +string(64) "fbe88daa74c89b9e29468fa3cd3a657d31845e21bb58dd3f8d806f5179a85c26" +string(4) "gost" +string(64) "5820c7c4a0650587538b30ef4099f2b5993069758d5c847a552e6ef7360766a5" +string(64) "5820c7c4a0650587538b30ef4099f2b5993069758d5c847a552e6ef7360766a5" +string(11) "gost-crypto" +string(64) "f7c4e35548d66aabe2b106f20515d289fde90969225d3d7b83f6dd12d694f043" +string(64) "f7c4e35548d66aabe2b106f20515d289fde90969225d3d7b83f6dd12d694f043" +string(7) "adler32" +string(8) "6f7c0928" +string(8) "6f7c0928" +string(5) "crc32" +string(8) "e5cfc160" +string(8) "e5cfc160" +string(6) "crc32b" +string(8) "69147a4e" +string(8) "69147a4e" +string(6) "crc32c" +string(8) "5e405e93" +string(8) "5e405e93" +string(6) "fnv132" +string(8) "98139504" +string(8) "98139504" +string(7) "fnv1a32" +string(8) "aae4e042" +string(8) "aae4e042" +string(6) "fnv164" +string(16) "14522659f8138684" +string(16) "14522659f8138684" +string(7) "fnv1a64" +string(16) "bebc746a33b6ab62" +string(16) "bebc746a33b6ab62" +string(5) "joaat" +string(8) "aaebf370" +string(8) "aaebf370" +string(10) "haval128,3" +string(32) "86362472c8895e68e223ef8b3711d8d9" +string(32) "86362472c8895e68e223ef8b3711d8d9" +string(10) "haval160,3" +string(40) "fabdf6905f3ba18a3c93d6a16b91e31f7222a7a4" +string(40) "fabdf6905f3ba18a3c93d6a16b91e31f7222a7a4" +string(10) "haval192,3" +string(48) "e05d0ff5723028bd5494f32c0c2494cd0b9ccf7540af7b47" +string(48) "e05d0ff5723028bd5494f32c0c2494cd0b9ccf7540af7b47" +string(10) "haval224,3" +string(56) "56b196289d8de8a22296588cf90e5b09cb6fa1b01ce8e92bca40cae2" +string(56) "56b196289d8de8a22296588cf90e5b09cb6fa1b01ce8e92bca40cae2" +string(10) "haval256,3" +string(64) "ff4d7ab0fac2ca437b945461f9b62fd16e71e9103524d5d140445a00e3d49239" +string(64) "ff4d7ab0fac2ca437b945461f9b62fd16e71e9103524d5d140445a00e3d49239" +string(10) "haval128,4" +string(32) "ee44418e0195a0c4a35d112722919a9c" +string(32) "ee44418e0195a0c4a35d112722919a9c" +string(10) "haval160,4" +string(40) "f320cce982d5201a1ccacc1c5ff835a258a97eb1" +string(40) "f320cce982d5201a1ccacc1c5ff835a258a97eb1" +string(10) "haval192,4" +string(48) "a96600107463e8e97a7fe6f260d9bf4f4587a281caafa6db" +string(48) "a96600107463e8e97a7fe6f260d9bf4f4587a281caafa6db" +string(10) "haval224,4" +string(56) "7147c9e1c1e67b942da3229f59a1ab18f121f5d7f5765ca88bc9f200" +string(56) "7147c9e1c1e67b942da3229f59a1ab18f121f5d7f5765ca88bc9f200" +string(10) "haval256,4" +string(64) "82fec42679ed5a77a841962827b88a9cddf7d677736e50bc81f1a14b99f06061" +string(64) "82fec42679ed5a77a841962827b88a9cddf7d677736e50bc81f1a14b99f06061" +string(10) "haval128,5" +string(32) "8d0b157828328ae7d34d60b4b60c1dab" +string(32) "8d0b157828328ae7d34d60b4b60c1dab" +string(10) "haval160,5" +string(40) "54dab5e10dc41503f9b8aa32ffe3bab7cf1da8a3" +string(40) "54dab5e10dc41503f9b8aa32ffe3bab7cf1da8a3" +string(10) "haval192,5" +string(48) "7d91265a1b27698279d8d95a5ee0a20014528070bf6415e7" +string(48) "7d91265a1b27698279d8d95a5ee0a20014528070bf6415e7" +string(10) "haval224,5" +string(56) "7772b2e22f2a3bce917e08cf57ebece46bb33168619a776c6f2f7234" +string(56) "7772b2e22f2a3bce917e08cf57ebece46bb33168619a776c6f2f7234" +string(10) "haval256,5" +string(64) "438a602cb1a761f7bd0a633b7bd8b3ccd0577b524d05174ca1ae1f559b9a2c2a" +string(64) "438a602cb1a761f7bd0a633b7bd8b3ccd0577b524d05174ca1ae1f559b9a2c2a" +string(3) "md2" +string(32) "5c36f61062d091a8324991132c5e8dbd" +string(32) "5c36f61062d091a8324991132c5e8dbd" +string(3) "md4" +string(32) "1d4196526aada3506efb4c7425651584" +string(32) "1d4196526aada3506efb4c7425651584" +string(3) "md5" +string(32) "f255c114bd6ce94aad092b5141c00d46" +string(32) "f255c114bd6ce94aad092b5141c00d46" +string(4) "sha1" +string(40) "a273396f056554dcd491b5dea1e7baa3b89b802b" +string(40) "a273396f056554dcd491b5dea1e7baa3b89b802b" +string(6) "sha224" +string(56) "1aee028400c56ceb5539625dc2f395abf491409336ca0f3e177a50e2" +string(56) "1aee028400c56ceb5539625dc2f395abf491409336ca0f3e177a50e2" +string(6) "sha256" +string(64) "268e7f4cf88504a53fd77136c4c4748169f46ff7150b376569ada9c374836944" +string(64) "268e7f4cf88504a53fd77136c4c4748169f46ff7150b376569ada9c374836944" +string(6) "sha384" +string(96) "0d44981d04bb11b1ef75d5c2932bd0aa2785e7bc454daac954d77e2ca10047879b58997533fc99650b20049c6cb9a6cc" +string(96) "0d44981d04bb11b1ef75d5c2932bd0aa2785e7bc454daac954d77e2ca10047879b58997533fc99650b20049c6cb9a6cc" +string(10) "sha512/224" +string(56) "cbc2bbf0028ed803af785b0f264962c84ec48d8ee0908322ef995ddb" +string(56) "cbc2bbf0028ed803af785b0f264962c84ec48d8ee0908322ef995ddb" +string(10) "sha512/256" +string(64) "2cec704878ffa7128e0c4a61eef87d1f3c823184d364dfa3fed73beb00499b00" +string(64) "2cec704878ffa7128e0c4a61eef87d1f3c823184d364dfa3fed73beb00499b00" +string(6) "sha512" +string(128) "28d7c721433782a880f840af0c3f3ea2cad4ef55de2114dda9d504cedeb110e1cf2519c49e4b5da3da4484bb6ba4fd1621ceadc6408f4410b2ebe9d83a4202c2" +string(128) "28d7c721433782a880f840af0c3f3ea2cad4ef55de2114dda9d504cedeb110e1cf2519c49e4b5da3da4484bb6ba4fd1621ceadc6408f4410b2ebe9d83a4202c2" +string(8) "sha3-224" +string(56) "9a21a5464794c2c9784df50cf89cf72234e11941bddaee93f912753e" +string(56) "9a21a5464794c2c9784df50cf89cf72234e11941bddaee93f912753e" +string(8) "sha3-256" +string(64) "57aa7a90f29b5ab66592760592780da247fd39b4c911773687450f9df8cc8ed0" +string(64) "57aa7a90f29b5ab66592760592780da247fd39b4c911773687450f9df8cc8ed0" +string(8) "sha3-384" +string(96) "5d6d7e42b241288bc707b74c50f90a37d69a4afa854ca72021a22cb379356e53b6233aea1be2f33d393d6effa9b5e36c" +string(96) "5d6d7e42b241288bc707b74c50f90a37d69a4afa854ca72021a22cb379356e53b6233aea1be2f33d393d6effa9b5e36c" +string(8) "sha3-512" +string(128) "9b88c689bc13a36e6983b32e8ee9464d63b619f246ca451d1fe2a6c9670f01e71d0c8eb245f3204d27d27c056f2a0fef76a1e3bc30fb74cccbc984dbd4883ae6" +string(128) "9b88c689bc13a36e6983b32e8ee9464d63b619f246ca451d1fe2a6c9670f01e71d0c8eb245f3204d27d27c056f2a0fef76a1e3bc30fb74cccbc984dbd4883ae6" +string(9) "ripemd128" +string(32) "f95f5e22b8875ee0c48219ae97f0674b" +string(32) "f95f5e22b8875ee0c48219ae97f0674b" +string(9) "ripemd160" +string(40) "900d615c1abe714e340f4ecd6a3d65599fd30ff4" +string(40) "900d615c1abe714e340f4ecd6a3d65599fd30ff4" +string(9) "ripemd256" +string(64) "b9799db40d1af5614118c329169cdcd2c718db6af03bf945ea7f7ba72b8e14f4" +string(64) "b9799db40d1af5614118c329169cdcd2c718db6af03bf945ea7f7ba72b8e14f4" +string(9) "ripemd320" +string(80) "d6d12c1fca7a9c4a59c1be4f40188e92a746a035219e0a6ca1ee53b36a8282527187f7dffaa57ecc" +string(80) "d6d12c1fca7a9c4a59c1be4f40188e92a746a035219e0a6ca1ee53b36a8282527187f7dffaa57ecc" +string(9) "whirlpool" +string(128) "e8c6a921e7d8eac2fd21d4df6054bb27a02321b2beb5b01b6f88c40706164e64d67ec97519bf76c8af8df896745478b78d42a0159f1a0db16777771fd9d420dc" +string(128) "e8c6a921e7d8eac2fd21d4df6054bb27a02321b2beb5b01b6f88c40706164e64d67ec97519bf76c8af8df896745478b78d42a0159f1a0db16777771fd9d420dc" +string(10) "tiger128,3" +string(32) "a99d2c0348d480dc0f3c35852926e0f1" +string(32) "a99d2c0348d480dc0f3c35852926e0f1" +string(10) "tiger160,3" +string(40) "a99d2c0348d480dc0f3c35852926e0f1e1825c16" +string(40) "a99d2c0348d480dc0f3c35852926e0f1e1825c16" +string(10) "tiger192,3" +string(48) "a99d2c0348d480dc0f3c35852926e0f1e1825c1651957ee3" +string(48) "a99d2c0348d480dc0f3c35852926e0f1e1825c1651957ee3" +string(10) "tiger128,4" +string(32) "66e2c0322421c4e5a9208e6aeed481e5" +string(32) "66e2c0322421c4e5a9208e6aeed481e5" +string(10) "tiger160,4" +string(40) "66e2c0322421c4e5a9208e6aeed481e5c4b00448" +string(40) "66e2c0322421c4e5a9208e6aeed481e5c4b00448" +string(10) "tiger192,4" +string(48) "66e2c0322421c4e5a9208e6aeed481e5c4b00448e344d9d0" +string(48) "66e2c0322421c4e5a9208e6aeed481e5c4b00448e344d9d0" +string(6) "snefru" +string(64) "614ca924864fa0e8fa309aa0944e047d5edbfd4964a35858f4d8ec66a0fb88b0" +string(64) "614ca924864fa0e8fa309aa0944e047d5edbfd4964a35858f4d8ec66a0fb88b0" +string(9) "snefru256" +string(64) "614ca924864fa0e8fa309aa0944e047d5edbfd4964a35858f4d8ec66a0fb88b0" +string(64) "614ca924864fa0e8fa309aa0944e047d5edbfd4964a35858f4d8ec66a0fb88b0" +string(4) "gost" +string(64) "a00961e371287c71c527a41c14564f13b6ed12ac7cd9d5f5dfb3542a25e28d3b" +string(64) "a00961e371287c71c527a41c14564f13b6ed12ac7cd9d5f5dfb3542a25e28d3b" +string(11) "gost-crypto" +string(64) "68ca9aea6729dc07d995fbe071a4b5c6490bb27fc4dc65ec0e96200d5e082996" +string(64) "68ca9aea6729dc07d995fbe071a4b5c6490bb27fc4dc65ec0e96200d5e082996" +string(7) "adler32" +string(8) "d9141747" +string(8) "d9141747" +string(5) "crc32" +string(8) "59f8d3d2" +string(8) "59f8d3d2" +string(6) "crc32b" +string(8) "3ee63999" +string(8) "3ee63999" +string(6) "crc32c" +string(8) "516ad412" +string(8) "516ad412" +string(6) "fnv132" +string(8) "59ad036f" +string(8) "59ad036f" +string(7) "fnv1a32" +string(8) "fadc2cef" +string(8) "fadc2cef" +string(6) "fnv164" +string(16) "5e8c64fba6a5ffcf" +string(16) "5e8c64fba6a5ffcf" +string(7) "fnv1a64" +string(16) "893899e4415a920f" +string(16) "893899e4415a920f" +string(5) "joaat" +string(8) "836fb0e5" +string(8) "836fb0e5" +string(10) "haval128,3" +string(32) "ebeeeb05c18af1e53d2d127b561d5e0d" +string(32) "ebeeeb05c18af1e53d2d127b561d5e0d" +string(10) "haval160,3" +string(40) "f1a2c9604fb40899ad502abe0dfcec65115c8a9a" +string(40) "f1a2c9604fb40899ad502abe0dfcec65115c8a9a" +string(10) "haval192,3" +string(48) "d3a7315773a326678208650ed02510ed96cd488d74cd5231" +string(48) "d3a7315773a326678208650ed02510ed96cd488d74cd5231" +string(10) "haval224,3" +string(56) "6d7132fabc83c9ab7913748b79ecf10e25409569d3ed144177f46731" +string(56) "6d7132fabc83c9ab7913748b79ecf10e25409569d3ed144177f46731" +string(10) "haval256,3" +string(64) "7a469868ad4b92891a3a44524c58a2b8d0f3bebb92b4cf47d19bc6aba973eb95" +string(64) "7a469868ad4b92891a3a44524c58a2b8d0f3bebb92b4cf47d19bc6aba973eb95" +string(10) "haval128,4" +string(32) "6ecddb39615f43fd211839287ff38461" +string(32) "6ecddb39615f43fd211839287ff38461" +string(10) "haval160,4" +string(40) "bcd2e7821723ac22e122b8b7cbbd2daaa9a862df" +string(40) "bcd2e7821723ac22e122b8b7cbbd2daaa9a862df" +string(10) "haval192,4" +string(48) "ae74619a88dcec1fbecde28e27f009a65ecc12170824d2cd" +string(48) "ae74619a88dcec1fbecde28e27f009a65ecc12170824d2cd" +string(10) "haval224,4" +string(56) "fdaba6563f1334d40de24e311f14b324577f97c3b78b9439c408cdca" +string(56) "fdaba6563f1334d40de24e311f14b324577f97c3b78b9439c408cdca" +string(10) "haval256,4" +string(64) "289a2ba4820218bdb25a6534fbdf693f9de101362584fdd41e32244c719caa37" +string(64) "289a2ba4820218bdb25a6534fbdf693f9de101362584fdd41e32244c719caa37" +string(10) "haval128,5" +string(32) "ffa7993a4e183b245263fb1f63e27343" +string(32) "ffa7993a4e183b245263fb1f63e27343" +string(10) "haval160,5" +string(40) "375ee5ab3a9bd07a1dbe5d071e07b2afb3165e3b" +string(40) "375ee5ab3a9bd07a1dbe5d071e07b2afb3165e3b" +string(10) "haval192,5" +string(48) "c650585f93c6e041e835caedc621f8c42d8bc6829fb76789" +string(48) "c650585f93c6e041e835caedc621f8c42d8bc6829fb76789" +string(10) "haval224,5" +string(56) "bc674d465a822817d939f19b38edde083fe5668759836c203c56e3e4" +string(56) "bc674d465a822817d939f19b38edde083fe5668759836c203c56e3e4" +string(10) "haval256,5" +string(64) "da70ad9bd09ed7c9675329ea2b5279d57761807c7aeac6340d94b5d494809457" +string(64) "da70ad9bd09ed7c9675329ea2b5279d57761807c7aeac6340d94b5d494809457" +Done diff --git a/ext/hash/tests/hash_serialize_002.phpt b/ext/hash/tests/hash_serialize_002.phpt new file mode 100644 index 0000000000..b6b4ccfb5e --- /dev/null +++ b/ext/hash/tests/hash_serialize_002.phpt @@ -0,0 +1,116 @@ +--TEST-- +Hash: serialize()/unserialize() with HASH_HMAC +--FILE-- +getMessage(), "\n"; + } +} + +echo "Done\n"; +?> +--EXPECT-- +string(3) "md2" +HashContext with HASH_HMAC option cannot be serialized +string(3) "md4" +HashContext with HASH_HMAC option cannot be serialized +string(3) "md5" +HashContext with HASH_HMAC option cannot be serialized +string(4) "sha1" +HashContext with HASH_HMAC option cannot be serialized +string(6) "sha224" +HashContext with HASH_HMAC option cannot be serialized +string(6) "sha256" +HashContext with HASH_HMAC option cannot be serialized +string(6) "sha384" +HashContext with HASH_HMAC option cannot be serialized +string(10) "sha512/224" +HashContext with HASH_HMAC option cannot be serialized +string(10) "sha512/256" +HashContext with HASH_HMAC option cannot be serialized +string(6) "sha512" +HashContext with HASH_HMAC option cannot be serialized +string(8) "sha3-224" +HashContext with HASH_HMAC option cannot be serialized +string(8) "sha3-256" +HashContext with HASH_HMAC option cannot be serialized +string(8) "sha3-384" +HashContext with HASH_HMAC option cannot be serialized +string(8) "sha3-512" +HashContext with HASH_HMAC option cannot be serialized +string(9) "ripemd128" +HashContext with HASH_HMAC option cannot be serialized +string(9) "ripemd160" +HashContext with HASH_HMAC option cannot be serialized +string(9) "ripemd256" +HashContext with HASH_HMAC option cannot be serialized +string(9) "ripemd320" +HashContext with HASH_HMAC option cannot be serialized +string(9) "whirlpool" +HashContext with HASH_HMAC option cannot be serialized +string(10) "tiger128,3" +HashContext with HASH_HMAC option cannot be serialized +string(10) "tiger160,3" +HashContext with HASH_HMAC option cannot be serialized +string(10) "tiger192,3" +HashContext with HASH_HMAC option cannot be serialized +string(10) "tiger128,4" +HashContext with HASH_HMAC option cannot be serialized +string(10) "tiger160,4" +HashContext with HASH_HMAC option cannot be serialized +string(10) "tiger192,4" +HashContext with HASH_HMAC option cannot be serialized +string(6) "snefru" +HashContext with HASH_HMAC option cannot be serialized +string(9) "snefru256" +HashContext with HASH_HMAC option cannot be serialized +string(4) "gost" +HashContext with HASH_HMAC option cannot be serialized +string(11) "gost-crypto" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval128,3" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval160,3" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval192,3" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval224,3" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval256,3" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval128,4" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval160,4" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval192,4" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval224,4" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval256,4" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval128,5" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval160,5" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval192,5" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval224,5" +HashContext with HASH_HMAC option cannot be serialized +string(10) "haval256,5" +HashContext with HASH_HMAC option cannot be serialized +Done diff --git a/ext/hash/tests/hash_serialize_003.phpt b/ext/hash/tests/hash_serialize_003.phpt new file mode 100644 index 0000000000..a687c2aeff --- /dev/null +++ b/ext/hash/tests/hash_serialize_003.phpt @@ -0,0 +1,261 @@ +--TEST-- +Hash: serialization formats +--FILE-- +getMessage(), "\n", $e->getTraceAsString(); + } +} + +foreach ($serializations as $slist) { + $algo = $slist[0]; + $hash = hash($algo, "I can't remember anythingCan’t tell if this is true or dream"); + + $ctx = hash_init($algo); + hash_update($ctx, "I can't remember anything"); + $serial = base64_encode(serialize($ctx)); + if (!in_array($serial, $slist)) { + echo "$algo: unexpected serialization $serial\n"; + } + + test_serialization($serial, $hash, $algo); +} + +echo "Done\n"; +?> +--EXPECT-- +Done diff --git a/ext/hash/tests/hash_serialize_004.phpt b/ext/hash/tests/hash_serialize_004.phpt new file mode 100644 index 0000000000..ee5c08f973 --- /dev/null +++ b/ext/hash/tests/hash_serialize_004.phpt @@ -0,0 +1,45 @@ +--TEST-- +Hash: serialization errors +--FILE-- +__unserialize($ctx->__serialize()); +} catch (Exception $e) { + echo $e->getMessage(), "\n"; +} + +// bad formats +foreach ([ + "TzoxMToiSGFzaENvbnRleHQiOjA6e30=", // no contents + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtpOjE7aToxO2k6MDtpOjI7YTo4OntpOjA7aToxNzMyNTg0MTkzO2k6MTtpOi0yNzE3MzM4Nzk7aToyO2k6LTE3MzI1ODQxOTQ7aTozO2k6MjcxNzMzODc4O2k6NDtpOi0xMDA5NTg5Nzc2O2k6NTtpOjIwMDtpOjY7aTowO2k6NztzOjY0OiJJIGNhbid0IHJlbWVtYmVyIGFueXRoaW5nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIjt9aTozO2k6MjtpOjQ7YTowOnt9fQ==", // algorithm is int + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjQ6InNoYTEiO2k6MTtzOjA6IiI7aToyO2E6ODp7aTowO2k6MTczMjU4NDE5MztpOjE7aTotMjcxNzMzODc5O2k6MjtpOi0xNzMyNTg0MTk0O2k6MztpOjI3MTczMzg3ODtpOjQ7aTotMTAwOTU4OTc3NjtpOjU7aToyMDA7aTo2O2k6MDtpOjc7czo2NDoiSSBjYW4ndCByZW1lbWJlciBhbnl0aGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7fWk6MztpOjI7aTo0O2E6MDp7fX0=", // flags are string + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjQ6InNoYTEiO2k6MTtpOjE7aToyO2E6ODp7aTowO2k6MTczMjU4NDE5MztpOjE7aTotMjcxNzMzODc5O2k6MjtpOi0xNzMyNTg0MTk0O2k6MztpOjI3MTczMzg3ODtpOjQ7aTotMTAwOTU4OTc3NjtpOjU7aToyMDA7aTo2O2k6MDtpOjc7czo2NDoiSSBjYW4ndCByZW1lbWJlciBhbnl0aGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7fWk6MztpOjI7aTo0O2E6MDp7fX0=", // flags indicate HASH_HMAC + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjQ6InNoYTEiO2k6MTtpOjI7aToyO3M6MTA6ImFiY2RlZmdoaWoiO2k6MztpOjI7aTo0O2E6MDp7fX0=", // serialization format wrong + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjQ6InNoYTEiO2k6MTtpOjA7aToyO2E6ODp7aTowO2k6MTczMjU4NDE5MztpOjE7aTotMjcxNzMzODc5O2k6MjtpOi0xNzMyNTg0MTk0O2k6MztpOjI3MTczMzg3ODtpOjQ7aTotMTAwOTU4OTc3NjtpOjU7aToyMDA7aTo2O3M6MDoiIjtpOjc7czo2NDoiSSBjYW4ndCByZW1lbWJlciBhbnl0aGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7fWk6MztpOjI7aTo0O2E6MDp7fX0=", // serialization internals wrong + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjQ6InNoYTEiO2k6MTtpOjA7aToyO2E6ODp7aTowO2k6MTczMjU4NDE5MztpOjE7aTotMjcxNzMzODc5O2k6MjtpOi0xNzMyNTg0MTk0O2k6MztpOjI3MTczMzg3ODtpOjQ7aTotMTAwOTU4OTc3NjtpOjU7aToyMDA7aTo2O2k6MDtpOjc7czo2NDoiSSBjYW4ndCByZW1lbWJlciBhbnl0aGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7fWk6MztpOjA7aTo0O2E6MDp7fX0=", // bad magic number + "TzoxMToiSGFzaENvbnRleHQiOjU6e2k6MDtzOjQ6Inh4eDEiO2k6MTtpOjA7aToyO2E6ODp7aTowO2k6MTczMjU4NDE5MztpOjE7aTotMjcxNzMzODc5O2k6MjtpOi0xNzMyNTg0MTk0O2k6MztpOjI3MTczMzg3ODtpOjQ7aTotMTAwOTU4OTc3NjtpOjU7aToyMDA7aTo2O2k6MDtpOjc7czo2NDoiSSBjYW4ndCByZW1lbWJlciBhbnl0aGluZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACI7fWk6MztpOjI7aTo0O2E6MDp7fX0=" // bad algorithm +] as $serial) { + try { + $ctx = unserialize(base64_decode($serial)); + echo "Unexpected success\n"; + } catch (Exception $e) { + echo $e->getMessage(), "\n"; + } +} + +echo "Done\n"; +?> +--EXPECT-- +HashContext::__unserialize called on initialized object +Incomplete or ill-formed serialization data +Incomplete or ill-formed serialization data +Incomplete or ill-formed serialization data +HashContext with HASH_HMAC option cannot be serialized +Incomplete or ill-formed serialization data ("sha1" code -1) +Incomplete or ill-formed serialization data ("sha1" code -1024) +Incomplete or ill-formed serialization data ("sha1" code -1) +Unknown hash algorithm +Done diff --git a/ext/hash/tests/serialize-context.phpt b/ext/hash/tests/serialize-context.phpt deleted file mode 100644 index 32aa0ab806..0000000000 --- a/ext/hash/tests/serialize-context.phpt +++ /dev/null @@ -1,13 +0,0 @@ ---TEST-- -Hash: Context serialization ---FILE-- -getMessage()}\n"; -} ---EXPECT-- -Exception: Serialization of 'HashContext' is not allowed diff --git a/ext/standard/md5.h b/ext/standard/md5.h index 15417990d7..ac60d7fca4 100644 --- a/ext/standard/md5.h +++ b/ext/standard/md5.h @@ -40,6 +40,7 @@ typedef struct { unsigned char buffer[64]; uint32_t block[16]; } PHP_MD5_CTX; +#define PHP_MD5_SPEC "llllllb64l16." PHPAPI void PHP_MD5Init(PHP_MD5_CTX *ctx); PHPAPI void PHP_MD5Update(PHP_MD5_CTX *ctx, const void *data, size_t size); diff --git a/ext/standard/sha1.h b/ext/standard/sha1.h index c904969dd3..ef98ecc29c 100644 --- a/ext/standard/sha1.h +++ b/ext/standard/sha1.h @@ -25,6 +25,7 @@ typedef struct { uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } PHP_SHA1_CTX; +#define PHP_SHA1_SPEC "l5l2b64." PHPAPI void PHP_SHA1Init(PHP_SHA1_CTX *); PHPAPI void PHP_SHA1Update(PHP_SHA1_CTX *, const unsigned char *, size_t); -- 2.50.1