[php-src] PR #24304: Fix sign extension of TLS stream SSL_CTX options
| From: | kwmonroe | Date: | Tue, 13 Oct 2026 18:30:16 +0000 |
| Subject: | [php-src] PR #24304: Fix sign extension of TLS stream SSL_CTX options | ||
| Groups: | php.git-pulls | ||
| Request: | Send a blank email to git-pulls+get-39392@lists.php.net to get a copy of this message | ||
Pull Request: https://github.com/php/php-src/pull/24304
Author: kwmonroe
I noticed an
internal error when testing a client application with php 8.4+ in an
openssl-4 fips-enabled environment. It looks like uint64 openssl options are overflowing a php int
var, and then inadvertently setting the high bits when cast back during set_options(uint64).
The description below was drafted with an LLM; I reviewed it and reproduced everything it describes.
> php_openssl_setup_crypto() keeps the SSL_CTX options in an int. SSL_OP_ALL includes
> SSL_OP_CRYPTOPRO_TLSEXT_BUG (bit 31), so the value is negative, and SSL_CTX_set_options(), which
> takes a uint64_t since OpenSSL 3.0, receives it sign-extended with bits 32-63 set. On OpenSSL 3.x
> that silently turns on options such as SSL_OP_NO_TX_CERTIFICATE_COMPRESSION,
> SSL_OP_NO_RX_CERTIFICATE_COMPRESSION and SSL_OP_PREFER_NO_DHE_KEX. OpenSSL 4.0 assigns
> SSL_OP_ECH_GREASE to bit 37, so every TLS client stream now sends an ECH GREASE extension.
>
> Generating the GREASE value needs an X25519 key. With the FIPS provider and
> default_properties = fips=yes, X25519 is not available (the provider
> registers it as fips=no), so the handshake fails before the
> ClientHello is sent:
>
> ```
> error:0308010C:digital envelope routines::unsupported
> error:078C0103:common libcrypto routines::internal error
> error:0A0C0103:SSL routines::internal error
> ```
>
> This reproduces with OpenSSL 4.0.3 built from source with
> enable-fips and the configuration from fips_module(7): every
> tls:// connection from PHP fails, and the same connection succeeds
> with this patch.
>
> Store the options in a uint64_t. The new test reads the ClientHello on a plain TCP server and
> checks that it has no encrypted_client_hello extension; on OpenSSL 4.0.3 it fails without the fix
> and passes with it.
>
> When merging up: PHP-8.5 and later no longer have php_openssl_get_crypto_method_ctx_flags(), so
> only the php_openssl_setup_crypto() hunk applies there.