#Mismatch in sending tickets incompatible with advertised PSK modes
Problem Description
A focused runtime recheck confirmed a real RFC 8446 Section 4.2.9 mismatch in wolfSSL.
When the client advertises only psk_ke and the server is configured to only allow psk_dhe_ke for PSK-based handshakes, wolfSSL still completes the initial full TLS 1.3 certificate handshake and sends a NewSessionTicket. That ticket is not compatible with the only advertised mode: a follow-up resumption attempt with the saved ticket fails on the server PSK path with PSK_KEY_ERROR.
This report deduplicates multiple candidate-level records that resolved to the same root cause.
Standard Requirement
- Official standard: RFC 8446
- Section: Section 4.2.9 Pre-Shared Key Exchange Modes (lines 2862-2864)
Servers SHOULD NOT
send NewSessionTicket with tickets that are not compatible with the
advertised modes;
Interpretation:
If the client advertises a PSK mode set and the server later sends NewSessionTicket, the ticket should be usable with at least one advertised mode. A ticket that is incompatible with every advertised mode should not be sent.
The key context from RFC 8446 Section 4.2.9 is that psk_key_exchange_modes
does not only constrain PSKs already offered in the current ClientHello; it
also constrains PSKs that the server may later create with NewSessionTicket.
Relevant Source Code
The runtime reproducer matches a concrete source path:
src/tls.c:16724-16735
ClientHello mode advertisement is built directly from the noPskDheKe / onlyPskDheKe options. With wolfSSL_CTX_no_dhe_psk() on the client, the extension advertises only PSK_KE.
/* Some servers do not generate session tickets unless
* the extension is seen in a non-resume client hello.
* We used to send it only if we were otherwise using PSK.
* Now always send it.
*/
/* Pre-shared key modes: mandatory extension for resumption. */
if (!ssl->options.onlyPskDheKe) {
modes = 1 << PSK_KE;
}
if (!ssl->options.noPskDheKe) {
modes |= 1 << PSK_DHE_KE;
}
src/tls13.c:13097-13217
SendTls13NewSessionTicket() creates and sends the ticket after the handshake, but does not check whether the current client's advertised PSK mode set can use that ticket.
if (!ssl->options.noTicketTls13) {
if ((ret = SetupTicket(ssl)) != 0)
return ret;
if ((ssl->options.mask & WOLFSSL_OP_NO_TICKET) == 0) {
if ((ret = CreateTicket(ssl)) != 0)
return ret;
}
}
...
ret = SendBuffered(ssl);
src/tls13.c:7007-7039
On the resumption path, a server configured with wolfSSL_CTX_only_dhe_psk() rejects a client that did not advertise PSK_DHE_KE.
if (((modes & (1 << PSK_DHE_KE)) != 0 && !ssl->options.noPskDheKe &&
ext != NULL)) {
...
}
else if (ssl->options.onlyPskDheKe ||
(ssl->options.failNoPSK && !ssl->options.resuming)) {
return PSK_KEY_ERROR;
}
else {
if ((modes & (1 << PSK_KE)) == 0) {
WOLFSSL_ERROR_VERBOSE(PSK_KEY_ERROR);
return PSK_KEY_ERROR;
}
ssl->options.noPskDheKe = 1;
}
src/tls13.c:15149-15183
wolfSSL_CTX_only_dhe_psk() is not a one-off runtime accident during the
second handshake; it is an explicit server policy stating that PSK handshakes
must use (EC)DHE.
/* Only allow (EC)DHE key exchange when using pre-shared keys. */
int wolfSSL_CTX_only_dhe_psk(WOLFSSL_CTX* ctx)
{
...
ctx->onlyPskDheKe = 1;
...
}
Runtime Evidence
The focused native client/server recheck on 2026-08-03 performed an initial full handshake, captured the delivered session ticket, and attempted a second handshake with that ticket under compatible and incompatible PSK-mode advertisements. It observed:
Observed log excerpt:
compatible_only_dhe: first_handshake_ok first_ticket_count=1 first_ticket_size=210
compatible_only_dhe: first_ticket_count=1 first_ticket_size=210 second_session_reused=1
incompatible_only_dhe: first_handshake_ok first_ticket_count=1 first_ticket_size=210
incompatible_only_dhe: second handshake failed client_err=-313 server_err=-333
The positive control shows the harness can successfully resume an only_dhe_psk ticket when the client advertises a compatible mode. The reproducer shows the same server configuration still sends a ticket after a psk_ke-only advertisement even though that ticket cannot later be used.
Inconsistency Reason
RFC 8446 says the server should not send a NewSessionTicket whose ticket is incompatible with the advertised modes.
wolfSSL does the opposite in the reproduced scenario:
- The client advertises only
psk_ke.
- The server is configured so PSK use requires
psk_dhe_ke.
- The initial certificate handshake succeeds and the server still sends a ticket.
- That ticket cannot be resumed under the advertised mode set and triggers
PSK_KEY_ERROR.
So the runtime behavior proves the ticket was incompatible with every advertised mode at the time it was sent.
Decision Reason
This is a real issue, not a static-only concern. The recheck added both:
- a positive control showing the harness and server configuration can resume tickets when the modes are compatible, and
- a concrete reproducer showing wolfSSL still sends a ticket after a
psk_ke-only advertisement even though the ticket is unusable.
Remaining Uncertainty
Low.
The factual behavior is confirmed by runtime execution. The remaining discussion is only about severity and remediation priority: the RFC text here is SHOULD NOT, but the incompatibility and the unnecessary ticket emission are real.
#Mismatch in sending tickets incompatible with advertised PSK modes
Problem Description
A focused runtime recheck confirmed a real RFC 8446 Section 4.2.9 mismatch in wolfSSL.
When the client advertises only
psk_keand the server is configured to only allowpsk_dhe_kefor PSK-based handshakes, wolfSSL still completes the initial full TLS 1.3 certificate handshake and sends aNewSessionTicket. That ticket is not compatible with the only advertised mode: a follow-up resumption attempt with the saved ticket fails on the server PSK path withPSK_KEY_ERROR.This report deduplicates multiple candidate-level records that resolved to the same root cause.
Standard Requirement
Interpretation:
If the client advertises a PSK mode set and the server later sends
NewSessionTicket, the ticket should be usable with at least one advertised mode. A ticket that is incompatible with every advertised mode should not be sent.The key context from RFC 8446 Section 4.2.9 is that
psk_key_exchange_modesdoes not only constrain PSKs already offered in the current
ClientHello; italso constrains PSKs that the server may later create with
NewSessionTicket.Relevant Source Code
The runtime reproducer matches a concrete source path:
src/tls.c:16724-16735ClientHello mode advertisement is built directly from the
noPskDheKe/onlyPskDheKeoptions. WithwolfSSL_CTX_no_dhe_psk()on the client, the extension advertises onlyPSK_KE.src/tls13.c:13097-13217SendTls13NewSessionTicket()creates and sends the ticket after the handshake, but does not check whether the current client's advertised PSK mode set can use that ticket.src/tls13.c:7007-7039On the resumption path, a server configured with
wolfSSL_CTX_only_dhe_psk()rejects a client that did not advertisePSK_DHE_KE.src/tls13.c:15149-15183wolfSSL_CTX_only_dhe_psk()is not a one-off runtime accident during thesecond handshake; it is an explicit server policy stating that PSK handshakes
must use
(EC)DHE.Runtime Evidence
The focused native client/server recheck on
2026-08-03performed an initial full handshake, captured the delivered session ticket, and attempted a second handshake with that ticket under compatible and incompatible PSK-mode advertisements. It observed:Compatible control:
compatible_only_dhewolfSSL_CTX_only_dhe_psk().1ticket of size210.second_session_reused=1.Incompatible reproducer:
incompatible_only_dhewolfSSL_CTX_no_dhe_psk(), so it advertised onlypsk_ke.wolfSSL_CTX_only_dhe_psk().1ticket of size210.FATAL_ERROR(-313), server errorPSK_KEY_ERROR(-333).Observed log excerpt:
The positive control shows the harness can successfully resume an
only_dhe_pskticket when the client advertises a compatible mode. The reproducer shows the same server configuration still sends a ticket after apsk_ke-only advertisement even though that ticket cannot later be used.Inconsistency Reason
RFC 8446 says the server should not send a
NewSessionTicketwhose ticket is incompatible with the advertised modes.wolfSSL does the opposite in the reproduced scenario:
psk_ke.psk_dhe_ke.PSK_KEY_ERROR.So the runtime behavior proves the ticket was incompatible with every advertised mode at the time it was sent.
Decision Reason
This is a real issue, not a static-only concern. The recheck added both:
psk_ke-only advertisement even though the ticket is unusable.Remaining Uncertainty
Low.
The factual behavior is confirmed by runtime execution. The remaining discussion is only about severity and remediation priority: the RFC text here is
SHOULD NOT, but the incompatibility and the unnecessary ticket emission are real.