/src/openssl/include/internal/quic_wire_pkt.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2022-2025 The OpenSSL Project Authors. All Rights Reserved. |
3 | | * |
4 | | * Licensed under the Apache License 2.0 (the "License"). You may not use |
5 | | * this file except in compliance with the License. You can obtain a copy |
6 | | * in the file LICENSE in the source distribution or at |
7 | | * https://www.openssl.org/source/license.html |
8 | | */ |
9 | | |
10 | | #ifndef OSSL_QUIC_WIRE_PKT_H |
11 | | # define OSSL_QUIC_WIRE_PKT_H |
12 | | |
13 | | # include <openssl/ssl.h> |
14 | | # include "internal/packet_quic.h" |
15 | | # include "internal/quic_types.h" |
16 | | |
17 | | # ifndef OPENSSL_NO_QUIC |
18 | | |
19 | 0 | # define QUIC_VERSION_NONE ((uint32_t)0) /* Used for version negotiation */ |
20 | 0 | # define QUIC_VERSION_1 ((uint32_t)1) /* QUIC v1 */ |
21 | | |
22 | | /* QUIC logical packet type. These do not match wire values. */ |
23 | 0 | # define QUIC_PKT_TYPE_INITIAL 1 |
24 | 0 | # define QUIC_PKT_TYPE_0RTT 2 |
25 | 0 | # define QUIC_PKT_TYPE_HANDSHAKE 3 |
26 | 0 | # define QUIC_PKT_TYPE_RETRY 4 |
27 | 0 | # define QUIC_PKT_TYPE_1RTT 5 |
28 | 0 | # define QUIC_PKT_TYPE_VERSION_NEG 6 |
29 | | |
30 | | /* |
31 | | * Determine encryption level from packet type. Returns QUIC_ENC_LEVEL_NUM if |
32 | | * the packet is not of a type which is encrypted. |
33 | | */ |
34 | | static ossl_inline ossl_unused uint32_t |
35 | | ossl_quic_pkt_type_to_enc_level(uint32_t pkt_type) |
36 | 0 | { |
37 | 0 | switch (pkt_type) { |
38 | 0 | case QUIC_PKT_TYPE_INITIAL: |
39 | 0 | return QUIC_ENC_LEVEL_INITIAL; |
40 | 0 | case QUIC_PKT_TYPE_HANDSHAKE: |
41 | 0 | return QUIC_ENC_LEVEL_HANDSHAKE; |
42 | 0 | case QUIC_PKT_TYPE_0RTT: |
43 | 0 | return QUIC_ENC_LEVEL_0RTT; |
44 | 0 | case QUIC_PKT_TYPE_1RTT: |
45 | 0 | return QUIC_ENC_LEVEL_1RTT; |
46 | 0 | default: |
47 | 0 | return QUIC_ENC_LEVEL_NUM; |
48 | 0 | } |
49 | 0 | } Unexecuted instantiation: ssl_lib.c:ossl_quic_pkt_type_to_enc_level Unexecuted instantiation: t1_lib.c:ossl_quic_pkt_type_to_enc_level Unexecuted instantiation: quic_impl.c:ossl_quic_pkt_type_to_enc_level Unexecuted instantiation: quic_method.c:ossl_quic_pkt_type_to_enc_level Unexecuted instantiation: quic_obj.c:ossl_quic_pkt_type_to_enc_level Unexecuted instantiation: quic_port.c:ossl_quic_pkt_type_to_enc_level Unexecuted instantiation: quic_record_rx.c:ossl_quic_pkt_type_to_enc_level Unexecuted instantiation: quic_record_shared.c:ossl_quic_pkt_type_to_enc_level Unexecuted instantiation: quic_record_tx.c:ossl_quic_pkt_type_to_enc_level Unexecuted instantiation: quic_record_util.c:ossl_quic_pkt_type_to_enc_level Unexecuted instantiation: quic_rstream.c:ossl_quic_pkt_type_to_enc_level Unexecuted instantiation: quic_sf_list.c:ossl_quic_pkt_type_to_enc_level Unexecuted instantiation: quic_sstream.c:ossl_quic_pkt_type_to_enc_level Unexecuted instantiation: quic_stream_map.c:ossl_quic_pkt_type_to_enc_level Unexecuted instantiation: quic_thread_assist.c:ossl_quic_pkt_type_to_enc_level Unexecuted instantiation: quic_txp.c:ossl_quic_pkt_type_to_enc_level Unexecuted instantiation: quic_wire.c:ossl_quic_pkt_type_to_enc_level Unexecuted instantiation: quic_wire_pkt.c:ossl_quic_pkt_type_to_enc_level Unexecuted instantiation: rec_layer_s3.c:ossl_quic_pkt_type_to_enc_level Unexecuted instantiation: qlog_event_helpers.c:ossl_quic_pkt_type_to_enc_level Unexecuted instantiation: quic_channel.c:ossl_quic_pkt_type_to_enc_level Unexecuted instantiation: quic_demux.c:ossl_quic_pkt_type_to_enc_level Unexecuted instantiation: quic_fifd.c:ossl_quic_pkt_type_to_enc_level Unexecuted instantiation: quic_rx_depack.c:ossl_quic_pkt_type_to_enc_level |
50 | | |
51 | | static ossl_inline ossl_unused uint32_t |
52 | | ossl_quic_enc_level_to_pkt_type(uint32_t enc_level) |
53 | 0 | { |
54 | 0 | switch (enc_level) { |
55 | 0 | case QUIC_ENC_LEVEL_INITIAL: |
56 | 0 | return QUIC_PKT_TYPE_INITIAL; |
57 | 0 | case QUIC_ENC_LEVEL_HANDSHAKE: |
58 | 0 | return QUIC_PKT_TYPE_HANDSHAKE; |
59 | 0 | case QUIC_ENC_LEVEL_0RTT: |
60 | 0 | return QUIC_PKT_TYPE_0RTT; |
61 | 0 | case QUIC_ENC_LEVEL_1RTT: |
62 | 0 | return QUIC_PKT_TYPE_1RTT; |
63 | 0 | default: |
64 | 0 | return UINT32_MAX; |
65 | 0 | } |
66 | 0 | } Unexecuted instantiation: ssl_lib.c:ossl_quic_enc_level_to_pkt_type Unexecuted instantiation: t1_lib.c:ossl_quic_enc_level_to_pkt_type Unexecuted instantiation: quic_impl.c:ossl_quic_enc_level_to_pkt_type Unexecuted instantiation: quic_method.c:ossl_quic_enc_level_to_pkt_type Unexecuted instantiation: quic_obj.c:ossl_quic_enc_level_to_pkt_type Unexecuted instantiation: quic_port.c:ossl_quic_enc_level_to_pkt_type Unexecuted instantiation: quic_record_rx.c:ossl_quic_enc_level_to_pkt_type Unexecuted instantiation: quic_record_shared.c:ossl_quic_enc_level_to_pkt_type Unexecuted instantiation: quic_record_tx.c:ossl_quic_enc_level_to_pkt_type Unexecuted instantiation: quic_record_util.c:ossl_quic_enc_level_to_pkt_type Unexecuted instantiation: quic_rstream.c:ossl_quic_enc_level_to_pkt_type Unexecuted instantiation: quic_sf_list.c:ossl_quic_enc_level_to_pkt_type Unexecuted instantiation: quic_sstream.c:ossl_quic_enc_level_to_pkt_type Unexecuted instantiation: quic_stream_map.c:ossl_quic_enc_level_to_pkt_type Unexecuted instantiation: quic_thread_assist.c:ossl_quic_enc_level_to_pkt_type Unexecuted instantiation: quic_txp.c:ossl_quic_enc_level_to_pkt_type Unexecuted instantiation: quic_wire.c:ossl_quic_enc_level_to_pkt_type Unexecuted instantiation: quic_wire_pkt.c:ossl_quic_enc_level_to_pkt_type Unexecuted instantiation: rec_layer_s3.c:ossl_quic_enc_level_to_pkt_type Unexecuted instantiation: qlog_event_helpers.c:ossl_quic_enc_level_to_pkt_type Unexecuted instantiation: quic_channel.c:ossl_quic_enc_level_to_pkt_type Unexecuted instantiation: quic_demux.c:ossl_quic_enc_level_to_pkt_type Unexecuted instantiation: quic_fifd.c:ossl_quic_enc_level_to_pkt_type Unexecuted instantiation: quic_rx_depack.c:ossl_quic_enc_level_to_pkt_type |
67 | | |
68 | | /* Determine if a packet type contains an encrypted payload. */ |
69 | | static ossl_inline ossl_unused int |
70 | | ossl_quic_pkt_type_is_encrypted(uint32_t pkt_type) |
71 | 0 | { |
72 | 0 | switch (pkt_type) { |
73 | 0 | case QUIC_PKT_TYPE_RETRY: |
74 | 0 | case QUIC_PKT_TYPE_VERSION_NEG: |
75 | 0 | return 0; |
76 | 0 | default: |
77 | 0 | return 1; |
78 | 0 | } |
79 | 0 | } Unexecuted instantiation: ssl_lib.c:ossl_quic_pkt_type_is_encrypted Unexecuted instantiation: t1_lib.c:ossl_quic_pkt_type_is_encrypted Unexecuted instantiation: quic_impl.c:ossl_quic_pkt_type_is_encrypted Unexecuted instantiation: quic_method.c:ossl_quic_pkt_type_is_encrypted Unexecuted instantiation: quic_obj.c:ossl_quic_pkt_type_is_encrypted Unexecuted instantiation: quic_port.c:ossl_quic_pkt_type_is_encrypted Unexecuted instantiation: quic_record_rx.c:ossl_quic_pkt_type_is_encrypted Unexecuted instantiation: quic_record_shared.c:ossl_quic_pkt_type_is_encrypted Unexecuted instantiation: quic_record_tx.c:ossl_quic_pkt_type_is_encrypted Unexecuted instantiation: quic_record_util.c:ossl_quic_pkt_type_is_encrypted Unexecuted instantiation: quic_rstream.c:ossl_quic_pkt_type_is_encrypted Unexecuted instantiation: quic_sf_list.c:ossl_quic_pkt_type_is_encrypted Unexecuted instantiation: quic_sstream.c:ossl_quic_pkt_type_is_encrypted Unexecuted instantiation: quic_stream_map.c:ossl_quic_pkt_type_is_encrypted Unexecuted instantiation: quic_thread_assist.c:ossl_quic_pkt_type_is_encrypted Unexecuted instantiation: quic_txp.c:ossl_quic_pkt_type_is_encrypted Unexecuted instantiation: quic_wire.c:ossl_quic_pkt_type_is_encrypted Unexecuted instantiation: quic_wire_pkt.c:ossl_quic_pkt_type_is_encrypted Unexecuted instantiation: rec_layer_s3.c:ossl_quic_pkt_type_is_encrypted Unexecuted instantiation: qlog_event_helpers.c:ossl_quic_pkt_type_is_encrypted Unexecuted instantiation: quic_channel.c:ossl_quic_pkt_type_is_encrypted Unexecuted instantiation: quic_demux.c:ossl_quic_pkt_type_is_encrypted Unexecuted instantiation: quic_fifd.c:ossl_quic_pkt_type_is_encrypted Unexecuted instantiation: quic_rx_depack.c:ossl_quic_pkt_type_is_encrypted |
80 | | |
81 | | /* Determine if a packet type contains a PN field. */ |
82 | | static ossl_inline ossl_unused int |
83 | | ossl_quic_pkt_type_has_pn(uint32_t pkt_type) |
84 | 0 | { |
85 | | /* |
86 | | * Currently a packet has a PN iff it is encrypted. This could change |
87 | | * someday. |
88 | | */ |
89 | 0 | return ossl_quic_pkt_type_is_encrypted(pkt_type); |
90 | 0 | } Unexecuted instantiation: ssl_lib.c:ossl_quic_pkt_type_has_pn Unexecuted instantiation: t1_lib.c:ossl_quic_pkt_type_has_pn Unexecuted instantiation: quic_impl.c:ossl_quic_pkt_type_has_pn Unexecuted instantiation: quic_method.c:ossl_quic_pkt_type_has_pn Unexecuted instantiation: quic_obj.c:ossl_quic_pkt_type_has_pn Unexecuted instantiation: quic_port.c:ossl_quic_pkt_type_has_pn Unexecuted instantiation: quic_record_rx.c:ossl_quic_pkt_type_has_pn Unexecuted instantiation: quic_record_shared.c:ossl_quic_pkt_type_has_pn Unexecuted instantiation: quic_record_tx.c:ossl_quic_pkt_type_has_pn Unexecuted instantiation: quic_record_util.c:ossl_quic_pkt_type_has_pn Unexecuted instantiation: quic_rstream.c:ossl_quic_pkt_type_has_pn Unexecuted instantiation: quic_sf_list.c:ossl_quic_pkt_type_has_pn Unexecuted instantiation: quic_sstream.c:ossl_quic_pkt_type_has_pn Unexecuted instantiation: quic_stream_map.c:ossl_quic_pkt_type_has_pn Unexecuted instantiation: quic_thread_assist.c:ossl_quic_pkt_type_has_pn Unexecuted instantiation: quic_txp.c:ossl_quic_pkt_type_has_pn Unexecuted instantiation: quic_wire.c:ossl_quic_pkt_type_has_pn Unexecuted instantiation: quic_wire_pkt.c:ossl_quic_pkt_type_has_pn Unexecuted instantiation: rec_layer_s3.c:ossl_quic_pkt_type_has_pn Unexecuted instantiation: qlog_event_helpers.c:ossl_quic_pkt_type_has_pn Unexecuted instantiation: quic_channel.c:ossl_quic_pkt_type_has_pn Unexecuted instantiation: quic_demux.c:ossl_quic_pkt_type_has_pn Unexecuted instantiation: quic_fifd.c:ossl_quic_pkt_type_has_pn Unexecuted instantiation: quic_rx_depack.c:ossl_quic_pkt_type_has_pn |
91 | | |
92 | | /* |
93 | | * Determine if a packet type can appear with other packets in a datagram. Some |
94 | | * packet types must be the sole packet in a datagram. |
95 | | */ |
96 | | static ossl_inline ossl_unused int |
97 | | ossl_quic_pkt_type_can_share_dgram(uint32_t pkt_type) |
98 | 0 | { |
99 | | /* |
100 | | * Currently only the encrypted packet types can share a datagram. This |
101 | | * could change someday. |
102 | | */ |
103 | 0 | return ossl_quic_pkt_type_is_encrypted(pkt_type); |
104 | 0 | } Unexecuted instantiation: ssl_lib.c:ossl_quic_pkt_type_can_share_dgram Unexecuted instantiation: t1_lib.c:ossl_quic_pkt_type_can_share_dgram Unexecuted instantiation: quic_impl.c:ossl_quic_pkt_type_can_share_dgram Unexecuted instantiation: quic_method.c:ossl_quic_pkt_type_can_share_dgram Unexecuted instantiation: quic_obj.c:ossl_quic_pkt_type_can_share_dgram Unexecuted instantiation: quic_port.c:ossl_quic_pkt_type_can_share_dgram Unexecuted instantiation: quic_record_rx.c:ossl_quic_pkt_type_can_share_dgram Unexecuted instantiation: quic_record_shared.c:ossl_quic_pkt_type_can_share_dgram Unexecuted instantiation: quic_record_tx.c:ossl_quic_pkt_type_can_share_dgram Unexecuted instantiation: quic_record_util.c:ossl_quic_pkt_type_can_share_dgram Unexecuted instantiation: quic_rstream.c:ossl_quic_pkt_type_can_share_dgram Unexecuted instantiation: quic_sf_list.c:ossl_quic_pkt_type_can_share_dgram Unexecuted instantiation: quic_sstream.c:ossl_quic_pkt_type_can_share_dgram Unexecuted instantiation: quic_stream_map.c:ossl_quic_pkt_type_can_share_dgram Unexecuted instantiation: quic_thread_assist.c:ossl_quic_pkt_type_can_share_dgram Unexecuted instantiation: quic_txp.c:ossl_quic_pkt_type_can_share_dgram Unexecuted instantiation: quic_wire.c:ossl_quic_pkt_type_can_share_dgram Unexecuted instantiation: quic_wire_pkt.c:ossl_quic_pkt_type_can_share_dgram Unexecuted instantiation: rec_layer_s3.c:ossl_quic_pkt_type_can_share_dgram Unexecuted instantiation: qlog_event_helpers.c:ossl_quic_pkt_type_can_share_dgram Unexecuted instantiation: quic_channel.c:ossl_quic_pkt_type_can_share_dgram Unexecuted instantiation: quic_demux.c:ossl_quic_pkt_type_can_share_dgram Unexecuted instantiation: quic_fifd.c:ossl_quic_pkt_type_can_share_dgram Unexecuted instantiation: quic_rx_depack.c:ossl_quic_pkt_type_can_share_dgram |
105 | | |
106 | | /* |
107 | | * Determine if the packet type must come at the end of the datagram (due to the |
108 | | * lack of a length field). |
109 | | */ |
110 | | static ossl_inline ossl_unused int |
111 | | ossl_quic_pkt_type_must_be_last(uint32_t pkt_type) |
112 | 0 | { |
113 | | /* |
114 | | * Any packet type which cannot share a datagram obviously must come last. |
115 | | * 1-RTT also must come last as it lacks a length field. |
116 | | */ |
117 | 0 | return !ossl_quic_pkt_type_can_share_dgram(pkt_type) |
118 | 0 | || pkt_type == QUIC_PKT_TYPE_1RTT; |
119 | 0 | } Unexecuted instantiation: ssl_lib.c:ossl_quic_pkt_type_must_be_last Unexecuted instantiation: t1_lib.c:ossl_quic_pkt_type_must_be_last Unexecuted instantiation: quic_impl.c:ossl_quic_pkt_type_must_be_last Unexecuted instantiation: quic_method.c:ossl_quic_pkt_type_must_be_last Unexecuted instantiation: quic_obj.c:ossl_quic_pkt_type_must_be_last Unexecuted instantiation: quic_port.c:ossl_quic_pkt_type_must_be_last Unexecuted instantiation: quic_record_rx.c:ossl_quic_pkt_type_must_be_last Unexecuted instantiation: quic_record_shared.c:ossl_quic_pkt_type_must_be_last Unexecuted instantiation: quic_record_tx.c:ossl_quic_pkt_type_must_be_last Unexecuted instantiation: quic_record_util.c:ossl_quic_pkt_type_must_be_last Unexecuted instantiation: quic_rstream.c:ossl_quic_pkt_type_must_be_last Unexecuted instantiation: quic_sf_list.c:ossl_quic_pkt_type_must_be_last Unexecuted instantiation: quic_sstream.c:ossl_quic_pkt_type_must_be_last Unexecuted instantiation: quic_stream_map.c:ossl_quic_pkt_type_must_be_last Unexecuted instantiation: quic_thread_assist.c:ossl_quic_pkt_type_must_be_last Unexecuted instantiation: quic_txp.c:ossl_quic_pkt_type_must_be_last Unexecuted instantiation: quic_wire.c:ossl_quic_pkt_type_must_be_last Unexecuted instantiation: quic_wire_pkt.c:ossl_quic_pkt_type_must_be_last Unexecuted instantiation: rec_layer_s3.c:ossl_quic_pkt_type_must_be_last Unexecuted instantiation: qlog_event_helpers.c:ossl_quic_pkt_type_must_be_last Unexecuted instantiation: quic_channel.c:ossl_quic_pkt_type_must_be_last Unexecuted instantiation: quic_demux.c:ossl_quic_pkt_type_must_be_last Unexecuted instantiation: quic_fifd.c:ossl_quic_pkt_type_must_be_last Unexecuted instantiation: quic_rx_depack.c:ossl_quic_pkt_type_must_be_last |
120 | | |
121 | | /* |
122 | | * Determine if the packet type has a version field. |
123 | | */ |
124 | | static ossl_inline ossl_unused int |
125 | | ossl_quic_pkt_type_has_version(uint32_t pkt_type) |
126 | 0 | { |
127 | 0 | return pkt_type != QUIC_PKT_TYPE_1RTT && pkt_type != QUIC_PKT_TYPE_VERSION_NEG; |
128 | 0 | } Unexecuted instantiation: ssl_lib.c:ossl_quic_pkt_type_has_version Unexecuted instantiation: t1_lib.c:ossl_quic_pkt_type_has_version Unexecuted instantiation: quic_impl.c:ossl_quic_pkt_type_has_version Unexecuted instantiation: quic_method.c:ossl_quic_pkt_type_has_version Unexecuted instantiation: quic_obj.c:ossl_quic_pkt_type_has_version Unexecuted instantiation: quic_port.c:ossl_quic_pkt_type_has_version Unexecuted instantiation: quic_record_rx.c:ossl_quic_pkt_type_has_version Unexecuted instantiation: quic_record_shared.c:ossl_quic_pkt_type_has_version Unexecuted instantiation: quic_record_tx.c:ossl_quic_pkt_type_has_version Unexecuted instantiation: quic_record_util.c:ossl_quic_pkt_type_has_version Unexecuted instantiation: quic_rstream.c:ossl_quic_pkt_type_has_version Unexecuted instantiation: quic_sf_list.c:ossl_quic_pkt_type_has_version Unexecuted instantiation: quic_sstream.c:ossl_quic_pkt_type_has_version Unexecuted instantiation: quic_stream_map.c:ossl_quic_pkt_type_has_version Unexecuted instantiation: quic_thread_assist.c:ossl_quic_pkt_type_has_version Unexecuted instantiation: quic_txp.c:ossl_quic_pkt_type_has_version Unexecuted instantiation: quic_wire.c:ossl_quic_pkt_type_has_version Unexecuted instantiation: quic_wire_pkt.c:ossl_quic_pkt_type_has_version Unexecuted instantiation: rec_layer_s3.c:ossl_quic_pkt_type_has_version Unexecuted instantiation: qlog_event_helpers.c:ossl_quic_pkt_type_has_version Unexecuted instantiation: quic_channel.c:ossl_quic_pkt_type_has_version Unexecuted instantiation: quic_demux.c:ossl_quic_pkt_type_has_version Unexecuted instantiation: quic_fifd.c:ossl_quic_pkt_type_has_version Unexecuted instantiation: quic_rx_depack.c:ossl_quic_pkt_type_has_version |
129 | | |
130 | | /* |
131 | | * Determine if the packet type has a SCID field. |
132 | | */ |
133 | | static ossl_inline ossl_unused int |
134 | | ossl_quic_pkt_type_has_scid(uint32_t pkt_type) |
135 | 0 | { |
136 | 0 | return pkt_type != QUIC_PKT_TYPE_1RTT; |
137 | 0 | } Unexecuted instantiation: ssl_lib.c:ossl_quic_pkt_type_has_scid Unexecuted instantiation: t1_lib.c:ossl_quic_pkt_type_has_scid Unexecuted instantiation: quic_impl.c:ossl_quic_pkt_type_has_scid Unexecuted instantiation: quic_method.c:ossl_quic_pkt_type_has_scid Unexecuted instantiation: quic_obj.c:ossl_quic_pkt_type_has_scid Unexecuted instantiation: quic_port.c:ossl_quic_pkt_type_has_scid Unexecuted instantiation: quic_record_rx.c:ossl_quic_pkt_type_has_scid Unexecuted instantiation: quic_record_shared.c:ossl_quic_pkt_type_has_scid Unexecuted instantiation: quic_record_tx.c:ossl_quic_pkt_type_has_scid Unexecuted instantiation: quic_record_util.c:ossl_quic_pkt_type_has_scid Unexecuted instantiation: quic_rstream.c:ossl_quic_pkt_type_has_scid Unexecuted instantiation: quic_sf_list.c:ossl_quic_pkt_type_has_scid Unexecuted instantiation: quic_sstream.c:ossl_quic_pkt_type_has_scid Unexecuted instantiation: quic_stream_map.c:ossl_quic_pkt_type_has_scid Unexecuted instantiation: quic_thread_assist.c:ossl_quic_pkt_type_has_scid Unexecuted instantiation: quic_txp.c:ossl_quic_pkt_type_has_scid Unexecuted instantiation: quic_wire.c:ossl_quic_pkt_type_has_scid Unexecuted instantiation: quic_wire_pkt.c:ossl_quic_pkt_type_has_scid Unexecuted instantiation: rec_layer_s3.c:ossl_quic_pkt_type_has_scid Unexecuted instantiation: qlog_event_helpers.c:ossl_quic_pkt_type_has_scid Unexecuted instantiation: quic_channel.c:ossl_quic_pkt_type_has_scid Unexecuted instantiation: quic_demux.c:ossl_quic_pkt_type_has_scid Unexecuted instantiation: quic_fifd.c:ossl_quic_pkt_type_has_scid Unexecuted instantiation: quic_rx_depack.c:ossl_quic_pkt_type_has_scid |
138 | | |
139 | | /* |
140 | | * Smallest possible QUIC packet size as per RFC (aside from version negotiation |
141 | | * packets). |
142 | | */ |
143 | 0 | # define QUIC_MIN_VALID_PKT_LEN_CRYPTO 21 |
144 | 0 | # define QUIC_MIN_VALID_PKT_LEN_VERSION_NEG 7 |
145 | 0 | # define QUIC_MIN_VALID_PKT_LEN QUIC_MIN_VALID_PKT_LEN_VERSION_NEG |
146 | | |
147 | | typedef struct quic_pkt_hdr_ptrs_st QUIC_PKT_HDR_PTRS; |
148 | | |
149 | | /* |
150 | | * QUIC Packet Header Protection |
151 | | * ============================= |
152 | | * |
153 | | * Functions to apply and remove QUIC packet header protection. A header |
154 | | * protector is initialised using ossl_quic_hdr_protector_init and must be |
155 | | * destroyed using ossl_quic_hdr_protector_cleanup when no longer needed. |
156 | | */ |
157 | | typedef struct quic_hdr_protector_st { |
158 | | OSSL_LIB_CTX *libctx; |
159 | | const char *propq; |
160 | | EVP_CIPHER_CTX *cipher_ctx; |
161 | | EVP_CIPHER *cipher; |
162 | | uint32_t cipher_id; |
163 | | } QUIC_HDR_PROTECTOR; |
164 | | |
165 | 0 | # define QUIC_HDR_PROT_CIPHER_AES_128 1 |
166 | 0 | # define QUIC_HDR_PROT_CIPHER_AES_256 2 |
167 | 0 | # define QUIC_HDR_PROT_CIPHER_CHACHA 3 |
168 | | |
169 | | /* |
170 | | * Initialises a header protector. |
171 | | * |
172 | | * cipher_id: |
173 | | * The header protection cipher method to use. One of |
174 | | * QUIC_HDR_PROT_CIPHER_*. Must be chosen based on negotiated TLS cipher |
175 | | * suite. |
176 | | * |
177 | | * quic_hp_key: |
178 | | * This must be the "quic hp" key derived from a traffic secret. |
179 | | * |
180 | | * The length of the quic_hp_key must correspond to that expected for the |
181 | | * given cipher ID. |
182 | | * |
183 | | * The header protector performs amortisable initialisation in this function, |
184 | | * therefore a header protector should be used for as long as possible. |
185 | | * |
186 | | * Returns 1 on success and 0 on failure. |
187 | | */ |
188 | | int ossl_quic_hdr_protector_init(QUIC_HDR_PROTECTOR *hpr, |
189 | | OSSL_LIB_CTX *libctx, |
190 | | const char *propq, |
191 | | uint32_t cipher_id, |
192 | | const unsigned char *quic_hp_key, |
193 | | size_t quic_hp_key_len); |
194 | | |
195 | | /* |
196 | | * Destroys a header protector. This is also safe to call on a zero-initialized |
197 | | * OSSL_QUIC_HDR_PROTECTOR structure which has not been initialized, or which |
198 | | * has already been destroyed. |
199 | | */ |
200 | | void ossl_quic_hdr_protector_cleanup(QUIC_HDR_PROTECTOR *hpr); |
201 | | |
202 | | /* |
203 | | * Removes header protection from a packet. The packet payload must currently be |
204 | | * encrypted (i.e., you must remove header protection before decrypting packets |
205 | | * received). The function examines the header buffer to determine which bytes |
206 | | * of the header need to be decrypted. |
207 | | * |
208 | | * If this function fails, no data is modified. |
209 | | * |
210 | | * This is implemented as a call to ossl_quic_hdr_protector_decrypt_fields(). |
211 | | * |
212 | | * Returns 1 on success and 0 on failure. |
213 | | */ |
214 | | int ossl_quic_hdr_protector_decrypt(QUIC_HDR_PROTECTOR *hpr, |
215 | | QUIC_PKT_HDR_PTRS *ptrs); |
216 | | |
217 | | /* |
218 | | * Applies header protection to a packet. The packet payload must already have |
219 | | * been encrypted (i.e., you must apply header protection after encrypting |
220 | | * a packet). The function examines the header buffer to determine which bytes |
221 | | * of the header need to be encrypted. |
222 | | * |
223 | | * This is implemented as a call to ossl_quic_hdr_protector_encrypt_fields(). |
224 | | * |
225 | | * Returns 1 on success and 0 on failure. |
226 | | */ |
227 | | int ossl_quic_hdr_protector_encrypt(QUIC_HDR_PROTECTOR *hpr, |
228 | | QUIC_PKT_HDR_PTRS *ptrs); |
229 | | |
230 | | /* |
231 | | * Removes header protection from a packet. The packet payload must currently |
232 | | * be encrypted. This is a low-level function which assumes you have already |
233 | | * determined which parts of the packet header need to be decrypted. |
234 | | * |
235 | | * sample: |
236 | | * The range of bytes in the packet to be used to generate the header |
237 | | * protection mask. It is permissible to set sample_len to the size of the |
238 | | * remainder of the packet; this function will only use as many bytes as |
239 | | * needed. If not enough sample bytes are provided, this function fails. |
240 | | * |
241 | | * first_byte: |
242 | | * The first byte of the QUIC packet header to be decrypted. |
243 | | * |
244 | | * pn: |
245 | | * Pointer to the start of the PN field. The caller is responsible |
246 | | * for ensuring at least four bytes follow this pointer. |
247 | | * |
248 | | * Returns 1 on success and 0 on failure. |
249 | | */ |
250 | | int ossl_quic_hdr_protector_decrypt_fields(QUIC_HDR_PROTECTOR *hpr, |
251 | | const unsigned char *sample, |
252 | | size_t sample_len, |
253 | | unsigned char *first_byte, |
254 | | unsigned char *pn_bytes); |
255 | | |
256 | | /* |
257 | | * Works analogously to ossl_hdr_protector_decrypt_fields, but applies header |
258 | | * protection instead of removing it. |
259 | | */ |
260 | | int ossl_quic_hdr_protector_encrypt_fields(QUIC_HDR_PROTECTOR *hpr, |
261 | | const unsigned char *sample, |
262 | | size_t sample_len, |
263 | | unsigned char *first_byte, |
264 | | unsigned char *pn_bytes); |
265 | | |
266 | | /* |
267 | | * QUIC Packet Header |
268 | | * ================== |
269 | | * |
270 | | * This structure provides a logical representation of a QUIC packet header. |
271 | | * |
272 | | * QUIC packet formats fall into the following categories: |
273 | | * |
274 | | * Long Packets, which is subdivided into five possible packet types: |
275 | | * Version Negotiation (a special case); |
276 | | * Initial; |
277 | | * 0-RTT; |
278 | | * Handshake; and |
279 | | * Retry |
280 | | * |
281 | | * Short Packets, which comprises only a single packet type (1-RTT). |
282 | | * |
283 | | * The packet formats vary and common fields are found in some packets but |
284 | | * not others. The below table indicates which fields are present in which |
285 | | * kinds of packet. * indicates header protection is applied. |
286 | | * |
287 | | * SLLLLL Legend: 1=1-RTT, i=Initial, 0=0-RTT, h=Handshake |
288 | | * 1i0hrv r=Retry, v=Version Negotiation |
289 | | * ------ |
290 | | * 1i0hrv Header Form (0=Short, 1=Long) |
291 | | * 1i0hr Fixed Bit (always 1) |
292 | | * 1 Spin Bit |
293 | | * 1 * Reserved Bits |
294 | | * 1 * Key Phase |
295 | | * 1i0h * Packet Number Length |
296 | | * i0hr? Long Packet Type |
297 | | * i0h Type-Specific Bits |
298 | | * i0hr Version (note: always 0 for Version Negotiation packets) |
299 | | * 1i0hrv Destination Connection ID |
300 | | * i0hrv Source Connection ID |
301 | | * 1i0h * Packet Number |
302 | | * i Token |
303 | | * i0h Length |
304 | | * r Retry Token |
305 | | * r Retry Integrity Tag |
306 | | * |
307 | | * For each field below, the conditions under which the field is valid are |
308 | | * specified. If a field is not currently valid, it is initialized to a zero or |
309 | | * NULL value. |
310 | | */ |
311 | | typedef struct quic_pkt_hdr_st { |
312 | | /* [ALL] A QUIC_PKT_TYPE_* value. Always valid. */ |
313 | | unsigned int type :8; |
314 | | |
315 | | /* [S] Value of the spin bit. Valid if (type == 1RTT). */ |
316 | | unsigned int spin_bit :1; |
317 | | |
318 | | /* |
319 | | * [S] Value of the Key Phase bit in the short packet. |
320 | | * Valid if (type == 1RTT && !partial). |
321 | | */ |
322 | | unsigned int key_phase :1; |
323 | | |
324 | | /* |
325 | | * [1i0h] Length of packet number in bytes. This is the decoded value. |
326 | | * Valid if ((type == 1RTT || (version && type != RETRY)) && !partial). |
327 | | */ |
328 | | unsigned int pn_len :4; |
329 | | |
330 | | /* |
331 | | * [ALL] Set to 1 if this is a partial decode because the packet header |
332 | | * has not yet been deprotected. pn_len, pn and key_phase are not valid if |
333 | | * this is set. |
334 | | */ |
335 | | unsigned int partial :1; |
336 | | |
337 | | /* |
338 | | * [ALL] Whether the fixed bit was set. Note that only Version Negotiation |
339 | | * packets are allowed to have this unset, so this will always be 1 for all |
340 | | * other packet types (decode will fail if it is not set). Ignored when |
341 | | * encoding unless encoding a Version Negotiation packet. |
342 | | */ |
343 | | unsigned int fixed :1; |
344 | | |
345 | | /* |
346 | | * The unused bits in the low 4 bits of a Retry packet header's first byte. |
347 | | * This is used to ensure that Retry packets have the same bit-for-bit |
348 | | * representation in their header when decoding and encoding them again. |
349 | | * This is necessary to validate Retry packet headers. |
350 | | */ |
351 | | unsigned int unused :4; |
352 | | |
353 | | /* |
354 | | * The 'Reserved' bits in an Initial, Handshake, 0-RTT or 1-RTT packet |
355 | | * header's first byte. These are provided so that the caller can validate |
356 | | * that they are zero, as this must be done after packet protection is |
357 | | * successfully removed to avoid creating a timing channel. |
358 | | */ |
359 | | unsigned int reserved :2; |
360 | | |
361 | | /* [L] Version field. Valid if (type != 1RTT). */ |
362 | | uint32_t version; |
363 | | |
364 | | /* [ALL] The destination connection ID. Always valid. */ |
365 | | QUIC_CONN_ID dst_conn_id; |
366 | | |
367 | | /* |
368 | | * [L] The source connection ID. |
369 | | * Valid if (type != 1RTT). |
370 | | */ |
371 | | QUIC_CONN_ID src_conn_id; |
372 | | |
373 | | /* |
374 | | * [1i0h] Relatively-encoded packet number in raw, encoded form. The correct |
375 | | * decoding of this value is context-dependent. The number of bytes valid in |
376 | | * this buffer is determined by pn_len above. If the decode was partial, |
377 | | * this field is not valid. |
378 | | * |
379 | | * Valid if ((type == 1RTT || (version && type != RETRY)) && !partial). |
380 | | */ |
381 | | unsigned char pn[4]; |
382 | | |
383 | | /* |
384 | | * [i] Token field in Initial packet. Points to memory inside the decoded |
385 | | * PACKET, and therefore is valid for as long as the PACKET's buffer is |
386 | | * valid. token_len is the length of the token in bytes. |
387 | | * |
388 | | * Valid if (type == INITIAL). |
389 | | */ |
390 | | const unsigned char *token; |
391 | | size_t token_len; |
392 | | |
393 | | /* |
394 | | * [ALL] Payload length in bytes. |
395 | | * |
396 | | * Though 1-RTT, Retry and Version Negotiation packets do not contain an |
397 | | * explicit length field, this field is always valid and is used by the |
398 | | * packet header encoding and decoding routines to describe the payload |
399 | | * length, regardless of whether the packet type encoded or decoded uses an |
400 | | * explicit length indication. |
401 | | */ |
402 | | size_t len; |
403 | | |
404 | | /* |
405 | | * Pointer to start of payload data in the packet. Points to memory inside |
406 | | * the decoded PACKET, and therefore is valid for as long as the PACKET'S |
407 | | * buffer is valid. The length of the buffer in bytes is in len above. |
408 | | * |
409 | | * For Version Negotiation packets, points to the array of supported |
410 | | * versions. |
411 | | * |
412 | | * For Retry packets, points to the Retry packet payload, which comprises |
413 | | * the Retry Token followed by a 16-byte Retry Integrity Tag. |
414 | | * |
415 | | * Regardless of whether a packet is a Version Negotiation packet (where the |
416 | | * payload contains a list of supported versions), a Retry packet (where the |
417 | | * payload contains a Retry Token and Retry Integrity Tag), or any other |
418 | | * packet type (where the payload contains frames), the payload is not |
419 | | * validated and the user must parse the payload bearing this in mind. |
420 | | * |
421 | | * If the decode was partial (partial is set), this points to the start of |
422 | | * the packet number field, rather than the protected payload, as the length |
423 | | * of the packet number field is unknown. The len field reflects this in |
424 | | * this case (i.e., the len field is the number of payload bytes plus the |
425 | | * number of bytes comprising the PN). |
426 | | */ |
427 | | const unsigned char *data; |
428 | | } QUIC_PKT_HDR; |
429 | | |
430 | | /* |
431 | | * Extra information which can be output by the packet header decode functions |
432 | | * for the assistance of the header protector. This avoids the header protector |
433 | | * needing to partially re-decode the packet header. |
434 | | */ |
435 | | struct quic_pkt_hdr_ptrs_st { |
436 | | unsigned char *raw_start; /* start of packet */ |
437 | | unsigned char *raw_sample; /* start of sampling range */ |
438 | | size_t raw_sample_len; /* maximum length of sampling range */ |
439 | | |
440 | | /* |
441 | | * Start of PN field. Guaranteed to be NULL unless at least four bytes are |
442 | | * available via this pointer. |
443 | | */ |
444 | | unsigned char *raw_pn; |
445 | | }; |
446 | | |
447 | | /* |
448 | | * If partial is 1, reads the unprotected parts of a protected packet header |
449 | | * from a PACKET, performing a partial decode. |
450 | | * |
451 | | * If partial is 0, the input is assumed to have already had header protection |
452 | | * removed, and all header fields are decoded. |
453 | | * |
454 | | * If nodata is 1, the input is assumed to have no payload data in it. Otherwise |
455 | | * payload data must be present. |
456 | | * |
457 | | * On success, the logical decode of the packet header is written to *hdr. |
458 | | * hdr->partial is set or cleared according to whether a partial decode was |
459 | | * performed. *ptrs is filled with pointers to various parts of the packet |
460 | | * buffer. |
461 | | * |
462 | | * In order to decode short packets, the connection ID length being used must be |
463 | | * known contextually, and should be passed as short_conn_id_len. If |
464 | | * short_conn_id_len is set to an invalid value (a value greater than |
465 | | * QUIC_MAX_CONN_ID_LEN), this function fails when trying to decode a short |
466 | | * packet, but succeeds for long packets. |
467 | | * |
468 | | * fail_cause is a bitmask of the reasons decode might have failed |
469 | | * as defined below, useful when you need to interrogate parts of |
470 | | * a header even if its otherwise undecodeable. May be NULL. |
471 | | * |
472 | | * Returns 1 on success and 0 on failure. |
473 | | */ |
474 | | |
475 | 0 | # define QUIC_PKT_HDR_DECODE_DECODE_ERR (1 << 0) |
476 | 0 | # define QUIC_PKT_HDR_DECODE_BAD_VERSION (1 << 1) |
477 | | |
478 | | int ossl_quic_wire_decode_pkt_hdr(PACKET *pkt, |
479 | | size_t short_conn_id_len, |
480 | | int partial, |
481 | | int nodata, |
482 | | QUIC_PKT_HDR *hdr, |
483 | | QUIC_PKT_HDR_PTRS *ptrs, |
484 | | uint64_t *fail_cause); |
485 | | |
486 | | /* |
487 | | * Encodes a packet header. The packet is written to pkt. |
488 | | * |
489 | | * The length of the (encrypted) packet payload should be written to hdr->len |
490 | | * and will be placed in the serialized packet header. The payload data itself |
491 | | * is not copied; the caller should write hdr->len bytes of encrypted payload to |
492 | | * the WPACKET immediately after the call to this function. However, |
493 | | * WPACKET_reserve_bytes is called for the payload size. |
494 | | * |
495 | | * This function does not apply header protection. You must apply header |
496 | | * protection yourself after calling this function. *ptrs is filled with |
497 | | * pointers which can be passed to a header protector, but this must be |
498 | | * performed after the encrypted payload is written. |
499 | | * |
500 | | * The pointers in *ptrs are direct pointers into the WPACKET buffer. If more |
501 | | * data is written to the WPACKET buffer, WPACKET buffer reallocations may |
502 | | * occur, causing these pointers to become invalid. Therefore, you must not call |
503 | | * any write WPACKET function between this call and the call to |
504 | | * ossl_quic_hdr_protector_encrypt. This function calls WPACKET_reserve_bytes |
505 | | * for the payload length, so you may assume hdr->len bytes are already free to |
506 | | * write at the WPACKET cursor location once this function returns successfully. |
507 | | * It is recommended that you call this function, write the encrypted payload, |
508 | | * call ossl_quic_hdr_protector_encrypt, and then call |
509 | | * WPACKET_allocate_bytes(hdr->len). |
510 | | * |
511 | | * Version Negotiation and Retry packets do not use header protection; for these |
512 | | * header types, the fields in *ptrs are all written as zero. Version |
513 | | * Negotiation, Retry and 1-RTT packets do not contain a Length field, but |
514 | | * hdr->len bytes of data are still reserved in the WPACKET. |
515 | | * |
516 | | * If serializing a short packet and short_conn_id_len does not match the DCID |
517 | | * specified in hdr, the function fails. |
518 | | * |
519 | | * Returns 1 on success and 0 on failure. |
520 | | */ |
521 | | int ossl_quic_wire_encode_pkt_hdr(WPACKET *pkt, |
522 | | size_t short_conn_id_len, |
523 | | const QUIC_PKT_HDR *hdr, |
524 | | QUIC_PKT_HDR_PTRS *ptrs); |
525 | | |
526 | | /* |
527 | | * Retrieves only the DCID from a packet header. This is intended for demuxer |
528 | | * use. It avoids the need to parse the rest of the packet header twice. |
529 | | * |
530 | | * Information on packet length is not decoded, as this only needs to be used on |
531 | | * the first packet in a datagram, therefore this takes a buffer and not a |
532 | | * PACKET. |
533 | | * |
534 | | * Returns 1 on success and 0 on failure. |
535 | | */ |
536 | | int ossl_quic_wire_get_pkt_hdr_dst_conn_id(const unsigned char *buf, |
537 | | size_t buf_len, |
538 | | size_t short_conn_id_len, |
539 | | QUIC_CONN_ID *dst_conn_id); |
540 | | |
541 | | /* |
542 | | * Precisely predicts the encoded length of a packet header structure. |
543 | | * |
544 | | * May return 0 if the packet header is not valid, but the fact that this |
545 | | * function returns non-zero does not guarantee that |
546 | | * ossl_quic_wire_encode_pkt_hdr() will succeed. |
547 | | */ |
548 | | int ossl_quic_wire_get_encoded_pkt_hdr_len(size_t short_conn_id_len, |
549 | | const QUIC_PKT_HDR *hdr); |
550 | | |
551 | | /* |
552 | | * Packet Number Encoding |
553 | | * ====================== |
554 | | */ |
555 | | |
556 | | /* |
557 | | * Decode an encoded packet header QUIC PN. |
558 | | * |
559 | | * enc_pn is the raw encoded PN to decode. enc_pn_len is its length in bytes as |
560 | | * indicated by packet headers. largest_pn is the largest PN successfully |
561 | | * processed in the relevant PN space. |
562 | | * |
563 | | * The resulting PN is written to *res_pn. |
564 | | * |
565 | | * Returns 1 on success or 0 on failure. |
566 | | */ |
567 | | int ossl_quic_wire_decode_pkt_hdr_pn(const unsigned char *enc_pn, |
568 | | size_t enc_pn_len, |
569 | | QUIC_PN largest_pn, |
570 | | QUIC_PN *res_pn); |
571 | | |
572 | | /* |
573 | | * Determine how many bytes should be used to encode a PN. Returns the number of |
574 | | * bytes (which will be in range [1, 4]). |
575 | | */ |
576 | | int ossl_quic_wire_determine_pn_len(QUIC_PN pn, QUIC_PN largest_acked); |
577 | | |
578 | | /* |
579 | | * Encode a PN for a packet header using the specified number of bytes, which |
580 | | * should have been determined by calling ossl_quic_wire_determine_pn_len. The |
581 | | * PN encoding process is done in two parts to allow the caller to override PN |
582 | | * encoding length if it wishes. |
583 | | * |
584 | | * Returns 1 on success and 0 on failure. |
585 | | */ |
586 | | int ossl_quic_wire_encode_pkt_hdr_pn(QUIC_PN pn, |
587 | | unsigned char *enc_pn, |
588 | | size_t enc_pn_len); |
589 | | |
590 | | /* |
591 | | * Retry Integrity Tags |
592 | | * ==================== |
593 | | */ |
594 | | |
595 | 0 | # define QUIC_RETRY_INTEGRITY_TAG_LEN 16 |
596 | | |
597 | | /* |
598 | | * Validate a retry integrity tag. Returns 1 if the tag is valid. |
599 | | * |
600 | | * Must be called on a hdr with a type of QUIC_PKT_TYPE_RETRY with a valid data |
601 | | * pointer. |
602 | | * |
603 | | * client_initial_dcid must be the original DCID used by the client in its first |
604 | | * Initial packet, as this is used to calculate the Retry Integrity Tag. |
605 | | * |
606 | | * Returns 0 if the tag is invalid, if called on any other type of packet or if |
607 | | * the body is too short. |
608 | | */ |
609 | | int ossl_quic_validate_retry_integrity_tag(OSSL_LIB_CTX *libctx, |
610 | | const char *propq, |
611 | | const QUIC_PKT_HDR *hdr, |
612 | | const QUIC_CONN_ID *client_initial_dcid); |
613 | | |
614 | | /* |
615 | | * Calculates a retry integrity tag. Returns 0 on error, for example if hdr does |
616 | | * not have a type of QUIC_PKT_TYPE_RETRY. |
617 | | * |
618 | | * client_initial_dcid must be the original DCID used by the client in its first |
619 | | * Initial packet, as this is used to calculate the Retry Integrity Tag. |
620 | | * |
621 | | * tag must point to a buffer of QUIC_RETRY_INTEGRITY_TAG_LEN bytes in size. |
622 | | * |
623 | | * Note that hdr->data must point to the Retry packet body, and hdr->len must |
624 | | * include the space for the Retry Integrity Tag. (This means that you can |
625 | | * easily fill in a tag in a Retry packet you are generating by calling this |
626 | | * function and passing (hdr->data + hdr->len - QUIC_RETRY_INTEGRITY_TAG_LEN) as |
627 | | * the tag argument.) This function fails if hdr->len is too short to contain a |
628 | | * Retry Integrity Tag. |
629 | | */ |
630 | | int ossl_quic_calculate_retry_integrity_tag(OSSL_LIB_CTX *libctx, |
631 | | const char *propq, |
632 | | const QUIC_PKT_HDR *hdr, |
633 | | const QUIC_CONN_ID *client_initial_dcid, |
634 | | unsigned char *tag); |
635 | | |
636 | | # endif |
637 | | |
638 | | #endif |