Uh oh!
There was an error while loading. Please reload this page.
openssl: Introduce TLS PSK support - #22057
Conversation
Add stream context options psk_client_cb and psk_server_cb that let clients and servers negotiate pre-shared key authentication on both TLS 1.2 and TLS 1.3. Callbacks return an Openssl\Psk instance carrying the key and, on clients, the identity, or null to refuse PSK. A new final Openssl\Psk class is added for that purpose, with readonly $psk and $identity properties and MAX_PSK_LEN / MAX_IDENTITY_LEN constants.
Uh oh!
There was an error while loading. Please reload this page.
| zval client_cb; | ||
| zval server_cb; |
There was a problem hiding this comment.
You should store the callbacks as FCCs rather than zvals.
There was a problem hiding this comment.
We should address it in the follow up PR to cover sessions as well.
| } | ||
| ZVAL_UNDEF(&retval); | ||
| call_user_function(NULL, NULL, cb, &retval, argc, args); |
There was a problem hiding this comment.
Store the callback as a FCC and use zend_call_known_fcc() instead of call_user_function(), as this checks every single time if the zval is a callable, something that should be checked prior to saving it.
| if (!zend_is_callable_ex(callable, NULL, 0, NULL, NULL, &is_callable_error)) { | ||
| if (is_callable_error) { | ||
| zend_type_error("%s must be a valid callback, %s", | ||
| callback_name, is_callable_error); | ||
| efree(is_callable_error); | ||
| } else { | ||
| zend_type_error("%s must be a valid callback", callback_name); | ||
| } | ||
| return FAILURE; | ||
| } | ||
| if (!sslsock->psk_callbacks) { | ||
| sslsock->psk_callbacks = (php_openssl_psk_callbacks_t *)pemalloc( | ||
| sizeof(php_openssl_psk_callbacks_t), is_persistent); | ||
| ZVAL_UNDEF(&sslsock->psk_callbacks->client_cb); | ||
| ZVAL_UNDEF(&sslsock->psk_callbacks->server_cb); | ||
| sslsock->psk_callbacks->refcount = 1; | ||
| } |
There was a problem hiding this comment.
Instead of storing the callbacks as zvals, pass an FCC as a storage to zend_is_callable_ex()
| ZEND_PARSE_PARAMETERS_END(); | ||
| if (ZSTR_LEN(psk) == 0) { | ||
| zend_argument_value_error(1, "must not be empty"); |
There was a problem hiding this comment.
| zend_argument_value_error(1, "must not be empty"); | |
| zend_argument_must_not_be_empty_error(1); |
There was a problem hiding this comment.
Will be done in the follow up PR as well as you are picking it up
bukka
commented
May 25, 2026
Gina is picking up the follow up bits so merging in this form as further improvements will be done seperately - they should be done in a separate PR as it applies to TLS session callback |
Adds pre-shared key authentication for OpenSSL streams, covering both TLS 1.2 (PSK ciphersuites) and TLS 1.3 (PSK as an external resumed session).
The
Openssl\Pskclass is following:Two new options under the
sslcontext:psk_client_cb:callable(resource $stream): ?Openssl\PskCalled on the client during the handshake to obtain the PSK and identity. Return
nullto decline PSK. The returnedPskmust have a non-null identity.psk_server_cb:callable(resource $stream, string $identity): ?Openssl\PskCalled on the server with the identity offered by the client. Return
nullto reject the identity. Only the key is read from the returnedPsk.For TLS 1.3 servers a default
session_id_contextis installed when the user does not supply one, since OpenSSL processes PSK as session resumption and would otherwise reject the constructedSSL_SESSIONwithSSL_R_SESSION_ID_CONTEXT_UNINITIALIZEDunder the defaultSSL_VERIFY_PEERconfiguration. An explicitsession_id_contextstill takes precedence.The RFC is not planned unless there are objections as it mirrors the previous Session proposal including all API decisions from it.