aboutsummaryrefslogtreecommitdiffstats
path: root/ssl/statem
Commit message (Collapse)AuthorAgeFilesLines
* TLS: Generate the server random before processing ClientHello extensionsDaniel Kubec4 days1-16/+19
| | | | | | | | | | | | | | | | | | | | | | | The server random was only generated after all of the ClientHello extensions had been processed. In (D)TLSv1.3 the PSK callbacks are invoked while the pre_shared_key extension is being parsed, so a call to SSL_get_server_random() from within them returned all zeros. The TLSv1.2 psk_server_callback runs during ClientKeyExchange processing and so already observed the real value, making the behaviour inconsistent between protocol versions. Move the generation of the server random to immediately after the protocol version has been selected and before any of the remaining ClientHello processing. As a result the server random is also visible from the other callbacks invoked during ClientHello processing, such as the session ticket and servername callbacks. Fixes #26404 Assisted-by: Claude:claude-fable-5-1 Reviewed-by: Tomas Mraz <[email protected]> Reviewed-by: Frederik Wedel-Heinen <[email protected]> Merge-date: Wed Oct 21 16:45:34 2026 Merged-from: https://github.com/openssl/openssl/pull/33102
* Cache decoded certs on client in CTX to avoid multiple asn1 parsingNeil Horman4 days1-13/+22
| | | | | | | | | | | | | | | | | our TLS client path has to do an ASN1 decode on every new connection it establishes. Other TLS stacks (notably rustls) seems to not do this decode, opting instead to to do just enough der parsing to verify the certificate chain. We can't really do that, but we can maybe do some things to speed up this path. Most notably we can cache the received certificate der string in the SSL_CTX along with a previously decoded X509 certificate to avoid the overhead of additional ASN1 parsings in future connections Reviewed-by: Bob Beck <[email protected]> Reviewed-by: Nikola Pajkovsky <[email protected]> Merge-date: Wed Oct 21 16:44:29 2026 Merged-from: https://github.com/openssl/openssl/pull/33085
* Fix TLS 1.3 alert for missing key_shareAnuj Ramesh4 days1-4/+10
| | | | | | | | | | | Fixes #30818 Co-authored-by: Anuj Ramesh <[email protected]> Assisted-by: Claude:claude-fable-5 Reviewed-by: Matt Caswell <[email protected]> Reviewed-by: Frederik Wedel-Heinen <[email protected]> Merge-date: Wed Oct 21 16:29:21 2026 Merged-from: https://github.com/openssl/openssl/pull/32527
* ssl: handle session ID cache lock failureMounir IDRASSI4 days1-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | SSL_has_matching_session_id() returns 0 both when no matching session exists and when the cache lock cannot be acquired. Its use in the built-in generator's retry loop and the final uniqueness check can therefore treat a lock failure as proof that no conflict exists. Add an internal tri-state lookup. The final uniqueness check uses it as a backstop for IDs produced by both built-in and application callbacks, recording an internal fatal error when the cache cannot be checked. The retry loop also uses it to prevent the built-in generator from returning an ID after its own lookup failed, through the existing callback failure path. Preserve the public API's boolean contract. Correct the callback-selection cache lock failure reason from SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED to ERR_R_INTERNAL_ERROR. Remove a redundant caller-side SSLfatal() that appended a generic ERR_R_INTERNAL_ERROR after the specific error already recorded. Add a deterministic unit test for final cache lookup failure. Fixes #32358 Assisted-by: Codex:gpt-5.6-sol Reviewed-by: Tomas Mraz <[email protected]> Reviewed-by: Dmitry Belyavskiy <[email protected]> Merge-date: Wed Oct 21 16:25:29 2026 Merged-from: https://github.com/openssl/openssl/pull/32359
* Don't dereference a NULL rbio in dtls1_read_failed()Matt Caswell5 days1-1/+5
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Connections created by a DTLS listener have no read BIO; they read from a queue that the listener's demux fills. dtls1_read_failed() still set BIO_FLAGS_READ on the read BIO unconditionally once the handshake had finished. A DTLS 1.3 server keeps its retransmission timer armed after the handshake until the client ACKs the NewSessionTickets. A client that never sends that ACK can arrange for the timer to expire while a non-blocking SSL_read() on the server is pumping the demux and finds no record (for example, by sending datagrams the record layer discards). dtls1_read_bytes() then calls dtls1_read_failed(), which crashes on the NULL BIO. Skip setting the flag when there is no read BIO. SSL_get_error() already returns SSL_ERROR_WANT_READ for listener connections without one. The DTLS listener has not been in any final release, so no released version of OpenSSL is affected. Discovered by Anthropic's OSS Scanner (finding ANT-2026-NPC3SFSW). Assisted-by: Claude Code:claude-opus-5-5 Reviewed-by: Tomas Mraz <[email protected]> Reviewed-by: Mounir Idrassi <[email protected]> Reviewed-by: Nikola Pajkovsky <[email protected]> Merge-date: Tue Oct 20 13:30:03 2026 Merged-from: https://github.com/openssl/openssl/pull/33257
* DTLS 1.3: only accept plaintext alerts once the hellos are doneMatt Caswell5 days3-9/+16
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | DTLS 1.3 defers installing the handshake read keys until the peer's first epoch 2 record arrives. Until then the read record layer stays in epoch 0 and accepted plaintext handshake and ACK records. A peer that never sends an epoch 2 record could therefore send its Finished in plaintext. That Finished was checked with a finished key that was never derived (all zero), and the connection completed with its application read keys numbered epoch 1 instead of 3. From that state a client can ACK only the second NewSessionTicket and then send a record claiming epoch 2. The server performs the deferred key change on the established connection, and dtls1_clear_sent_buffer() on the partly acknowledged queue leaves a freed item linked in sent_messages, which is a use-after-free. A malicious server can do the same to a client. Once the hellos are done, tell the epoch 0 read layer that only plaintext alerts may still arrive, and discard any handshake fragments buffered before then. Make tls_process_finished() refuse a DTLS 1.3 Finished read before the handshake keys are installed. Disarm the deferred key change once it has run, and reset it with the connection. DTLS 1.3 has not been in any final release, so no released version of OpenSSL is affected. Discovered by Anthropic's OSS Scanner (finding ANT-2026-YZ5U4MXB). Assisted-by: Claude Code:claude-opus-5-5 Reviewed-by: Tomas Mraz <[email protected]> Reviewed-by: Mounir Idrassi <[email protected]> Reviewed-by: Daniel Kubec <[email protected]> Merge-date: Tue Oct 20 12:38:20 2026 Merged-from: https://github.com/openssl/openssl/pull/33256
* TLS 1.3: Enforce the ticket lifetime when offering a ticketDaniel Kubec6 days1-3/+15
| | | | | | | | | | | | | | | | | | | | | | | | | Bound the effective lifetime to 604800 seconds and treat a zero lifetime as unusable in tls13_check_tick_lifetime_hint(), which gates both the pre_shared_key offer and the early_data advertisement. The cap in the message parser is kept so that SSL_SESSION_get_ticket_lifetime_hint() and the session cache callbacks keep seeing the capped value for tickets received from the wire. - RFC 9846 4.7.1: Servers MUST NOT use any value greater than 604800 seconds (7 days). The value of zero indicates that the ticket should be discarded immediately. Clients MUST NOT use tickets for longer than 7 days after issuance, regardless of the ticket_lifetime, and MAY delete tickets earlier based on local policy. A server MAY treat a ticket as valid for a shorter period of time than what is stated in the ticket_lifetime. Complements: 17bf6c48ea8a "TLS 1.3: Suppress early_data on PSK ticket age mismatch" Complements: 66985198d233 "TLS 1.3: Apply the cap to the lifetime hint in the session" Co-authored-by: Mounir IDRASSI <[email protected]> Reviewed-by: Mounir Idrassi <[email protected]> Reviewed-by: Tomas Mraz <[email protected]> Reviewed-by: Eugene Syromiatnikov <[email protected]> Merge-date: Mon Oct 19 12:37:00 2026 Merged-from: https://github.com/openssl/openssl/pull/32808
* PSK: Check for invalid server PSK ciphersViktor Dukhovni2026-10-091-0/+23
| | | | | | | | | | | | | If an application fails to set the PSK session cipher, or sets it to a TLS 1.2 cipher by mistake, skip the invalid PSK, avoiding a crash or an invalid outcome. Tests added to make sure a full handshake takes place instead. Reviewed-by: Mounir Idrassi <[email protected]> Reviewed-by: Nikola Pajkovsky <[email protected]> Merge-date: Fri Oct 9 13:56:05 2026 Merged-from: https://github.com/openssl/openssl/pull/31925
* Polish psk callback error path cleanupViktor Dukhovni2026-10-092-3/+9
| | | | | | | | | | - Avoid SSL_SESSION leak - Always cleanse the returned PSK secret Reviewed-by: Mounir Idrassi <[email protected]> Reviewed-by: Nikola Pajkovsky <[email protected]> Merge-date: Fri Oct 9 13:56:04 2026 Merged-from: https://github.com/openssl/openssl/pull/31925
* Test PHA verification results across session resumptionMounir IDRASSI2026-10-081-39/+35
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | An application verification callback may accept a nonempty client certificate or RPK while retaining a nonzero verification error. That result must survive post-handshake authentication and resumption, without changing the previously published session. Expand pending-identity coverage to exercise X.509 and RPK replacement with successful and callback-accepted error results, using stateful and stateless refreshed tickets. Check the replacement identity and result on the live connection and session, then on a resumed connection. Also check that the retained cache-owned session remains unchanged. Start empty-RPK tests with a nonzero prior verification result. An optional empty response must remove that stale result, while a required empty response must fail without replacing the previous session state. Document that the empty-response helper retains the SSL_get_verify_result() semantics for an absent peer certificate: X509_V_OK does not establish authentication. The helper does not clear errors for supplied credentials. Remove two unused local pointer resets immediately before successful parse returns. No library verification-result behavior is changed. Validation: debug --strict-warnings build; test_sslapi, test_rpk, test_dtls and test_dtls13_internal all pass (no-fips). Assisted-by: Codex:gpt-6-astra Reviewed-by: Neil Horman <[email protected]> Reviewed-by: Matt Caswell <[email protected]> Reviewed-by: Tomas Mraz <[email protected]> Merge-date: Thu Oct 8 16:16:17 2026 Merged-from: https://github.com/openssl/openssl/pull/32638
* Keep pending client credentials out of cached sessionsMounir IDRASSI2026-10-081-30/+76
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The server retry-verification split in 95dcb1b719 introduced two regressions in client credential handling on master. The parse step stores a received client certificate chain or raw public key in SSL_SESSION before validation has finished. During (D)TLS 1.3 post-handshake authentication, that session may already be published in a server cache. A paused or failed attempt can then expose an unverified identity through an older stateful ticket and can mutate a shared session. The X.509 empty-response path also leaves the previous peer certificate installed. The state machine then expects CertificateVerify and rejects the legal Finished sent by the client. Keep the received credential on SSL_CONNECTION while validation is in progress. Once certificate-chain or RPK validation succeeds, duplicate the PHA session and install the accepted identity in that copy. An allowed empty Certificate now clears the previous client identity, verified chain, matched peer name, verification result, and DANE match state before the state machine chooses between Finished and CertificateVerify. Add coverage for paused validation with a retained cache-owned session, concurrent RPK resumption and rejection, and optional and required empty X.509 and RPK PHA responses, including connection-level DANE state. Fixes: 95dcb1b719a1 "Allow SSL_set_retry_verify() on server session" Assisted-by: Codex:gpt-5.6-sol Reviewed-by: Neil Horman <[email protected]> Reviewed-by: Matt Caswell <[email protected]> Reviewed-by: Tomas Mraz <[email protected]> Merge-date: Thu Oct 8 16:16:16 2026 Merged-from: https://github.com/openssl/openssl/pull/32638
* dtls: honour SSL_OP_COOKIE_EXCHANGE for DTLS 1.3Jakub Zelenka2026-10-063-24/+41
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Setting SSL_OP_COOKIE_EXCHANGE on a server connection only ever produced a HelloVerifyRequest, so once the peer negotiated DTLS 1.3 the option was silently ignored and the client was accepted without any address validation. The HelloRetryRequest cookie code was gated purely on the internal stateless flag, which only SSL_stateless() and the DTLS listener set, leaving no way for an application driving its own per-peer SSL objects with SSL_accept() to get a cookie exchange. Treat the option as "a cookie is required" for DTLS 1.3 as well. A ClientHello without a valid cookie is answered with a HelloRetryRequest carrying one, and the handshake continues only once it is echoed back. The stateless cookie callbacks are used for the application part of the cookie, falling back to the HelloVerifyRequest callbacks so existing servers written for DTLS 1.2 keep working unchanged. A client that repeats its ClientHello after the HelloRetryRequest and still presents no valid cookie now gets an illegal_parameter alert rather than tripping an internal error. The listener is unaffected since it sets both the flag and the option. s_server always sets the option for DTLS, so teach the TLSProxy handshake checker that every DTLS handshake now starts with a cookie round trip. Add a test covering the 1.2 and 1.3 paths, the callback fallback, the missing-callback failure and the PSK-only resumption, and make the dtlsecho demo server validate its peer this way. Assisted-by: Claude:claude-fable-5-1 Reviewed-by: Matt Caswell <[email protected]> Reviewed-by: Mounir Idrassi <[email protected]> Reviewed-by: Tomas Mraz <[email protected]> Merge-date: Tue Oct 6 14:46:56 2026 Merged-from: https://github.com/openssl/openssl/pull/33093
* Omit key_share from a cookie-only HelloRetryRequestJakub Zelenka2026-10-061-4/+8
| | | | | | | | | | | | | | | | | | | | | | | | When the server requires a HelloRetryRequest cookie and the client is resuming with a PSK-only key exchange, no (EC)DHE group is selected, so there is no key_share to process and the group id stays at zero. The HelloRetryRequest construction still treated a missing peer key share as "ask for a different group" and emitted a key_share extension naming group 0, which the client rightly rejects with illegal_parameter. Only include key_share in the HelloRetryRequest when a different group was actually selected, and record the same decision in the cookie so the transcript is reconstructed correctly on the second ClientHello. A DTLS test for this follows with the SSL_OP_COOKIE_EXCHANGE change that exposed it. SSL_stateless() cannot be used for it since it fails the PSK binder check on the second ClientHello for an unrelated reason. Assisted-by: Claude:claude-fable-5-1 Reviewed-by: Matt Caswell <[email protected]> Reviewed-by: Mounir Idrassi <[email protected]> Reviewed-by: Tomas Mraz <[email protected]> Merge-date: Tue Oct 6 14:46:54 2026 Merged-from: https://github.com/openssl/openssl/pull/33093
* Enforce the supported_groups/key_share pairing in TLS 1.3 ClientHellosPaul Grubbs2026-10-021-0/+17
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | RFC 8446, section 9.2, lists the requirements a ClientHello that offers TLS 1.3 must meet, including: If containing a "supported_groups" extension, it MUST also contain a "key_share" extension, and vice versa. An empty KeyShare.client_shares vector is permitted. Servers receiving a ClientHello which does not conform to the requirements in this section MUST abort the handshake with a "missing_extension" alert. The server only enforced half of this: tls_parse_ctos_key_share() rejects a key_share without supported_groups (except when resuming with the psk_dhe_ke mode not offered, where it returns early), but nothing checked the other direction. A PSK resumption ClientHello that carries supported_groups and psk_key_exchange_modes = {psk_ke, psk_dhe_ke} but no key_share was therefore accepted, and resumed with psk_ke, whenever the server allows non-DHE PSK key exchange (SSL_OP_ALLOW_NO_DHE_KEX). Check both directions at the start of the server branch of final_key_share(), which runs for every TLS 1.3 ClientHello (including the one following a HelloRetryRequest) after all extensions have been parsed, using the extension presence recorded in the pre-processed ClientHello like final_psk() already does for psk_key_exchange_modes. A ClientHello with neither extension is still accepted, as permitted for a PSK-only ClientHello. The rule in section 4.2.9 that a client offering psk_dhe_ke supply a key_share is deliberately not enforced here since that text is about the mode the server selects rather than a well-formedness requirement. Add two cases to 70-test_tls13kexmodes.t: a resumption ClientHello with both kex modes and supported_groups but no key_share must now fail with a missing_extension alert, and one with psk_ke only and neither extension must still resume. Fixes #25124 Assisted-by: Claude:claude-fable-5 Reviewed-by: Frederik Wedel-Heinen <[email protected]> Reviewed-by: Mounir Idrassi <[email protected]> Reviewed-by: Tomas Mraz <[email protected]> Merge-date: Fri Oct 2 08:40:59 2026 Merged-from: https://github.com/openssl/openssl/pull/32529
* Bring recent comments into line with the STYLE.md comment rulesBob Beck2026-10-022-17/+10
| | | | | | | | | | | | | | | | Comments added by AI-assisted commits over the last three months often narrate the change rather than describe the code: the behaviour being replaced, the alternative not taken, or the bug the test was written for. STYLE.md now says that a comment states what the code does and the constraint it satisfies, and that the reasoning behind a change does not belong in one. Reword those comments to that standard. Reviewed-by: Milan Broz <[email protected]> Reviewed-by: Neil Horman <[email protected]> Merge-date: Fri Oct 2 08:06:12 2026 Merged-from: https://github.com/openssl/openssl/pull/32779
* Removes redundant SSLv3 version checks and check against TLS1_VERSION_MAJOR ↵Frederik Wedel-Heinen2026-10-022-2/+2
| | | | | | | | | instead of SSL3_VERSION_MAJOR. Reviewed-by: Andrew Dinh <[email protected]> Reviewed-by: Mounir Idrassi <[email protected]> Merge-date: Fri Oct 2 07:28:05 2026 Merged-from: https://github.com/openssl/openssl/pull/31823
* dtls: avoid meaningless retry on EMSGSIZE in dtls1_do_write (#27905)vatsal-dp2026-10-021-3/+10
| | | | | | | | | | | | | When a DTLS send fails with EMSGSIZE, only retry if the MTU actually changed. This avoids repeating a failing send attempt. Fixes #27905 Reviewed-by: Frederik Wedel-Heinen <[email protected]> Reviewed-by: Mounir Idrassi <[email protected]> Reviewed-by: Tomas Mraz <[email protected]> Merge-date: Fri Oct 2 07:10:38 2026 Merged-from: https://github.com/openssl/openssl/pull/29598
* DTLS 1.3: Retain the previous read epoch to recover from lost ACKsRyan Hooper2026-10-022-8/+60
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | After processing the client's Finished or a peer KeyUpdate, the read record layer advanced to the new epoch and the old one was freed immediately. If the ACK we sent for that message was lost, the peer's retransmission arrived at the now-discarded epoch: it could not be authenticated, so no replacement ACK was ever produced and the peer exhausted its retransmission budget. RFC9147 section 5.8.1 requires the finished peer to ACK retransmissions of the other side's final flight, and section 8 requires receive keys from before a KeyUpdate to be retained until decryption with the new keys succeeds. Retain exactly one prior read epoch's record layer instead of freeing it, add a record-layer dispatch hook so the DTLS method can take ownership of it, and authenticate a record at that epoch with its own retained keys and replay window when the current epoch's epoch-bits check would otherwise just drop it. This isn't limited to replacing lost ACKs: a previous *application* epoch (from KeyUpdate recovery) can also legitimately supply application data that arrives reordered relative to the epoch change. Successful authentication with the retained keys doesn't by itself prove a record is a retransmission, so let it reach the handshake layer instead of deciding that here: the DTLS 1.2-only Finished special case (retransmit our own flight) is skipped for DTLS 1.3, and the existing out-of-sequence duplicate-ACK path is widened from post-handshake epochs only to include the epoch a Finished is sent at -- the sequence and epoch checks in that path are what actually decide whether a retained-epoch record can be acknowledged. Fixes: #32891 Assisted-by: Claude:claude-sonnet-5 Reviewed-by: Mounir Idrassi <[email protected]> Reviewed-by: Tomas Mraz <[email protected]> Merge-date: Fri Oct 2 06:36:27 2026 Merged-from: https://github.com/openssl/openssl/pull/32963
* DTLS 1.3: Track sent message ACKs by byte range across retransmitsRyan Hooper2026-10-011-6/+71
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | dtls1_retransmit_message() cleared a message's record numbers right before resending it, keeping only the most recent transmission round's numbers. If the ACK for an earlier round's copy of that record arrived after a retransmission had already happened, it no longer matched anything: the message never retired and its retransmit timer kept running, even though the peer already had it. rfc9147 section 7.2 requires treating a record as acknowledged if it appears in any ACK, and a message can need more than one record per round (a fragmented NewSessionTicket), so matching by record identity alone is not enough either: acking one fragment of one round must not retire a message the peer is still missing other fragments of. Track each sent record's byte range alongside its record number, and stop clearing that list on retransmit so it accumulates across every round instead of only the most recent one. dtls_process_ack() marks the matched range covered in a bitmask mirrored from the receive-side reassembly code, and once a message's full range is covered, drains every remaining record number for it, regardless of which round produced them or whether they were ever individually matched. Fixes: #32975 Assisted-by: Claude:claude-sonnet-5 Reviewed-by: Mounir Idrassi <[email protected]> Reviewed-by: Tomas Mraz <[email protected]> Merge-date: Thu Oct 1 14:18:19 2026 Merged-from: https://github.com/openssl/openssl/pull/32996
* Bound DTLS 1.3 ACK bookkeeping and fit ACKs to recordsMounir IDRASSI2026-09-301-5/+35
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Repeated fragments of an incomplete handshake message can arrive in fresh records without making reassembly progress. Each record adds an ACK entry and scans all previous entries, allowing unbounded storage and quadratic work. Limit the list to 1023 record numbers, the capacity of a maximum-sized plaintext ACK, and check this limit before the duplicate scan. Even a bounded list may exceed the current MTU or configured fragment limit. dtls1_do_write() currently splits the encoded ACK vector without updating its length prefix, so a valid fragmented ticket can cause the peer to abort with SSL_R_LENGTH_TOO_LONG when it reads the ACK. Send complete ACK vectors containing whole 16-byte record numbers within the existing output limits. Reuse two already-sent bytes for each next vector's length prefix, preserving progress across write retries. Report each emitted ACK through the message callback. All retained record numbers are sent, without requiring a state-machine change. Add regressions for repeated fragments while reassembly stays incomplete, and completed ticket exchanges at a small MTU, under a configured fragment limit, and with a write retry between ACK records. The growth test fails on the original code; all three output cases also fail with only the storage cap applied. Validation: 12 DTLS and bad-DTLS test recipes, strict warning compilation of both changed files, and clang-format checks. Additional local diagnostics verified padding, per-record callbacks, and retransmission recovery after ACK-list saturation and completion of a valid ticket. Fixes #32957 Assisted-by: Codex:gpt-6-astra Reviewed-by: Ryan Hooper <[email protected]> Reviewed-by: Frederik Wedel-Heinen <[email protected]> Reviewed-by: Tomas Mraz <[email protected]> Merge-date: Wed Sep 30 08:19:46 2026 Merged-from: https://github.com/openssl/openssl/pull/32958
* ssl/statem/statem_srvr.c: drop needless s->d1 NULL checkEugene Syromiatnikov2026-09-291-3/+1
| | | | | | | | | | | | | | | | | | Remove a needless s->d1 check for NULL in tls_early_post_process_client_hello(), as it is under SSL_CONNECTION_IS_DTLS(s). Reported by Coverity as dereference of potential NULL s->d1 pointer when using s->d1->cookie_len, CID 1700558. Resolves: https://scan5.scan.coverity.com/#/project-view/65248/10222?selectedIssue=1700558 Complements: 2f0ad0d852ea "DTLS 1.3 Limit DTLSv1_listen to DTLS1.2 and add SSL Listener for DTLS" Signed-off-by: Eugene Syromiatnikov <[email protected]> Reviewed-by: Norbert Pocs <[email protected]> Reviewed-by: Nikola Pajkovsky <[email protected]> Reviewed-by: Tomas Mraz <[email protected]> Merge-date: Tue Sep 29 16:43:45 2026 Merged-from: https://github.com/openssl/openssl/pull/32900
* ssl/statem/statem_dtls.c: remove a dead write in dtls1_do_write()Eugene Syromiatnikov2026-09-291-1/+0
| | | | | | | | | | | | | | | | | | Adjusting written for the header size became a dead write after a refactoring in db95a7cac8c3 "Place start of ClientHello correctly when calculating binder for DTLS 1.3", as written is overwritten on each iteration by dtls1_write_bytes() if it returns without an error. The issue was reported by Coverity as an integer underflow, CID 1652003. Resolves: https://scan5.scan.coverity.com/#/project-view/65248/10222?selectedIssue=1652003 Complements: db95a7cac8c3 "Place start of ClientHello correctly when calculating binder for DTLS 1.3" Signed-off-by: Eugene Syromiatnikov <[email protected]> Reviewed-by: Norbert Pocs <[email protected]> Reviewed-by: Nikola Pajkovsky <[email protected]> Reviewed-by: Tomas Mraz <[email protected]> Merge-date: Tue Sep 29 16:43:44 2026 Merged-from: https://github.com/openssl/openssl/pull/32900
* Fix TLS 1.3 ticket age decoding when the offset wrapsMounir IDRASSI2026-09-291-2/+2
| | | | | | | | | | | | | | | | | | | | | | | Subtract the ticket age offset modulo 2^32 before converting to OSSL_TIME. Saturating subtraction turns a wrapped age into zero, which can reject valid early data or let an incorrect age pass the freshness check. Restore modular ticket age subtraction lost in f0131dc04a when libssl moved to OSSL_TIME. This regression first shipped in 3.2.0; 3.0 and 3.1 retain modular subtraction and are not affected. Add TLS and DTLS tests with controlled ages and offsets, checking acceptance and rejection with both stateful and stateless tickets. After rejecting early data, verify that both peers complete session resumption and can exchange ordinary application data. Fixes: https://github.com/openssl/openssl/issues/32834 Assisted-by: Codex:gpt-6-astra Reviewed-by: Matt Caswell <[email protected]> Reviewed-by: Tomas Mraz <[email protected]> Merge-date: Tue Sep 29 16:38:27 2026 Merged-from: https://github.com/openssl/openssl/pull/32889
* dtls: reset init_off before retransmitting a messageRyan Hooper2026-09-291-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | dtls1_retransmit_message() copies a queued message's saved bytes into s->init_buf and sets s->init_num to its length, but left s->init_off untouched. If a different message was still mid-write (suspended on WANT_WRITE, e.g. because the underlying BIO couldn't take any more) when a retransmit fired, s->init_off would still hold whatever offset that suspended write had reached - and dtls1_do_write() would resume the retransmitted message from that stale, unrelated offset instead of from the start. The result is a corrupted retransmission: the message goes out mislabelled with a bogus fragment offset/length, and its body is whatever bytes happen to sit at that offset in the now-repurposed init_buf - typically leftover content from the other, larger message that was mid-write when the retransmit happened, rather than the message actually meant to be sent. Fix this by always resetting s->init_off to 0 before resending, so every retransmit starts from the beginning of the message being sent, regardless of what any other in-progress write had left behind. dtls1_handle_timeout() also needs a guard: if write_state is anything other than WRITE_STATE_TRANSITION, a write is still parked mid-flight from a previous call into the state machine, so there is nothing valid to retransmit yet. Retransmitting anyway would reconstruct an already-sent message from the retransmit queue into s->init_buf/s->init_off/s->init_num/s->d1->w_msg - the same fields the parked write is still using - corrupting that write's state out from under it. Skip retransmission in that case and let the next SSL_read()/SSL_write()/SSL_accept()/SSL_connect() call resume the parked write normally instead. Add test_dtls_client_retransmit() and test_dtls_server_retransmit() to test/dtlstest.c, covering both directions on DTLS1.2: use a fragment-limiting BIO to suspend a large in-flight write mid-fragment, then fire the retransmit timer several times via DTLSv1_get_timeout()/DTLSv1_handle_timeout() while it stays parked, verifying no retransmission is attempted and the suspended write's state is reproduced unchanged on every timer fire, and that resuming the write afterward completes as an ordinary handshake continuation instead of hitting dtls1_do_write()'s entry assertion. Also add test_dtls_client_retransmit_dtls13() and test_dtls_server_retransmit_dtls13() covering the same guard under DTLS1.3. Both rely on the same write-call-count invariant rather than a byte-for-byte comparison, since only the plaintext portion of the flight (ClientHello on the client side, ServerHello on the server side) is exchanged at epoch zero - everything sent under a non-zero epoch is encrypted and legitimately differs on every retransmit regardless of this fix. Assited-by: Claude:claude-sonnet-5 Fixes: CVE-2026-84782 Reviewed-by: Milan Broz <[email protected]> Reviewed-by: Tomas Mraz <[email protected]> Merge-date: Tue Sep 29 11:17:20 2026
* Suppress unusable PSK offers and 0-RTT client-sideViktor Dukhovni2026-09-233-64/+167
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Check that offered PSKs and early data can actually be used before sending them, rather than offering them and letting the server refuse. - Offer a resumption ticket or accept a psk_use_session callback PSK only if some offered TLS 1.3 ciphersuite shares the PSK's handshake digest. Otherwise the PSK is unusable: retire the ticket (falling through to the next candidate) or drop the callback PSK. - Attempt 0-RTT only when the first-offered PSK's exact ciphersuite is offered and its ALPN, if any, is among those offered; otherwise suppress early data but keep the PSK for a 1-RTT handshake. An ALPN inconsistency detected by the client was previously fatal (SSL_R_INCONSISTENT_EARLY_DATA_ALPN); it now suppresses 0-RTT only. - Reject a psk_use_session callback PSK with an empty master key with SSL_R_BAD_PSK instead of failing later in binder computation. Along the way, to compare handshake digests, factor the digest lookup out of SSL_CIPHER_get_handshake_digest() into a new internal helper ssl_cipher_get_handshake_digest_nid(). The client now declines PSKs and 0-RTT it cannot use, so several sslapitest early data tests are adjusted to offer a client configuration under which 0-RTT still proceeds, keeping their tests of server-side rejection effective. Also add test_tls13_ticket_cipher_mismatch_reject_early_data, covering server-side 0-RTT rejection on a cipher mismatch with a resumption ticket; only the external-PSK cipher mismatch was previously tested. All the while keep the client's PSK and 0-RTT offer self-consistent: When resuming with a PSK and offering 0-RTT early data, the client decided the same things in more than one place: whether the resumption ticket is usable, which PSK it offers first, and whether that PSK's cipher is actually on the wire. These were worked out separately while building the early_data and pre_shared_key parts of the ClientHello and could disagree -- notably when the application's security callback does not give the same answer each time it is consulted. That disagreement could break confidentiality. If early data was set up against the resumption ticket but the ticket was then dropped while the pre_shared_key extension was built, its binder never ran, the early secret was left all zero, and the client still encrypted its 0-RTT data under keys derived from that zero value -- which a passive observer can reconstruct from the visible ClientHello alone. Decide once and reuse the result: - Settle whether the ticket is offered when early data is prepared, and have the pre_shared_key extension follow that decision instead of computing it again. - Do not install the client's 0-RTT keys unless the first offered PSK actually derived the early secret during this handshake, so 0-RTT is never protected by an all-zero key. - Count a cipher as offered only if it was placed in the ClientHello, so 0-RTT is not advertised for a cipher the security callback kept off the wire. - After a HelloRetryRequest, do not add a PSK the first ClientHello did not carry. Add tests for the suppressed-0-RTT and HelloRetryRequest cases. Assisted-by: Claude:claude-opus-4-8 Reviewed-by: Mounir Idrassi <[email protected]> Reviewed-by: Norbert Pocs <[email protected]> Reviewed-by: Nikola Pajkovsky <[email protected]> MergeDate: Wed Sep 23 14:44:15 2026 (Merged from https://github.com/openssl/openssl/pull/32542)
* dtls: read the rest of a DTLS 1.3 ACK body from the current recordMounir IDRASSI2026-09-221-16/+21
| | | | | | | | | | | | | | | An ACK never spans records (RFC 9147 section 4), so once the first DTLS1_HM_HEADER_LENGTH bytes are read, the remainder of the body is exactly what is left in the current record. Take it directly instead of calling ssl_read_bytes() a second time: that call re-enters the timeout handling and can overwrite the ACK bytes already copied into init_buf. Assisted-by: pi:kimi-k3 Reviewed-by: Matt Caswell <[email protected]> Reviewed-by: Tomas Mraz <[email protected]> Merge-date: Tue Sep 22 15:47:56 2026 Merged-from: https://github.com/openssl/openssl/pull/32871
* DTLS: preserve outstanding flights after incomplete ACKsMounir IDRASSI2026-09-214-4/+73
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Do not finish reading after a DTLS 1.3 ACK while sent records remain unacknowledged. Finishing reading stops the retransmit timer and clears the entire sent queue, even for an empty or partial ACK. Restore the preceding handshake state when ACK processing continues. This preserves application-data handling and allows the expected post-handshake authentication response to follow an incomplete ACK. Limit the ACK epoch restriction to the initial handshake. Subsequent sending and receiving epochs can differ, and the old restriction produced empty ACKs for repeated unilateral KeyUpdates. Those exchanges previously depended on the receive-side coverage bug to complete. Exercise empty, nonmatching, partial and duplicate ACKs on both peers, followed by application data and complete acknowledgement. Correct two existing KeyUpdate tests which relied on unrelated ACKs clearing the sent queue. The regression fails on the parent. All 15 selected DTLS and SSL recipes pass with --strict-warnings, including the default and FIPS SSL API runs. Fixes openssl#32853 Assisted-by: Codex:gpt-6-astra Reviewed-by: Matt Caswell <[email protected]> Reviewed-by: Ryan Hooper <[email protected]> Merge-date: Mon Sep 21 09:48:30 2026 Merged-from: https://github.com/openssl/openssl/pull/32854
* Bound the DTLS 1.3 ACK body read by the record, not init_numMatt Caswell2026-09-181-3/+9
| | | | | | | | | | | | | | | | | | | | | | | | | dtls_get_reassembled_message() reads an ACK in two steps: the first DTLS1_HM_HEADER_LENGTH bytes, then the rest. The second read was bounded by "s->init_num - DTLS1_HM_HEADER_LENGTH", but s->init_num does not describe this message -- the read state machine zeroes it after the previous one, so the subtraction usually underflows to near SIZE_MAX. Ask for what is left of the record instead: an ACK never spans records. The read also has to stop when the first one emptied the record. An ACK body is 2 + 16n bytes, so a record holding exactly DTLS1_HM_HEADER_LENGTH bytes of body is malformed, and is spent by the time we look at it. The old bound sent the second read after another record, which appended whatever arrived next -- an ACK, or a handshake message -- to the ACK body and lost it. Because that bound was not a bound at all, a full sized record appended there would also have run past the end of s->init_buf, which is SSL3_RT_MAX_PLAIN_LENGTH long. Assisted-by: Claude Code:claude-opus-5 Reviewed-by: Mounir Idrassi <[email protected]> Reviewed-by: Ryan Hooper <[email protected]> Merge-date: Fri Sep 18 14:14:28 2026 Merged-from: https://github.com/openssl/openssl/pull/32783
* DTLS: reject trailing bytes after the ACK record number vectorMounir IDRASSI2026-09-181-1/+1
| | | | | | | | | | | | | | | | Require the length-prefixed record number vector to consume the entire DTLS 1.3 ACK body. Previously, dtls_process_ack() ignored bytes following the vector. Add direct parser tests for empty and single-entry ACKs, both with and without trailing data. Both trailing-data cases are accepted without the fix, while the valid encodings remain accepted with it. Assisted-by: Codex:gpt-6-astra Reviewed-by: Matt Caswell <[email protected]> Reviewed-by: Frederik Wedel-Heinen <[email protected]> Merge-date: Fri Sep 18 09:22:41 2026 Merged-from: https://github.com/openssl/openssl/pull/32850
* dtls: Don't check for NULL when it can't beNorbert Pocs2026-09-171-3/+1
| | | | | | | | | | | | | | In dtls context SSL_CONNECTION->d1 is always set by dtls1_new(), therefore checking for it only makes the static analysis to think it can be otherwise and the variable can be dereferenced later in the function. Fixes coverity issue 1700558 and 1700557. Signed-off-by: Norbert Pocs <[email protected]> Reviewed-by: Neil Horman <[email protected]> Reviewed-by: Andrew Dinh <[email protected]> Merge-date: Thu Sep 17 16:51:00 2026 Merged-from: https://github.com/openssl/openssl/pull/32666
* dtls: Add missing pqueue freeNorbert Pocs2026-09-171-1/+4
| | | | | | | | | | Fixes coverity issue 1700559. Signed-off-by: Norbert Pocs <[email protected]> Reviewed-by: Neil Horman <[email protected]> Reviewed-by: Andrew Dinh <[email protected]> Merge-date: Thu Sep 17 16:50:59 2026 Merged-from: https://github.com/openssl/openssl/pull/32666
* statem: fail ClientHello construction on ECH GREASE failureJakub Zelenka2026-09-161-1/+1
| | | | | | | | | | | | | | | | tls_construct_ctos_ech() called SSLfatal() on an ECH GREASE construction failure but returned EXT_RETURN_NOT_SENT, so extension construction reported success while the connection was already in the fatal error state. The ClientHello would still be sent together with the fatal alert and the state machine kept running until it tripped over the error state later. Return EXT_RETURN_FAIL to fail the construction immediately. Assisted-by: Claude:claude-fable-5 Reviewed-by: Matt Caswell <[email protected]> Reviewed-by: Tomas Mraz <[email protected]> Merge-date: Wed Sep 16 09:31:48 2026 Merged-from: https://github.com/openssl/openssl/pull/32201
* Fix double free in server client-certificate parse error pathMounir IDRASSI2026-09-161-0/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Commit 95dcb1b719a1 ("Allow SSL_set_retry_verify() on server session") split the server client-certificate processing path so that applications can retry verification on the server side. During that reshuffle, tls_process_client_certificate() lost the ownership-clearing assignment after sk_X509_push(sk, x). When parsing an X.509 client Certificate message, if at least one certificate is parsed successfully and malformed trailing data then makes the next loop iteration fail its length checks, x still aliases the previous stack-owned certificate. The err path frees x and then frees the stack, causing a second X509_free() on the same object. That second free performs an atomic reference count update on freed heap storage. The observable runtime effect is allocator- and build-dependent: a normal functional handshake test may still see only the expected parse-time decode_error, while ASan, valgrind, or enabled refcount assertions detect the invalid access. Restore the ownership-clearing assignment after the stack push. Add a TLS 1.2 memory-BIO regression test which sends one valid DER-encoded client certificate followed by malformed trailing data and checks that the server rejects it with decode_error / SSL_R_CERT_LENGTH_MISMATCH. Fixes: 95dcb1b719a1 ("Allow SSL_set_retry_verify() on server session") Assisted-by: pi:kimi-k3 Reviewed-by: Jakub Zelenka <[email protected]> Reviewed-by: Viktor Dukhovni <[email protected]> Merge-date: Wed Sep 16 08:43:45 2026 Merged-from: https://github.com/openssl/openssl/pull/32627
* Free WPACKETs on error pathsNorbert Pocs2026-09-151-1/+3
| | | | | | | | | | Fixes coverity issue 1700560. Signed-off-by: Norbert Pocs <[email protected]> Reviewed-by: Neil Horman <[email protected]> Reviewed-by: Jakub Zelenka <[email protected]> Merge-date: Tue Sep 15 10:11:12 2026 Merged-from: https://github.com/openssl/openssl/pull/32663
* Fix clang-format violation in tls_process_client_hello()Matt Caswell2026-09-071-1/+1
| | | | | | | | | | | | | | | | | | | Fix a minor style violation in ssl/statem/statem_srvr.c. The violation arrived with the DTLS 1.3 series and was never caught locally, because git rebase does not run the pre-commit hooks over the commits it replays. CI did not catch it either: the check-style job enumerates a pull request's changed files with `gh pr view --json files`, which returns at most 100 entries, and the DTLS 1.3 pull request changed 186 files -- ssl/statem/statem_srvr.c fell outside the checked set. The following commit fixes that workflow bug. Assisted-by: Claude:claude-opus-5 Reviewed-by: Nikola Pajkovsky <[email protected]> Reviewed-by: Paul Dale <[email protected]> Reviewed-by: Tomas Mraz <[email protected]> Merge-date: Mon Sep 7 14:09:39 2026 Merged-from: https://github.com/openssl/openssl/pull/32516
* Keep GREASE key shares valid after HelloRetryRequestF1xGOD2026-09-011-2/+8
| | | | | | | | | | | | | | | | | | | | SSL_OP_GREASE prepends a reserved key share to every ClientHello. When a server requests a new group in a HelloRetryRequest, the second ClientHello must contain only the requested key share. The extra GREASE entry therefore causes the handshake to fail with a bad key share error. Omit the GREASE key share only when the retry requests a replacement. Retain it for cookie-only retries, where the original key share must be repeated. Extend the GREASE test to capture both ClientHellos and cover selected-group and stateless cookie retries. Assisted-by: Codex:gpt-5.6-sol Reviewed-by: Richard Levitte <[email protected]> Reviewed-by: Mounir Idrassi <[email protected]> Reviewed-by: Tomas Mraz <[email protected]> Merge-date: Tue Sep 1 14:40:03 2026 Merged-from: https://github.com/openssl/openssl/pull/32505
* TLS 1.3: Apply the cap to the lifetime hint in the sessionDaniel Kubec2026-09-011-1/+1
| | | | | | | | | | | | | | | | | | | | | | | Commit 5a85e41 added a 7 day cap on the TLSv1.3 ticket lifetime as required by RFC 9846, but applied it to a local variable after the value had already been stored in the session and after its last use, so it had no effect. The uncapped value was still returned by SSL_SESSION_get_ticket_lifetime_hint() and used by the client when deciding whether to offer the ticket for resumption. Apply the cap to the lifetime hint in the session. - RFC 9846 4.7.1: Servers MUST NOT use any value greater than 604800 seconds (7 days). The value of zero indicates that the ticket should be discarded immediately. Clients MUST NOT use tickets for longer than 7 days after issuance, regardless of the ticket_lifetime, and MAY delete tickets earlier based on local policy. Fixes #32244 Reviewed-by: Tom Cosgrove <[email protected]> Reviewed-by: Richard Levitte <[email protected]> Reviewed-by: Mounir Idrassi <[email protected]> Merge-date: Tue Sep 1 13:47:48 2026 Merged-from: https://github.com/openssl/openssl/pull/32240
* Allow SSL_set_retry_verify() on server sessionwfurt2026-08-272-51/+108
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Split server-side client-certificate processing into a parse phase (tls_process_client_certificate) and a post-process verification phase (tls_post_process_client_certificate), mirroring the existing client-side tls_process_server_certificate / tls_post_process_server_certificate split. Split tls_process_client_rpk() into a parse phase and a new post-process phase (tls_post_process_client_rpk), mirroring the client-side RPK split. tls_post_process_client_certificate() now dispatches to the RPK helper based on client_cert_type, so an application verify callback can call SSL_set_retry_verify() during server-side RPK verification and SSL_accept()/SSL_do_handshake() returns SSL_ERROR_WANT_RETRY_VERIFY. This lets an application's verify callback call SSL_set_retry_verify() during server-side client-cert verification: the post-process step now returns WORK_MORE_A so SSL_accept()/SSL_do_handshake() returns SSL_ERROR_WANT_RETRY_VERIFY, and re-entry resumes verification once the application has supplied a verdict. Until now SSL_set_retry_verify was documented as supported but only worked on the client. A new regression test (test_server_cert_verify_cb in test/sslapitest.c) exercises the server-side retry-verify path end-to-end. Update SSL_set_retry_verify and SSL_CTX_set_cert_verify_callback documentation to describe client and server retry-verify flow. Fixes https://github.com/openssl/openssl/issues/30068 Reviewed-by: Viktor Dukhovni <[email protected]> Reviewed-by: Andrew Dinh <[email protected]> Merge-date: Thu Aug 27 13:35:46 2026 Merged-from: https://github.com/openssl/openssl/pull/31485
* PSK: Fix ALPN handlingDaniel Kubec2026-08-272-0/+40
| | | | | | | | | | | | | | | | | | | | | | | Prevent acceptance of 0-RTT data when the negotiated ALPN protocol differs from the one associated with the session used for early data, and complete an abbreviated handshake without processing early data. Clear stale ALPN in client-side session on ticket receipt, tls_process_new_session_ticket() (client) never updated s->session->ext.alpn_selected when installing a new ticket, so a session that had negotiated ALPN on an earlier connection kept reporting that protocol even after a later resumption negotiated a different one, or none at all. Assisted-by: Claude:claude-opus-4-8 Fixes #11197 Reviewed-by: Neil Horman <[email protected]> Reviewed-by: Tomas Mraz <[email protected]> Reviewed-by: Viktor Dukhovni <[email protected]> MergeDate: Thu Aug 27 08:34:15 2026 (Merged from https://github.com/openssl/openssl/pull/32401)
* Make the TLS 1.3 resumption PSK check aware of DTLS 1.3Matt Caswell2026-08-251-1/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | tls13_check_resumption_psk() tells tls_construct_ctos_early_data() whether the resumption session can key 0-RTT, but compared the session version against TLS1_3_VERSION only. A DTLS 1.3 session records DTLS1_3_VERSION, so the check never matched for DTLS. The caller then fell back to the external PSK session, which is NULL when resuming, and took the suppression path: max_early_data was set to 0, early_data_suppressed was set, and the early_data extension was not sent. SSL_connect() ran an ordinary handshake and returned WANT_READ with an empty error queue, so SSL_write_early_data() returned 0 with nothing to indicate why. Compare against DTLS1_3_VERSION for DTLS, using the version1_3 idiom the calling function already uses. The helper is newer than the DTLS 1.3 work: it was factored out of tls_construct_ctos_early_data() after that function had been made version aware, so it never picked up the DTLS case. Fixes the DTLS 1.3 iterations of nine sslapitest early data tests. Assisted-by: Claude Code:claude-opus-5 Reviewed-by: Ryan Hooper <[email protected]> Reviewed-by: Tomas Mraz <[email protected]> Merge-date: Fri Aug 21 18:10:39 2026 Merged-from: https://github.com/openssl/openssl/pull/32441
* DTLS 1.3 Fix no-dtls1_3 build configuration CI failuresRyan Hooper2026-08-251-0/+4
| | | | | | | | | | | | | | | | | | | | Guard the DTLS1_3_VERSION entry in dtls_version_table with OPENSSL_NO_DTLS1_3 (NULL fallback), matching the pattern used by tls_version_table for TLS1_3. Add a min_version clamp for DTLS1_3 in ssl_check_allowed_versions() to fix SSL_CTX_set_min_proto_version() incorrectly returning failure under no-dtls1_3, caused by DTLS inverted wire-number ordering making the range check fire after max was clamped to DTLS1_2. Guard _dtls13 test functions and their ADD_TEST calls in dtlstest.c. Guard DTLS 1.3-only helpers and tests in dtlsssllistenertest.c, and move SSL_poll tests outside the DTLS 1.3 guard so they run for any DTLS version. Add no-dtls1_3 to the daily CI checker matrix. Assisted-by: Claude:claude-sonnet-4-6 Reviewed-by: Tomas Mraz <[email protected]> Reviewed-by: Matt Caswell <[email protected]> Merge-date: Thu Aug 20 09:55:41 2026 Merged-from: https://github.com/openssl/openssl/pull/32340
* Reject HelloRequest in TLS and DTLS 1.3Mounir IDRASSI2026-08-251-9/+20
| | | | | | | | | | | | | | | | | TLS and DTLS 1.3 reserve handshake message type 0, but legacy client-side HelloRequest skip paths could consume such messages before the state machines rejected them. Keep the skip paths only for connections that cannot use TLS or DTLS 1.3. Add TLSProxy coverage for TLS and DTLS 1.3 rejection, and for the preserved TLS and DTLS 1.2 legacy behavior. The DTLS test insertion also adjusts record sequencing so the injected HelloRequest is a valid standalone server record. Reviewed-by: Andrew Dinh <[email protected]> Reviewed-by: Matt Caswell <[email protected]> Merge-date: Mon Aug 17 08:32:42 2026 Merged-from: https://github.com/openssl/openssl/pull/31637
* DTLS 1.3 SSL Listener does not currently buffer handshake messagesRyan Hooper2026-08-251-8/+8
| | | | | | | | | | | | | | Now when a buffer BIO is created for the initial DTLS handshake from an SSL listener messages are now buffered until a flush is called. Fixes: openssl/project#1982 Assisted-by: Claude:claude-opus-4-7 Reviewed-by: Matt Caswell <[email protected]> Reviewed-by: Jakub Zelenka <[email protected]> MergeDate: Tue Aug 11 14:41:07 2026 (Merged from https://github.com/openssl/openssl/pull/31979)
* DTLS 1.3 Don't reset the handshake seq number after connection finishRyan Hooper2026-08-251-3/+10
| | | | | | | | | | | | | | | | In DTLS 1.3 the handshake sequence number is not reset to 0 after the connection is establish. This means New Session tickets will not send out with a handshake seq of 0. Instead it will pick up where it left off. Fixes: openssl/project#2008 Assisted-by: Claude:claude-opus-4-7 Reviewed-by: Frederik Wedel-Heinen <[email protected]> Reviewed-by: Paul Dale <[email protected]> Reviewed-by: Tomas Mraz <[email protected]> MergeDate: Mon Jul 27 12:20:10 2026 (Merged from https://github.com/openssl/openssl/pull/31978)
* DTLS 1.3 Fix CI failuresRyan Hooper2026-08-252-4/+13
| | | | | | | | | | Need to fix a deprecated API in dtlsecho. Also updated the sslecho usage information since it is no longer correct. Reviewed-by: Frederik Wedel-Heinen <[email protected]> Reviewed-by: Tomas Mraz <[email protected]> MergeDate: Thu Jul 16 07:29:15 2026 (Merged from https://github.com/openssl/openssl/pull/31935)
* DTLS 1.3 Limit DTLSv1_listen to DTLS1.2 and add SSL Listener for DTLSRyan Hooper2026-08-252-32/+98
| | | | | | | | | | | | | | | | | | | DTLSv1_listen will not support DTLSv1.3. Instead its max version is DTLSv1.2 Adding DTLS SSL Listener that utilizes a similar DEMUX approach as QUIC and passes traffic through the URXE structure. This will establish full connection and an application can ask for a ready SSL connection. The DTLS SSL listener also supports HVR and HRR cookie validation. Fixes: openssl/project#1946 Reviewed-by: Tomas Mraz <[email protected]> Reviewed-by: Matt Caswell <[email protected]> MergeDate: Mon Jul 6 09:29:09 2026 (Merged from https://github.com/openssl/openssl/pull/31137)
* DTLS 1.3 Demo and Bug FixRyan Hooper2026-08-251-4/+8
| | | | | | | | | | | | | | | | | | Added a DTLS 1.3 demo based off of the SSL echo demo. The client takes input from the user and sends it to the server. The server echos that input back. There was a bug if the server retransmitted New Session tickets cause it didn't receive the ACK for the first set of New Session tickets. The changes outside of the demo application are to fix that bug. Fixes: openssl/project#1943 Reviewed-by: Frederik Wedel-Heinen <[email protected]> Reviewed-by: Tomas Mraz <[email protected]> MergeDate: Wed May 27 08:02:57 2026 (Merged from https://github.com/openssl/openssl/pull/31042)
* DTLS 1.3 Interop Issue with NSS using ChaCha20Ryan Hooper2026-08-251-2/+2
| | | | | | | | | | | | | | | When using ChaCha20 for DTLS1.3 the encrypted sequence number was never being decrypted properly. Instead it was always a larger number. Updated the dlts_crypt_sequence_number to match the RFC. Fixes: openssl/project#1929 Reviewed-by: Frederik Wedel-Heinen <[email protected]> Reviewed-by: Tomas Mraz <[email protected]> MergeDate: Thu Apr 30 09:55:50 2026 (Merged from https://github.com/openssl/openssl/pull/30807)
* Addressing how DTLS 1.3 handles Read Record Layer transitions.Ryan Hooper2026-08-253-3/+26
| | | | | | | | | | | | | | | | | | | | Currently the state machine moves the read record layer to the next epoch base off of state events. The problem with this is when either the client or the server sent out a record during the handshake that causes an alert. If the state machine moved either the client or server to the next epoch it will not be able to handle that alert message. This approach delays moving the read record layer to the next epoch until we actually receive a record in that epoch. This allows us to process the alert messages. Fixes: openssl/project#1786 Fixes: openssl/project#1785 Reviewed-by: Matt Caswell <[email protected]> Reviewed-by: Frederik Wedel-Heinen <[email protected]> MergeDate: Thu Apr 16 17:22:48 2026 (Merged from https://github.com/openssl/openssl/pull/29946)
* DTLS 1.3 Enable Resumption TestsRyan Hooper2026-08-251-13/+21
| | | | | | | | | | | | Enable teh DTLS resumption tests for DTLS1.3. Fixes: openssl/project#1794 Reviewed-by: Frederik Wedel-Heinen <[email protected]> Reviewed-by: Tomas Mraz <[email protected]> Reviewed-by: Matt Caswell <[email protected]> MergeDate: Mon Mar 16 11:07:16 2026 (Merged from https://github.com/openssl/openssl/pull/30258)