From 7f0d3f5413dfbd989ffe34a417c61210441763f3 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 8 Oct 2021 14:07:05 +0200 Subject: [PATCH] Fixed bug #81502 Allow $tag to be null. This is the value that openssl_encrypt() sets it to for non-AEAD ciphers, so we should also accept this as an input to openssl_decrypt(). Prior to PHP 8.1, null was accepted in weak mode due to the special treatment of null arguments to internal functions. --- NEWS | 4 ++++ ext/openssl/openssl.c | 2 +- ext/openssl/openssl.stub.php | 2 +- ext/openssl/openssl_arginfo.h | 4 ++-- ext/openssl/tests/openssl_decrypt_basic.phpt | 7 +++++++ 5 files changed, 15 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 2db0ec4eaff..ef6be7ca869 100644 --- a/NEWS +++ b/NEWS @@ -22,6 +22,10 @@ PHP NEWS - PgSQL: . Fixed bug #81509 (pg_end_copy still expects a resource). (Matteo) +- OpenSSL: + . Fixed bug #81502 ($tag argument of openssl_decrypt() should accept + null/empty string). (Nikita) + - Standard: . Fixed bug #81491 (Incorrectly using libsodium for argon2 hashing). (Dan Pock) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 4e9839f834a..506074172a3 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -7614,7 +7614,7 @@ PHP_FUNCTION(openssl_decrypt) size_t data_len, method_len, password_len, iv_len = 0, tag_len = 0, aad_len = 0; zend_string *ret; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|lsss", &data, &data_len, &method, &method_len, + if (zend_parse_parameters(ZEND_NUM_ARGS(), "sss|lss!s", &data, &data_len, &method, &method_len, &password, &password_len, &options, &iv, &iv_len, &tag, &tag_len, &aad, &aad_len) == FAILURE) { RETURN_THROWS(); } diff --git a/ext/openssl/openssl.stub.php b/ext/openssl/openssl.stub.php index 3cdefce9ff4..b1e5a06b4f0 100644 --- a/ext/openssl/openssl.stub.php +++ b/ext/openssl/openssl.stub.php @@ -236,7 +236,7 @@ function openssl_digest(string $data, string $digest_algo, bool $binary = false) /** @param string $tag */ function openssl_encrypt(string $data, string $cipher_algo, string $passphrase, int $options = 0, string $iv = "", &$tag = null, string $aad = "", int $tag_length = 16): string|false {} -function openssl_decrypt(string $data, string $cipher_algo, string $passphrase, int $options = 0, string $iv = "", string $tag = "", string $aad = ""): string|false {} +function openssl_decrypt(string $data, string $cipher_algo, string $passphrase, int $options = 0, string $iv = "", ?string $tag = null, string $aad = ""): string|false {} function openssl_cipher_iv_length(string $cipher_algo): int|false {} diff --git a/ext/openssl/openssl_arginfo.h b/ext/openssl/openssl_arginfo.h index 05c8fafe74a..ea6bc4bdb09 100644 --- a/ext/openssl/openssl_arginfo.h +++ b/ext/openssl/openssl_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 3ad007a0b29648c29051f9ee00fe43dd6f2a766d */ + * Stub hash: 320aca9647019329a42dc3e7937420610a8a4419 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_openssl_x509_export_to_file, 0, 2, _IS_BOOL, 0) ZEND_ARG_OBJ_TYPE_MASK(0, certificate, OpenSSLCertificate, MAY_BE_STRING, NULL) @@ -342,7 +342,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_openssl_decrypt, 0, 3, MAY_BE_ST ZEND_ARG_TYPE_INFO(0, passphrase, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, options, IS_LONG, 0, "0") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, iv, IS_STRING, 0, "\"\"") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, tag, IS_STRING, 0, "\"\"") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, tag, IS_STRING, 1, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, aad, IS_STRING, 0, "\"\"") ZEND_END_ARG_INFO() diff --git a/ext/openssl/tests/openssl_decrypt_basic.phpt b/ext/openssl/tests/openssl_decrypt_basic.phpt index 9885953b7f1..6cb2297a979 100644 --- a/ext/openssl/tests/openssl_decrypt_basic.phpt +++ b/ext/openssl/tests/openssl_decrypt_basic.phpt @@ -25,6 +25,11 @@ $encrypted = openssl_encrypt($padded_data, $method, $password, OPENSSL_RAW_DATA| $output = openssl_decrypt($encrypted, $method, $password, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv); var_dump(rtrim($output)); +$output2 = openssl_decrypt($encrypted, $method, $password, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv, tag: ''); +var_dump($output2 === $output); +$output3 = openssl_decrypt($encrypted, $method, $password, OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING, $iv, tag: null); +var_dump($output3 === $output); + if (in_array("bf-ecb", openssl_get_cipher_methods())) { // if we want to prefer variable length cipher setting $encrypted = openssl_encrypt($data, "bf-ecb", $password, OPENSSL_DONT_ZERO_PAD_KEY); @@ -45,4 +50,6 @@ string(45) "openssl_encrypt() and openssl_decrypt() tests" string(45) "openssl_encrypt() and openssl_decrypt() tests" string(45) "openssl_encrypt() and openssl_decrypt() tests" bool(true) +bool(true) +bool(true) NULL