跳到主要内容

4. The DTLS Record Layer (DTLS记录层)

4. The DTLS Record Layer (DTLS记录层)

DTLS 1.3记录层与TLS 1.3记录层不同, 也与DTLS 1.2记录层不同。

  1. DTLSCiphertext结构省略了多余的版本号和类型字段。

  2. DTLS在TLS记录头中添加了epoch和序列号。该序列号允许接收方正确解密和验证DTLS记录。然而, DTLSCiphertext结构中用于epoch和序列号字段的比特数已从先前版本中减少。

  3. DTLSPlaintext中序列化的DTLS epoch为2个八位字节长, 以与DTLS 1.2兼容。然而, 该值被设置为连接epoch的最低有效2个八位字节, 连接epoch是一个8个八位字节的计数器, 在每次KeyUpdate时递增。详见第4.2节。序列号被设置为64位序列号的低48位。明文记录绝对不能使用超过2^48-1的序列号发送, 因此高16位始终为0。

  4. DTLSCiphertext结构具有可变长度的头部。

DTLSPlaintext记录用于发送未受保护的记录, DTLSCiphertext记录用于发送受保护的记录。

DTLS记录格式如下所示。除非明确说明, 否则这些字段的含义与先前的TLS/DTLS版本相同。

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;

图2: DTLS 1.3记录格式

legacy_record_version: 对于除初始ClientHello(即未在HelloRetryRequest之后生成的ClientHello)之外的所有记录, 此值必须设置为{254, 253}, 为了兼容性目的, 初始ClientHello也可以是{254, 255}。它必须在所有情况下被忽略。有关此原因, 请参见[TLS13]附录D.1。

epoch: 连接epoch值的最低有效2个字节。

unified_hdr: 统一头部(unified_hdr)是一个可变长度的结构, 如图3所示。

encrypted_record: 序列化的DTLSInnerPlaintext结构的加密形式。

  0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+
|0|0|1|C|S|L|E E|
+-+-+-+-+-+-+-+-+
| Connection ID | 图例:
| (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) |
+-+-+-+-+-+-+-+-+

图3: DTLS 1.3统一头部

Fixed Bits: 统一头部第一个字节的高三位被设置为001。这确保当执行如[RFC7983]所述的多路复用时, 该值将适合DTLS区域。它还确保当加密的DTLS 1.3记录和加密的DTLS 1.2记录在同一主机/端口四元组上传输时, 可以区分它们; 这种多路复用仅在使用CID [RFC9146]时才可能, 在这种情况下, DTLS 1.2记录将具有内容类型tls12_cid (25)。

C: 如果存在Connection ID, 则设置C位(0x10)。

S: S位(0x08)表示序列号的大小。0表示8位序列号, 1表示16位。实现可以在同一连接上混合使用不同长度的序列号。

L: 如果存在长度字段, 则设置L位(0x04)。

E: 低两位(0x03)包含epoch的低两位。

Connection ID: 可变长度的CID。CID功能在[RFC9146]中描述。示例见第9.1节。

Sequence Number: 记录序列号的低8位或16位。如果S位设置为1, 则此值为16位; 如果S位为0, 则为8位。

Length: 与TLS 1.3记录中的长度字段相同。

与先前版本的DTLS一样, 多个DTLSPlaintext和DTLSCiphertext记录可以包含在同一底层传输数据报中。

图4展示了不同的记录头部。

 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

图4: DTLS 1.3头部示例

可以通过清除L位来省略长度字段, 这意味着记录将消耗较低级别传输中数据报的整个剩余部分。在这种情况下, 不可能在同一数据报中有多个没有长度字段的DTLSCiphertext格式记录。省略长度字段必须仅用于数据报中的最后一条记录。实现可以在同一连接上混合使用带长度字段和不带长度字段的记录。

如果协商了Connection ID, 则它必须包含在所有数据报中。发送实现绝对不能在同一数据报中混合来自多个DTLS关联的记录。如果第二条或之后的记录具有与先前记录使用的关联不对应的connection ID, 则数据报的其余部分必须被丢弃。

扩展后, epoch和序列号可以组合成一个未打包的RecordNumber结构, 如下所示:

struct {
uint64 epoch;
uint64 sequence_number;
} RecordNumber;

该128位值用于ACK消息以及带关联数据的认证加密(AEAD)函数的"record_sequence_number"输入。图4中显示的整个头部值(但在记录号加密之前; 见第4.2.3节)用作AEAD函数的附加数据值。例如, 如果使用最小变体, 则关联数据(AD)长度为2个八位字节。请注意, 此设计与DTLS 1.2以及带Connection ID的DTLS 1.2的附加数据计算不同。在DTLS 1.3中, 64位sequence_number用作AEAD计算的序列号; 与DTLS 1.2不同, 不包括epoch。