From 4951d717df72dd9d3e4eead91aab6d3a96ae3ab0 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Thu, 18 Aug 2022 14:24:44 +0100 Subject: [PATCH] Add openssl_cipher_key_length function This function works in exactly the same way as openssl_cipher_iv_length but for a key length. This is especially useful to make sure that the right key length is provided to openssl_encrypt and openssl_decrypt. --- ext/openssl/openssl.c | 52 +++++++++++++++---- ext/openssl/openssl.stub.php | 2 + ext/openssl/openssl_arginfo.h | 6 ++- ext/openssl/php_openssl.h | 1 + .../tests/openssl_cipher_iv_length_basic.phpt | 12 +++++ .../tests/openssl_cipher_iv_length_error.phpt | 21 ++++++++ .../openssl_cipher_key_length_basic.phpt | 14 +++++ .../openssl_cipher_key_length_error.phpt | 21 ++++++++ 8 files changed, 118 insertions(+), 11 deletions(-) create mode 100644 ext/openssl/tests/openssl_cipher_iv_length_basic.phpt create mode 100644 ext/openssl/tests/openssl_cipher_iv_length_error.phpt create mode 100644 ext/openssl/tests/openssl_cipher_key_length_basic.phpt create mode 100644 ext/openssl/tests/openssl_cipher_key_length_error.phpt diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 10939276b60eb..442ea7e4d37d3 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -7600,44 +7600,76 @@ PHP_FUNCTION(openssl_decrypt) } /* }}} */ -PHP_OPENSSL_API zend_long php_openssl_cipher_iv_length(const char *method) +static inline const EVP_CIPHER *php_openssl_get_evp_cipher_by_name(const char *method) { const EVP_CIPHER *cipher_type; cipher_type = EVP_get_cipherbyname(method); if (!cipher_type) { php_error_docref(NULL, E_WARNING, "Unknown cipher algorithm"); - return -1; + return NULL; } - return EVP_CIPHER_iv_length(cipher_type); + return cipher_type; +} + +PHP_OPENSSL_API zend_long php_openssl_cipher_iv_length(const char *method) +{ + const EVP_CIPHER *cipher_type = php_openssl_get_evp_cipher_by_name(method); + + return cipher_type == NULL ? -1 : EVP_CIPHER_iv_length(cipher_type); } -/* {{{ */ PHP_FUNCTION(openssl_cipher_iv_length) { - char *method; - size_t method_len; + zend_string *method; zend_long ret; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &method, &method_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &method) == FAILURE) { RETURN_THROWS(); } - if (!method_len) { + if (ZSTR_LEN(method) == 0) { zend_argument_value_error(1, "cannot be empty"); RETURN_THROWS(); } /* Warning is emitted in php_openssl_cipher_iv_length */ - if ((ret = php_openssl_cipher_iv_length(method)) == -1) { + if ((ret = php_openssl_cipher_iv_length(ZSTR_VAL(method))) == -1) { RETURN_FALSE; } RETURN_LONG(ret); } -/* }}} */ +PHP_OPENSSL_API zend_long php_openssl_cipher_key_length(const char *method) +{ + const EVP_CIPHER *cipher_type = php_openssl_get_evp_cipher_by_name(method); + + return cipher_type == NULL ? -1 : EVP_CIPHER_key_length(cipher_type); +} + +PHP_FUNCTION(openssl_cipher_key_length) +{ + zend_string *method; + zend_long ret; + + if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &method) == FAILURE) { + RETURN_THROWS(); + } + + if (ZSTR_LEN(method) == 0) { + zend_argument_value_error(1, "cannot be empty"); + RETURN_THROWS(); + } + + /* Warning is emitted in php_openssl_cipher_key_length */ + if ((ret = php_openssl_cipher_key_length(ZSTR_VAL(method))) == -1) { + RETURN_FALSE; + } + + RETURN_LONG(ret); +} PHP_OPENSSL_API zend_string* php_openssl_random_pseudo_bytes(zend_long buffer_length) { diff --git a/ext/openssl/openssl.stub.php b/ext/openssl/openssl.stub.php index ccefc2da14d96..8a0f678f3d968 100644 --- a/ext/openssl/openssl.stub.php +++ b/ext/openssl/openssl.stub.php @@ -610,6 +610,8 @@ function openssl_decrypt(string $data, string $cipher_algo, #[\SensitiveParamete function openssl_cipher_iv_length(string $cipher_algo): int|false {} +function openssl_cipher_key_length(string $cipher_algo): int|false {} + function openssl_dh_compute_key(string $public_key, #[\SensitiveParameter] OpenSSLAsymmetricKey $private_key): string|false {} /** diff --git a/ext/openssl/openssl_arginfo.h b/ext/openssl/openssl_arginfo.h index 21e39515ccc79..1a79c777b914b 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: 4ceb7805924cd343a223d60383892c49c90a104d */ + * Stub hash: 02ee3cc08e7bda875321cb63e879deed48d7a389 */ 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) @@ -350,6 +350,8 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_openssl_cipher_iv_length, 0, 1, ZEND_ARG_TYPE_INFO(0, cipher_algo, IS_STRING, 0) ZEND_END_ARG_INFO() +#define arginfo_openssl_cipher_key_length arginfo_openssl_cipher_iv_length + ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_openssl_dh_compute_key, 0, 2, MAY_BE_STRING|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, public_key, IS_STRING, 0) ZEND_ARG_OBJ_INFO(0, private_key, OpenSSLAsymmetricKey, 0) @@ -440,6 +442,7 @@ ZEND_FUNCTION(openssl_digest); ZEND_FUNCTION(openssl_encrypt); ZEND_FUNCTION(openssl_decrypt); ZEND_FUNCTION(openssl_cipher_iv_length); +ZEND_FUNCTION(openssl_cipher_key_length); ZEND_FUNCTION(openssl_dh_compute_key); ZEND_FUNCTION(openssl_pkey_derive); ZEND_FUNCTION(openssl_random_pseudo_bytes); @@ -508,6 +511,7 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(openssl_encrypt, arginfo_openssl_encrypt) ZEND_FE(openssl_decrypt, arginfo_openssl_decrypt) ZEND_FE(openssl_cipher_iv_length, arginfo_openssl_cipher_iv_length) + ZEND_FE(openssl_cipher_key_length, arginfo_openssl_cipher_key_length) ZEND_FE(openssl_dh_compute_key, arginfo_openssl_dh_compute_key) ZEND_FE(openssl_pkey_derive, arginfo_openssl_pkey_derive) ZEND_FE(openssl_random_pseudo_bytes, arginfo_openssl_random_pseudo_bytes) diff --git a/ext/openssl/php_openssl.h b/ext/openssl/php_openssl.h index 3f0c436190fa3..e55f404d9bce7 100644 --- a/ext/openssl/php_openssl.h +++ b/ext/openssl/php_openssl.h @@ -93,6 +93,7 @@ php_stream_transport_factory_func php_openssl_ssl_socket_factory; void php_openssl_store_errors(void); PHP_OPENSSL_API zend_long php_openssl_cipher_iv_length(const char *method); +PHP_OPENSSL_API zend_long php_openssl_cipher_key_length(const char *method); PHP_OPENSSL_API zend_string* php_openssl_random_pseudo_bytes(zend_long length); PHP_OPENSSL_API zend_string* php_openssl_encrypt( const char *data, size_t data_len, diff --git a/ext/openssl/tests/openssl_cipher_iv_length_basic.phpt b/ext/openssl/tests/openssl_cipher_iv_length_basic.phpt new file mode 100644 index 0000000000000..82110ab83d317 --- /dev/null +++ b/ext/openssl/tests/openssl_cipher_iv_length_basic.phpt @@ -0,0 +1,12 @@ +--TEST-- +openssl_cipher_iv_length() basic test +--EXTENSIONS-- +openssl +--FILE-- + +--EXPECT-- +int(16) diff --git a/ext/openssl/tests/openssl_cipher_iv_length_error.phpt b/ext/openssl/tests/openssl_cipher_iv_length_error.phpt new file mode 100644 index 0000000000000..8fca1fdd71e66 --- /dev/null +++ b/ext/openssl/tests/openssl_cipher_iv_length_error.phpt @@ -0,0 +1,21 @@ +--TEST-- +openssl_cipher_iv_length() error test +--EXTENSIONS-- +openssl +--FILE-- +getMessage() . "\n"; +} + +?> +--EXPECTF-- + +Warning: openssl_cipher_iv_length(): Unknown cipher algorithm in %s on line %d +bool(false) +openssl_cipher_iv_length(): Argument #1 ($cipher_algo) cannot be empty diff --git a/ext/openssl/tests/openssl_cipher_key_length_basic.phpt b/ext/openssl/tests/openssl_cipher_key_length_basic.phpt new file mode 100644 index 0000000000000..a72cdda526975 --- /dev/null +++ b/ext/openssl/tests/openssl_cipher_key_length_basic.phpt @@ -0,0 +1,14 @@ +--TEST-- +openssl_cipher_key_length() basic test +--EXTENSIONS-- +openssl +--FILE-- + +--EXPECT-- +int(16) +int(32) diff --git a/ext/openssl/tests/openssl_cipher_key_length_error.phpt b/ext/openssl/tests/openssl_cipher_key_length_error.phpt new file mode 100644 index 0000000000000..08c08d382eb0c --- /dev/null +++ b/ext/openssl/tests/openssl_cipher_key_length_error.phpt @@ -0,0 +1,21 @@ +--TEST-- +openssl_cipher_key_length() error test +--EXTENSIONS-- +openssl +--FILE-- +getMessage() . "\n"; +} + +?> +--EXPECTF-- + +Warning: openssl_cipher_key_length(): Unknown cipher algorithm in %s on line %d +bool(false) +openssl_cipher_key_length(): Argument #1 ($cipher_algo) cannot be empty