diff options
| author | Remi Collet <remi@remirepo.net> | 2026-07-02 10:34:29 +0200 |
|---|---|---|
| committer | Remi Collet <remi@php.net> | 2026-07-02 10:34:29 +0200 |
| commit | a6a73cf6d843268c9a5b8eb9b3245f4defbf08bf (patch) | |
| tree | 40d5386ae7704ec32ffa4d6b076229b3edb972e8 /php-gh22187.patch | |
| parent | 4cd51d2ae8cfc95f3393faeea5fbefd09c769089 (diff) | |
Diffstat (limited to 'php-gh22187.patch')
| -rw-r--r-- | php-gh22187.patch | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/php-gh22187.patch b/php-gh22187.patch new file mode 100644 index 0000000..f90a801 --- /dev/null +++ b/php-gh22187.patch @@ -0,0 +1,123 @@ +From 5c2cc46b45cf286666671df14edf25fc23676cd8 Mon Sep 17 00:00:00 2001 +From: David Carlier <devnexen@gmail.com> +Date: Fri, 29 May 2026 21:44:14 +0100 +Subject: [PATCH] ext/openssl: openssl_encrypt() zend mm heap overflow on + AES-WRAP-PAD mode. + +Fix #22186 + +close GH-22187 + +(cherry picked from commit cbc0489126a7682796aad1e5fb4e51de74af162c) +(cherry picked from commit 95e9851111d249e43948b76663cff1baeb5e758d) +(cherry picked from commit 2a73e91a9f9136fbbfcc9177573b6af71e3d5dce) +(cherry picked from commit e058b01e1bd23421a425cffae9f458b0fa8db222) +(cherry picked from commit 09cccab30d53614bb826e4390ad23ad7451b6d6c) +(cherry picked from commit f15d1e26160a8175474160907eb6ab7e10090fa0) +(cherry picked from commit 58c39c2f8402261fd4e8ffd327c37adc53a9c861) +(cherry picked from commit 4eeb25a7ae8f91e517b760423b50a5a5ef9e98fb) +--- + NEWS | 6 ++++++ + ext/openssl/openssl.c | 22 ++++++++++++++++++++++ + ext/openssl/tests/gh22186.phpt | 32 ++++++++++++++++++++++++++++++++ + 3 files changed, 60 insertions(+) + create mode 100644 ext/openssl/tests/gh22186.phpt + +diff --git a/NEWS b/NEWS +index d8ae595068..1f7e3dfd8c 100644 +--- a/NEWS ++++ b/NEWS +@@ -1,6 +1,12 @@ + PHP NEWS + ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| + ++Backported from 8.2.32 ++ ++- OpenSSL: ++ . Fixed bug GH-22187 (Memory corruption (zend_mm_heap corrupted) in ++ openssl_encrypt with AES-WRAP-PAD). (David Carlier) ++ + Backported from 8.2.31 + + - FPM: +diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c +index eda68f2ff1..b6a79249b0 100644 +--- a/ext/openssl/openssl.c ++++ b/ext/openssl/openssl.c +@@ -5422,6 +5422,17 @@ PHP_FUNCTION(openssl_encrypt) + free_iv = php_openssl_validate_iv(&iv, &iv_len, max_iv_len TSRMLS_CC); + + outlen = data_len + EVP_CIPHER_block_size(cipher_type); ++#ifdef EVP_CIPH_WRAP_MODE ++ if ((EVP_CIPHER_mode(cipher_type)) == EVP_CIPH_WRAP_MODE) { ++ /* ++ * RFC 5649 wrap-with-padding rounds the input up to the block size ++ * and prepends an integrity block, we reserve one extra block. ++ * See EVP_EncryptUpdate(3): wrap mode may write up to ++ * inl + cipher_block_size bytes. ++ */ ++ outlen += EVP_CIPHER_block_size(cipher_type); ++ } ++#endif + outbuf = safe_emalloc(outlen, 1, 1); + + EVP_EncryptInit(cipher_ctx, cipher_type, NULL, NULL); +@@ -5526,6 +5537,17 @@ PHP_FUNCTION(openssl_decrypt) + free_iv = php_openssl_validate_iv(&iv, &iv_len, EVP_CIPHER_iv_length(cipher_type) TSRMLS_CC); + + outlen = data_len + EVP_CIPHER_block_size(cipher_type); ++#ifdef EVP_CIPH_WRAP_MODE ++ if ((EVP_CIPHER_mode(cipher_type)) == EVP_CIPH_WRAP_MODE) { ++ /* ++ * RFC 5649 wrap-with-padding rounds the input up to the block size ++ * and prepends an integrity block, we reserve one extra block. ++ * See EVP_EncryptUpdate(3): wrap mode may write up to ++ * inl + cipher_block_size bytes. ++ */ ++ outlen += EVP_CIPHER_block_size(cipher_type); ++ } ++#endif + outbuf = emalloc(outlen + 1); + + EVP_DecryptInit(cipher_ctx, cipher_type, NULL, NULL); +diff --git a/ext/openssl/tests/gh22186.phpt b/ext/openssl/tests/gh22186.phpt +new file mode 100644 +index 0000000000..8f28e6c45b +--- /dev/null ++++ b/ext/openssl/tests/gh22186.phpt +@@ -0,0 +1,32 @@ ++--TEST-- ++GH-22186 (Heap buffer overflow in openssl_encrypt with AES-WRAP-PAD) ++--EXTENSIONS-- ++openssl ++--SKIPIF-- ++<?php ++/* openssl_get_cipher_methods() enumerates provider ciphers, but openssl_encrypt() ++ * resolves names via the legacy EVP_get_cipherbyname(), so on some builds the ++ * cipher is listed yet not usable. Probe the actual call path instead. */ ++if (!@openssl_encrypt("test", "aes-128-wrap-pad", str_repeat("k", 16), ++ OPENSSL_RAW_DATA | OPENSSL_DONT_ZERO_PAD_KEY, str_repeat("\0", 4))) { ++ die('skip aes-128-wrap-pad not usable on this OpenSSL build'); ++} ++?> ++--FILE-- ++<?php ++$pass = str_repeat("k", 16); ++$iv = str_repeat("\0", 4); ++ ++for ($i = 1; $i < 258; $i++) { ++ $data = str_repeat("a", $i); ++ $enc = openssl_encrypt($data, 'aes-128-wrap-pad', $pass, OPENSSL_RAW_DATA | OPENSSL_DONT_ZERO_PAD_KEY, $iv); ++ $dec = openssl_decrypt($enc, 'aes-128-wrap-pad', $pass, OPENSSL_RAW_DATA | OPENSSL_DONT_ZERO_PAD_KEY, $iv); ++ if ($dec !== $data) { ++ die("mismatch at $i\n"); ++ } ++} ++ ++echo "done\n"; ++?> ++--EXPECT-- ++done +-- +2.43.7 + |
