Skip to content

Commit 7759f81

Browse files
committed
Merge branch 'PHP-8.2' into PHP-8.3
* PHP-8.2: ext/openssl: openssl_encrypt() zend mm heap overflow on AES-WRAP-PAD mode.
2 parents 79a9acc + cbc0489 commit 7759f81

3 files changed

Lines changed: 54 additions & 3 deletions

File tree

NEWS

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
3-
?? ??? ????, PHP 8.3.31
3+
?? ??? ????, PHP 8.3.32
4+
5+
- OpenSSL:
6+
. Fixed bug GH-22187 (Memory corruption (zend_mm_heap corrupted) in
7+
openssl_encrypt with AES-WRAP-PAD). (David Carlier)
8+
9+
07 May 2026, PHP 8.3.31
410

511
- Curl:
612
. Add support for brotli and zstd on Windows. (Shivam Mathur)

ext/openssl/openssl.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7616,6 +7616,7 @@ static int php_openssl_cipher_update(const EVP_CIPHER *cipher_type,
76167616
const char *aad, size_t aad_len, int enc) /* {{{ */
76177617
{
76187618
int i = 0;
7619+
size_t outlen = data_len + EVP_CIPHER_block_size(cipher_type);
76197620

76207621
if (mode->is_single_run_aead && !EVP_CipherUpdate(cipher_ctx, NULL, &i, NULL, (int)data_len)) {
76217622
php_openssl_store_errors();
@@ -7629,7 +7630,19 @@ static int php_openssl_cipher_update(const EVP_CIPHER *cipher_type,
76297630
return FAILURE;
76307631
}
76317632

7632-
*poutbuf = zend_string_alloc((int)data_len + EVP_CIPHER_block_size(cipher_type), 0);
7633+
#ifdef EVP_CIPH_WRAP_MODE
7634+
if ((EVP_CIPHER_mode(cipher_type)) == EVP_CIPH_WRAP_MODE) {
7635+
/*
7636+
* RFC 5649 wrap-with-padding rounds the input up to the block size
7637+
* and prepends an integrity block, we reserve one extra block.
7638+
* See EVP_EncryptUpdate(3): wrap mode may write up to
7639+
* inl + cipher_block_size bytes.
7640+
*/
7641+
outlen += EVP_CIPHER_block_size(cipher_type);
7642+
}
7643+
#endif
7644+
7645+
*poutbuf = zend_string_alloc(outlen, false);
76337646

76347647
if (!EVP_CipherUpdate(cipher_ctx, (unsigned char*)ZSTR_VAL(*poutbuf),
76357648
&i, (const unsigned char *)data, (int)data_len)) {
@@ -7641,7 +7654,7 @@ static int php_openssl_cipher_update(const EVP_CIPHER *cipher_type,
76417654
}
76427655
*/
76437656
php_openssl_store_errors();
7644-
zend_string_release_ex(*poutbuf, 0);
7657+
zend_string_release_ex(*poutbuf, false);
76457658
return FAILURE;
76467659
}
76477660

ext/openssl/tests/gh22186.phpt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
GH-22186 (Heap buffer overflow in openssl_encrypt with AES-WRAP-PAD)
3+
--EXTENSIONS--
4+
openssl
5+
--SKIPIF--
6+
<?php
7+
/* openssl_get_cipher_methods() enumerates provider ciphers, but openssl_encrypt()
8+
* resolves names via the legacy EVP_get_cipherbyname(), so on some builds the
9+
* cipher is listed yet not usable. Probe the actual call path instead. */
10+
if (!@openssl_encrypt("test", "aes-128-wrap-pad", str_repeat("k", 16),
11+
OPENSSL_RAW_DATA | OPENSSL_DONT_ZERO_PAD_KEY, str_repeat("\0", 4))) {
12+
die('skip aes-128-wrap-pad not usable on this OpenSSL build');
13+
}
14+
?>
15+
--FILE--
16+
<?php
17+
$pass = str_repeat("k", 16);
18+
$iv = str_repeat("\0", 4);
19+
20+
for ($i = 1; $i < 258; $i++) {
21+
$data = str_repeat("a", $i);
22+
$enc = openssl_encrypt($data, 'aes-128-wrap-pad', $pass, OPENSSL_RAW_DATA | OPENSSL_DONT_ZERO_PAD_KEY, $iv);
23+
$dec = openssl_decrypt($enc, 'aes-128-wrap-pad', $pass, OPENSSL_RAW_DATA | OPENSSL_DONT_ZERO_PAD_KEY, $iv);
24+
if ($dec !== $data) {
25+
die("mismatch at $i\n");
26+
}
27+
}
28+
29+
echo "done\n";
30+
?>
31+
--EXPECT--
32+
done

0 commit comments

Comments
 (0)