Skip to main content

4. The DTLS Record Layer

4. The DTLS Record Layer

The DTLS 1.3 record layer is different from the TLS 1.3 record layer and also different from the DTLS 1.2 record layer.

  1. The DTLSCiphertext structure omits the superfluous version number and type fields.

  2. DTLS adds an epoch and sequence number to the TLS record header. This sequence number allows the recipient to correctly decrypt and verify DTLS records. However, the number of bits used for the epoch and sequence number fields in the DTLSCiphertext structure has been reduced from those in previous versions.

  3. The DTLS epoch serialized in DTLSPlaintext is 2 octets long for compatibility with DTLS 1.2. However, this value is set as the least significant 2 octets of the connection epoch, which is an 8 octet counter incremented on every KeyUpdate. See Section 4.2 for details. The sequence number is set to be the low order 48 bits of the 64 bit sequence number. Plaintext records MUST NOT be sent with sequence numbers that would exceed 2^48-1, so the upper 16 bits will always be 0.

  4. The DTLSCiphertext structure has a variable-length header.

DTLSPlaintext records are used to send unprotected records and DTLSCiphertext records are used to send protected records.

The DTLS record formats are shown below. Unless explicitly stated the meaning of the fields is unchanged from previous TLS/DTLS versions.

struct {
ContentType type;
ProtocolVersion legacy_record_version;
uint16 epoch = 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;

Figure 2: DTLS 1.3 Record Formats

legacy_record_version: This value MUST be set to {254, 253} for all records other than the initial ClientHello (i.e., one not generated after a HelloRetryRequest), where it may also be {254, 255} for compatibility purposes. It MUST be ignored for all purposes. See [TLS13], Appendix D.1 for the rationale for this.

epoch: The least significant 2 bytes of the connection epoch value.

unified_hdr: The unified header (unified_hdr) is a structure of variable length, shown in Figure 3.

encrypted_record: The encrypted form of the serialized DTLSInnerPlaintext structure.

  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) |
+-+-+-+-+-+-+-+-+

Figure 3: DTLS 1.3 Unified Header

Fixed Bits: The three high bits of the first byte of the unified header are set to 001. This ensures that the value will fit within the DTLS region when multiplexing is performed as described in [RFC7983]. It also ensures that distinguishing encrypted DTLS 1.3 records from encrypted DTLS 1.2 records is possible when they are carried on the same host/port quartet; such multiplexing is only possible when CIDs [RFC9146] are in use, in which case DTLS 1.2 records will have the content type tls12_cid (25).

C: The C bit (0x10) is set if the Connection ID is present.

S: The S bit (0x08) indicates the size of the sequence number. 0 means an 8-bit sequence number, 1 means 16-bit. Implementations MAY mix sequence numbers of different lengths on the same connection.

L: The L bit (0x04) is set if the length is present.

E: The two low bits (0x03) include the low-order two bits of the epoch.

Connection ID: Variable-length CID. The CID functionality is described in [RFC9146]. An example can be found in Section 9.1.

Sequence Number: The low-order 8 or 16 bits of the record sequence number. This value is 16 bits if the S bit is set to 1, and 8 bits if the S bit is 0.

Length: Identical to the length field in a TLS 1.3 record.

As with previous versions of DTLS, multiple DTLSPlaintext and DTLSCiphertext records can be included in the same underlying transport datagram.

Figure 4 illustrates different record headers.

 0 1 2 3 4 5 6 7       0 1 2 3 4 5 6 7       0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
| Content Type | |0|0|1|1|1|1|E E| |0|0|1|0|0|0|E E|
+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
| 16 bit | | | |8 bit Seq. No. |
| Version | / Connection ID / +-+-+-+-+-+-+-+-+
+-+-+-+-+-+-+-+-+ | | | |
| 16 bit | +-+-+-+-+-+-+-+-+ | Encrypted |
| Epoch | | 16 bit | / Record /
+-+-+-+-+-+-+-+-+ |Sequence Number| | |
| | +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
| | | 16 bit |
| 48 bit | | Length | DTLSCiphertext
|Sequence Number| +-+-+-+-+-+-+-+-+ Structure
| | | | (minimal)
| | | Encrypted |
+-+-+-+-+-+-+-+-+ / Record /
| 16 bit | | |
| Length | +-+-+-+-+-+-+-+-+
+-+-+-+-+-+-+-+-+
| | DTLSCiphertext
| | Structure
/ Fragment / (full)
| |
+-+-+-+-+-+-+-+-+

DTLSPlaintext
Structure

Figure 4: DTLS 1.3 Header Examples

The length field MAY be omitted by clearing the L bit, which means that the record consumes the entire rest of the datagram in the lower level transport. In this case, it is not possible to have multiple DTLSCiphertext format records without length fields in the same datagram. Omitting the length field MUST only be used for the last record in a datagram. Implementations MAY mix records with and without length fields on the same connection.

If a Connection ID is negotiated, then it MUST be contained in all datagrams. Sending implementations MUST NOT mix records from multiple DTLS associations in the same datagram. If the second or later record has a connection ID which does not correspond to the same association used for previous records, the rest of the datagram MUST be discarded.

When expanded, the epoch and sequence number can be combined into an unpacked RecordNumber structure, as shown below:

struct {
uint64 epoch;
uint64 sequence_number;
} RecordNumber;

This 128-bit value is used in the ACK message as well as in the "record_sequence_number" input to the Authenticated Encryption with Associated Data (AEAD) function. The entire header value shown in Figure 4 (but prior to record number encryption; see Section 4.2.3) is used as the additional data value for the AEAD function. For instance, if the minimal variant is used, the Associated Data (AD) is 2 octets long. Note that this design is different from the additional data calculation for DTLS 1.2 and for DTLS 1.2 with Connection IDs. In DTLS 1.3 the 64-bit sequence_number is used as the sequence number for the AEAD computation; unlike DTLS 1.2, the epoch is not included.