Repository navigation
DTLS v1.3 #5000
Description
Activity
Originally posted here, but this ticket is probably more appropriate.
It turns out we have a use case for DTLS 1.3 and will likely start working on an implementation based on the existing TLS 1.3 code. I did a first read-through of RFC 9147 and below are some scratchy notes on what probably has to be done. At this point, we're not ready to provide an exact time frame for this, but it should be measured in months not in years.
TL;DR: We'll probably need alternative implementations or significant extensions of
TLS::Record_Layer,TLS::Handshake_Layer, andTLS::Cipher_State. All the higher layers of the protocol, particularly the implementation of the actual handshake messages and the TLS state machines inTLS::[Client/Server]_Impl_13can probably stay mostly untouched.-
Record Layer
- Support demux of DTLS records ✅
- Handling of Epoch and Sequence Number ✅
- Deprotection of Epoch/SeqNumber (see here) ✅
- Replay protection via a sliding window per epoch ✅
-
Handshake Layer
- Fragmentation (additional header values + handling of them) ✅
Note: Transcript hash is calculated from the TLS marshalling (w/o the additional headers) - Allow re-fragmenting handshake messages if necessary (MTU discovery)
- Timeout and Retransmission ✅
- Handle the retransmission state machine (see RFC 9147 Section 5.8.1)
- Example: https://www.rfc-editor.org/rfc/rfc9147.html#section-6
- Probably
Handshake_Layer_13will need to be able to actively create messages (i.e. ACKs)
- Fragmentation (additional header values + handling of them) ✅
-
Key Management in
Cipher_State- Explicit cipher state handling (Epochs) ✅
Out-of-order messages at epoch boundaries requires keeping multiple sets of keys for some period ✅ - Adopt DTLS-specific HKDF labels ✅
- Explicit cipher state handling (Epochs) ✅
-
Handshake Messages and Extensions
-
ClientHello/HelloRetryRequest
- Add active support of the Cookie extension for DoS protection in the server implementation. ✅
- Optionally always enforce Hello Retry Request (see also here) ✅
-
Client Hello
- additionally contains a legacy_cookie field from DTLS 1.2 ✅
-
ACK Message ✅
-
Optional? New Post-Handshake Message: RequestConnectionID
-
Optional? New Post-Handshake Message: NewConnectionID
-
Optional? Connection_ID extension
-
-
Misc
- DTLS 1.3 does not support TLS 1.3 "compatibility mode" ✅
- RFC 9147 5.11 specifies epoch0-restart (e.g. re-association after a client restarted): we'll likely not implement this in DTLS 1.3, see also: Bound DTLS handshake retry attempts and properly abandon timed out states #5793 (comment) ✅
-
@atreiber94 and I are starting to work on this. It'll be some time before anything lands of course. We're planning to introduce a new
dtls13module that allows disabling support for DTLS 1.3 at compile time and to centralize DTLS-variants of the internal TLS structures. If it appears sensible, we might -- at some point -- flag this new module as "experimental" and start opening pull requests for integration even before the full implementation is ready to go.At this point, we don't expect a fully functional implementation to be ready in time for Botan 3.13 but certainly 3.14 is a reasonable goal.
FYI: @randombit
Reacted by Jack Lloyd@reneme Great. FYI I have a WIP branch addressing some issues with DTLS 1.2 handshaking (retransmit logic, etc) I'll try to get that up ASAP to minimize conflicts.
@atreiber94 and I are happy to report that our prototypical DTLS implementation just passed essentially all BoGo tests that seem reasonable to enable at this point. Note-worthy omissions include
proper support for SRTPand the ability to re-fragment messages to react to changing PMTU requirements. We think that both are reasonable additions after upstreaming the current feature set.Major clean-up, unittest and refactoring work is still needed. We hope to create some more preparatory PRs that introduce hooks and abstractions in the existing TLS 1.3 machinery. In the best case, the final DTLS PR should then contain mostly additions to
tls_channel_impl13.*and code in a newdtls13submodule.We still aim to get that ready for Botan 3.14.
Reacted by Jack LloydThe clean-up of the actual logic is mostly done. Just the unit tests are currently in a pretty bad shape, because we based the final refactorings entirely on the BoGo integration tests (to avoid having to re-shape the unit tests several times). I'll re-align the unit tests along the way, when opening pull requests for the different preparatory refactorings in the existing TLS implementation.
Essentially, the TLS 1.3
Channel_Impl_13will become fairly dumb and most of its logic moves into aChannel_IOclass (similar to the TLS 1.2 setup).Channel_IOis abstract and splits intoTLS_Channel_IOandDTLS_Channel_IO. The base class holds some common functionality, but most of the beef will be in the flavor-dependent sub classes. Similarly,Handshake_Layer,Record_LayerandCipher_Statewill become polymorphic. The concreteChannel_IOimplementations orchestrate their respective concrete "layers". For instance, the entire retransmission and acknowledgement state handling is encapsulated behindDTLS_Channel_IO. The state machines inClient_Impl_13andServer_Impl_13stay mostly unchanged and rest on top of the flavor-specific transport that I just layed out.I'm using this draft PR to keep an overview of the full diff. I will update the base of this PR along with the split-out aspects as they land. That might be useful for context while reviewing.
@randombit Please let me know if there's anything I can do to make your life easier while upstreaming these ~10k new LOC.
- pinned this issue
on Oct 2, 2026 @reneme Thanks I will start looking asap. The new TLS test suite I mentioned is basically done but not yet quite baked for release, I invited you as a collab probably worth extending the shim there to support DTLS 1.3 and running the tests to see what falls out - so far I have only run the DTLS 1.3 support against BoringSSL, so there may be some rough bits or incorrect test expectations.
Checking in, because I'll be AFK until Tuesday: The preparatory PRs are moving along nicely! Thanks to @randombit for the swift reviews. Much appreciated! That saves me a lot of cumbersome stacking work. Also, AI is a real help in breaking up the large patch set into smaller parts. I really like that workflow, as it also provides a decent self-review opportunity.
What's already in (or on the way in)
Cipher_Statenow (de)protects full record structs, and is prepared for (D)TLS polymorphy. Also, it now performs the check that was introduces due to CVE-2026-34582Channel_IOnow manages the "record" and "handshake" layers. Here is where most of the differences between TLS and DTLS liveTranscript_Hash_Statenow handles the TLS handshake header independently from the serialized messages and learned about strong types- The
Flightabstraction is flexible enough to handle DTLS, mostly because it now keeps messages individually. Also, it now allows to schedule dummy-CCS records for the "compatibility mode" - The (D)TLS 1.2 stack is ready for DTLS 1.3, mostly to act as a downgrade landing pad (e.g. to hand down message fragment sequence numbers)
What's outstanding (in the planned order of integration)
- Polymorphic
Handshake_Layer, living in theChannel_IO- plus test coverage
- Polymorphic
Record_Layer, living in theChannel_IO- pls test coverage
- DTLS-related adaptions to various helper structures (handshake messages, message extensions, client/server state machines, etc.)
- I think many of those should go in before the actual DTLS-impl lands. Most are like
if(flavor == DTLS) { /* ... */}
- I think many of those should go in before the actual DTLS-impl lands. Most are like
- The actual DTLS I/O implementation
DTLS_Channel_IODTLS_Record_LayerDTLS_Handshake_LayerDTLS_Cipher_State- plus helper structures
Needs a second look
- Dummy CCS before a client replies with an Alert as its second flight
Sometimes BoGo insists on it, sometimes it doesn't. My understanding: if the alert happens in response to a TLS 1.2 ServerHello (i.e. during downgrade) it has to be omitted, because a TLS 1.2 implementation doesn't expect it. - Interleaving of Handshake records carrying fragmented Handshake messages (both in TLS and DTLS) and other record types MUST be prevented, as stated in RFC 9846 in various places. For DTLS this seems hard to check, due to out-of-order delivery of records. Similarly KeyUpdates must always be aligned with a record boundary. These checks aren't well covered by BoGo and our validation story is vague at best.
/cc @atreiber94
Reacted by Jack Lloyd
Holding ticket