.\" -*- mode: troff; coding: utf-8 -*- .\" Automatically generated by Pod::Man v6.0.2 (Pod::Simple 3.48) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" \*(C` and \*(C' are quotes in nroff, nothing in troff, for use with C<>. .ie n \{\ . ds C` "" . ds C' "" 'br\} .el\{\ . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Required to disable full justification in groff 1.23.0. .if n .ds AD l .\" ======================================================================== .\" .IX Title "OSSL-GUIDE-DTLSV13 7ssl" .TH OSSL-GUIDE-DTLSV13 7ssl 2026-10-23 4.1.0 OpenSSL .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH NAME ossl\-guide\-dtlsv13 \- OpenSSL DTLSv1.3 .SH INTRODUCTION .IX Header "INTRODUCTION" This page provides an introduction to the DTLSv1.3 protocol. It explains the concepts behind the protocol and how it differs from previous versions of DTLS. .SH DESCRIPTION .IX Header "DESCRIPTION" DTLSv1.3 is a version of the Datagram Transport Layer Security (DTLS) protocol. DTLSv1.3 is defined in RFC 9147. It is based on TLSv1.3 and provides similar security guarantees to TLSv1.3 but is designed to work over datagram transport protocols such as UDP. .PP The Supported Versions extension in the ClientHello and ServerHello is updated to include support for DTLSv1.3 by adding the value 0xFEFD to the list of supported versions. .PP The TLSv1.3 state machine has been updated to support the DTLSv1.3 protocol. The main difference in the state machine between TLSv1.3 and DTLSv1.3 is the addition of Acknowledgement messages that are used to acknowledge the receipt of messages in the DTLSv1.3 protocol. This allows either the client or the server to signal to the peer that they have received and processed a handshake message. This prevents unnecessary retransmissions of messages. .PP A major difference between DTLSv1.3 and DTLSv1.2 is the addition of the Unified Header. This Unified Header is in plaintext, and it contains an encrypted sequence number. The handshake header follows the Unified Header, and both the handshake header and all of its contents are encrypted. .PP .Vb 8 \& struct { \& ContentType type; \& ProtocolVersion legacy_record_version; \& uint16 epoch_val = 0; \& uint48 sequence_number; \& uint16 length; \& opaque fragment[DTLSPlaintext.length]; \& } DTLSPlaintext; \& \& struct { \& opaque content[DTLSPlaintext.length]; \& ContentType type; \& uint8 zeros[length_of_padding]; \& } DTLSInnerPlaintext; \& \& struct { \& opaque unified_hdr[variable]; \& opaque encrypted_record[length]; \& } DTLSCiphertext; .Ve .SH "UNIFIED HEADER" .IX Header "UNIFIED HEADER" The first byte of a Unified Header indicates which fields are present in the Unified Header. .PP .Vb 10 \& 0 1 2 3 4 5 6 7 \& +\-+\-+\-+\-+\-+\-+\-+\-+ \& |0|0|1|C|S|L|E E| \& +\-+\-+\-+\-+\-+\-+\-+\-+ \& | Connection ID | Legend: \& | (if any, | \& / length as / C \- Connection ID (CID) present \& | negotiated) | S \- Sequence number length \& +\-+\-+\-+\-+\-+\-+\-+\-+ L \- Length present \& | 8 or 16 bit | E \- Epoch \& |Sequence Number| \& +\-+\-+\-+\-+\-+\-+\-+\-+ \& | 16 bit Length | \& | (if present) | \& +\-+\-+\-+\-+\-+\-+\-+\-+ .Ve .PP When OpenSSL is generating a Unified Header it will always have Connection ID (C) set to zero. The Sequence Number will always be set to 1, indicating a 2 byte Sequence Number. Lastly the length bit will always be set indicating a length is present in the Unified Header. .SS Epoch .IX Subsection "Epoch" The Epoch value is incremented every time the cryptographic parameters change. ClientHello and ServerHello use an Epoch of 0. Only the client uses an Epoch of 1 when it is sending Early Data. The rest of the handshake messages use an Epoch of 2. .SS "Encrypted Sequence Numbers" .IX Subsection "Encrypted Sequence Numbers" The Sequence Number in the Unified Header is encrypted. For each Epoch, it always starts at 0, but since it is encrypted, it will not appear as zero when viewing it on the wire. The Sequence Number increments with every new DTLSv1.3 record. .SH "ACKNOWLEDGEMENT MESSAGE" .IX Header "ACKNOWLEDGEMENT MESSAGE" DTLSv1.3 adds explicit Acknowledgement messages to the protocol. There are also implicit acknowledgements in DTLSv1.3. For instance, when the client receives ServerHello, that ServerHello implicitly acknowledges the receipt of the ClientHello message. Also, ClientFinished implicitly acknowledges the receipt of ServerFinished. The new explicit Acknowledgement messages are used for the server to acknowledge the receipt of the ClientFinished message. The client uses an explicit Acknowledgement message to acknowledge the receipt of NewSessionTicket messages. Both the server and the client use the explicit Acknowledgement to acknowledge the receipt of KeyUpdate messages. .PP When the server sends data immediately after the connection is established, there is a potential race condition where the Application Data may be received by the client before the Acknowledgement message for the ClientFinished message is received. OpenSSL buffers the Application Data until the Acknowledgement message is received and processed. .SH "END OF EARLY DATA MESSAGE" .IX Header "END OF EARLY DATA MESSAGE" In DTLSv1.3, the End of Early Data message is not sent. Instead, when the client starts sending messages in Epoch 2, this signals to the server that the client has finished sending Early Data. .SH "HELLO RETRY REQUEST" .IX Header "HELLO RETRY REQUEST" For DTLSv1.3 server applications, use \fBSSL_new_listener\fR\|(3): HelloRetryRequest cookie validation is enabled by default. This provides connection demultiplexing for multiple clients on a single UDP socket. .PP Note that \fBDTLSv1_listen\fR\|(3) only supports DTLS 1.0/1.2 with HelloVerifyRequest and cannot be used with DTLSv1.3. .SH "DTLS LISTENER API" .IX Header "DTLS LISTENER API" For DTLSv1.3 server applications that need to handle multiple clients on a single UDP socket, the SSL Listener API provides connection demultiplexing and address validation. Unlike \fBDTLSv1_listen\fR\|(3) which only supports DTLS 1.0/1.2 with HelloVerifyRequest, the listener API fully supports DTLSv1.3 with HelloRetryRequest cookie validation. .PP Create a DTLS listener using \fBSSL_new_listener\fR\|(3) with an SSL_CTX configured for DTLS. Address validation is enabled by default. The following flags adjust listener behavior: .IP \fBSSL_LISTENER_FLAG_ADDRESS_VALIDATION\fR 4 .IX Item "SSL_LISTENER_FLAG_ADDRESS_VALIDATION" Requests address validation by HelloRetryRequest and HelloVerifyRequest. This is the default. .IP \fBSSL_LISTENER_FLAG_NO_VALIDATE\fR 4 .IX Item "SSL_LISTENER_FLAG_NO_VALIDATE" Disables all address validation. The listener will not send HelloVerifyRequest (for DTLS 1.0/1.2) or HelloRetryRequest with cookie (for DTLSv1.3). This is faster but provides no protection against amplification attacks. Not recommended for use in untrusted network environments. If both this flag and \&\fBSSL_LISTENER_FLAG_ADDRESS_VALIDATION\fR are specified, the listener fails safe and performs address validation. .IP \fBSSL_LISTENER_FLAG_SINGLE_THREAD\fR 4 .IX Item "SSL_LISTENER_FLAG_SINGLE_THREAD" Specifies that the DTLS listener will operate in single\-threaded mode. When this flag is set, the listener and all connections accepted from it should only be used from a single thread. This avoids the overhead of internal synchronization mechanisms. .PP By default (when \fBSSL_LISTENER_FLAG_SINGLE_THREAD\fR is not set), the listener initializes internal synchronization mechanisms that allow connections accepted from the listener to be safely used from multiple threads concurrently. This includes a notifier mechanism that enables efficient polling across threads. .PP After attaching a UDP socket BIO with \fBSSL_set0_rbio\fR\|(3) and \fBSSL_set0_wbio\fR\|(3) and calling \fBSSL_listen\fR\|(3), use \fBSSL_accept_connection\fR\|(3) to accept incoming connections. Each accepted connection has completed cookie validation (if required) but still requires \fBSSL_do_handshake\fR\|(3) or \fBSSL_accept\fR\|(3) to complete the TLS handshake before application data can be exchanged. .PP By default a DTLS listener created with \fBSSL_new_listener\fR\|(3) operates in blocking mode. Because a listener demultiplexes a single UDP socket across many connections, it cannot allow a read for one connection to block and thereby stall the others. Its network BIO is therefore configured for nonblocking operation, and blocking is instead provided by waiting for readiness of the underlying socket. This applies to \fBSSL_accept_connection\fR\|(3) on the listener as well as to \fBSSL_read\fR\|(3) and \fBSSL_write\fR\|(3) on the connections it returns. .PP Use \fBSSL_set_blocking_mode\fR\|(3) to enable or disable blocking mode, and \&\fBSSL_get_blocking_mode\fR\|(3) to query it. The blocking mode of a listener is normally configured once, before it is used. .PP A connection SSL object returned by \fBSSL_accept_connection\fR\|(3) inherits the blocking mode of the listener it came from. Calling \fBSSL_set_blocking_mode\fR\|(3) on such a connection overrides that inheritance for that connection only. To perform a single nonblocking accept on an otherwise blocking listener, pass the \&\fBSSL_ACCEPT_CONNECTION_NO_BLOCK\fR flag to \fBSSL_accept_connection\fR\|(3). .PP See \fBSSL_set_blocking_mode\fR\|(3) for full details. .PP The following tunables are available via \fBSSL_get_value_uint\fR\|(3) / \&\fBSSL_set_value_uint\fR\|(3): \fBSSL_VALUE_DTLS_LISTENER_MAX_PENDING_CONNS\fR (cap on listener\-owned connections, default 256), \&\fBSSL_VALUE_DTLS_LISTENER_PENDING_TIMEOUT\fR (pending connection timeout in milliseconds, default 30000; pending connections that do not complete their handshake within this period are automatically cleaned up), and \fBSSL_VALUE_DTLS_LISTENER_MAX_DGRAM_SIZE\fR (maximum received datagram size in bytes, default 2000). .PP See \fBSSL_new_listener\fR\|(3) for complete API documentation. .PP The complete source code for an example DTLS listener server (and a matching client) is available in the \fBdemos/dtlslistenerecho\fR directory of the OpenSSL source distribution in the file \fBmain.c\fR. It is also available online at . .SH "APPLICATION DATA" .IX Header "APPLICATION DATA" When either the DTLSv1.3 client or server is awaiting an Acknowledgement message, Application Data will be buffered until the Acknowledgement message is received and processed. Once either the DTLSv1.3 client or server processes the Acknowledgement message it will then process the buffered Application Data. .PP Another scenario when Application Data is buffered is when multiple handshake messages like the NewSessionTicket are received with Application Data. The Application Data will be buffered until all the handshake messages have been processed. .SH SCTP .IX Header "SCTP" Even though DTLSv1.3 is enabled, the client will only perform a DTLSv1.2 or DTLSv1.0 handshake. If a DTLSv1.3 over SCTP compatible client connects to an OpenSSL server, the server will downgrade to DTLSv1.2 or earlier. .SH "CONNECTION ID" .IX Header "CONNECTION ID" OpenSSL does not support Connection IDs in DTLSv1.3. If a client that supports Connection IDs connects to an OpenSSL server, the server will ignore the Connection ID and will not include a Connection ID in its responses. .SH "CIPHER SUITES" .IX Header "CIPHER SUITES" RFC 9147 requires that TLS_AES_128_CCM_8_SHA256 must not be used with DTLS without additional safeguards against forgery, due to its short authentication tag. OpenSSL does not implement such safeguards, so this ciphersuite is not available when negotiating DTLS, even though it remains available for TLS. .SH "HOW TO UTILIZE DTLSV1.3 IN OPENSSL" .IX Header "HOW TO UTILIZE DTLSV1.3 IN OPENSSL" .SS "SSL_set_min_proto_version and SSL_set_max_proto_version" .IX Subsection "SSL_set_min_proto_version and SSL_set_max_proto_version" Use \fBSSL_set_min_proto_version\fR\|(3) and \fBSSL_set_max_proto_version\fR\|(3) with the DTLS1_3_VERSION macro to set the minimum and maximum protocol version to DTLSv1.3. .SS "SSL_CTX_set_min_proto_version and SSL_CTX_set_max_proto_version" .IX Subsection "SSL_CTX_set_min_proto_version and SSL_CTX_set_max_proto_version" Use \fBSSL_CTX_set_min_proto_version\fR\|(3) and \fBSSL_CTX_set_max_proto_version\fR\|(3) with the DTLS1_3_VERSION macro to set the minimum and maximum protocol version to DTLSv1.3. .SS s_client .IX Subsection "s_client" Use the min_protocol and max_protocol parameters and set them to DTLSv1.3. Use the \-dtls option to specify that you want to use DTLS instead of TLS. .SS s_server .IX Subsection "s_server" Use the min_protocol and max_protocol parameters and set them to DTLSv1.3. .SH DEMOS .IX Header "DEMOS" OpenSSL is distributed with two DTLS demo applications that illustrate the concepts described on this page. They can be found in the \fBdemos\fR directory of the OpenSSL source distribution: .IP \fBdemos/dtlsecho\fR 4 .IX Item "demos/dtlsecho" A simple DTLSv1.3 echo client and server built on a single \fBSSL\fR object per connection. The complete source code is available in the \fBdemos/dtlsecho\fR directory of the OpenSSL source distribution in the file \fBmain.c\fR. It is also available online at . .IP \fBdemos/dtlslistenerecho\fR 4 .IX Item "demos/dtlslistenerecho" A DTLS echo server that uses the DTLS listener API (\fBSSL_new_listener\fR\|(3), \&\fBSSL_listen\fR\|(3) and \fBSSL_accept_connection\fR\|(3)) to demultiplex and handle multiple client connections on a single UDP socket, together with a matching client. The complete source code is available in the \fBdemos/dtlslistenerecho\fR directory of the OpenSSL source distribution in the file \fBmain.c\fR. It is also available online at . .SH "SEE ALSO" .IX Header "SEE ALSO" \&\fBossl\-guide\-introduction\fR\|(7), \fBossl\-guide\-libraries\-introduction\fR\|(7), \&\fBossl\-guide\-libssl\-introduction\fR\|(7), \fBossl\-guide\-tls\-introduction\fR\|(7), \&\fBSSL_set_blocking_mode\fR\|(3), \fBSSL_new_listener\fR\|(3), \fBSSL_accept_connection\fR\|(3) .SH COPYRIGHT .IX Header "COPYRIGHT" Copyright 2026 The OpenSSL Project Authors. All Rights Reserved. .PP Licensed under the Apache License 2.0 (the "License"). You may not use this file except in compliance with the License. You can obtain a copy in the file LICENSE in the source distribution or at .