Skip to content

Add stream crypto status for exposing OSSL WANT_READ / WANT_WRITE#22193

Open
bukka wants to merge 1 commit into
php:masterfrom
bukka:openssl_stream_crypto_status
Open

Add stream crypto status for exposing OSSL WANT_READ / WANT_WRITE#22193
bukka wants to merge 1 commit into
php:masterfrom
bukka:openssl_stream_crypto_status

Conversation

@bukka
Copy link
Copy Markdown
Member

@bukka bukka commented May 30, 2026

On a non-blocking stream, stream_socket_enable_crypto() returns 0 and fread()/fwrite() return an empty result when the TLS engine needs more I/O, but there was no way to tell whether OpenSSL was waiting to read or to write. Callers therefore could not reliably decide which direction to poll for with stream_select(), which is required to drive a non-blocking handshake or renegotiation correctly (e.g. SSL_read() wanting a write).

This tracks the last SSL_ERROR_WANT_READ/WANT_WRITE on the stream and exposes it via a new stream_socket_get_crypto_status() function and three constants:

  STREAM_CRYPTO_STATUS_NONE
  STREAM_CRYPTO_STATUS_WANT_READ
  STREAM_CRYPTO_STATUS_WANT_WRITE

The status is updated during the handshake (php_openssl_enable_crypto()) and during reads / writes (php_openssl_sockop_io()), reset to NONE before each operation, and retrieved through a new STREAM_XPORT_CRYPTO_OP_GET_STATUS transport op. It is meaningful immediately after an operation that returned 0/false on a non-blocking stream.

Tests cover the status during a non-blocking handshake, a non-blocking read with no application data pending, and the constant values.

On a non-blocking stream, stream_socket_enable_crypto() returns 0 and
fread()/fwrite() return an empty result when the TLS engine needs more
I/O, but there was no way to tell whether OpenSSL was waiting to read or
to write. Callers therefore could not reliably decide which direction to
poll for with stream_select(), which is required to drive a non-blocking
handshake or renegotiation correctly (e.g. SSL_read() wanting a write).

This tracks the last SSL_ERROR_WANT_READ/WANT_WRITE on the stream and
exposes it via a new stream_socket_get_crypto_status() function and three
constants:

  STREAM_CRYPTO_STATUS_NONE
  STREAM_CRYPTO_STATUS_WANT_READ
  STREAM_CRYPTO_STATUS_WANT_WRITE

The status is updated during the handshake (php_openssl_enable_crypto())
and during reads/writes (php_openssl_sockop_io()), reset to NONE before
each operation, and retrieved through a new STREAM_XPORT_CRYPTO_OP_GET_STATUS
transport op. It is meaningful immediately after an operation that
returned 0/false on a non-blocking stream; a completed operation reports
NONE.

Tests cover the status during a non-blocking handshake, a non-blocking
read with no application data pending, and the constant values.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant