Skip to content

Commit 35e2a25

Browse files
committed
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. In addtion the change also updates implementation of openssl_cipher_iv_length and adds a test for it.
1 parent 39b2380 commit 35e2a25

10 files changed

+123
-11
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ PHP NEWS
1919
open_basedir). (Jakub Zelenka)
2020
. Implement FR #76935 ("chacha20-poly1305" is an AEAD but does not work like
2121
AEAD). (Jakub Zelenka)
22+
. Added openssl_cipher_key_length function. (Jakub Zelenka)
2223

2324
- Random:
2425
. Fixed bug GH-9415 (Randomizer::getInt(0, 2**32 - 1) with Mt19937

UPGRADING

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,10 @@ PHP 8.2 UPGRADE NOTES
227227
- mysqli:
228228
. mysqli_execute_query()
229229

230+
- OpenSSL:
231+
. openssl_cipher_key_length(): Returns a key length for the supplied
232+
cipher.
233+
230234
- Reflection:
231235
. ReflectionFunction::isAnonymous()
232236
. ReflectionMethod::hasPrototype()

ext/openssl/openssl.c

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7590,44 +7590,76 @@ PHP_FUNCTION(openssl_decrypt)
75907590
}
75917591
/* }}} */
75927592

7593-
PHP_OPENSSL_API zend_long php_openssl_cipher_iv_length(const char *method)
7593+
static inline const EVP_CIPHER *php_openssl_get_evp_cipher_by_name(const char *method)
75947594
{
75957595
const EVP_CIPHER *cipher_type;
75967596

75977597
cipher_type = EVP_get_cipherbyname(method);
75987598
if (!cipher_type) {
75997599
php_error_docref(NULL, E_WARNING, "Unknown cipher algorithm");
7600-
return -1;
7600+
return NULL;
76017601
}
76027602

7603-
return EVP_CIPHER_iv_length(cipher_type);
7603+
return cipher_type;
7604+
}
7605+
7606+
PHP_OPENSSL_API zend_long php_openssl_cipher_iv_length(const char *method)
7607+
{
7608+
const EVP_CIPHER *cipher_type = php_openssl_get_evp_cipher_by_name(method);
7609+
7610+
return cipher_type == NULL ? -1 : EVP_CIPHER_iv_length(cipher_type);
76047611
}
76057612

7606-
/* {{{ */
76077613
PHP_FUNCTION(openssl_cipher_iv_length)
76087614
{
7609-
char *method;
7610-
size_t method_len;
7615+
zend_string *method;
76117616
zend_long ret;
76127617

7613-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &method, &method_len) == FAILURE) {
7618+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &method) == FAILURE) {
76147619
RETURN_THROWS();
76157620
}
76167621

7617-
if (!method_len) {
7622+
if (ZSTR_LEN(method) == 0) {
76187623
zend_argument_value_error(1, "cannot be empty");
76197624
RETURN_THROWS();
76207625
}
76217626

76227627
/* Warning is emitted in php_openssl_cipher_iv_length */
7623-
if ((ret = php_openssl_cipher_iv_length(method)) == -1) {
7628+
if ((ret = php_openssl_cipher_iv_length(ZSTR_VAL(method))) == -1) {
76247629
RETURN_FALSE;
76257630
}
76267631

76277632
RETURN_LONG(ret);
76287633
}
7629-
/* }}} */
76307634

7635+
PHP_OPENSSL_API zend_long php_openssl_cipher_key_length(const char *method)
7636+
{
7637+
const EVP_CIPHER *cipher_type = php_openssl_get_evp_cipher_by_name(method);
7638+
7639+
return cipher_type == NULL ? -1 : EVP_CIPHER_key_length(cipher_type);
7640+
}
7641+
7642+
PHP_FUNCTION(openssl_cipher_key_length)
7643+
{
7644+
zend_string *method;
7645+
zend_long ret;
7646+
7647+
if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &method) == FAILURE) {
7648+
RETURN_THROWS();
7649+
}
7650+
7651+
if (ZSTR_LEN(method) == 0) {
7652+
zend_argument_value_error(1, "cannot be empty");
7653+
RETURN_THROWS();
7654+
}
7655+
7656+
/* Warning is emitted in php_openssl_cipher_key_length */
7657+
if ((ret = php_openssl_cipher_key_length(ZSTR_VAL(method))) == -1) {
7658+
RETURN_FALSE;
7659+
}
7660+
7661+
RETURN_LONG(ret);
7662+
}
76317663

76327664
PHP_OPENSSL_API zend_string* php_openssl_random_pseudo_bytes(zend_long buffer_length)
76337665
{

ext/openssl/openssl.stub.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -610,6 +610,8 @@ function openssl_decrypt(string $data, string $cipher_algo, #[\SensitiveParamete
610610

611611
function openssl_cipher_iv_length(string $cipher_algo): int|false {}
612612

613+
function openssl_cipher_key_length(string $cipher_algo): int|false {}
614+
613615
function openssl_dh_compute_key(string $public_key, #[\SensitiveParameter] OpenSSLAsymmetricKey $private_key): string|false {}
614616

615617
/**

ext/openssl/openssl_arginfo.h

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/openssl/php_openssl.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ static inline bool php_openssl_check_path_str(
123123
}
124124

125125
PHP_OPENSSL_API zend_long php_openssl_cipher_iv_length(const char *method);
126+
PHP_OPENSSL_API zend_long php_openssl_cipher_key_length(const char *method);
126127
PHP_OPENSSL_API zend_string* php_openssl_random_pseudo_bytes(zend_long length);
127128
PHP_OPENSSL_API zend_string* php_openssl_encrypt(
128129
const char *data, size_t data_len,
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
--TEST--
2+
openssl_cipher_iv_length() basic test
3+
--EXTENSIONS--
4+
openssl
5+
--FILE--
6+
<?php
7+
8+
var_dump(openssl_cipher_iv_length('AES-128-CBC'));
9+
10+
?>
11+
--EXPECT--
12+
int(16)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
openssl_cipher_iv_length() error test
3+
--EXTENSIONS--
4+
openssl
5+
--FILE--
6+
<?php
7+
8+
var_dump(openssl_cipher_iv_length('unknown'));
9+
10+
try {
11+
var_dump(openssl_cipher_iv_length(''));
12+
} catch (ValueError $e) {
13+
echo $e->getMessage() . "\n";
14+
}
15+
16+
?>
17+
--EXPECTF--
18+
19+
Warning: openssl_cipher_iv_length(): Unknown cipher algorithm in %s on line %d
20+
bool(false)
21+
openssl_cipher_iv_length(): Argument #1 ($cipher_algo) cannot be empty
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
--TEST--
2+
openssl_cipher_key_length() basic test
3+
--EXTENSIONS--
4+
openssl
5+
--FILE--
6+
<?php
7+
8+
var_dump(openssl_cipher_key_length('AES-128-CBC'));
9+
var_dump(openssl_cipher_key_length('AES-256-CBC'));
10+
11+
?>
12+
--EXPECT--
13+
int(16)
14+
int(32)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
openssl_cipher_key_length() error test
3+
--EXTENSIONS--
4+
openssl
5+
--FILE--
6+
<?php
7+
8+
var_dump(openssl_cipher_key_length('unknown'));
9+
10+
try {
11+
var_dump(openssl_cipher_key_length(''));
12+
} catch (ValueError $e) {
13+
echo $e->getMessage() . "\n";
14+
}
15+
16+
?>
17+
--EXPECTF--
18+
19+
Warning: openssl_cipher_key_length(): Unknown cipher algorithm in %s on line %d
20+
bool(false)
21+
openssl_cipher_key_length(): Argument #1 ($cipher_algo) cannot be empty

0 commit comments

Comments
 (0)