2 * Routines for QUIC (IETF) dissection
3 * Copyright 2017, Alexis La Goutte <alexis.lagoutte at gmail dot com>
4 * Copyright 2018 Peter Wu <peter@lekensteyn.nl>
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
14 * See https://quicwg.org
15 * RFC9000 QUIC: A UDP-Based Multiplexed and Secure Transport
16 * RFC9001 Using TLS to Secure QUIC
17 * RFC8889 Version-Independent Properties of QUIC
18 * RFC9221 An Unreliable Datagram Extension to QUIC
19 * RFC9369 QUIC Version 2
20 * RFC9368 Compatible Version Negotiation for QUIC
23 * https://tools.ietf.org/html/draft-ferrieuxhamchaoui-quic-lossbits-03
24 * https://tools.ietf.org/html/draft-huitema-quic-ts-02
25 * https://tools.ietf.org/html/draft-ietf-quic-ack-frequency-07 (and also draft-04/05)
26 * https://tools.ietf.org/html/draft-banks-quic-cibir-01
27 * https://tools.ietf.org/html/draft-ietf-quic-multipath-11 (and also >= draft-07)
30 * Currently supported QUIC version(s): draft-21, draft-22, draft-23, draft-24,
31 * draft-25, draft-26, draft-27, draft-28, draft-29, draft-30, draft-31, draft-32,
32 * draft-33, draft-34, v1, v2
33 * For a table of supported QUIC versions per Wireshark version, see
34 * https://github.com/quicwg/base-drafts/wiki/Tools#wireshark
36 * Decryption is supported via TLS 1.3 secrets in the "TLS Key Log File",
37 * configured either at the TLS Protocol preferences, or embedded in a pcapng
38 * file. Sample captures and secrets can be found at:
39 * https://gitlab.com/wireshark/wireshark/-/issues/13881
42 * - STREAM offsets larger than 32-bit are unsupported.
43 * - STREAM with sizes larger than 32 bit are unsupported. STREAM sizes can be
44 * up to 62 bit in QUIC, but the TVB and reassembly API is limited to 32 bit.
45 * - Out-of-order and overlapping STREAM frame data is not handled.
46 * - "Follow QUIC Stream" doesn't work with STREAM IDs larger than 32 bit
51 #include <epan/packet.h>
52 #include <epan/expert.h>
53 #include <epan/proto_data.h>
54 #include <epan/to_str.h>
55 #include "packet-tls-utils.h"
56 #include "packet-tls.h"
57 #include "packet-tcp.h" /* used for STREAM reassembly. */
58 #include "packet-udp.h"
59 #include "packet-quic.h"
60 #include <epan/reassemble.h>
61 #include <epan/prefs.h>
62 #include <wsutil/pint.h>
65 #include <epan/follow.h>
66 #include <epan/addr_resolv.h>
69 void proto_reg_handoff_quic(void);
70 void proto_register_quic(void);
72 static int quic_follow_tap
;
74 /* Initialize the protocol and registered fields */
75 static int proto_quic
;
76 static int hf_quic_connection_number
;
77 static int hf_quic_packet_length
;
78 static int hf_quic_header_form
;
79 static int hf_quic_long_packet_type
;
80 static int hf_quic_long_packet_type_v2
;
81 static int hf_quic_long_reserved
;
82 static int hf_quic_packet_number_length
;
83 static int hf_quic_dcid
;
84 static int hf_quic_scid
;
85 static int hf_quic_dcil
;
86 static int hf_quic_scil
;
87 static int hf_quic_token_length
;
88 static int hf_quic_token
;
89 static int hf_quic_length
;
90 static int hf_quic_packet_number
;
91 static int hf_quic_version
;
92 static int hf_quic_supported_version
;
93 static int hf_quic_vn_unused
;
94 static int hf_quic_short
;
95 static int hf_quic_fixed_bit
;
96 static int hf_quic_spin_bit
;
97 static int hf_quic_short_reserved
;
98 static int hf_quic_q_bit
;
99 static int hf_quic_l_bit
;
100 static int hf_quic_key_phase
;
101 static int hf_quic_payload
;
102 static int hf_quic_protected_payload
;
103 static int hf_quic_remaining_payload
;
104 static int hf_quic_odcil
;
105 static int hf_quic_odcid
;
106 static int hf_quic_retry_token
;
107 static int hf_quic_retry_integrity_tag
;
109 static int hf_quic_frame
;
110 static int hf_quic_frame_type
;
112 static int hf_quic_padding_length
;
113 static int hf_quic_ack_largest_acknowledged
;
114 static int hf_quic_ack_ack_delay
;
115 static int hf_quic_ack_ack_range_count
;
116 static int hf_quic_ack_first_ack_range
;
117 static int hf_quic_ack_gap
;
118 static int hf_quic_ack_ack_range
;
119 static int hf_quic_ack_ect0_count
;
120 static int hf_quic_ack_ect1_count
;
121 static int hf_quic_ack_ecn_ce_count
;
122 static int hf_quic_rsts_stream_id
;
123 static int hf_quic_rsts_application_error_code
;
124 static int hf_quic_rsts_final_size
;
125 static int hf_quic_ss_stream_id
;
126 static int hf_quic_ss_application_error_code
;
127 static int hf_quic_crypto_offset
;
128 static int hf_quic_crypto_length
;
129 static int hf_quic_crypto_crypto_data
;
130 static int hf_quic_nt_length
;
131 static int hf_quic_nt_token
;
132 static int hf_quic_stream_fin
;
133 static int hf_quic_stream_len
;
134 static int hf_quic_stream_off
;
135 static int hf_quic_stream_stream_id
;
136 static int hf_quic_stream_initiator
;
137 static int hf_quic_stream_direction
;
138 static int hf_quic_stream_offset
;
139 static int hf_quic_stream_length
;
140 static int hf_quic_stream_data
;
141 static int hf_quic_md_maximum_data
;
142 static int hf_quic_msd_stream_id
;
143 static int hf_quic_msd_maximum_stream_data
;
144 static int hf_quic_ms_max_streams
;
145 static int hf_quic_db_stream_data_limit
;
146 static int hf_quic_sdb_stream_id
;
147 static int hf_quic_sdb_stream_data_limit
;
148 static int hf_quic_sb_stream_limit
;
149 static int hf_quic_nci_retire_prior_to
;
150 static int hf_quic_nci_sequence
;
151 static int hf_quic_nci_connection_id_length
;
152 static int hf_quic_nci_connection_id
;
153 static int hf_quic_nci_stateless_reset_token
;
154 static int hf_quic_rci_sequence
;
155 static int hf_quic_path_challenge_data
;
156 static int hf_quic_path_response_data
;
157 static int hf_quic_cc_error_code
;
158 static int hf_quic_cc_error_code_app
;
159 static int hf_quic_cc_error_code_tls_alert
;
160 static int hf_quic_cc_frame_type
;
161 static int hf_quic_cc_reason_phrase_length
;
162 static int hf_quic_cc_reason_phrase
;
163 static int hf_quic_dg_length
;
164 static int hf_quic_dg
;
165 static int hf_quic_af_sequence_number
;
166 static int hf_quic_af_ack_eliciting_threshold
;
167 static int hf_quic_af_request_max_ack_delay
;
168 static int hf_quic_af_reordering_threshold
;
169 //static int hf_quic_af_ignore_order;
170 //static int hf_quic_af_ignore_ce;
171 static int hf_quic_ts
;
172 static int hf_quic_unpredictable_bits
;
173 static int hf_quic_stateless_reset_token
;
174 static int hf_quic_reassembled_in
;
175 static int hf_quic_reassembled_length
;
176 static int hf_quic_reassembled_data
;
177 static int hf_quic_fragments
;
178 static int hf_quic_fragment
;
179 static int hf_quic_fragment_overlap
;
180 static int hf_quic_fragment_overlap_conflict
;
181 static int hf_quic_fragment_multiple_tails
;
182 static int hf_quic_fragment_too_long_fragment
;
183 static int hf_quic_fragment_error
;
184 static int hf_quic_fragment_count
;
186 static int hf_quic_crypto_reassembled_in
;
187 static int hf_quic_crypto_fragments
;
188 static int hf_quic_crypto_fragment
;
189 static int hf_quic_crypto_fragment_count
;
192 static int hf_quic_mp_pnci_path_identifier
;
193 static int hf_quic_mp_rc_path_identifier
;
194 static int hf_quic_mp_path_ack_path_identifier
;
195 static int hf_quic_mp_pa_path_identifier
;
196 static int hf_quic_mp_pa_error_code
;
197 static int hf_quic_mp_ps_path_identifier
;
198 static int hf_quic_mp_ps_path_status_sequence_number
;
199 static int hf_quic_mp_ps_path_status
;
200 static int hf_quic_mp_maximum_paths
;
201 static int hf_quic_mp_maximum_path_identifier
;
203 static expert_field ei_quic_connection_unknown
;
204 static expert_field ei_quic_ft_unknown
;
205 static expert_field ei_quic_decryption_failed
;
206 static expert_field ei_quic_protocol_violation
;
207 static expert_field ei_quic_bad_retry
;
208 static expert_field ei_quic_coalesced_padding_data
;
209 static expert_field ei_quic_retransmission
;
210 static expert_field ei_quic_overlap
;
211 static expert_field ei_quic_data_after_forcing_vn
;
214 static int ett_quic_af
;
215 static int ett_quic_short_header
;
216 static int ett_quic_connection_info
;
217 static int ett_quic_ft
;
218 static int ett_quic_ftflags
;
219 static int ett_quic_ftid
;
220 static int ett_quic_fragments
;
221 static int ett_quic_fragment
;
222 static int ett_quic_crypto_fragments
;
223 static int ett_quic_crypto_fragment
;
225 static dissector_handle_t quic_handle
;
226 static dissector_handle_t tls13_handshake_handle
;
228 static dissector_table_t quic_proto_dissector_table
;
230 /* Fields for showing reassembly results for fragments of QUIC stream data. */
231 static const fragment_items quic_stream_fragment_items
= {
236 &hf_quic_fragment_overlap
,
237 &hf_quic_fragment_overlap_conflict
,
238 &hf_quic_fragment_multiple_tails
,
239 &hf_quic_fragment_too_long_fragment
,
240 &hf_quic_fragment_error
,
241 &hf_quic_fragment_count
,
242 &hf_quic_reassembled_in
,
243 &hf_quic_reassembled_length
,
244 &hf_quic_reassembled_data
,
248 /* Fields for showing reassembly results for fragments of QUIC crypto packets. */
249 static const fragment_items quic_crypto_fragment_items
= {
250 &ett_quic_crypto_fragment
,
251 &ett_quic_crypto_fragments
,
252 &hf_quic_crypto_fragments
,
253 &hf_quic_crypto_fragment
,
254 &hf_quic_fragment_overlap
, /* We can reuse the error fields. */
255 &hf_quic_fragment_overlap_conflict
,
256 &hf_quic_fragment_multiple_tails
,
257 &hf_quic_fragment_too_long_fragment
,
258 &hf_quic_fragment_error
,
259 &hf_quic_crypto_fragment_count
,
260 &hf_quic_crypto_reassembled_in
,
261 NULL
, /* length, redundant */
262 NULL
, /* data, redundant */
267 * PROTECTED PAYLOAD DECRYPTION (done in first pass)
269 * Long packet types always use a single cipher depending on packet type.
270 * Short packet types always use 1-RTT secrets for packet protection (pp).
273 * - QUIC packets might appear out-of-order (short packets before handshake
274 * message is captured), lost or retransmitted/duplicated.
275 * - During live capture, keys might not be immediately be available. 1-RTT
276 * client keys will be ready while client processes Server Hello (Handshake).
277 * 1-RTT server keys will be ready while server creates Handshake message in
278 * response to Initial Handshake.
279 * - So delay cipher creation until first short packet is received.
281 * Required input from TLS dissector: TLS-Exporter 0-RTT/1-RTT secrets and
282 * cipher/hash algorithms.
284 * QUIC payload decryption requires proper reconstruction of the packet number
285 * which requires proper header decryption. The different states are:
287 * Packet type Packet number space Secrets
288 * Long: Initial Initial Initial secrets
289 * Long: Handshake Handshake Handshake
290 * Long: 0-RTT 0/1-RTT (appdata) 0-RTT
291 * Short header 0/1-RTT (appdata) 1-RTT (KP0 / KP1)
293 * Important to note is that Short Header decryption requires TWO ciphers (one
294 * for each key phase), but that header protection uses only KP0. Total state
295 * needed for each peer (client and server):
296 * - 3 packet number spaces: Initial, Handshake, 0/1-RTT (appdata).
297 * - 4 header protection ciphers: initial, 0-RTT, HS, 1-RTT.
298 * - 5 payload protection ciphers: initial, 0-RTT, HS, 1-RTT (KP0), 1-RTT (KP1).
300 * The multipath draft features introduces separate appdata number spaces for
301 * each Path ID. (prior to draft-07, for each Destination Connection ID.)
304 /* Loss bits feature: https://tools.ietf.org/html/draft-ferrieuxhamchaoui-quic-lossbits-03
305 "The use of the loss bits is negotiated using a transport parameter.
307 When loss_bits parameter is present, the peer is allowed to use
308 reserved bits in the short packet header as loss bits if the peer
310 When loss_bits is set to 1, the sender will use reserved bits as loss
311 bits if the peer includes the loss_bits transport parameter.
313 Unlike the reserved (R) bits, the loss (Q and L) bits are not
314 protected. When sending loss bits has been negotiated, the first
315 byte of the header protection mask used to protect short packet
316 headers has its five most significant bits masked out instead of
320 typedef struct quic_decrypt_result
{
321 const unsigned char *error
; /**< Error message or NULL for success. */
322 const uint8_t *data
; /**< Decrypted result on success (file-scoped). */
323 unsigned data_len
; /**< Size of decrypted data. */
324 } quic_decrypt_result_t
;
326 /** QUIC decryption context. */
329 typedef struct quic_hp_cipher
{
330 gcry_cipher_hd_t hp_cipher
; /**< Header protection cipher. */
332 typedef struct quic_pp_cipher
{
333 gcry_cipher_hd_t pp_cipher
; /**< Packet protection cipher. */
334 uint8_t pp_iv
[TLS13_AEAD_NONCE_LENGTH
];
336 typedef struct quic_ciphers
{
337 quic_hp_cipher hp_cipher
;
338 quic_pp_cipher pp_cipher
;
342 * Packet protection state for an endpoint.
344 typedef struct quic_pp_state
{
345 uint8_t *next_secret
; /**< Next application traffic secret. */
346 quic_pp_cipher pp_ciphers
[2]; /**< PP cipher for Key Phase 0/1 */
347 quic_hp_cipher hp_cipher
; /**< HP cipher for both Key Phases; it does not change after KeyUpdate */
348 uint64_t changed_in_pkn
; /**< Packet number where key change occurred. */
349 bool key_phase
: 1; /**< Current key phase. */
352 /** Singly-linked list of Connection IDs. */
353 typedef struct quic_cid_item quic_cid_item_t
;
354 struct quic_cid_item
{
355 struct quic_cid_item
*next
;
360 * CRYPTO stream state.
363 typedef struct _quic_crypto_state
{
364 uint64_t max_contiguous_offset
;
365 uint8_t encryption_level
; /**< AKA packet type */
366 wmem_tree_t
*multisegment_pdus
;
367 wmem_map_t
*retrans_offsets
;
371 * Per-STREAM state, identified by QUIC Stream ID.
373 * Assume that every QUIC Short Header packet has no STREAM frames that overlap
374 * each other in the same QUIC packet (identified by "frame_num"). Thus, the
375 * Stream ID and offset uniquely identifies the STREAM Frame info in per packet.
377 typedef struct _quic_stream_state
{
379 wmem_tree_t
*multisegment_pdus
;
380 void *subdissector_private
;
384 * Data used to allow "Follow QUIC Stream" functionality
386 typedef struct _quic_follow_stream
{
389 } quic_follow_stream
;
391 typedef struct quic_follow_tap_data
{
395 } quic_follow_tap_data_t
;
397 typedef struct quic_endpoint
{
398 address server_address
;
399 uint16_t server_port
;
403 * State for a single QUIC connection, identified by one or more Destination
404 * Connection IDs (DCID).
406 typedef struct quic_info_data quic_info_data_t
;
407 struct quic_info_data
{
408 uint32_t number
; /** Similar to "udp.stream", but for identifying QUIC connections across migrations. */
410 wmem_list_t
*server_endpoints
; /**< List of server endpoints, primarily used with 0 length DCIDs */
411 bool skip_decryption
: 1; /**< Set to 1 if no keys are available. */
412 bool client_dcid_set
: 1; /**< Set to 1 if client_dcid_initial is set. */
413 bool client_loss_bits_recv
: 1; /**< The client is able to read loss bits info */
414 bool client_loss_bits_send
: 1; /**< The client wants to send loss bits info */
415 bool server_loss_bits_recv
: 1; /**< The server is able to read loss bits info */
416 bool server_loss_bits_send
: 1; /**< The server wants to send loss bits info */
417 unsigned client_multipath
: 2; /**< The client supports multipath */
418 unsigned server_multipath
: 2; /**< The server supports multipath */
419 bool client_grease_quic_bit
: 1; /**< The client supports greasing the Fixed (QUIC) bit */
420 bool server_grease_quic_bit
: 1; /**< The server supports greasing the Fixed (QUIC) bit */
421 int hash_algo
; /**< Libgcrypt hash algorithm for key derivation. */
422 int cipher_algo
; /**< Cipher algorithm for packet number and packet encryption. */
423 int cipher_mode
; /**< Cipher mode for packet encryption. */
424 quic_ciphers client_initial_ciphers
;
425 quic_ciphers server_initial_ciphers
;
426 quic_ciphers client_0rtt_ciphers
;
427 quic_ciphers client_handshake_ciphers
;
428 quic_ciphers server_handshake_ciphers
;
429 quic_pp_state_t client_pp
;
430 quic_pp_state_t server_pp
;
431 uint64_t max_client_pkn
[3]; /**< Packet number spaces for Initial, Handshake and appdata. */
432 uint64_t max_server_pkn
[3];
433 wmem_map_t
*max_client_mp_pkn
; /**< Appdata packet number spaces for multipath, by sequence number. */
434 wmem_map_t
*max_server_mp_pkn
;
435 quic_cid_item_t client_cids
; /**< SCID of client from first Initial Packet. */
436 quic_cid_item_t server_cids
; /**< SCID of server from first Retry/Handshake. */
437 quic_cid_t client_dcid_initial
; /**< DCID from Initial Packet. */
438 dissector_handle_t app_handle
; /**< Application protocol handle (NULL if unknown). */
439 dissector_handle_t zrtt_app_handle
; /**< Application protocol handle (NULL if unknown) for 0-RTT data. */
440 wmem_map_t
*client_streams
; /**< Map from Stream ID -> STREAM info (uint64_t -> quic_stream_state), sent by the client. */
441 wmem_map_t
*server_streams
; /**< Map from Stream ID -> STREAM info (uint64_t -> quic_stream_state), sent by the server. */
442 wmem_list_t
*streams_list
; /**< Ordered list of QUIC Stream ID in this connection (both directions). Used by "Follow QUIC Stream" functionality */
443 wmem_map_t
*streams_map
; /**< Map pinfo->num --> First stream in that frame (unsigned -> quic_follow_stream). Used by "Follow QUIC Stream" functionality */
444 wmem_map_t
*client_crypto
;
445 wmem_map_t
*server_crypto
;
446 gquic_info_data_t
*gquic_info
; /**< GQUIC info for >Q050 flows. */
447 quic_info_data_t
*prev
; /**< The previous QUIC connection multiplexed on the same network 5-tuple. Used by checking Stateless Reset tokens */
450 typedef struct _quic_crypto_info
{
451 const uint64_t packet_number
; /**< Reconstructed full packet number. */
452 uint64_t crypto_offset
; /**< 62-bit stream offset. */
453 uint32_t offset
; /**< Offset within the stream (different for reassembled data). */
457 /** Per-packet information about QUIC, populated on the first pass. */
458 struct quic_packet_info
{
459 struct quic_packet_info
*next
;
460 uint64_t packet_number
; /**< Reconstructed full packet number. */
461 quic_decrypt_result_t decryption
;
462 uint8_t pkn_len
; /**< Length of PKN (1/2/3/4) or unknown (0). */
463 uint8_t first_byte
; /**< Decrypted flag byte, valid only if pkn_len is non-zero. */
465 bool retry_integrity_failure
: 1;
466 bool retry_integrity_success
: 1;
468 typedef struct quic_packet_info quic_packet_info_t
;
470 /** A UDP datagram contains one or more QUIC packets. */
471 typedef struct quic_datagram
{
472 quic_info_data_t
*conn
;
473 quic_packet_info_t first_packet
;
474 uint64_t path_id
; /**< Path ID of the connection ID */
475 /* For multipath prior to draft-07, sequence number and path ID are the
476 * same and unique for each CID on the connection.
478 bool from_server
: 1;
479 bool stateless_reset
: 1;
483 * Maps CID (quic_cid_t *) to a QUIC Connection (quic_info_data_t *).
484 * This assumes that the CIDs are not shared between two different connections
485 * (potentially with different versions) as that would break dissection.
487 * These mappings are authoritative. For example, Initial.SCID is stored in
488 * quic_client_connections while Retry.SCID is stored in
489 * quic_server_connections. Retry.DCID should normally correspond to an entry in
490 * quic_client_connections.
492 static wmem_map_t
*quic_client_connections
, *quic_server_connections
;
493 static wmem_map_t
*quic_initial_connections
; /* Initial.DCID -> connection */
494 static wmem_list_t
*quic_connections
; /* All unique connections. */
495 static uint32_t quic_cid_lengths
; /* Bitmap of CID lengths. */
496 static unsigned quic_connections_count
;
499 quic_multipath_negotiated(quic_info_data_t
*conn
);
501 /* Returns the QUIC draft version or 0 if not applicable. */
502 static inline uint8_t quic_draft_version(uint32_t version
) {
503 /* IETF Draft versions */
504 if ((version
>> 8) == 0xff0000) {
505 return (uint8_t) version
;
507 /* Facebook mvfst, based on draft -22. */
508 if (version
== 0xfaceb001) {
511 /* Facebook mvfst, based on draft -27. */
512 if (version
== 0xfaceb002 || version
== 0xfaceb00e) {
515 /* GQUIC Q050, T050 and T051: they are not really based on any drafts,
516 * but we must return a sensible value */
517 if (version
== 0x51303530 ||
518 version
== 0x54303530 ||
519 version
== 0x54303531) {
522 /* https://tools.ietf.org/html/draft-ietf-quic-transport-32#section-15
523 "Versions that follow the pattern 0x?a?a?a?a are reserved for use in
524 forcing version negotiation to be exercised"
525 We can't return a correct draft version because we don't have a real
526 version here! That means that we can't decode any data and we can dissect
527 only the cleartext header.
528 Let's return v1 (any other numbers should be fine, anyway) to only allow
529 the dissection of the (expected) long header */
530 if ((version
& 0x0F0F0F0F) == 0x0a0a0a0a) {
533 /* QUIC (final?) constants for v1 are defined in draft-33, but draft-34 is the
534 final draft version */
535 if (version
== 0x00000001) {
539 if (version
== 0x6b3343cf) {
545 static inline bool is_quic_v2(uint32_t version
) {
546 return version
== 0x6b3343cf;
549 static inline bool is_quic_draft_max(uint32_t version
, uint8_t max_version
) {
550 uint8_t draft_version
= quic_draft_version(version
);
551 return draft_version
&& draft_version
<= max_version
;
554 const range_string quic_version_vals
[] = {
555 { 0x00000000, 0x00000000, "Version Negotiation" },
556 { 0x00000001, 0x00000001, "1" },
557 { 0x45474700, 0x454747ff, "Quant" },
558 { 0x50435130, 0x50435131, "Picoquic internal" },
559 { 0x50524f58, 0x50524f58, "Proxied QUIC (PROX)" },
560 /* Versions QXXX < Q050 are dissected by Wireshark as GQUIC and not as QUIC.
561 Nonetheless, some implementations report these values in "Version Negotiation"
562 packets, so decode these fields */
563 { 0x51303433, 0x51303433, "Google Q043" },
564 { 0x51303434, 0x51303434, "Google Q044" },
565 { 0x51303436, 0x51303436, "Google Q046" },
566 { 0x51303530, 0x51303530, "Google Q050" },
567 { 0x51474f00, 0x51474fff, "QGO (QUIC GO)" },
568 { 0x54303530, 0x54303530, "Google T050" },
569 { 0x54303531, 0x54303531, "Google T051" },
570 { 0x91c17000, 0x91c170ff, "Quicly" },
571 { 0xabcd0000, 0xabcd000f, "MsQuic" },
572 { 0xf0f0f0f0, 0xf0f0f0ff, "ETH Zürich (Measurability experiments)" },
573 { 0xf0f0f1f0, 0xf0f0f1ff, "Telecom Italia (Measurability experiments)" },
574 { 0xf123f0c0, 0xf123f0cf, "MozQuic" },
575 { 0xfaceb001, 0xfaceb001, "Facebook mvfst (draft-22)" },
576 { 0xfaceb002, 0xfaceb002, "Facebook mvfst (draft-27)" },
577 { 0xfaceb003, 0xfaceb00d, "Facebook mvfst" },
578 { 0xfaceb00e, 0xfaceb00e, "Facebook mvfst (Experimental)" },
579 { 0xfaceb00f, 0xfaceb00f, "Facebook mvfst" },
580 { 0xff000004, 0xff000004, "draft-04" },
581 { 0xff000005, 0xff000005, "draft-05" },
582 { 0xff000006, 0xff000006, "draft-06" },
583 { 0xff000007, 0xff000007, "draft-07" },
584 { 0xff000008, 0xff000008, "draft-08" },
585 { 0xff000009, 0xff000009, "draft-09" },
586 { 0xff00000a, 0xff00000a, "draft-10" },
587 { 0xff00000b, 0xff00000b, "draft-11" },
588 { 0xff00000c, 0xff00000c, "draft-12" },
589 { 0xff00000d, 0xff00000d, "draft-13" },
590 { 0xff00000e, 0xff00000e, "draft-14" },
591 { 0xff00000f, 0xff00000f, "draft-15" },
592 { 0xff000010, 0xff000010, "draft-16" },
593 { 0xff000011, 0xff000011, "draft-17" },
594 { 0xff000012, 0xff000012, "draft-18" },
595 { 0xff000013, 0xff000013, "draft-19" },
596 { 0xff000014, 0xff000014, "draft-20" },
597 { 0xff000015, 0xff000015, "draft-21" },
598 { 0xff000016, 0xff000016, "draft-22" },
599 { 0xff000017, 0xff000017, "draft-23" },
600 { 0xff000018, 0xff000018, "draft-24" },
601 { 0xff000019, 0xff000019, "draft-25" },
602 { 0xff00001a, 0xff00001a, "draft-26" },
603 { 0xff00001b, 0xff00001b, "draft-27" },
604 { 0xff00001c, 0xff00001c, "draft-28" },
605 { 0xff00001d, 0xff00001d, "draft-29" },
606 { 0xff00001e, 0xff00001e, "draft-30" },
607 { 0xff00001f, 0xff00001f, "draft-31" },
608 { 0xff000020, 0xff000020, "draft-32" },
609 { 0xff000021, 0xff000021, "draft-33" },
610 { 0xff000022, 0xff000022, "draft-34" },
612 { 0xff020000, 0xff020000, "v2-draft-00" }, /* Never used; not really supported */
613 { 0x709A50C4, 0x709A50C4, "v2-draft-01" }, /* Never used; not really supported */
614 { 0x6b3343cf, 0x6b3343cf, "2" },
618 static const value_string quic_short_long_header_vals
[] = {
619 { 0, "Short Header" },
620 { 1, "Long Header" },
626 /* Note that these values are "internal-value" used by Wireshark only.
627 Real wire-format values depends on QUIC version */
628 #define QUIC_LPT_INITIAL 0x0
629 #define QUIC_LPT_0RTT 0x1
630 #define QUIC_LPT_HANDSHAKE 0x2
631 #define QUIC_LPT_RETRY 0x3
632 #define QUIC_LPT_VER_NEG 0xfe /* Version Negotiation packets don't have any real packet type */
633 #define QUIC_SHORT_PACKET 0xff /* dummy value that is definitely not LPT */
635 static const value_string quic_v1_long_packet_type_vals
[] = {
638 { 0x02, "Handshake" },
640 /* Version Negotiation packets never use this mapping, so no need to add QUIC_LPT_VER_NEG */
643 static const value_string quic_v2_long_packet_type_vals
[] = {
647 { 0x03, "Handshake" },
648 /* Version Negotiation packets never use this mapping, so no need to add QUIC_LPT_VER_NEG */
652 /* https://github.com/quicwg/base-drafts/wiki/Temporary-IANA-Registry#quic-frame-types */
653 #define FT_PADDING 0x00
656 #define FT_ACK_ECN 0x03
657 #define FT_RESET_STREAM 0x04
658 #define FT_STOP_SENDING 0x05
659 #define FT_CRYPTO 0x06
660 #define FT_NEW_TOKEN 0x07
661 #define FT_STREAM_8 0x08
662 #define FT_STREAM_9 0x09
663 #define FT_STREAM_A 0x0a
664 #define FT_STREAM_B 0x0b
665 #define FT_STREAM_C 0x0c
666 #define FT_STREAM_D 0x0d
667 #define FT_STREAM_E 0x0e
668 #define FT_STREAM_F 0x0f
669 #define FT_MAX_DATA 0x10
670 #define FT_MAX_STREAM_DATA 0x11
671 #define FT_MAX_STREAMS_BIDI 0x12
672 #define FT_MAX_STREAMS_UNI 0x13
673 #define FT_DATA_BLOCKED 0x14
674 #define FT_STREAM_DATA_BLOCKED 0x15
675 #define FT_STREAMS_BLOCKED_BIDI 0x16
676 #define FT_STREAMS_BLOCKED_UNI 0x17
677 #define FT_NEW_CONNECTION_ID 0x18
678 #define FT_RETIRE_CONNECTION_ID 0x19
679 #define FT_PATH_CHALLENGE 0x1a
680 #define FT_PATH_RESPONSE 0x1b
681 #define FT_IMMEDIATE_ACK 0x1f
682 #define FT_CONNECTION_CLOSE_TPT 0x1c
683 #define FT_CONNECTION_CLOSE_APP 0x1d
684 #define FT_HANDSHAKE_DONE 0x1e
685 #define FT_DATAGRAM 0x30
686 #define FT_DATAGRAM_LENGTH 0x31
687 #define FT_IMMEDIATE_ACK_DRAFT05 0xac /* ack-frequency-draft-05 */
688 #define FT_ACK_FREQUENCY 0xaf
689 #define FT_PATH_ACK 0x15228c00
690 #define FT_PATH_ACK_ECN 0x15228c01
691 #define FT_PATH_ABANDON 0x15228c05
692 #define FT_PATH_STATUS 0x15228c06 /* multipath-draft-05 */
693 #define FT_PATH_BACKUP 0x15228c07 /* multipath-draft-06 */
694 #define FT_PATH_AVAILABLE 0x15228c08 /* multipath-draft-06 */
695 #define FT_PATH_NEW_CONNECTION_ID 0x15228c09 /* multipath-draft-07 */
696 #define FT_PATH_RETIRE_CONNECTION_ID 0x15228c0a /* multipath-draft-07 */
697 #define FT_MAX_PATHS 0x15228c0b /* multipath-draft-07 */
698 #define FT_MAX_PATH_ID 0x15228c0c /* multipath-draft-09 */
699 #define FT_PATHS_BLOCKED 0x15228c0d /* multipath-draft-11 */
700 #define FT_TIME_STAMP 0x02F5
702 static const range_string quic_frame_type_vals
[] = {
703 { 0x00, 0x00, "PADDING" },
704 { 0x01, 0x01, "PING" },
705 { 0x02, 0x03, "ACK" },
706 { 0x04, 0x04, "RESET_STREAM" },
707 { 0x05, 0x05, "STOP_SENDING" },
708 { 0x06, 0x06, "CRYPTO" },
709 { 0x07, 0x07, "NEW_TOKEN" },
710 { 0x08, 0x0f, "STREAM" },
711 { 0x10, 0x10, "MAX_DATA" },
712 { 0x11, 0x11, "MAX_STREAM_DATA" },
713 { 0x12, 0x12, "MAX_STREAMS (BIDI)" },
714 { 0x13, 0x13, "MAX_STREAMS (UNI)" },
715 { 0x14, 0x14, "DATA_BLOCKED" },
716 { 0x15, 0x15, "STREAM_DATA_BLOCKED" },
717 { 0x16, 0x16, "STREAMS_BLOCKED (BIDI)" },
718 { 0x16, 0x17, "STREAMS_BLOCKED (UNI)" },
719 { 0x18, 0x18, "NEW_CONNECTION_ID" },
720 { 0x19, 0x19, "RETIRE_CONNECTION_ID" },
721 { 0x1a, 0x1a, "PATH_CHALLENGE" },
722 { 0x1b, 0x1b, "PATH_RESPONSE" },
723 { 0x1c, 0x1c, "CONNECTION_CLOSE (Transport)" },
724 { 0x1d, 0x1d, "CONNECTION_CLOSE (Application)" },
725 { 0x1e, 0x1e, "HANDSHAKE_DONE" },
726 { 0x1f, 0x1f, "IMMEDIATE_ACK" },
727 { 0x30, 0x31, "DATAGRAM" },
728 { 0xac, 0xac, "IMMEDIATE_ACK (draft05)" }, /* ack-frequency-draft-05 */
729 { 0xaf, 0xaf, "ACK_FREQUENCY" },
730 { 0x02f5, 0x02f5, "TIME_STAMP" },
731 { 0xbaba00, 0xbaba01, "ACK_MP" }, /* multipath-draft-04 */
732 { 0xbaba05, 0xbaba05, "PATH_ABANDON" }, /* multipath-draft-04 */
733 { 0xbaba06, 0xbaba06, "PATH_STATUS" }, /* multipath-draft-04 */
734 { 0x15228c00, 0x15228c01, "PATH_ACK" }, /* >= multipath-draft-05 */
735 { 0x15228c05, 0x15228c05, "PATH_ABANDON" }, /* >= multipath-draft-05 */
736 { 0x15228c06, 0x15228c06, "PATH_STATUS" }, /* = multipath-draft-05 */
737 { 0x15228c07, 0x15228c07, "PATH_BACKUP" }, /* >= multipath-draft-06 */
738 { 0x15228c08, 0x15228c08, "PATH_AVAILABLE" }, /* >= multipath-draft-06 */
739 { 0x15228c09, 0x15228c09, "PATH_NEW_CONNECTION_ID" }, /* >= multipath-draft-07 */
740 { 0x15228c0a, 0x15228c0a, "PATH_RETIRE_CONNECTION_ID" }, /* >= multipath-draft-07 */
741 { 0x15228c0b, 0x15228c0b, "MAX_PATHS" }, /* >= multipath-draft-07 */
742 { 0x15228c0c, 0x15228c0c, "MAX_PATH_ID" }, /* >= multipath-draft-09 */
743 { 0x15228c0d, 0x15228c0d, "PATHS_BLOCKED" }, /* >= multipath-draft-11 */
749 #define FTFLAGS_STREAM_FIN 0x01
750 #define FTFLAGS_STREAM_LEN 0x02
751 #define FTFLAGS_STREAM_OFF 0x04
753 #define FTFLAGS_STREAM_INITIATOR 0x01
754 #define FTFLAGS_STREAM_DIRECTION 0x02
756 static const range_string quic_transport_error_code_vals
[] = {
757 /* 0x00 - 0x3f Assigned via Standards Action or IESG Review policies. */
758 { 0x0000, 0x0000, "NO_ERROR" },
759 { 0x0001, 0x0001, "INTERNAL_ERROR" },
760 { 0x0002, 0x0002, "CONNECTION_REFUSED" },
761 { 0x0003, 0x0003, "FLOW_CONTROL_ERROR" },
762 { 0x0004, 0x0004, "STREAM_ID_ERROR" },
763 { 0x0005, 0x0005, "STREAM_STATE_ERROR" },
764 { 0x0006, 0x0006, "FINAL_SIZE_ERROR" },
765 { 0x0007, 0x0007, "FRAME_ENCODING_ERROR" },
766 { 0x0008, 0x0008, "TRANSPORT_PARAMETER_ERROR" },
767 { 0x0009, 0x0009, "CONNECTION_ID_LIMIT_ERROR" },
768 { 0x000a, 0x000a, "PROTOCOL_VIOLATION" },
769 { 0x000b, 0x000b, "INVALID_TOKEN" },
770 { 0x000c, 0x000c, "APPLICATION_ERROR" },
771 { 0x000d, 0x000d, "CRYPTO_BUFFER_EXCEEDED" },
772 { 0x000e, 0x000e, "KEY_UPDATE_ERROR" },
773 { 0x000f, 0x000f, "AEAD_LIMIT_REACHED" },
774 { 0x0010, 0x0010, "NO_VIABLE_PATH" },
775 { 0x0011, 0x0011, "VERSION_NEGOTIATION_ERROR" },
776 { 0x0100, 0x01ff, "CRYPTO_ERROR" },
777 /* 0x40 - 0x3fff Assigned via Specification Required policy. */
781 static const value_string quic_packet_number_lengths
[] = {
789 static const val64_string quic_frame_id_initiator
[] = {
790 { 0, "Client-initiated" },
791 { 1, "Server-initiated" },
795 static const val64_string quic_frame_id_direction
[] = {
796 { 0, "Bidirectional" },
797 { 1, "Unidirectional" },
801 static const val64_string quic_mp_path_status
[] = {
809 quic_extract_header(tvbuff_t
*tvb
, uint8_t *long_packet_type
, uint32_t *version
,
810 quic_cid_t
*dcid
, quic_cid_t
*scid
);
813 quic_get_long_packet_type(uint8_t first_byte
, uint32_t version
)
816 if (!is_quic_v2(version
)) {
817 if ((first_byte
& 0x30) >> 4 == 0)
818 return QUIC_LPT_INITIAL
;
819 if ((first_byte
& 0x30) >> 4 == 1)
820 return QUIC_LPT_0RTT
;
821 if ((first_byte
& 0x30) >> 4 == 2)
822 return QUIC_LPT_HANDSHAKE
;
823 return QUIC_LPT_RETRY
;
825 if ((first_byte
& 0x30) >> 4 == 0)
826 return QUIC_LPT_RETRY
;
827 if ((first_byte
& 0x30) >> 4 == 1)
828 return QUIC_LPT_INITIAL
;
829 if ((first_byte
& 0x30) >> 4 == 2)
830 return QUIC_LPT_0RTT
;
831 return QUIC_LPT_HANDSHAKE
;
836 quic_streams_add(packet_info
*pinfo
, quic_info_data_t
*quic_info
, uint64_t stream_id
);
839 quic_hp_cipher_reset(quic_hp_cipher
*hp_cipher
)
841 gcry_cipher_close(hp_cipher
->hp_cipher
);
842 memset(hp_cipher
, 0, sizeof(*hp_cipher
));
845 quic_pp_cipher_reset(quic_pp_cipher
*pp_cipher
)
847 gcry_cipher_close(pp_cipher
->pp_cipher
);
848 memset(pp_cipher
, 0, sizeof(*pp_cipher
));
851 quic_ciphers_reset(quic_ciphers
*ciphers
)
853 quic_hp_cipher_reset(&ciphers
->hp_cipher
);
854 quic_pp_cipher_reset(&ciphers
->pp_cipher
);
858 quic_is_hp_cipher_initialized(quic_hp_cipher
*hp_cipher
)
860 return hp_cipher
&& hp_cipher
->hp_cipher
;
863 quic_is_pp_cipher_initialized(quic_pp_cipher
*pp_cipher
)
865 return pp_cipher
&& pp_cipher
->pp_cipher
;
868 quic_are_ciphers_initialized(quic_ciphers
*ciphers
)
871 quic_is_hp_cipher_initialized(&ciphers
->hp_cipher
) &&
872 quic_is_pp_cipher_initialized(&ciphers
->pp_cipher
);
875 /* Inspired from ngtcp2 */
876 static uint64_t quic_pkt_adjust_pkt_num(uint64_t max_pkt_num
, uint64_t pkt_num
,
878 uint64_t k
= max_pkt_num
== UINT64_MAX
? max_pkt_num
: max_pkt_num
+ 1;
879 uint64_t u
= k
& ~((UINT64_C(1) << n
) - 1);
880 uint64_t a
= u
| pkt_num
;
881 uint64_t b
= (u
+ (UINT64_C(1) << n
)) | pkt_num
;
882 uint64_t a1
= k
< a
? a
- k
: k
- a
;
883 uint64_t b1
= k
< b
? b
- k
: k
- b
;
892 * Given a header protection cipher, a buffer and the packet number offset,
893 * return the unmasked first byte and packet number.
894 * If the loss bits feature is enabled, the protected bits in the first byte
895 * are fewer than usual: 3 instead of 5 (on short headers only)
898 quic_decrypt_header(tvbuff_t
*tvb
, unsigned pn_offset
, quic_hp_cipher
*hp_cipher
, int hp_cipher_algo
,
899 uint8_t *first_byte
, uint32_t *pn
, bool loss_bits_negotiated
)
901 if (!hp_cipher
->hp_cipher
) {
902 // need to know the cipher.
905 gcry_cipher_hd_t h
= hp_cipher
->hp_cipher
;
907 // Sample is always 16 bytes and starts after PKN (assuming length 4).
908 // https://tools.ietf.org/html/draft-ietf-quic-tls-22#section-5.4.2
910 tvb_memcpy(tvb
, sample
, pn_offset
+ 4, 16);
912 uint8_t mask
[5] = { 0 };
913 switch (hp_cipher_algo
) {
914 case GCRY_CIPHER_AES128
:
915 case GCRY_CIPHER_AES256
:
916 /* Encrypt in-place with AES-ECB and extract the mask. */
917 if (gcry_cipher_encrypt(h
, sample
, sizeof(sample
), NULL
, 0)) {
920 memcpy(mask
, sample
, sizeof(mask
));
922 case GCRY_CIPHER_CHACHA20
:
923 /* If Gcrypt receives a 16 byte IV, it will assume the buffer to be
924 * counter || nonce (in little endian), as desired. */
925 if (gcry_cipher_setiv(h
, sample
, 16)) {
928 /* Apply ChaCha20, encrypt in-place five zero bytes. */
929 if (gcry_cipher_encrypt(h
, mask
, sizeof(mask
), NULL
, 0)) {
937 // https://tools.ietf.org/html/draft-ietf-quic-tls-22#section-5.4.1
938 uint8_t packet0
= tvb_get_uint8(tvb
, 0);
939 if ((packet0
& 0x80) == 0x80) {
940 // Long header: 4 bits masked
941 packet0
^= mask
[0] & 0x0f;
944 if (loss_bits_negotiated
== false) {
945 // Standard mask: 5 bits masked
946 packet0
^= mask
[0] & 0x1F;
948 // https://tools.ietf.org/html/draft-ferrieuxhamchaoui-quic-lossbits-03#section-5.3
949 packet0
^= mask
[0] & 0x07;
952 unsigned pkn_len
= (packet0
& 0x03) + 1;
954 uint8_t pkn_bytes
[4];
955 tvb_memcpy(tvb
, pkn_bytes
, pn_offset
, pkn_len
);
956 uint32_t pkt_pkn
= 0;
957 for (unsigned i
= 0; i
< pkn_len
; i
++) {
958 pkt_pkn
|= (pkn_bytes
[i
] ^ mask
[1 + i
]) << (8 * (pkn_len
- 1 - i
));
960 *first_byte
= packet0
;
966 * Retrieve the maximum valid packet number space for a peer.
969 quic_max_packet_number(quic_info_data_t
*quic_info
, uint64_t path_id
, bool from_server
, uint8_t first_byte
)
972 if ((first_byte
& 0x80) && quic_get_long_packet_type(first_byte
, quic_info
->version
) == QUIC_LPT_INITIAL
) {
973 // Long header, Initial
975 } else if ((first_byte
& 0x80) && quic_get_long_packet_type(first_byte
, quic_info
->version
) == QUIC_LPT_HANDSHAKE
) {
976 // Long header, Handshake
979 // Long header (0-RTT) or Short Header (1-RTT appdata).
982 if (quic_multipath_negotiated(quic_info
) && path_id
> 0) {
983 /* The multipath draft states that key negotiation must
984 * happen before 2^32 CID sequence numbers are used, so
985 * possibly we could get away with using GUINT_TO_POINTER
986 * and saving some memory here.
988 wmem_map_t
**mp_pkn_map
;
990 if (quic_info
->max_server_mp_pkn
== NULL
) {
991 quic_info
->max_server_mp_pkn
= wmem_map_new(wmem_file_scope(), wmem_int64_hash
, g_int64_equal
);
993 mp_pkn_map
= &quic_info
->max_server_mp_pkn
;
995 if (quic_info
->max_client_mp_pkn
== NULL
) {
996 quic_info
->max_client_mp_pkn
= wmem_map_new(wmem_file_scope(), wmem_int64_hash
, g_int64_equal
);
998 mp_pkn_map
= &quic_info
->max_client_mp_pkn
;
1000 uint64_t *pkt_num
= wmem_map_lookup(*mp_pkn_map
, &path_id
);
1001 if (pkt_num
== NULL
) {
1002 uint64_t *path_id_p
= wmem_new(wmem_file_scope(), uint64_t);
1003 *path_id_p
= path_id
;
1004 pkt_num
= wmem_new0(wmem_file_scope(), uint64_t);
1005 wmem_map_insert(*mp_pkn_map
, path_id_p
, pkt_num
);
1010 return &quic_info
->max_server_pkn
[pkn_space
];
1012 return &quic_info
->max_client_pkn
[pkn_space
];
1018 * Calculate the full packet number and store it for later use.
1021 quic_set_full_packet_number(quic_info_data_t
*quic_info
, quic_packet_info_t
*quic_packet
,
1022 uint64_t path_id
, bool from_server
,
1023 uint8_t first_byte
, uint32_t pkn32
)
1025 unsigned pkn_len
= (first_byte
& 3) + 1;
1027 uint64_t max_pn
= *quic_max_packet_number(quic_info
, path_id
, from_server
, first_byte
);
1029 /* Sequential first pass, try to reconstruct full packet number. */
1030 pkn_full
= quic_pkt_adjust_pkt_num(max_pn
, pkn32
, 8 * pkn_len
);
1031 quic_packet
->pkn_len
= pkn_len
;
1032 quic_packet
->packet_number
= pkn_full
;
1036 cid_to_string(wmem_allocator_t
*pool
, const quic_cid_t
*cid
)
1038 if (cid
->len
== 0) {
1041 char *str
= (char *)wmem_alloc0(pool
, 2 * cid
->len
+ 1);
1042 bytes_to_hexstr(str
, cid
->cid
, cid
->len
);
1046 /* QUIC Connection tracking. {{{ */
1048 quic_connection_hash(const void *key
)
1050 const quic_cid_t
*cid
= (const quic_cid_t
*)key
;
1052 return wmem_strong_hash((const uint8_t *)cid
->cid
, cid
->len
);
1055 /* Note this function intentionally does not consider the reset token. */
1057 quic_connection_equal(const void *a
, const void *b
)
1059 const quic_cid_t
*cid1
= (const quic_cid_t
*)a
;
1060 const quic_cid_t
*cid2
= (const quic_cid_t
*)b
;
1062 return cid1
->len
== cid2
->len
&& !memcmp(cid1
->cid
, cid2
->cid
, cid1
->len
);
1066 quic_cids_has_match(const quic_cid_item_t
*items
, quic_cid_t
*raw_cid
)
1069 const quic_cid_t
*cid
= &items
->data
;
1070 // "raw_cid" potentially has some trailing data that is not part of the
1071 // actual CID, so accept any prefix match against "cid".
1072 // Note that this explicitly matches an empty CID.
1073 if (raw_cid
->len
>= cid
->len
&& !memcmp(raw_cid
->cid
, cid
->cid
, cid
->len
)) {
1074 raw_cid
->seq_num
= cid
->seq_num
;
1075 raw_cid
->path_id
= cid
->path_id
;
1078 items
= items
->next
;
1084 quic_cids_insert(quic_cid_t
*cid
, quic_info_data_t
*conn
, bool from_server
)
1086 wmem_map_t
*connections
= from_server
? quic_server_connections
: quic_client_connections
;
1087 // Replace any previous CID key with the new one.
1088 wmem_map_remove(connections
, cid
);
1089 wmem_map_insert(connections
, cid
, conn
);
1090 G_STATIC_ASSERT(QUIC_MAX_CID_LENGTH
<= 8 * sizeof(quic_cid_lengths
));
1091 quic_cid_lengths
|= (1ULL << cid
->len
);
1095 quic_cids_is_known_length(const quic_cid_t
*cid
)
1097 return (quic_cid_lengths
& (1ULL << cid
->len
)) != 0;
1101 * Checks if a address and port combination is associated with the server
1102 * side of a connection. This is primarily useful when 0 length Destination
1103 * Connection IDs are used.
1104 * "Clients are responsible for initiating all migrations" (RFC 9000 Section 9),
1105 * so this uses the destination address and port of the packet info.
1108 quic_connection_from_server_endpoint(packet_info
*pinfo
, quic_info_data_t
*conn
)
1110 quic_endpoint_t
*server_endpoint
;
1111 for (wmem_list_frame_t
*frame
= wmem_list_head(conn
->server_endpoints
); frame
; frame
= wmem_list_frame_next(frame
)) {
1113 server_endpoint
= wmem_list_frame_data(frame
);
1114 if (server_endpoint
->server_port
== pinfo
->srcport
&&
1115 addresses_equal(&server_endpoint
->server_address
, &pinfo
->src
)) {
1124 * Adds a server endpoint to the list of used server endpoints for the address.
1125 * This is most useful when 0 length Destination Connection IDs are used.
1126 * "Clients are responsible for initiating all migrations" (RFC 9000 Section 9),
1127 * so this uses the destination address and port from pinfo as the server.
1130 quic_connection_add_server_endpoint(packet_info
*pinfo
, quic_info_data_t
*conn
)
1132 quic_endpoint_t
*server_endpoint
= wmem_new(wmem_file_scope(), quic_endpoint_t
);
1133 copy_address_wmem(wmem_file_scope(), &server_endpoint
->server_address
, &pinfo
->dst
);
1134 server_endpoint
->server_port
= pinfo
->destport
;
1135 wmem_list_append(conn
->server_endpoints
, server_endpoint
);
1139 * Returns the most recent QUIC connection for the current UDP stream. This may
1140 * return NULL after connection migration if the new UDP association was not
1141 * properly linked via a match based on the Connection ID.
1143 * There may be more than one QUIC connection multiplexed on the same UDP
1144 * 5-tuple; previous connections can be found by looking at the ->prev pointer.
1145 * Per RFC 9000, multiplexed connections with zero-length CIDs will fail.
1147 static quic_info_data_t
*
1148 quic_connection_from_conv(packet_info
*pinfo
)
1150 conversation_t
*conv
= find_conversation_pinfo(pinfo
, 0);
1152 return (quic_info_data_t
*)conversation_get_proto_data(conv
, proto_quic
);
1158 * Tries to lookup a matching connection (if Connection ID is NULL, the
1159 * most recent connection on the network 5-tuple is returned, if any).
1160 * If connection is found, "from_server" is set accordingly.
1162 static quic_info_data_t
*
1163 quic_connection_find_dcid(packet_info
*pinfo
, quic_cid_t
*dcid
, bool *from_server
)
1165 /* https://tools.ietf.org/html/draft-ietf-quic-transport-22#section-5.2
1167 * "If the packet has a Destination Connection ID corresponding to an
1168 * existing connection, QUIC processes that packet accordingly."
1169 * "If the Destination Connection ID is zero length and the packet matches
1170 * the address/port tuple of a connection where the host did not require
1171 * connection IDs, QUIC processes the packet as part of that connection."
1173 quic_info_data_t
*conn
= NULL
;
1174 const quic_cid_t
*original_dcid
;
1175 bool check_ports
= false;
1177 if (dcid
&& dcid
->len
> 0) {
1178 // Optimization: avoid lookup for invalid CIDs.
1179 if (!quic_cids_is_known_length(dcid
)) {
1182 if (wmem_map_lookup_extended(quic_client_connections
, dcid
, (const void**)&original_dcid
, (void**)&conn
)) {
1183 // DCID recognized by client, so it was from server.
1184 *from_server
= true;
1185 // On collision (both client and server choose the same CID), check
1186 // the port to learn about the side.
1187 // This is required for supporting draft -10 which has a single CID.
1188 check_ports
= !!wmem_map_lookup(quic_server_connections
, dcid
);
1189 // Copy the other information, like sequence number and path ID
1191 *dcid
= *original_dcid
;
1193 if (wmem_map_lookup_extended(quic_server_connections
, dcid
, (const void**)&original_dcid
, (void**)&conn
)) {
1194 // DCID recognized by server, so it was from client.
1195 *from_server
= false;
1196 // Copy the other information, like sequence number and path ID.
1197 *dcid
= *original_dcid
;
1201 conn
= quic_connection_from_conv(pinfo
);
1208 *from_server
= quic_connection_from_server_endpoint(pinfo
, conn
);
1215 * Try to find a QUIC connection based on DCID. For short header packets, DCID
1216 * will be modified in order to find the actual length.
1217 * DCID can be empty, in that case a connection is looked up by address only.
1219 static quic_info_data_t
*
1220 quic_connection_find(packet_info
*pinfo
, uint8_t long_packet_type
,
1221 quic_cid_t
*dcid
, bool *from_server
)
1223 bool is_long_packet
= long_packet_type
!= QUIC_SHORT_PACKET
;
1224 quic_info_data_t
*conn
= NULL
;
1226 if (long_packet_type
== QUIC_LPT_0RTT
&& dcid
->len
> 0) {
1227 // The 0-RTT packet always matches the SCID/DCID of the Client Initial
1228 conn
= (quic_info_data_t
*) wmem_map_lookup(quic_initial_connections
, dcid
);
1229 *from_server
= false;
1231 // Find a connection for Handshake, Version Negotiation and Server Initial packets by
1232 // matching their DCID against the SCIDs of the original Initial packets
1233 // from the peer. For Client Initial packets, match DCID of the first
1234 // Client Initial (these may contain ACK frames).
1235 conn
= quic_connection_find_dcid(pinfo
, dcid
, from_server
);
1236 /* Handle cases where we get a second Client Initial packet before a
1237 * Server Initial packet (so this is not recognized by the server yet),
1238 * e.g. the TLS Client Hello is fragmented in more than one frame.
1240 if (long_packet_type
== QUIC_LPT_INITIAL
&& !conn
&& dcid
->len
> 0) {
1241 conn
= (quic_info_data_t
*) wmem_map_lookup(quic_initial_connections
, dcid
);
1243 *from_server
= false;
1246 if (long_packet_type
== QUIC_LPT_INITIAL
&& conn
&& !*from_server
&& dcid
->len
> 0 &&
1247 !quic_connection_equal(dcid
, &conn
->client_dcid_initial
) &&
1248 !quic_cids_has_match(&conn
->server_cids
, dcid
)) {
1249 // If the Initial Packet is from the client, it must either match
1250 // the DCID from the first Client Initial, or the DCID that was
1251 // assigned by the server. Otherwise this must be considered a fresh
1252 // Client Initial, for example after the Version Negotiation packet,
1253 // and the connection must be cleared to avoid decryption failure.
1258 if (!is_long_packet
&& !conn
) {
1259 // For short packets, first try to find a match based on the address.
1260 // (This is necessary to match a zero-length connection ID - for
1261 // other cases, the second method below also works, and it can vary
1262 // which is faster to try first.)
1263 conn
= quic_connection_find_dcid(pinfo
, NULL
, from_server
);
1264 /* Since we don't know the DCID, check all connections multiplexed
1265 * on the same 5-tuple for a match. */
1267 if ((*from_server
&& quic_cids_has_match(&conn
->client_cids
, dcid
)) ||
1268 (!*from_server
&& quic_cids_has_match(&conn
->server_cids
, dcid
))) {
1269 // Connection matches packet.
1275 // No match found so far, potentially connection migration. Length of
1276 // actual DCID is unknown, so just keep decrementing until found.
1277 while (!conn
&& dcid
->len
> 1) {
1279 if (quic_cids_is_known_length(dcid
)) {
1280 conn
= quic_connection_find_dcid(pinfo
, dcid
, from_server
);
1284 // No match found, truncate DCID (not really needed, but this
1285 // ensures that debug prints clearly show that DCID is invalid).
1287 } else if (quic_connection_from_conv(pinfo
) == NULL
) {
1288 // Connection information might not be attached to the conversation,
1289 // because of connection migration.
1290 conversation_t
*conv
= find_conversation_pinfo(pinfo
, 0);
1292 // attach the connection information to the conversation.
1293 conversation_add_proto_data(conv
, proto_quic
, conn
);
1294 // Found this connection, but (especially if 0 length DCIDs
1295 // are used for the client) we need to add the server endpoint
1296 // to the list seen.
1297 // XXX - RFC 9000 Section 9 appears to say that the client can
1298 // migrate its own address freely, but should only migrate to
1299 // a server address given in the preferred_address transport
1300 // parameter in the TLS handshake. Should there be an expert
1301 // info if this is an unknown address? (#20165)
1302 quic_connection_add_server_endpoint(pinfo
, conn
);
1309 /** Create a new QUIC Connection based on a Client Initial packet. */
1310 static quic_info_data_t
*
1311 quic_connection_create(packet_info
*pinfo
, uint32_t version
)
1313 conversation_t
*conv
;
1314 quic_info_data_t
*prev_conn
, *conn
= NULL
;
1316 conn
= wmem_new0(wmem_file_scope(), quic_info_data_t
);
1317 wmem_list_append(quic_connections
, conn
);
1318 conn
->number
= quic_connections_count
++;
1319 conn
->version
= version
;
1320 conn
->server_endpoints
= wmem_list_new(wmem_file_scope());
1321 quic_connection_add_server_endpoint(pinfo
, conn
);
1323 // For faster lookups without having to check DCID
1324 conv
= find_or_create_conversation(pinfo
);
1325 // Check for another connection multiplexed on the 5-tuple
1326 prev_conn
= conversation_get_proto_data(conv
, proto_quic
);
1328 conn
->prev
= prev_conn
;
1330 conversation_add_proto_data(conv
, proto_quic
, conn
);
1332 conv
= find_or_create_conversation_by_id(pinfo
, CONVERSATION_QUIC
, conn
->number
);
1333 conversation_add_proto_data(conv
, proto_quic
, conn
);
1335 if (version
== 0x51303530 || version
== 0x54303530 || version
== 0x54303531) {
1336 gquic_info_data_t
*gquic_info
;
1338 gquic_info
= wmem_new(wmem_file_scope(), gquic_info_data_t
);
1339 if (version
== 0x51303530)
1340 gquic_info
->version
= 50;
1341 else if (version
== 0x54303530)
1342 gquic_info
->version
= 150;
1344 gquic_info
->version
= 151;
1345 gquic_info
->encoding
= ENC_BIG_ENDIAN
;
1346 gquic_info
->version_valid
= true;
1347 gquic_info
->server_port
= pinfo
->destport
;
1348 conn
->gquic_info
= gquic_info
;
1354 /** Update client/server connection identifiers, assuming the information is
1355 * from the Client Initial. */
1357 quic_connection_update_initial(quic_info_data_t
*conn
, const quic_cid_t
*scid
, const quic_cid_t
*dcid
)
1359 // Key connection by Client CID (if provided).
1361 memcpy(&conn
->client_cids
.data
, scid
, sizeof(quic_cid_t
));
1362 quic_cids_insert(&conn
->client_cids
.data
, conn
, false);
1364 if (dcid
->len
> 0) {
1365 // According to the spec, the Initial Packet DCID MUST be at least 8
1366 // bytes, but non-conforming implementations could exist.
1367 memcpy(&conn
->client_dcid_initial
, dcid
, sizeof(quic_cid_t
));
1368 wmem_map_insert(quic_initial_connections
, &conn
->client_dcid_initial
, conn
);
1369 conn
->client_dcid_set
= true;
1374 * Use the new CID as additional identifier for the specified connection and
1375 * remember it for connection tracking.
1378 quic_connection_add_cid(quic_info_data_t
*conn
, quic_cid_t
*new_cid
, bool from_server
)
1380 DISSECTOR_ASSERT(new_cid
->len
> 0);
1381 quic_cid_item_t
*items
= from_server
? &conn
->server_cids
: &conn
->client_cids
;
1383 if (quic_cids_has_match(items
, new_cid
)) {
1384 // CID is already known for this connection.
1385 // XXX: If the same CID is reused with a new sequence number or path
1386 // id and multipath is being used, that's an issue. (Expert info?)
1390 // Insert new CID right after the first known CID (the very first CID cannot
1391 // be overwritten since it might be used as key somewhere else).
1392 quic_cid_item_t
*new_item
= wmem_new0(wmem_file_scope(), quic_cid_item_t
);
1393 new_item
->data
= *new_cid
;
1394 new_item
->next
= items
->next
;
1395 items
->next
= new_item
;
1397 quic_cids_insert(&new_item
->data
, conn
, from_server
);
1400 /** Create or update a connection. */
1402 quic_connection_create_or_update(quic_info_data_t
**conn_p
,
1403 packet_info
*pinfo
, uint32_t long_packet_type
,
1404 uint32_t version
, const quic_cid_t
*scid
,
1405 const quic_cid_t
*dcid
, bool from_server
)
1407 quic_info_data_t
*conn
= *conn_p
;
1409 switch (long_packet_type
) {
1410 case QUIC_LPT_INITIAL
:
1413 // The first Initial Packet from the client creates a new connection.
1414 *conn_p
= quic_connection_create(pinfo
, version
);
1415 quic_connection_update_initial(*conn_p
, scid
, dcid
);
1416 } else if (!conn
->client_dcid_set
&& dcid
->len
) {
1417 // If this client Initial Packet responds to a Retry Packet,
1418 // then remember the new client SCID and initial DCID for the
1419 // new Initial cipher and clear the first server CID such that
1420 // the next server Initial Packet can link the connection with
1422 quic_connection_update_initial(conn
, scid
, dcid
);
1423 wmem_map_remove(quic_server_connections
, &conn
->server_cids
.data
);
1424 memset(&conn
->server_cids
, 0, sizeof(quic_cid_t
));
1429 case QUIC_LPT_RETRY
:
1430 case QUIC_LPT_HANDSHAKE
:
1431 // Remember CID from first server Retry/Handshake packet
1432 // (or from the first server Initial packet, since draft -13).
1433 if (from_server
&& conn
) {
1434 if (long_packet_type
== QUIC_LPT_RETRY
) {
1435 // Retry Packet: the next Initial Packet from the
1436 // client should start a new cryptographic handshake. Erase the
1437 // current "Initial DCID" such that the next client Initial
1438 // packet populates the new value.
1439 wmem_map_remove(quic_initial_connections
, &conn
->client_dcid_initial
);
1440 memset(&conn
->client_dcid_initial
, 0, sizeof(quic_cid_t
));
1441 conn
->client_dcid_set
= false;
1443 if (conn
->server_cids
.data
.len
== 0 && scid
->len
) {
1444 memcpy(&conn
->server_cids
.data
, scid
, sizeof(quic_cid_t
));
1445 quic_cids_insert(&conn
->server_cids
.data
, conn
, true);
1453 quic_connection_destroy(void *data
, void *user_data _U_
)
1455 quic_info_data_t
*conn
= (quic_info_data_t
*)data
;
1456 quic_ciphers_reset(&conn
->client_initial_ciphers
);
1457 quic_ciphers_reset(&conn
->server_initial_ciphers
);
1458 quic_ciphers_reset(&conn
->client_handshake_ciphers
);
1459 quic_ciphers_reset(&conn
->server_handshake_ciphers
);
1461 quic_ciphers_reset(&conn
->client_0rtt_ciphers
);
1463 quic_hp_cipher_reset(&conn
->client_pp
.hp_cipher
);
1464 quic_pp_cipher_reset(&conn
->client_pp
.pp_ciphers
[0]);
1465 quic_pp_cipher_reset(&conn
->client_pp
.pp_ciphers
[1]);
1467 quic_hp_cipher_reset(&conn
->server_pp
.hp_cipher
);
1468 quic_pp_cipher_reset(&conn
->server_pp
.pp_ciphers
[0]);
1469 quic_pp_cipher_reset(&conn
->server_pp
.pp_ciphers
[1]);
1471 /* QUIC Connection tracking. }}} */
1473 /* QUIC Streams tracking and reassembly. {{{ */
1474 static reassembly_table quic_reassembly_table
;
1476 /** Perform sequence analysis for STREAM frames. */
1477 static quic_stream_state
*
1478 quic_get_stream_state(packet_info
*pinfo
, quic_info_data_t
*quic_info
, bool from_server
, uint64_t stream_id
)
1480 wmem_map_t
**streams_p
= from_server
? &quic_info
->server_streams
: &quic_info
->client_streams
;
1481 wmem_map_t
*streams
= *streams_p
;
1482 quic_stream_state
*stream
= NULL
;
1484 if (PINFO_FD_VISITED(pinfo
)) {
1485 DISSECTOR_ASSERT(streams
);
1486 stream
= (quic_stream_state
*)wmem_map_lookup(streams
, &stream_id
);
1487 DISSECTOR_ASSERT(stream
);
1491 // Initialize per-connection and per-stream state.
1493 streams
= wmem_map_new(wmem_file_scope(), wmem_int64_hash
, g_int64_equal
);
1494 *streams_p
= streams
;
1496 stream
= (quic_stream_state
*)wmem_map_lookup(streams
, &stream_id
);
1499 stream
= wmem_new0(wmem_file_scope(), quic_stream_state
);
1500 stream
->stream_id
= stream_id
;
1501 stream
->multisegment_pdus
= wmem_tree_new(wmem_file_scope());
1502 wmem_map_insert(streams
, &stream
->stream_id
, stream
);
1508 process_quic_stream(tvbuff_t
*tvb
, int offset
, packet_info
*pinfo
, proto_tree
*tree
,
1509 quic_info_data_t
*quic_info
, quic_stream_info
*stream_info
,
1510 const quic_packet_info_t
*quic_packet
)
1512 if (quic_packet
->packet_type
!= QUIC_LPT_0RTT
&& quic_info
->app_handle
) {
1513 tvbuff_t
*next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
1514 // Traverse the STREAM frame tree.
1515 proto_tree
*top_tree
= proto_tree_get_parent_tree(tree
);
1516 top_tree
= proto_tree_get_parent_tree(top_tree
);
1517 // Subdissectors MUST NOT assume that 'stream_info' remains valid after
1518 // returning. Copying the pointer will result in illegal memory access.
1519 call_dissector_with_data(quic_info
->app_handle
, next_tvb
, pinfo
, top_tree
, stream_info
);
1520 } else if (quic_packet
->packet_type
== QUIC_LPT_0RTT
&& quic_info
->zrtt_app_handle
) {
1521 tvbuff_t
*next_tvb
= tvb_new_subset_remaining(tvb
, offset
);
1522 proto_tree
*top_tree
= proto_tree_get_parent_tree(tree
);
1523 top_tree
= proto_tree_get_parent_tree(top_tree
);
1524 call_dissector_with_data(quic_info
->zrtt_app_handle
, next_tvb
, pinfo
, top_tree
, stream_info
);
1529 * Reassemble stream data within a STREAM frame.
1532 desegment_quic_stream(tvbuff_t
*tvb
, int offset
, int length
, packet_info
*pinfo
,
1533 proto_tree
*tree
, quic_info_data_t
*quic_info
,
1534 quic_stream_info
*stream_info
,
1535 quic_stream_state
*stream
,
1536 const quic_packet_info_t
*quic_packet
)
1539 int last_fragment_len
;
1540 bool must_desegment
;
1541 bool called_dissector
;
1542 int another_pdu_follows
;
1544 struct tcp_multisegment_pdu
*msp
;
1545 uint32_t seq
= (uint32_t)stream_info
->stream_offset
;
1546 const uint32_t nxtseq
= seq
+ (uint32_t)length
;
1547 uint32_t reassembly_id
= 0;
1549 // XXX fix the tvb accessors below such that no new tvb is needed.
1550 tvb
= tvb_new_subset_length(tvb
, 0, offset
+ length
);
1554 last_fragment_len
= 0;
1555 must_desegment
= false;
1556 called_dissector
= false;
1557 another_pdu_follows
= 0;
1561 * Initialize these to assume no desegmentation.
1562 * If that's not the case, these will be set appropriately
1563 * by the subdissector.
1565 pinfo
->desegment_offset
= 0;
1566 pinfo
->desegment_len
= 0;
1569 * Initialize this to assume that this segment will just be
1570 * added to the middle of a desegmented chunk of data, so
1571 * that we should show it all as data.
1572 * If that's not the case, it will be set appropriately.
1574 deseg_offset
= offset
;
1576 /* Have we seen this PDU before (and is it the start of a multi-
1579 if ((msp
= (struct tcp_multisegment_pdu
*)wmem_tree_lookup32(stream
->multisegment_pdus
, seq
)) &&
1580 nxtseq
<= msp
->nxtpdu
) {
1581 // XXX: This also happens the second time through the data for an MSP normally
1582 // TODO show expert info for retransmission? Additional checks may be
1583 // necessary here to tell a retransmission apart from other (normal?)
1584 // conditions. See also similar code in packet-tcp.c.
1586 proto_tree_add_debug_text(tree
, "TODO retransmission expert info frame %d stream_id=%" PRIu64
" offset=%d visited=%d reassembly_id=0x%08x",
1587 pinfo
->num
, stream
->stream_id
, offset
, PINFO_FD_VISITED(pinfo
), reassembly_id
);
1591 /* Else, find the most previous PDU starting before this sequence number */
1592 if (!msp
&& seq
> 0) {
1593 msp
= (struct tcp_multisegment_pdu
*)wmem_tree_lookup32_le(stream
->multisegment_pdus
, seq
-1);
1594 /* Unless if we already fully reassembled the msp that covers seq-1
1595 * and seq is beyond the end of that msp. In that case this segment
1596 * will be the start of a new msp.
1598 if (msp
&& (msp
->flags
& MSP_FLAGS_GOT_ALL_SEGMENTS
) &&
1599 seq
>= msp
->nxtpdu
) {
1605 // A single stream can contain multiple fragments (e.g. for HTTP/3
1606 // HEADERS and DATA frames). Let's hope that a single stream within a
1607 // QUIC packet does not contain multiple partial fragments, that would
1608 // result in a reassembly ID collision here. If that collision becomes
1609 // an issue, we would have to replace "msp->first_frame" with a new
1610 // field in "msp" that is initialized with "stream_info->stream_offset".
1612 uint64_t reassembly_id_data
[2];
1613 reassembly_id_data
[0] = stream_info
->stream_id
;
1614 reassembly_id_data
[1] = msp
? msp
->first_frame
: pinfo
->num
;
1615 reassembly_id
= wmem_strong_hash((const uint8_t *)&reassembly_id_data
, sizeof(reassembly_id_data
));
1617 // XXX for debug (visibility) purposes, do not use a hash but concatenate
1618 reassembly_id
= ((msp
? msp
->first_frame
: pinfo
->num
) << 16) | (uint32_t)stream_info
->stream_id
;
1622 if (msp
&& msp
->seq
<= seq
&& msp
->nxtpdu
> seq
) {
1625 if (!PINFO_FD_VISITED(pinfo
)) {
1626 msp
->last_frame
=pinfo
->num
;
1627 msp
->last_frame_time
=pinfo
->abs_ts
;
1630 /* OK, this PDU was found, which means the segment continues
1631 * a higher-level PDU and that we must desegment it.
1633 if (msp
->flags
& MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT
) {
1634 /* The dissector asked for the entire segment */
1635 len
= tvb_captured_length_remaining(tvb
, offset
);
1637 len
= MIN(nxtseq
, msp
->nxtpdu
) - seq
;
1639 last_fragment_len
= len
;
1641 fh
= fragment_add(&quic_reassembly_table
, tvb
, offset
,
1642 pinfo
, reassembly_id
, NULL
,
1643 seq
- msp
->seq
, len
,
1644 nxtseq
< msp
->nxtpdu
);
1646 msp
->flags
|= MSP_FLAGS_GOT_ALL_SEGMENTS
;
1648 if (!PINFO_FD_VISITED(pinfo
)
1649 && msp
->flags
& MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT
) {
1650 msp
->flags
&= (~MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT
);
1652 /* If we consumed the entire segment there is no
1653 * other pdu starting anywhere inside this segment.
1654 * So update nxtpdu to point at least to the start
1655 * of the next segment.
1656 * (If the subdissector asks for even more data we
1657 * will advance nxtpdu even further later down in
1660 msp
->nxtpdu
= nxtseq
;
1663 if( (msp
->nxtpdu
< nxtseq
)
1664 && (msp
->nxtpdu
>= seq
)
1666 another_pdu_follows
=msp
->nxtpdu
- seq
;
1669 /* This segment was not found in our table, so it doesn't
1670 * contain a continuation of a higher-level PDU.
1671 * Call the normal subdissector.
1674 stream_info
->offset
= seq
;
1675 process_quic_stream(tvb
, offset
, pinfo
, tree
, quic_info
, stream_info
, quic_packet
);
1676 called_dissector
= true;
1678 /* Did the subdissector ask us to desegment some more data
1679 * before it could handle the packet?
1680 * If so we'll have to handle that later.
1682 if (pinfo
->desegment_len
) {
1683 must_desegment
= true;
1684 if (!PINFO_FD_VISITED(pinfo
)) {
1686 msp
->flags
&= ~MSP_FLAGS_GOT_ALL_SEGMENTS
;
1690 * Set "deseg_offset" to the offset in "tvb"
1691 * of the first byte of data that the
1692 * subdissector didn't process.
1694 deseg_offset
= offset
+ pinfo
->desegment_offset
;
1697 /* Either no desegmentation is necessary, or this is
1698 * segment contains the beginning but not the end of
1699 * a higher-level PDU and thus isn't completely
1705 /* is it completely desegmented? */
1708 * Yes, we think it is.
1709 * We only call subdissector for the last segment.
1710 * Note that the last segment may include more than what
1713 if (fh
->reassembled_in
== pinfo
->num
) {
1715 * OK, this is the last segment.
1716 * Let's call the subdissector with the desegmented data.
1719 tvbuff_t
*next_tvb
= tvb_new_chain(tvb
, fh
->tvb_data
);
1720 add_new_data_source(pinfo
, next_tvb
, "Reassembled QUIC");
1721 stream_info
->offset
= seq
;
1722 process_quic_stream(next_tvb
, 0, pinfo
, tree
, quic_info
, stream_info
, quic_packet
);
1723 called_dissector
= true;
1725 int old_len
= (int)(tvb_reported_length(next_tvb
) - last_fragment_len
);
1726 if (pinfo
->desegment_len
&&
1727 pinfo
->desegment_offset
<= old_len
) {
1729 * "desegment_len" isn't 0, so it needs more
1730 * data for something - and "desegment_offset"
1731 * is before "old_len", so it needs more data
1732 * to dissect the stuff we thought was
1733 * completely desegmented (as opposed to the
1734 * stuff at the beginning being completely
1735 * desegmented, but the stuff at the end
1736 * being a new higher-level PDU that also
1737 * needs desegmentation).
1739 fragment_set_partial_reassembly(&quic_reassembly_table
,
1740 pinfo
, reassembly_id
, NULL
);
1742 /* Update msp->nxtpdu to point to the new next
1745 if (pinfo
->desegment_len
== DESEGMENT_ONE_MORE_SEGMENT
) {
1746 /* We want reassembly of at least one
1747 * more segment so set the nxtpdu
1748 * boundary to one byte into the next
1750 * This means that the next segment
1751 * will complete reassembly even if it
1752 * is only one single byte in length.
1753 * If this is an OoO segment, then increment the MSP end.
1755 msp
->nxtpdu
= MAX(seq
+ tvb_reported_length_remaining(tvb
, offset
), msp
->nxtpdu
) + 1;
1756 msp
->flags
|= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT
;
1758 } else if (pinfo
->desegment_len
== DESEGMENT_UNTIL_FIN
) {
1759 tcpd
->fwd
->flags
|= TCP_FLOW_REASSEMBLE_UNTIL_FIN
;
1762 if (seq
+ last_fragment_len
>= msp
->nxtpdu
) {
1763 /* This is the segment (overlapping) the end of the MSP. */
1764 msp
->nxtpdu
= seq
+ last_fragment_len
+ pinfo
->desegment_len
;
1766 /* This is a segment before the end of the MSP, so it
1767 * must be an out-of-order segmented that completed the
1768 * MSP. The requested additional data is relative to
1771 msp
->nxtpdu
+= pinfo
->desegment_len
;
1775 /* Since we need at least some more data
1776 * there can be no pdu following in the
1777 * tail of this segment.
1779 another_pdu_follows
= 0;
1780 offset
+= last_fragment_len
;
1781 seq
+= last_fragment_len
;
1782 if (tvb_captured_length_remaining(tvb
, offset
) > 0)
1785 proto_item
*frag_tree_item
;
1786 proto_tree
*parent_tree
= proto_tree_get_parent(tree
);
1787 show_fragment_tree(fh
, &quic_stream_fragment_items
,
1788 parent_tree
, pinfo
, next_tvb
, &frag_tree_item
);
1789 // TODO move tree item if needed.
1791 if(pinfo
->desegment_len
) {
1792 if (!PINFO_FD_VISITED(pinfo
)) {
1793 must_desegment
= true;
1795 msp
->flags
&= ~MSP_FLAGS_GOT_ALL_SEGMENTS
;
1797 /* See packet-tcp.h for details about this. */
1798 deseg_offset
= fh
->datalen
- pinfo
->desegment_offset
;
1799 deseg_offset
= tvb_reported_length(tvb
) - deseg_offset
;
1805 if (must_desegment
) {
1807 uint32_t deseg_seq
= seq
+ (deseg_offset
- offset
);
1809 if (!PINFO_FD_VISITED(pinfo
)) {
1810 // TODO handle DESEGMENT_UNTIL_FIN if needed, maybe use the FIN bit?
1811 if ((nxtseq
- deseg_seq
) <= 1024*1024) {
1812 if(pinfo
->desegment_len
== DESEGMENT_ONE_MORE_SEGMENT
) {
1813 /* The subdissector asked to reassemble using the
1814 * entire next segment.
1815 * Just ask reassembly for one more byte
1816 * but set this msp flag so we can pick it up
1819 msp
= pdu_store_sequencenumber_of_next_pdu(pinfo
, deseg_seq
,
1820 nxtseq
+1, stream
->multisegment_pdus
);
1821 msp
->flags
|= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT
;
1823 msp
= pdu_store_sequencenumber_of_next_pdu(pinfo
,
1824 deseg_seq
, nxtseq
+pinfo
->desegment_len
, stream
->multisegment_pdus
);
1827 /* add this segment as the first one for this new pdu */
1828 fragment_add(&quic_reassembly_table
, tvb
, deseg_offset
,
1829 pinfo
, reassembly_id
, NULL
,
1830 0, nxtseq
- deseg_seq
,
1831 nxtseq
< msp
->nxtpdu
);
1834 /* If this is not the first time we have seen the packet, then
1835 * the MSP should already be created. Retrieve it to see if we
1836 * know what later frame the PDU is reassembled in.
1838 if (((struct tcp_multisegment_pdu
*)wmem_tree_lookup32(stream
->multisegment_pdus
, deseg_seq
))) {
1839 fh
= fragment_get(&quic_reassembly_table
, pinfo
, reassembly_id
, NULL
);
1844 if (!called_dissector
|| pinfo
->desegment_len
!= 0) {
1845 if (fh
!= NULL
&& fh
->reassembled_in
!= 0 &&
1846 !(fh
->flags
& FD_PARTIAL_REASSEMBLY
)) {
1848 * We know what frame this PDU is reassembled in;
1849 * let the user know.
1851 proto_item
*item
= proto_tree_add_uint(tree
, hf_quic_reassembled_in
, tvb
, 0,
1852 0, fh
->reassembled_in
);
1853 proto_item_set_generated(item
);
1856 /* TODO: Show what's left in the packet as a raw QUIC "segment", like
1857 * packet-tcp.c does here.
1860 pinfo
->can_desegment
= 0;
1861 pinfo
->desegment_offset
= 0;
1862 pinfo
->desegment_len
= 0;
1864 if (another_pdu_follows
) {
1865 /* there was another pdu following this one. */
1866 pinfo
->can_desegment
= 2;
1867 offset
+= another_pdu_follows
;
1868 seq
+= another_pdu_follows
;
1874 dissect_quic_stream_payload(tvbuff_t
*tvb
, int offset
, int length
, packet_info
*pinfo
,
1875 proto_tree
*tree
, quic_info_data_t
*quic_info
,
1876 quic_stream_info
*stream_info
,
1877 quic_stream_state
*stream
,
1878 const quic_packet_info_t
*quic_packet
)
1880 /* QUIC application data is most likely not properly dissected when
1881 * reassembly is not enabled. Therefore we do not even offer "desegment"
1882 * preference to disable reassembly.
1886 /* Don't call a subdissector for a zero length segment. It won't
1887 * work for dissection (see #12368), and our methods of determing
1888 * if desegmentation is needed won't work either (#19497). If there
1889 * ever is an app_handle on top of QUIC that needs to be called with
1890 * a zero length segment, revisit this. (Cf. #15159)
1892 pinfo
->can_desegment
= 2;
1893 desegment_quic_stream(tvb
, offset
, length
, pinfo
, tree
, quic_info
, stream_info
, stream
, quic_packet
);
1896 /* QUIC Streams tracking and reassembly. }}} */
1898 static bool quic_crypto_out_of_order
= true;
1900 static reassembly_table quic_crypto_reassembly_table
;
1902 typedef struct _quic_crypto_retrans_key
{
1903 uint64_t pkt_number
; /* QUIC packet number */
1905 uint32_t num
; /* Frame number in the capture file, pinfo->num */
1906 } quic_crypto_retrans_key
;
1909 quic_crypto_retrans_hash(const void *k
)
1911 const quic_crypto_retrans_key
* key
= (const quic_crypto_retrans_key
*) k
;
1914 return wmem_strong_hash((const uint8_t *)key
, sizeof(quic_crypto_retrans_key
));
1918 /* Most of the time the packet number in the capture file suffices. */
1919 hash_val
= key
->num
;
1925 quic_crypto_retrans_equal(const void *k1
, const void *k2
)
1927 const quic_crypto_retrans_key
* key1
= (const quic_crypto_retrans_key
*) k1
;
1928 const quic_crypto_retrans_key
* key2
= (const quic_crypto_retrans_key
*) k2
;
1930 return (key1
->num
== key2
->num
) &&
1931 (key1
->pkt_number
== key2
->pkt_number
) &&
1932 (key1
->offset
== key2
->offset
);
1935 static quic_crypto_state
*
1936 quic_get_crypto_state(packet_info
*pinfo
, quic_info_data_t
*quic_info
, bool from_server
, const uint8_t encryption_level
)
1938 wmem_map_t
**cryptos_p
= from_server
? &quic_info
->server_crypto
: &quic_info
->client_crypto
;
1939 wmem_map_t
*cryptos
= *cryptos_p
;
1940 quic_crypto_state
*crypto
= NULL
;
1942 if (PINFO_FD_VISITED(pinfo
)) {
1943 DISSECTOR_ASSERT(cryptos
);
1944 crypto
= (quic_crypto_state
*)wmem_map_lookup(cryptos
, GUINT_TO_POINTER(encryption_level
));
1945 DISSECTOR_ASSERT(crypto
);
1949 // Initialize per-connection and per-stream state.
1951 cryptos
= wmem_map_new(wmem_file_scope(), g_direct_hash
, g_direct_equal
);
1952 *cryptos_p
= cryptos
;
1954 crypto
= (quic_crypto_state
*)wmem_map_lookup(cryptos
, GUINT_TO_POINTER(encryption_level
));
1957 crypto
= wmem_new0(wmem_file_scope(), quic_crypto_state
);
1958 crypto
->multisegment_pdus
= wmem_tree_new(wmem_file_scope());
1959 crypto
->retrans_offsets
= wmem_map_new(wmem_file_scope(),
1960 quic_crypto_retrans_hash
, quic_crypto_retrans_equal
);
1961 crypto
->encryption_level
= encryption_level
;
1962 wmem_map_insert(cryptos
, GUINT_TO_POINTER(encryption_level
), crypto
);
1969 process_quic_crypto(tvbuff_t
*tvb
, int offset
, int length
, packet_info
*pinfo
,
1970 proto_tree
*tree
, quic_crypto_info
*crypto_info
)
1973 tvbuff_t
*next_tvb
= tvb_new_subset_length(tvb
, offset
, length
);
1974 col_set_writable(pinfo
->cinfo
, -1, false);
1976 * Dissect TLS handshake record. The Client/Server Hello (CH/SH)
1977 * are contained in the Initial Packet. 0-RTT keys are ready
1978 * after CH. HS + 1-RTT keys are ready after SH.
1979 * (Note: keys captured from the client might become available
1980 * after capturing the packets due to processing delay.)
1981 * These keys will be loaded in the first HS/0-RTT/1-RTT msg.
1983 call_dissector_with_data(tls13_handshake_handle
, next_tvb
, pinfo
, tree
, GUINT_TO_POINTER(crypto_info
->offset
));
1984 col_set_writable(pinfo
->cinfo
, -1, true);
1988 * Reassemble data within a CRYPTO frame.
1990 * This always gets handed to the TLS handshake dissector, which does its own
1991 * fragmentation handling, so all we do is the Out Of Order handling.
1992 * RFC 9001 4.1.3 "Sending and Receiving Handshake Messages"
1993 * "TLS is responsible for buffering handshake bytes that have arrived in order.
1994 * QUIC is responsible for buffering handshake bytes that arrive out of order or
1995 * for encryption levels that are not yet ready."
1997 * XXX: We are only buffering bytes that arive out of order within an encryption
1998 * level. Buffering for encryption levels that are not yet ready requires
1999 * determining that they are not ready (and they may never be ready from our
2000 * perspective if we don't have the keys.)
2004 desegment_quic_crypto(tvbuff_t
*tvb
, int offset
, int length
, packet_info
*pinfo
,
2005 proto_tree
*tree
, quic_info_data_t
*quic_info _U_
,
2006 quic_crypto_info
*crypto_info
,
2007 quic_crypto_state
*crypto
)
2010 bool called_dissector
;
2012 struct tcp_multisegment_pdu
*msp
;
2014 /* XXX: There are a few elements in QUIC that can be up to 64 bit
2015 * integers that we're truncating to 32 bit here to re-use current
2019 uint32_t seq
= (uint32_t)crypto_info
->crypto_offset
;
2020 const uint32_t nxtseq
= seq
+ (uint32_t)length
;
2021 uint32_t reassembly_id
= 0;
2024 called_dissector
= false;
2028 /* Look for retransmissions and overlap and discard them, only handing
2029 * new in order bytes to TLS.
2031 * It's possible to have multiple QUIC packets in the same capture
2032 * file frame, so to really be assured of no collision we need the
2033 * QUIC connection ID, the QUIC packet number space, the QUIC
2034 * packet number, and the offset within the QUIC packet in addition
2035 * to the frame number in the capture file.
2037 * crypto (a quic_crypto_state*) is already unique to the connection
2038 * ID and packet number space, so we need to store the other two
2041 * Alternatively we could have the real offset in the capture
2042 * file frame, but we can't easily get that since the tvb is the
2043 * result of decryption.
2045 quic_crypto_retrans_key
*tmp_key
= wmem_new(pinfo
->pool
, quic_crypto_retrans_key
);
2046 tmp_key
->num
= pinfo
->num
;
2047 tmp_key
->offset
= offset
;
2048 tmp_key
->pkt_number
= crypto_info
->packet_number
;
2050 if (!PINFO_FD_VISITED(pinfo
)) {
2051 if (crypto_info
->crypto_offset
+ length
<= crypto
->max_contiguous_offset
) {
2052 /* No new data. Remember this. */
2053 proto_tree_add_expert(tree
, pinfo
, &ei_quic_retransmission
, tvb
, offset
, length
);
2054 uint64_t* contiguous_offset
= wmem_new(wmem_file_scope(), uint64_t);
2055 *contiguous_offset
= crypto
->max_contiguous_offset
;
2056 quic_crypto_retrans_key
*fkey
= wmem_new(wmem_file_scope(), quic_crypto_retrans_key
);
2058 wmem_map_insert(crypto
->retrans_offsets
, fkey
, contiguous_offset
);
2060 } else if (crypto_info
->crypto_offset
< crypto
->max_contiguous_offset
) {
2061 /* XXX: Retrieve the previous data and compare for conflicts? */
2062 proto_tree_add_expert(tree
, pinfo
, &ei_quic_overlap
, tvb
, offset
, length
);
2063 uint64_t overlap
= crypto
->max_contiguous_offset
- crypto_info
->crypto_offset
;
2064 length
-= (int)overlap
;
2065 seq
= (uint32_t)(crypto
->max_contiguous_offset
);
2066 offset
+= (uint32_t)(overlap
);
2067 /* Store this offset */
2068 uint64_t* contiguous_offset
= wmem_new(wmem_file_scope(), uint64_t);
2069 *contiguous_offset
= crypto
->max_contiguous_offset
;
2070 quic_crypto_retrans_key
*fkey
= wmem_new(wmem_file_scope(), quic_crypto_retrans_key
);
2072 wmem_map_insert(crypto
->retrans_offsets
, fkey
, contiguous_offset
);
2075 /* Retrieve any per-frame state about retransmitted and overlapping
2078 uint64_t *contiguous_offset
= (uint64_t *)wmem_map_lookup(crypto
->retrans_offsets
, tmp_key
);
2079 if (contiguous_offset
!= NULL
) {
2080 if (crypto_info
->crypto_offset
+ length
<= *contiguous_offset
) {
2081 proto_tree_add_expert(tree
, pinfo
, &ei_quic_retransmission
, tvb
, offset
, length
);
2083 } else if (crypto_info
->crypto_offset
< *contiguous_offset
) {
2084 /* XXX: Retrieve the previous data and compare for conflicts? */
2085 proto_tree_add_expert(tree
, pinfo
, &ei_quic_overlap
, tvb
, offset
, length
);
2086 uint64_t overlap
= *contiguous_offset
- crypto_info
->crypto_offset
;
2087 length
-= (int)overlap
;
2088 seq
= (uint32_t)(*contiguous_offset
);
2089 offset
+= (uint32_t)(overlap
);
2091 DISSECTOR_ASSERT_NOT_REACHED();
2096 /* By doing the above we should not have any retransmissions from in
2097 * order bytes. Retransmission and overlaps in out of order bytes are
2098 * still possible, but those will be handled by adding them to the
2099 * msp fragments. TLS is also going to handle defragmenting (instead
2100 * of returning info about PDU ends via pinfo->desegment_offset and
2101 * pinfo->desegment_len), so we can make this simpler than for payload
2104 * Since TLS doesn't set pinfo->desegment_offset and pinfo->desegment_len,
2105 * we can't align our msps to PDU boundaries, and so we can't skip past
2106 * any missing out of order bytes to send TLS later whole received PDUs.
2109 /* Find the most recent msp that starts before this sequence number. */
2110 msp
= (struct tcp_multisegment_pdu
*)wmem_tree_lookup32_le(crypto
->multisegment_pdus
, seq
);
2112 /* If we already fully reassembled that msp and seq is beyond its end
2113 * (the latter should always be the case since we're discarding
2114 * retransmitted bytes above), this segment isn't part of the msp.
2116 if (msp
&& (msp
->flags
& MSP_FLAGS_GOT_ALL_SEGMENTS
) &&
2117 seq
>= msp
->nxtpdu
) {
2121 /* The TCP reassembly functions already use msp->seq as a tiebreaker in
2122 * case we do have more than one OOO reassembly in a given frame, which
2123 * happens with Chrome's "Chaos Protection".
2125 * XXX: It would be better to use functions that use the QUIC connection
2126 * instead of addresses and ports, since concurrent connections on the
2127 * same 5 tuple is possible, but using the frame number as well limits
2128 * problems to more unusual encapsulations.
2130 * RFC 9000 9. "Connection Migration": "An endpoint MUST NOT initiate
2131 * connection migration before the handshake is confirmed" so we shouldn't
2132 * have to worry about CRYPTO packets for the same connection being
2133 * fragmented on different 5-tuples. (There may be new CRYPTO packets
2134 * with session tickets later, but we should handle that.)
2136 reassembly_id
= ((msp
? msp
->first_frame
: pinfo
->num
) << 8) | crypto
->encryption_level
;
2138 if (!PINFO_FD_VISITED(pinfo
)) {
2139 has_gap
= crypto
->max_contiguous_offset
< seq
;
2142 /* No gap, so either this is a standalone in order
2143 * segment, or it's part of our in progress out of
2144 * order MSP and we need to look at the MSP fragments
2145 * to see what the last contiguous offset is.
2146 * Advance the contiguous offset appropriately.
2148 * XXX: A slightly different approach would involve splitting
2149 * the MSP as now done in the TCP dissector. That would send
2150 * any new bytes to TLS sooner and is closer to what RFC 9001
2151 * recommends. It's less important to do so than in TCP, but
2152 * is a possible future improvement.
2155 fh
= fragment_get(&quic_crypto_reassembly_table
, pinfo
, reassembly_id
, msp
);
2156 DISSECTOR_ASSERT(fh
);
2157 /* The offsets in the fragment list are relative to msp->seq */
2158 uint32_t max
= nxtseq
- msp
->seq
;
2159 for (fragment_item
*frag
= fh
->next
; frag
; frag
= frag
->next
) {
2160 uint32_t frag_end
= frag
->offset
+ frag
->len
;
2161 if (frag
->offset
<= max
&& max
< frag_end
) {
2165 crypto
->max_contiguous_offset
= max
+ msp
->seq
;
2167 crypto
->max_contiguous_offset
= nxtseq
;
2171 /* We always want to hand the entire segment to the TLS dissector.
2172 * So update nxtpdu to point at least to the start of the next segment.
2175 msp
->nxtpdu
= MAX(msp
->nxtpdu
, nxtseq
);
2179 if (msp
&& msp
->seq
<= seq
&& msp
->nxtpdu
> seq
) {
2180 if (!PINFO_FD_VISITED(pinfo
)) {
2181 msp
->last_frame
=pinfo
->num
;
2182 msp
->last_frame_time
=pinfo
->abs_ts
;
2185 /* OK, this PDU was found, which means the segment continues
2186 * a higher-level PDU and that we must desegment it.
2188 fragment_reset_tot_len(&quic_crypto_reassembly_table
, pinfo
, reassembly_id
, msp
,
2189 MAX(nxtseq
, msp
->nxtpdu
) - msp
->seq
);
2191 fh
= fragment_add(&quic_crypto_reassembly_table
, tvb
, offset
,
2192 pinfo
, reassembly_id
, msp
,
2193 seq
- msp
->seq
, length
,
2194 nxtseq
< msp
->nxtpdu
);
2196 msp
->flags
|= MSP_FLAGS_GOT_ALL_SEGMENTS
;
2197 if (msp
->flags
& MSP_FLAGS_MISSING_FIRST_SEGMENT
) {
2198 msp
->first_frame_with_seq
= seq
; // Overloading this
2199 /* We use "first_frame_with_seq" to mean "the sequence number
2200 * of the fragment that completed the MSP" because many
2201 * CRYPTO frames can be at the same layer, so the normal
2202 * methods of determining the reassembled in fragment don't
2203 * work. (We could store the seq in last_frame instead.)
2205 msp
->flags
&= (~MSP_FLAGS_MISSING_FIRST_SEGMENT
);
2208 } else if (has_gap
) {
2209 /* We need to start a new Out of Order MSP on our first visit.
2210 * We shouldn't get here on a second visit.
2212 if (!PINFO_FD_VISITED(pinfo
)) {
2213 msp
= pdu_store_sequencenumber_of_next_pdu(pinfo
, (uint32_t)crypto
->max_contiguous_offset
, nxtseq
, crypto
->multisegment_pdus
);
2214 msp
->flags
|= MSP_FLAGS_MISSING_FIRST_SEGMENT
;
2215 fh
= fragment_add(&quic_crypto_reassembly_table
, tvb
, offset
,
2216 pinfo
, reassembly_id
, msp
,
2217 seq
- msp
->seq
, length
,
2218 nxtseq
< msp
->nxtpdu
);
2221 /* This segment was not found in our table, so it doesn't
2222 * contain a continuation of a higher-level PDU.
2223 * Call the normal subdissector.
2226 crypto_info
->offset
= seq
;
2227 process_quic_crypto(tvb
, offset
, length
, pinfo
, tree
, crypto_info
);
2228 called_dissector
= true;
2231 /* is it completely desegmented? */
2234 * Yes, we think it is.
2235 * We only call TLS for the segment that reassembled it.
2237 if (fh
->reassembled_in
== pinfo
->num
&& seq
== msp
->first_frame_with_seq
) {
2240 * Let's call the subdissector with the desegmented data.
2243 tvbuff_t
*next_tvb
= tvb_new_chain(tvb
, fh
->tvb_data
);
2244 add_new_data_source(pinfo
, next_tvb
, "Reassembled QUIC CRYPTO");
2245 proto_item
*frag_tree_item
;
2246 /* XXX: Should we use the proto_tree_get_root for these?
2247 * There are PADDING and PINGs after the crypto, so maybe not?
2249 show_fragment_tree(fh
, &quic_crypto_fragment_items
, tree
, pinfo
, next_tvb
, &frag_tree_item
);
2250 crypto_info
->offset
= seq
;
2251 process_quic_crypto(next_tvb
, 0, tvb_captured_length(next_tvb
), pinfo
, tree
, crypto_info
);
2252 called_dissector
= true;
2256 if (!called_dissector
) {
2257 if (fh
!= NULL
&& fh
->reassembled_in
!= 0 &&
2258 fh
->reassembled_in
!= pinfo
->num
) {
2260 * We know what frame this PDU is reassembled in;
2261 * let the user know.
2263 proto_item
*item
= proto_tree_add_uint(tree
, hf_quic_reassembled_in
, tvb
, 0,
2264 0, fh
->reassembled_in
);
2265 proto_item_set_generated(item
);
2271 dissect_quic_crypto_payload(tvbuff_t
*tvb
, int offset
, int length
, packet_info
*pinfo
,
2272 proto_tree
*tree
, quic_info_data_t
*quic_info
,
2273 quic_crypto_info
*crypto_info
,
2274 quic_crypto_state
*crypto
)
2276 /* Make sure that TLS can also desegment */
2277 pinfo
->can_desegment
= 2;
2278 if (quic_crypto_out_of_order
) {
2279 desegment_quic_crypto(tvb
, offset
, length
, pinfo
, tree
, quic_info
, crypto_info
, crypto
);
2281 crypto_info
->offset
= (uint32_t)crypto_info
->crypto_offset
;
2282 process_quic_crypto(tvb
, offset
, length
, pinfo
, tree
, crypto_info
);
2287 quic_stream_add_proto_data(packet_info
*pinfo
, quic_stream_info
*stream_info
, void *proto_data
)
2289 quic_stream_state
*stream
= quic_get_stream_state(pinfo
, stream_info
->quic_info
, stream_info
->from_server
, stream_info
->stream_id
);
2290 stream
->subdissector_private
= proto_data
;
2293 void *quic_stream_get_proto_data(packet_info
*pinfo
, quic_stream_info
*stream_info
)
2295 quic_stream_state
*stream
= quic_get_stream_state(pinfo
, stream_info
->quic_info
, stream_info
->from_server
, stream_info
->stream_id
);
2296 return stream
->subdissector_private
;
2300 dissect_quic_frame_type(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*quic_tree
, unsigned offset
, quic_info_data_t
*quic_info
, const quic_packet_info_t
*quic_packet
, bool from_server
)
2302 proto_item
*ti_ft
, *ti_ftflags
, *ti_ftid
, *ti
;
2303 proto_tree
*ft_tree
, *ftflags_tree
, *ftid_tree
;
2304 uint64_t frame_type
;
2306 unsigned orig_offset
= offset
;
2308 ti_ft
= proto_tree_add_item(quic_tree
, hf_quic_frame
, tvb
, offset
, 1, ENC_NA
);
2309 ft_tree
= proto_item_add_subtree(ti_ft
, ett_quic_ft
);
2311 ti_ftflags
= proto_tree_add_item_ret_varint(ft_tree
, hf_quic_frame_type
, tvb
, offset
, -1, ENC_VARINT_QUIC
, &frame_type
, &lenft
);
2312 proto_item_set_text(ti_ft
, "%s", rval_to_str_const((uint32_t)frame_type
, quic_frame_type_vals
, "Unknown"));
2319 col_append_str(pinfo
->cinfo
, COL_INFO
, ", PADDING");
2321 /* A padding frame consists of a single zero octet, but for brevity
2322 * sake let's combine multiple zeroes into a single field. */
2323 pad_len
= 1 + tvb_skip_uint8(tvb
, offset
, tvb_reported_length_remaining(tvb
, offset
), '\0') - offset
;
2324 ti
= proto_tree_add_uint(ft_tree
, hf_quic_padding_length
, tvb
, offset
, 0, pad_len
);
2325 proto_item_set_generated(ti
);
2326 proto_item_append_text(ti_ft
, " Length: %u", pad_len
);
2327 offset
+= pad_len
- 1;
2331 col_append_str(pinfo
->cinfo
, COL_INFO
, ", PING");
2337 case FT_PATH_ACK_ECN
:{
2338 uint64_t ack_range_count
, path_id
;
2343 col_append_str(pinfo
->cinfo
, COL_INFO
, ", ACK");
2346 col_append_str(pinfo
->cinfo
, COL_INFO
, ", ACK_ECN");
2349 col_append_str(pinfo
->cinfo
, COL_INFO
, ", PATH_ACK");
2350 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_mp_path_ack_path_identifier
, tvb
, offset
, -1, ENC_VARINT_QUIC
, &path_id
, &lenvar
);
2352 proto_item_append_text(ti_ft
, " path_id=%" PRIu64
, path_id
);
2354 case FT_PATH_ACK_ECN
:
2355 col_append_str(pinfo
->cinfo
, COL_INFO
, ", PATH_ACK_ECN");
2356 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_mp_path_ack_path_identifier
, tvb
, offset
, -1, ENC_VARINT_QUIC
, &path_id
, &lenvar
);
2358 proto_item_append_text(ti_ft
, " path_id=%" PRIu64
, path_id
);
2362 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_ack_largest_acknowledged
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &lenvar
);
2365 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_ack_ack_delay
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &lenvar
);
2368 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_ack_ack_range_count
, tvb
, offset
, -1, ENC_VARINT_QUIC
, &ack_range_count
, &lenvar
);
2371 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_ack_first_ack_range
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &lenvar
);
2374 /* ACK Ranges - Repeated "Ack Range Count" */
2375 while (ack_range_count
) {
2377 /* Gap To Next Block */
2378 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_ack_gap
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &lenvar
);
2381 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_ack_ack_range
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &lenvar
);
2388 if (frame_type
== FT_ACK_ECN
|| frame_type
== FT_PATH_ACK_ECN
) {
2389 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_ack_ect0_count
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &lenvar
);
2392 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_ack_ect1_count
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &lenvar
);
2395 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_ack_ecn_ce_count
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &lenvar
);
2400 case FT_RESET_STREAM
:{
2401 uint64_t stream_id
, error_code
;
2402 int32_t len_streamid
= 0, len_finalsize
= 0, len_error_code
= 0;
2404 col_append_str(pinfo
->cinfo
, COL_INFO
, ", RS");
2406 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_rsts_stream_id
, tvb
, offset
, -1, ENC_VARINT_QUIC
, &stream_id
, &len_streamid
);
2407 offset
+= len_streamid
;
2409 proto_item_append_text(ti_ft
, " id=%" PRIu64
, stream_id
);
2410 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "(%" PRIu64
")", stream_id
);
2412 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_rsts_application_error_code
, tvb
, offset
, -1, ENC_VARINT_QUIC
, &error_code
, &len_error_code
);
2413 offset
+= len_error_code
;
2415 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_rsts_final_size
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &len_finalsize
);
2416 offset
+= len_finalsize
;
2418 proto_item_append_text(ti_ft
, " Error code: %#" PRIx64
, error_code
);
2421 case FT_STOP_SENDING
:{
2422 int32_t len_streamid
;
2423 uint64_t stream_id
, error_code
;
2424 int32_t len_error_code
= 0;
2426 col_append_str(pinfo
->cinfo
, COL_INFO
, ", SS");
2428 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_ss_stream_id
, tvb
, offset
, -1, ENC_VARINT_QUIC
, &stream_id
, &len_streamid
);
2429 offset
+= len_streamid
;
2431 proto_item_append_text(ti_ft
, " id=%" PRIu64
, stream_id
);
2432 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "(%" PRIu64
")", stream_id
);
2434 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_ss_application_error_code
, tvb
, offset
, -1, ENC_VARINT_QUIC
, &error_code
, &len_error_code
);
2435 offset
+= len_error_code
;
2437 proto_item_append_text(ti_ft
, " Error code: %#" PRIx64
, error_code
);
2441 uint64_t crypto_offset
, crypto_length
;
2443 col_append_str(pinfo
->cinfo
, COL_INFO
, ", CRYPTO");
2444 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_crypto_offset
, tvb
, offset
, -1, ENC_VARINT_QUIC
, &crypto_offset
, &lenvar
);
2446 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_crypto_length
, tvb
, offset
, -1, ENC_VARINT_QUIC
, &crypto_length
, &lenvar
);
2448 proto_tree_add_item(ft_tree
, hf_quic_crypto_crypto_data
, tvb
, offset
, (uint32_t)crypto_length
, ENC_NA
);
2449 quic_crypto_state
*crypto
= quic_get_crypto_state(pinfo
, quic_info
, from_server
, quic_packet
->packet_type
);
2450 quic_crypto_info crypto_info
= {
2451 .packet_number
= quic_packet
->packet_number
,
2452 .crypto_offset
= crypto_offset
,
2453 .from_server
= from_server
,
2455 dissect_quic_crypto_payload(tvb
, offset
, (int)crypto_length
, pinfo
, ft_tree
, quic_info
, &crypto_info
, crypto
);
2456 offset
+= (uint32_t)crypto_length
;
2459 case FT_NEW_TOKEN
: {
2460 uint64_t token_length
;
2463 col_append_str(pinfo
->cinfo
, COL_INFO
, ", NT");
2465 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_nt_length
, tvb
, offset
, -1, ENC_VARINT_QUIC
, &token_length
, &lenvar
);
2468 proto_tree_add_item(ft_tree
, hf_quic_nt_token
, tvb
, offset
, (uint32_t)token_length
, ENC_NA
);
2469 offset
+= (uint32_t)token_length
;
2480 uint64_t stream_id
, stream_offset
= 0, length
;
2485 col_append_str(pinfo
->cinfo
, COL_INFO
, ", STREAM");
2487 ftflags_tree
= proto_item_add_subtree(ti_ftflags
, ett_quic_ftflags
);
2488 proto_tree_add_item(ftflags_tree
, hf_quic_stream_fin
, tvb
, offset
, 1, ENC_NA
);
2489 proto_tree_add_item(ftflags_tree
, hf_quic_stream_len
, tvb
, offset
, 1, ENC_NA
);
2490 proto_tree_add_item(ftflags_tree
, hf_quic_stream_off
, tvb
, offset
, 1, ENC_NA
);
2493 ti_ftid
= proto_tree_add_item_ret_varint(ft_tree
, hf_quic_stream_stream_id
, tvb
, offset
, -1, ENC_VARINT_QUIC
, &stream_id
, &lenvar
);
2494 ftid_tree
= proto_item_add_subtree(ti_ftid
, ett_quic_ftid
);
2495 proto_tree_add_item_ret_varint(ftid_tree
, hf_quic_stream_initiator
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, NULL
);
2496 proto_tree_add_item_ret_varint(ftid_tree
, hf_quic_stream_direction
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, NULL
);
2499 proto_item_append_text(ti_ft
, " id=%" PRIu64
, stream_id
);
2500 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "(%" PRIu64
")", stream_id
);
2502 proto_item_append_text(ti_ft
, " fin=%d", !!(frame_type
& FTFLAGS_STREAM_FIN
));
2504 if (!PINFO_FD_VISITED(pinfo
)) {
2505 quic_streams_add(pinfo
, quic_info
, stream_id
);
2508 if (frame_type
& FTFLAGS_STREAM_OFF
) {
2509 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_stream_offset
, tvb
, offset
, -1, ENC_VARINT_QUIC
, &stream_offset
, &lenvar
);
2512 proto_item_append_text(ti_ft
, " off=%" PRIu64
, stream_offset
);
2514 if (frame_type
& FTFLAGS_STREAM_LEN
) {
2515 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_stream_length
, tvb
, offset
, -1, ENC_VARINT_QUIC
, &length
, &lenvar
);
2518 length
= tvb_reported_length_remaining(tvb
, offset
);
2520 proto_item_append_text(ti_ft
, " len=%" PRIu64
" dir=%s origin=%s", length
,
2521 val64_to_str_const(!!(stream_id
& FTFLAGS_STREAM_DIRECTION
), quic_frame_id_direction
, "unknown"),
2522 val64_to_str_const(!!(stream_id
& FTFLAGS_STREAM_INITIATOR
), quic_frame_id_initiator
, "unknown"));
2524 proto_tree_add_item(ft_tree
, hf_quic_stream_data
, tvb
, offset
, (int)length
, ENC_NA
);
2525 if (have_tap_listener(quic_follow_tap
)) {
2526 quic_follow_tap_data_t
*follow_data
= wmem_new0(pinfo
->pool
, quic_follow_tap_data_t
);
2528 follow_data
->tvb
= tvb_new_subset_length(tvb
, offset
, (int)length
);
2529 follow_data
->stream_id
= stream_id
;
2530 follow_data
->from_server
= from_server
;
2532 tap_queue_packet(quic_follow_tap
, pinfo
, follow_data
);
2534 quic_stream_state
*stream
= quic_get_stream_state(pinfo
, quic_info
, from_server
, stream_id
);
2535 quic_stream_info stream_info
= {
2536 .stream_id
= stream_id
,
2537 .stream_offset
= stream_offset
,
2538 .quic_info
= quic_info
,
2539 .from_server
= from_server
,
2541 dissect_quic_stream_payload(tvb
, offset
, (int)length
, pinfo
, ft_tree
, quic_info
, &stream_info
, stream
, quic_packet
);
2542 offset
+= (int)length
;
2546 int32_t len_maximumdata
;
2548 col_append_str(pinfo
->cinfo
, COL_INFO
, ", MD");
2550 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_md_maximum_data
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &len_maximumdata
);
2551 offset
+= len_maximumdata
;
2554 case FT_MAX_STREAM_DATA
:{
2555 int32_t len_streamid
, len_maximumstreamdata
;
2558 col_append_str(pinfo
->cinfo
, COL_INFO
, ", MSD");
2560 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_msd_stream_id
, tvb
, offset
, -1, ENC_VARINT_QUIC
, &stream_id
, &len_streamid
);
2561 offset
+= len_streamid
;
2563 proto_item_append_text(ti_ft
, " id=%" PRIu64
, stream_id
);
2564 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "(%" PRIu64
")", stream_id
);
2566 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_msd_maximum_stream_data
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &len_maximumstreamdata
);
2567 offset
+= len_maximumstreamdata
;
2570 case FT_MAX_STREAMS_BIDI
:
2571 case FT_MAX_STREAMS_UNI
:{
2572 int32_t len_streamid
;
2574 col_append_str(pinfo
->cinfo
, COL_INFO
, ", MS");
2576 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_ms_max_streams
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &len_streamid
);
2577 offset
+= len_streamid
;
2580 case FT_DATA_BLOCKED
:{
2583 col_append_str(pinfo
->cinfo
, COL_INFO
, ", DB");
2585 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_db_stream_data_limit
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &len_offset
);
2586 offset
+= len_offset
;
2589 case FT_STREAM_DATA_BLOCKED
:{
2590 int32_t len_streamid
, len_offset
;
2593 col_append_str(pinfo
->cinfo
, COL_INFO
, ", SDB");
2595 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_sdb_stream_id
, tvb
, offset
, -1, ENC_VARINT_QUIC
, &stream_id
, &len_streamid
);
2596 offset
+= len_streamid
;
2598 proto_item_append_text(ti_ft
, " id=%" PRIu64
, stream_id
);
2599 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "(%" PRIu64
")", stream_id
);
2601 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_sdb_stream_data_limit
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &len_offset
);
2602 offset
+= len_offset
;
2605 case FT_STREAMS_BLOCKED_BIDI
:
2606 case FT_STREAMS_BLOCKED_UNI
:{
2607 int32_t len_streamid
;
2609 col_append_str(pinfo
->cinfo
, COL_INFO
, ", SB");
2611 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_sb_stream_limit
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &len_streamid
);
2612 offset
+= len_streamid
;
2615 case FT_NEW_CONNECTION_ID
:
2616 case FT_PATH_NEW_CONNECTION_ID
:{
2617 int32_t len_sequence
;
2618 int32_t len_retire_prior_to
;
2619 uint64_t seq_num
= 0, path_id
= 0;
2622 bool valid_cid
= false;
2625 case FT_NEW_CONNECTION_ID
:
2626 col_append_str(pinfo
->cinfo
, COL_INFO
, ", NCI");
2628 case FT_PATH_NEW_CONNECTION_ID
:
2629 col_append_str(pinfo
->cinfo
, COL_INFO
, ", PNCI");
2630 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_mp_pnci_path_identifier
, tvb
, offset
, -1, ENC_VARINT_QUIC
, &path_id
, &lenvar
);
2632 proto_item_append_text(ti_ft
, " path_id=%" PRIu64
, path_id
);
2636 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_nci_sequence
, tvb
, offset
, -1, ENC_VARINT_QUIC
, &seq_num
, &len_sequence
);
2637 offset
+= len_sequence
;
2639 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_nci_retire_prior_to
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &len_retire_prior_to
);
2640 offset
+= len_retire_prior_to
;
2642 ti
= proto_tree_add_item_ret_uint(ft_tree
, hf_quic_nci_connection_id_length
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &nci_length
);
2645 valid_cid
= nci_length
>= 1 && nci_length
<= QUIC_MAX_CID_LENGTH
;
2647 expert_add_info_format(pinfo
, ti
, &ei_quic_protocol_violation
,
2648 "Connection ID Length must be between 1 and %d bytes", QUIC_MAX_CID_LENGTH
);
2651 proto_tree_add_item(ft_tree
, hf_quic_nci_connection_id
, tvb
, offset
, nci_length
, ENC_NA
);
2652 quic_cid_t cid
= {.len
=0};
2653 if (valid_cid
&& quic_info
) {
2654 tvb_memcpy(tvb
, cid
.cid
, offset
, nci_length
);
2655 cid
.len
= nci_length
;
2656 cid
.seq_num
= seq_num
;
2657 cid
.path_id
= path_id
;
2658 quic_connection_add_cid(quic_info
, &cid
, from_server
);
2660 offset
+= nci_length
;
2662 proto_tree_add_item(ft_tree
, hf_quic_nci_stateless_reset_token
, tvb
, offset
, 16, ENC_NA
);
2663 if (valid_cid
&& quic_info
) {
2664 quic_add_stateless_reset_token(pinfo
, tvb
, offset
, &cid
);
2669 case FT_RETIRE_CONNECTION_ID
:
2670 case FT_PATH_RETIRE_CONNECTION_ID
:{
2671 int32_t len_sequence
;
2676 case FT_RETIRE_CONNECTION_ID
:
2677 col_append_str(pinfo
->cinfo
, COL_INFO
, ", RC");
2679 case FT_PATH_RETIRE_CONNECTION_ID
:
2680 col_append_str(pinfo
->cinfo
, COL_INFO
, ", PATH_RC");
2681 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_mp_rc_path_identifier
, tvb
, offset
, -1, ENC_VARINT_QUIC
, &path_id
, &lenvar
);
2683 proto_item_append_text(ti_ft
, " path_id=%" PRIu64
, path_id
);
2687 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_rci_sequence
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &len_sequence
);
2688 offset
+= len_sequence
;
2691 case FT_PATH_CHALLENGE
:{
2692 col_append_str(pinfo
->cinfo
, COL_INFO
, ", PC");
2694 proto_tree_add_item(ft_tree
, hf_quic_path_challenge_data
, tvb
, offset
, 8, ENC_NA
);
2698 case FT_PATH_RESPONSE
:{
2699 col_append_str(pinfo
->cinfo
, COL_INFO
, ", PR");
2701 proto_tree_add_item(ft_tree
, hf_quic_path_response_data
, tvb
, offset
, 8, ENC_NA
);
2705 case FT_PATH_ABANDON
:{
2706 int32_t lenvar
, len_error_code
;
2707 uint64_t path_id
, error_code
;
2709 col_append_str(pinfo
->cinfo
, COL_INFO
, ", PA");
2710 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_mp_pa_path_identifier
, tvb
, offset
, -1, ENC_VARINT_QUIC
, &path_id
, &lenvar
);
2712 proto_item_append_text(ti_ft
, " path_id=%" PRIu64
, path_id
);
2714 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_mp_pa_error_code
, tvb
, offset
, -1, ENC_VARINT_QUIC
, &error_code
, &len_error_code
);
2715 offset
+= len_error_code
;
2716 proto_item_append_text(ti_ft
, " Error code=%" PRIu64
, error_code
);
2719 case FT_CONNECTION_CLOSE_TPT
:
2720 case FT_CONNECTION_CLOSE_APP
:{
2721 int32_t len_reasonphrase
, len_frametype
, len_error_code
;
2722 uint64_t len_reason
= 0;
2723 uint64_t error_code
;
2724 const char *tls_alert
= NULL
;
2726 col_append_str(pinfo
->cinfo
, COL_INFO
, ", CC");
2728 if (frame_type
== FT_CONNECTION_CLOSE_TPT
) {
2729 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_cc_error_code
, tvb
, offset
, -1, ENC_VARINT_QUIC
, &error_code
, &len_error_code
);
2730 if ((error_code
>> 8) == 1) { // CRYPTO_ERROR (0x1XX)
2731 tls_alert
= try_val_to_str(error_code
& 0xff, ssl_31_alert_description
);
2733 proto_tree_add_item(ft_tree
, hf_quic_cc_error_code_tls_alert
, tvb
, offset
+ len_error_code
- 1, 1, ENC_BIG_ENDIAN
);
2736 offset
+= len_error_code
;
2738 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_cc_frame_type
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &len_frametype
);
2739 offset
+= len_frametype
;
2740 } else { /* FT_CONNECTION_CLOSE_APP) */
2741 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_cc_error_code_app
, tvb
, offset
, -1, ENC_VARINT_QUIC
, &error_code
, &len_error_code
);
2742 offset
+= len_error_code
;
2745 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_cc_reason_phrase_length
, tvb
, offset
, -1, ENC_VARINT_QUIC
, &len_reason
, &len_reasonphrase
);
2746 offset
+= len_reasonphrase
;
2748 proto_tree_add_item(ft_tree
, hf_quic_cc_reason_phrase
, tvb
, offset
, (uint32_t)len_reason
, ENC_ASCII
);
2749 offset
+= (uint32_t)len_reason
;
2751 // Transport Error codes higher than 0x3fff are for Private Use.
2752 if (frame_type
== FT_CONNECTION_CLOSE_TPT
&& error_code
<= 0x3fff) {
2753 proto_item_append_text(ti_ft
, " Error code: %s", rval_to_str((uint32_t)error_code
, quic_transport_error_code_vals
, "Unknown (%d)"));
2755 proto_item_append_text(ti_ft
, " Error code: %#" PRIx64
, error_code
);
2758 proto_item_append_text(ti_ft
, " (%s)", tls_alert
);
2762 case FT_HANDSHAKE_DONE
:
2763 col_append_str(pinfo
->cinfo
, COL_INFO
, ", DONE");
2766 case FT_DATAGRAM_LENGTH
:{
2769 col_append_str(pinfo
->cinfo
, COL_INFO
, ", DG");
2770 if (frame_type
== FT_DATAGRAM_LENGTH
) {
2772 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_dg_length
, tvb
, offset
, -1, ENC_VARINT_QUIC
, &length
, &dg_length
);
2773 offset
+= dg_length
;
2775 length
= (uint32_t) tvb_reported_length_remaining(tvb
, offset
);
2777 proto_tree_add_item(ft_tree
, hf_quic_dg
, tvb
, offset
, (uint32_t)length
, ENC_NA
);
2778 offset
+= (uint32_t)length
;
2781 case FT_IMMEDIATE_ACK_DRAFT05
:
2782 case FT_IMMEDIATE_ACK
:
2783 col_append_str(pinfo
->cinfo
, COL_INFO
, ", IA");
2785 case FT_ACK_FREQUENCY
:{
2788 col_append_str(pinfo
->cinfo
, COL_INFO
, ", AF");
2789 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_af_sequence_number
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &length
);
2790 offset
+= (uint32_t)length
;
2792 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_af_ack_eliciting_threshold
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &length
);
2793 offset
+= (uint32_t)length
;
2795 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_af_request_max_ack_delay
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &length
);
2796 offset
+= (uint32_t)length
;
2798 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_af_reordering_threshold
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &length
);
2799 offset
+= (uint32_t)length
;
2802 case FT_TIME_STAMP
:{
2805 col_append_str(pinfo
->cinfo
, COL_INFO
, ", TS");
2806 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_ts
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &length
);
2807 offset
+= (uint32_t)length
;
2811 case FT_PATH_STATUS
:
2812 case FT_PATH_BACKUP
:
2813 case FT_PATH_AVAILABLE
:{
2816 col_append_str(pinfo
->cinfo
, COL_INFO
, ", PS");
2817 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_mp_ps_path_identifier
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &length
);
2818 offset
+= (uint32_t)length
;
2820 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_mp_ps_path_status_sequence_number
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &length
);
2821 offset
+= (uint32_t)length
;
2823 if (frame_type
== FT_PATH_STATUS
) {
2824 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_mp_ps_path_status
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &length
);
2825 offset
+= (uint32_t)length
;
2832 /* multipath draft-07: "If any of the endpoints does not advertise
2833 * the initial_max_paths transport parameter, then the endpoints
2834 * MUST NOT use any frame or mechanism defined in this document."
2836 * So we do not call quic_add_multipath here, and possibly should
2837 * set a expert info if MP is not supported (similar with other
2840 col_append_str(pinfo
->cinfo
, COL_INFO
, ", MP");
2841 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_mp_maximum_paths
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &length
);
2842 offset
+= (uint32_t)length
;
2845 case FT_MAX_PATH_ID
:{
2848 col_append_str(pinfo
->cinfo
, COL_INFO
, ", MPI");
2849 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_mp_maximum_path_identifier
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &length
);
2850 offset
+= (uint32_t)length
;
2853 case FT_PATHS_BLOCKED
:{
2856 col_append_str(pinfo
->cinfo
, COL_INFO
, ", PB");
2857 proto_tree_add_item_ret_varint(ft_tree
, hf_quic_mp_maximum_path_identifier
, tvb
, offset
, -1, ENC_VARINT_QUIC
, NULL
, &length
);
2858 offset
+= (uint32_t)length
;
2862 expert_add_info_format(pinfo
, ti_ft
, &ei_quic_ft_unknown
, "Unknown Frame Type %#" PRIx64
, frame_type
);
2866 proto_item_set_len(ti_ft
, offset
- orig_offset
);
2872 quic_hp_cipher_init(quic_hp_cipher
*hp_cipher
, int hash_algo
, uint8_t key_length
, uint8_t *secret
, uint32_t version
);
2874 quic_pp_cipher_init(quic_pp_cipher
*pp_cipher
, int hash_algo
, uint8_t key_length
, uint8_t *secret
, uint32_t version
);
2877 * Given a QUIC message (header + non-empty payload), the actual packet number,
2878 * try to decrypt it using the PP cipher.
2879 * As the header points to the original buffer with an encrypted packet number,
2880 * the (encrypted) packet number length is also included.
2882 * The actual packet number must be constructed according to
2883 * https://tools.ietf.org/html/draft-ietf-quic-transport-22#section-12.3
2886 quic_decrypt_message(quic_pp_cipher
*pp_cipher
, tvbuff_t
*head
, unsigned header_length
,
2887 uint8_t first_byte
, unsigned pkn_len
, uint64_t packet_number
, quic_decrypt_result_t
*result
, packet_info
*pinfo
)
2891 uint8_t nonce
[TLS13_AEAD_NONCE_LENGTH
];
2894 unsigned buffer_length
;
2895 const unsigned char **error
= &result
->error
;
2896 quic_datagram
*dgram_info
;
2898 dgram_info
= (quic_datagram
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_quic
, 0);
2900 DISSECTOR_ASSERT(pp_cipher
!= NULL
);
2901 DISSECTOR_ASSERT(pp_cipher
->pp_cipher
!= NULL
);
2902 DISSECTOR_ASSERT(pkn_len
< header_length
);
2903 DISSECTOR_ASSERT(1 <= pkn_len
&& pkn_len
<= 4);
2904 // copy header, but replace encrypted first byte and PKN by plaintext.
2905 header
= (uint8_t *)tvb_memdup(pinfo
->pool
, head
, 0, header_length
);
2906 header
[0] = first_byte
;
2907 for (unsigned i
= 0; i
< pkn_len
; i
++) {
2908 header
[header_length
- 1 - i
] = (uint8_t)(packet_number
>> (8 * i
));
2911 /* Input is "header || ciphertext (buffer) || auth tag (16 bytes)" */
2912 buffer_length
= tvb_captured_length_remaining(head
, header_length
+ 16);
2913 if (buffer_length
== 0) {
2914 *error
= "Decryption not possible, ciphertext is too short";
2917 buffer
= (uint8_t *)tvb_memdup(wmem_file_scope(), head
, header_length
, buffer_length
);
2918 tvb_memcpy(head
, atag
, header_length
+ buffer_length
, 16);
2920 memcpy(nonce
, pp_cipher
->pp_iv
, TLS13_AEAD_NONCE_LENGTH
);
2921 /* Packet number is left-padded with zeroes and XORed with write_iv */
2922 phton64(nonce
+ sizeof(nonce
) - 8, pntoh64(nonce
+ sizeof(nonce
) - 8) ^ packet_number
);
2923 /* QUIC Multipath draft-07 also uses the lower 32 bits of the Path ID
2924 * (CID sequence number prior to draft-07), which MUST NOT go over 2^32
2925 * when multipath is used; also, the nonce must be at least 12 bytes.
2927 if (dgram_info
&& dgram_info
->conn
&& quic_multipath_negotiated(dgram_info
->conn
)) {
2928 DISSECTOR_ASSERT_CMPINT(TLS13_AEAD_NONCE_LENGTH
, >=, 12);
2929 phton32(nonce
+ sizeof(nonce
) - 12, pntoh32(nonce
+ sizeof(nonce
) - 12) ^ (UINT32_MAX
& dgram_info
->path_id
));
2932 gcry_cipher_reset(pp_cipher
->pp_cipher
);
2933 err
= gcry_cipher_setiv(pp_cipher
->pp_cipher
, nonce
, TLS13_AEAD_NONCE_LENGTH
);
2935 *error
= wmem_strdup_printf(wmem_file_scope(), "Decryption (setiv) failed: %s", gcry_strerror(err
));
2939 /* associated data (A) is the contents of QUIC header */
2940 err
= gcry_cipher_authenticate(pp_cipher
->pp_cipher
, header
, header_length
);
2942 *error
= wmem_strdup_printf(wmem_file_scope(), "Decryption (authenticate) failed: %s", gcry_strerror(err
));
2946 /* Output ciphertext (C) */
2947 err
= gcry_cipher_decrypt(pp_cipher
->pp_cipher
, buffer
, buffer_length
, NULL
, 0);
2949 *error
= wmem_strdup_printf(wmem_file_scope(), "Decryption (decrypt) failed: %s", gcry_strerror(err
));
2953 err
= gcry_cipher_checktag(pp_cipher
->pp_cipher
, atag
, 16);
2955 *error
= wmem_strdup_printf(wmem_file_scope(), "Decryption (checktag) failed: %s", gcry_strerror(err
));
2959 result
->error
= NULL
;
2960 result
->data
= buffer
;
2961 result
->data_len
= buffer_length
;
2965 quic_hkdf_expand_label(int hash_algo
, uint8_t *secret
, unsigned secret_len
, const char *label
, uint8_t *out
, unsigned out_len
)
2967 const StringInfo secret_si
= { secret
, secret_len
};
2968 unsigned char *out_mem
= NULL
;
2969 if (tls13_hkdf_expand_label(hash_algo
, &secret_si
, "tls13 ", label
, out_len
, &out_mem
)) {
2970 memcpy(out
, out_mem
, out_len
);
2971 wmem_free(NULL
, out_mem
);
2978 * Compute the client and server initial secrets given Connection ID "cid".
2980 * On success true is returned and the two initial secrets are set.
2981 * false is returned on error (see "error" parameter for the reason).
2984 quic_derive_initial_secrets(const quic_cid_t
*cid
,
2985 uint8_t client_initial_secret
[HASH_SHA2_256_LENGTH
],
2986 uint8_t server_initial_secret
[HASH_SHA2_256_LENGTH
],
2991 * https://tools.ietf.org/html/draft-ietf-quic-tls-29#section-5.2
2993 * initial_salt = 0xafbfec289993d24c9e9786f19c6111e04390a899
2994 * initial_secret = HKDF-Extract(initial_salt, client_dst_connection_id)
2996 * client_initial_secret = HKDF-Expand-Label(initial_secret,
2997 * "client in", "", Hash.length)
2998 * server_initial_secret = HKDF-Expand-Label(initial_secret,
2999 * "server in", "", Hash.length)
3001 * Hash for handshake packets is SHA-256 (output size 32).
3003 static const uint8_t handshake_salt_draft_22
[20] = {
3004 0x7f, 0xbc, 0xdb, 0x0e, 0x7c, 0x66, 0xbb, 0xe9, 0x19, 0x3a,
3005 0x96, 0xcd, 0x21, 0x51, 0x9e, 0xbd, 0x7a, 0x02, 0x64, 0x4a
3007 static const uint8_t handshake_salt_draft_23
[20] = {
3008 0xc3, 0xee, 0xf7, 0x12, 0xc7, 0x2e, 0xbb, 0x5a, 0x11, 0xa7,
3009 0xd2, 0x43, 0x2b, 0xb4, 0x63, 0x65, 0xbe, 0xf9, 0xf5, 0x02,
3011 static const uint8_t handshake_salt_draft_29
[20] = {
3012 0xaf, 0xbf, 0xec, 0x28, 0x99, 0x93, 0xd2, 0x4c, 0x9e, 0x97,
3013 0x86, 0xf1, 0x9c, 0x61, 0x11, 0xe0, 0x43, 0x90, 0xa8, 0x99
3015 static const uint8_t handshake_salt_v1
[20] = {
3016 0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17,
3017 0x9a, 0xe6, 0xa4, 0xc8, 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a
3019 static const uint8_t hanshake_salt_draft_q50
[20] = {
3020 0x50, 0x45, 0x74, 0xEF, 0xD0, 0x66, 0xFE, 0x2F, 0x9D, 0x94,
3021 0x5C, 0xFC, 0xDB, 0xD3, 0xA7, 0xF0, 0xD3, 0xB5, 0x6B, 0x45
3023 static const uint8_t hanshake_salt_draft_t50
[20] = {
3024 0x7f, 0xf5, 0x79, 0xe5, 0xac, 0xd0, 0x72, 0x91, 0x55, 0x80,
3025 0x30, 0x4c, 0x43, 0xa2, 0x36, 0x7c, 0x60, 0x48, 0x83, 0x10
3027 static const int8_t hanshake_salt_draft_t51
[20] = {
3028 0x7a, 0x4e, 0xde, 0xf4, 0xe7, 0xcc, 0xee, 0x5f, 0xa4, 0x50,
3029 0x6c, 0x19, 0x12, 0x4f, 0xc8, 0xcc, 0xda, 0x6e, 0x03, 0x3d
3031 static const uint8_t handshake_salt_v2
[20] = {
3032 0x0d, 0xed, 0xe3, 0xde, 0xf7, 0x00, 0xa6, 0xdb, 0x81, 0x93,
3033 0x81, 0xbe, 0x6e, 0x26, 0x9d, 0xcb, 0xf9, 0xbd, 0x2e, 0xd9
3037 uint8_t secret
[HASH_SHA2_256_LENGTH
];
3039 if (version
== 0x51303530) {
3040 err
= hkdf_extract(GCRY_MD_SHA256
, hanshake_salt_draft_q50
, sizeof(hanshake_salt_draft_q50
),
3041 cid
->cid
, cid
->len
, secret
);
3042 } else if (version
== 0x54303530) {
3043 err
= hkdf_extract(GCRY_MD_SHA256
, hanshake_salt_draft_t50
, sizeof(hanshake_salt_draft_t50
),
3044 cid
->cid
, cid
->len
, secret
);
3045 } else if (version
== 0x54303531) {
3046 err
= hkdf_extract(GCRY_MD_SHA256
, hanshake_salt_draft_t51
, sizeof(hanshake_salt_draft_t51
),
3047 cid
->cid
, cid
->len
, secret
);
3048 } else if (is_quic_draft_max(version
, 22)) {
3049 err
= hkdf_extract(GCRY_MD_SHA256
, handshake_salt_draft_22
, sizeof(handshake_salt_draft_22
),
3050 cid
->cid
, cid
->len
, secret
);
3051 } else if (is_quic_draft_max(version
, 28)) {
3052 err
= hkdf_extract(GCRY_MD_SHA256
, handshake_salt_draft_23
, sizeof(handshake_salt_draft_23
),
3053 cid
->cid
, cid
->len
, secret
);
3054 } else if (is_quic_draft_max(version
, 32)) {
3055 err
= hkdf_extract(GCRY_MD_SHA256
, handshake_salt_draft_29
, sizeof(handshake_salt_draft_29
),
3056 cid
->cid
, cid
->len
, secret
);
3057 } else if (is_quic_draft_max(version
, 34)) {
3058 err
= hkdf_extract(GCRY_MD_SHA256
, handshake_salt_v1
, sizeof(handshake_salt_v1
),
3059 cid
->cid
, cid
->len
, secret
);
3061 err
= hkdf_extract(GCRY_MD_SHA256
, handshake_salt_v2
, sizeof(handshake_salt_v2
),
3062 cid
->cid
, cid
->len
, secret
);
3065 *error
= wmem_strdup_printf(wmem_packet_scope(), "Failed to extract secrets: %s", gcry_strerror(err
));
3069 if (!quic_hkdf_expand_label(GCRY_MD_SHA256
, secret
, sizeof(secret
), "client in",
3070 client_initial_secret
, HASH_SHA2_256_LENGTH
)) {
3071 *error
= "Key expansion (client) failed";
3075 if (!quic_hkdf_expand_label(GCRY_MD_SHA256
, secret
, sizeof(secret
), "server in",
3076 server_initial_secret
, HASH_SHA2_256_LENGTH
)) {
3077 *error
= "Key expansion (server) failed";
3086 * Maps a Packet Protection cipher to the Packet Number protection cipher.
3087 * See https://tools.ietf.org/html/draft-ietf-quic-tls-22#section-5.4.3
3090 quic_get_pn_cipher_algo(int cipher_algo
, int *hp_cipher_mode
)
3092 switch (cipher_algo
) {
3093 case GCRY_CIPHER_AES128
:
3094 case GCRY_CIPHER_AES256
:
3095 *hp_cipher_mode
= GCRY_CIPHER_MODE_ECB
;
3097 case GCRY_CIPHER_CHACHA20
:
3098 *hp_cipher_mode
= GCRY_CIPHER_MODE_STREAM
;
3106 * (Re)initialize the PNE/PP ciphers using the given cipher algorithm.
3107 * If the optional base secret is given, then its length MUST match the hash
3111 quic_hp_cipher_prepare(quic_hp_cipher
*hp_cipher
, int hash_algo
, int cipher_algo
, uint8_t *secret
, const char **error
, uint32_t version
)
3113 /* Clear previous state (if any). */
3114 quic_hp_cipher_reset(hp_cipher
);
3117 if (!quic_get_pn_cipher_algo(cipher_algo
, &hp_cipher_mode
)) {
3118 *error
= "Unsupported cipher algorithm";
3122 if (gcry_cipher_open(&hp_cipher
->hp_cipher
, cipher_algo
, hp_cipher_mode
, 0)) {
3123 quic_hp_cipher_reset(hp_cipher
);
3124 *error
= "Failed to create HP cipher";
3129 unsigned cipher_keylen
= (uint8_t) gcry_cipher_get_algo_keylen(cipher_algo
);
3130 if (!quic_hp_cipher_init(hp_cipher
, hash_algo
, cipher_keylen
, secret
, version
)) {
3131 quic_hp_cipher_reset(hp_cipher
);
3132 *error
= "Failed to derive key material for HP cipher";
3140 quic_pp_cipher_prepare(quic_pp_cipher
*pp_cipher
, int hash_algo
, int cipher_algo
, int cipher_mode
, uint8_t *secret
, const char **error
, uint32_t version
)
3142 /* Clear previous state (if any). */
3143 quic_pp_cipher_reset(pp_cipher
);
3146 if (!quic_get_pn_cipher_algo(cipher_algo
, &hp_cipher_mode
)) {
3147 *error
= "Unsupported cipher algorithm";
3151 if (gcry_cipher_open(&pp_cipher
->pp_cipher
, cipher_algo
, cipher_mode
, 0)) {
3152 quic_pp_cipher_reset(pp_cipher
);
3153 *error
= "Failed to create PP cipher";
3158 unsigned cipher_keylen
= (uint8_t) gcry_cipher_get_algo_keylen(cipher_algo
);
3159 if (!quic_pp_cipher_init(pp_cipher
, hash_algo
, cipher_keylen
, secret
, version
)) {
3160 quic_pp_cipher_reset(pp_cipher
);
3161 *error
= "Failed to derive key material for PP cipher";
3169 quic_ciphers_prepare(quic_ciphers
*ciphers
, int hash_algo
, int cipher_algo
, int cipher_mode
, uint8_t *secret
, const char **error
, uint32_t version
)
3171 return quic_hp_cipher_prepare(&ciphers
->hp_cipher
, hash_algo
, cipher_algo
, secret
, error
, version
) &&
3172 quic_pp_cipher_prepare(&ciphers
->pp_cipher
, hash_algo
, cipher_algo
, cipher_mode
, secret
, error
, version
);
3177 quic_create_initial_decoders(const quic_cid_t
*cid
, const char **error
, quic_info_data_t
*quic_info
)
3179 uint8_t client_secret
[HASH_SHA2_256_LENGTH
];
3180 uint8_t server_secret
[HASH_SHA2_256_LENGTH
];
3182 if (!quic_derive_initial_secrets(cid
, client_secret
, server_secret
, quic_info
->version
, error
)) {
3186 /* Packet numbers are protected with AES128-CTR,
3187 * initial packets are protected with AEAD_AES_128_GCM. */
3188 if (!quic_ciphers_prepare(&quic_info
->client_initial_ciphers
, GCRY_MD_SHA256
,
3189 GCRY_CIPHER_AES128
, GCRY_CIPHER_MODE_GCM
, client_secret
, error
, quic_info
->version
) ||
3190 !quic_ciphers_prepare(&quic_info
->server_initial_ciphers
, GCRY_MD_SHA256
,
3191 GCRY_CIPHER_AES128
, GCRY_CIPHER_MODE_GCM
, server_secret
, error
, quic_info
->version
)) {
3199 quic_create_0rtt_decoder(unsigned i
, char *early_data_secret
, unsigned early_data_secret_len
,
3200 quic_ciphers
*ciphers
, int *cipher_algo
, uint32_t version
)
3202 static const uint16_t tls13_ciphers
[] = {
3203 0x1301, /* TLS_AES_128_GCM_SHA256 */
3204 0x1302, /* TLS_AES_256_GCM_SHA384 */
3205 0x1303, /* TLS_CHACHA20_POLY1305_SHA256 */
3206 0x1304, /* TLS_AES_128_CCM_SHA256 */
3207 0x1305, /* TLS_AES_128_CCM_8_SHA256 */
3209 if (i
>= G_N_ELEMENTS(tls13_ciphers
)) {
3213 int cipher_mode
= 0, hash_algo
= 0;
3214 const char *error_ignored
= NULL
;
3215 if (tls_get_cipher_info(NULL
, tls13_ciphers
[i
], cipher_algo
, &cipher_mode
, &hash_algo
)) {
3216 unsigned hash_len
= gcry_md_get_algo_dlen(hash_algo
);
3217 if (hash_len
== early_data_secret_len
&& quic_ciphers_prepare(ciphers
, hash_algo
, *cipher_algo
, cipher_mode
, early_data_secret
, &error_ignored
, version
)) {
3221 /* This cipher failed, but there are more to try. */
3222 quic_ciphers_reset(ciphers
);
3227 quic_create_decoders(packet_info
*pinfo
, quic_info_data_t
*quic_info
, quic_ciphers
*ciphers
,
3228 bool from_server
, TLSRecordType type
, const char **error
)
3230 if (!quic_info
->hash_algo
) {
3231 if (!tls_get_cipher_info(pinfo
, 0, &quic_info
->cipher_algo
, &quic_info
->cipher_mode
, &quic_info
->hash_algo
)) {
3232 *error
= "Unable to retrieve cipher information";
3237 unsigned hash_len
= gcry_md_get_algo_dlen(quic_info
->hash_algo
);
3238 char *secret
= (char *)wmem_alloc0(pinfo
->pool
, hash_len
);
3240 if (!tls13_get_quic_secret(pinfo
, from_server
, type
, hash_len
, hash_len
, secret
)) {
3241 *error
= "Secrets are not available";
3245 if (!quic_ciphers_prepare(ciphers
, quic_info
->hash_algo
,
3246 quic_info
->cipher_algo
, quic_info
->cipher_mode
, secret
, error
, quic_info
->version
)) {
3254 * Tries to obtain the QUIC application traffic secrets.
3257 quic_get_traffic_secret(packet_info
*pinfo
, int hash_algo
, quic_pp_state_t
*pp_state
, bool from_client
)
3259 unsigned hash_len
= gcry_md_get_algo_dlen(hash_algo
);
3260 char *secret
= (char *)wmem_alloc0(pinfo
->pool
, hash_len
);
3261 if (!tls13_get_quic_secret(pinfo
, !from_client
, TLS_SECRET_APP
, hash_len
, hash_len
, secret
)) {
3264 pp_state
->next_secret
= (uint8_t *)wmem_memdup(wmem_file_scope(), secret
, hash_len
);
3269 * Expands the secret (length MUST be the same as the "hash_algo" digest size)
3270 * and initialize cipher with the new key.
3273 quic_hp_cipher_init(quic_hp_cipher
*hp_cipher
, int hash_algo
, uint8_t key_length
, uint8_t *secret
, uint32_t version
)
3275 unsigned char hp_key
[256/8];
3276 unsigned hash_len
= gcry_md_get_algo_dlen(hash_algo
);
3277 char *label
= !is_quic_v2(version
) ? "quic hp" : "quicv2 hp";
3279 if (!quic_hkdf_expand_label(hash_algo
, secret
, hash_len
, label
, hp_key
, key_length
)) {
3283 return gcry_cipher_setkey(hp_cipher
->hp_cipher
, hp_key
, key_length
) == 0;
3286 quic_pp_cipher_init(quic_pp_cipher
*pp_cipher
, int hash_algo
, uint8_t key_length
, uint8_t *secret
, uint32_t version
)
3288 unsigned char write_key
[256/8]; /* Maximum key size is for AES256 cipher. */
3289 unsigned hash_len
= gcry_md_get_algo_dlen(hash_algo
);
3290 char *key_label
= !is_quic_v2(version
) ? "quic key" : "quicv2 key";
3291 char *iv_label
= !is_quic_v2(version
) ? "quic iv" : "quicv2 iv";
3293 if (key_length
> sizeof(write_key
)) {
3297 if (!quic_hkdf_expand_label(hash_algo
, secret
, hash_len
, key_label
, write_key
, key_length
) ||
3298 !quic_hkdf_expand_label(hash_algo
, secret
, hash_len
, iv_label
, pp_cipher
->pp_iv
, sizeof(pp_cipher
->pp_iv
))) {
3302 return gcry_cipher_setkey(pp_cipher
->pp_cipher
, write_key
, key_length
) == 0;
3307 * Updates the packet protection secret to the next one.
3310 quic_update_key(uint32_t version
, int hash_algo
, quic_pp_state_t
*pp_state
)
3312 unsigned hash_len
= gcry_md_get_algo_dlen(hash_algo
);
3313 const char *label
= is_quic_draft_max(version
, 23) ? "traffic upd" : (is_quic_draft_max(version
, 34) ? "quic ku" : "quicv2 ku");
3314 bool ret
= quic_hkdf_expand_label(hash_algo
, pp_state
->next_secret
, hash_len
,
3315 label
, pp_state
->next_secret
, hash_len
);
3316 /* This must always succeed as our hash algorithm was already validated. */
3317 DISSECTOR_ASSERT(ret
);
3321 * Retrieves the header protection cipher for short header packets and prepares
3322 * the packet protection cipher. The application layer protocol is also queried.
3324 static quic_hp_cipher
*
3325 quic_get_1rtt_hp_cipher(packet_info
*pinfo
, quic_info_data_t
*quic_info
, bool from_server
, const char **error
)
3327 /* Keys were previously not available. */
3328 if (quic_info
->skip_decryption
) {
3332 quic_pp_state_t
*client_pp
= &quic_info
->client_pp
;
3333 quic_pp_state_t
*server_pp
= &quic_info
->server_pp
;
3334 quic_pp_state_t
*pp_state
= !from_server
? client_pp
: server_pp
;
3336 /* Try to lookup secrets if not available. */
3337 if (!quic_info
->client_pp
.next_secret
) {
3338 /* Query TLS for the cipher suite. */
3339 if (!tls_get_cipher_info(pinfo
, 0, &quic_info
->cipher_algo
, &quic_info
->cipher_mode
, &quic_info
->hash_algo
)) {
3340 /* We end up here if:
3341 * no previous TLS handshake is found
3342 * the used ciphers are unsupported
3343 * some (unencrypted) padding is misdetected as SH coalesced packet
3344 Because of the third scenario, we can't set quic_info->skip_decryption
3345 to true; otherwise we will stop decrypting the entire session, even if
3347 Unfortunately, this way, we lost the optimization that allows skipping checks
3348 for future packets in case the capture starts in midst of a
3349 connection where the handshake is not present.
3350 Note that even if we have a basic logic to detect unencrypted padding (via
3351 check_dcid_on_coalesced_packet()), there is not a proper way to detect it
3352 other than checking if the decryption successed
3354 *error
= "Missing TLS handshake, unsupported ciphers or padding";
3358 /* XXX: What if this is padding (or anything else) that is falsely
3359 * detected as a SH packet after the TLS handshake in Initial frames
3360 * but before the TLS handshake in the Handshake frames? The most
3361 * likely case is padding that starts with a byte that looks like
3362 * a short header when a 0 length DCID is being used. Then the check
3363 * above won't fail and we will retrieve the wrong TLS information,
3367 /* Retrieve secrets for both the client and server. */
3368 if (!quic_get_traffic_secret(pinfo
, quic_info
->hash_algo
, client_pp
, true) ||
3369 !quic_get_traffic_secret(pinfo
, quic_info
->hash_algo
, server_pp
, false)) {
3370 quic_info
->skip_decryption
= true;
3371 *error
= "Secrets are not available";
3375 // Create initial cipher handles for Key Phase 0 using the 1-RTT keys.
3376 if (!quic_hp_cipher_prepare(&client_pp
->hp_cipher
, quic_info
->hash_algo
,
3377 quic_info
->cipher_algo
, client_pp
->next_secret
, error
, quic_info
->version
) ||
3378 !quic_pp_cipher_prepare(&client_pp
->pp_ciphers
[0], quic_info
->hash_algo
,
3379 quic_info
->cipher_algo
, quic_info
->cipher_mode
, client_pp
->next_secret
, error
, quic_info
->version
) ||
3380 !quic_hp_cipher_prepare(&server_pp
->hp_cipher
, quic_info
->hash_algo
,
3381 quic_info
->cipher_algo
, server_pp
->next_secret
, error
, quic_info
->version
) ||
3382 !quic_pp_cipher_prepare(&server_pp
->pp_ciphers
[0], quic_info
->hash_algo
,
3383 quic_info
->cipher_algo
, quic_info
->cipher_mode
, server_pp
->next_secret
, error
, quic_info
->version
)) {
3384 quic_info
->skip_decryption
= true;
3387 // Rotate the 1-RTT key for the client and server for the next key update.
3388 quic_update_key(quic_info
->version
, quic_info
->hash_algo
, client_pp
);
3389 quic_update_key(quic_info
->version
, quic_info
->hash_algo
, server_pp
);
3391 // For efficiency, look up the application layer protocol once. The
3392 // handshake must have been completed before, so ALPN is known.
3393 const char *proto_name
= tls_get_alpn(pinfo
);
3395 quic_info
->app_handle
= dissector_get_string_handle(quic_proto_dissector_table
, proto_name
);
3396 // If no specific handle is found, alias "h3-*" to "h3" and "doq-*" to "doq"
3397 if (!quic_info
->app_handle
) {
3398 if (g_str_has_prefix(proto_name
, "h3-")) {
3399 quic_info
->app_handle
= dissector_get_string_handle(quic_proto_dissector_table
, "h3");
3400 } else if (g_str_has_prefix(proto_name
, "doq-")) {
3401 quic_info
->app_handle
= dissector_get_string_handle(quic_proto_dissector_table
, "doq");
3407 // Note: Header Protect cipher does not change after Key Update.
3408 return &pp_state
->hp_cipher
;
3412 * Tries to construct the appropriate cipher for the current key phase.
3413 * See also "PROTECTED PAYLOAD DECRYPTION" comment on top of this file.
3414 * Returns true if the cipher was newly created (and needs to be either
3415 * freed or added to the array of ciphers), false if an existing cipher
3419 quic_get_pp_cipher(quic_pp_cipher
*pp_cipher
, bool key_phase
, quic_info_data_t
*quic_info
, bool from_server
, uint64_t pkn
)
3421 const char *error
= NULL
;
3423 /* Keys were previously not available. */
3424 if (quic_info
->skip_decryption
) {
3428 quic_pp_state_t
*client_pp
= &quic_info
->client_pp
;
3429 quic_pp_state_t
*server_pp
= &quic_info
->server_pp
;
3430 quic_pp_state_t
*pp_state
= !from_server
? client_pp
: server_pp
;
3433 * If the key phase changed, try to decrypt the packet using the new cipher.
3434 * However, if the packet number is before we changed to the current phase,
3435 * try the previous cipher instead.
3436 * If that fails, then it is either a malicious packet or out-of-order.
3437 * '!!' is due to key_phase being a signed bitfield, it forces -1 into 1.
3439 if (key_phase
!= !!pp_state
->key_phase
&& pkn
> pp_state
->changed_in_pkn
) {
3440 memset(pp_cipher
, 0, sizeof(quic_pp_cipher
));
3441 if (!quic_pp_cipher_prepare(pp_cipher
, quic_info
->hash_algo
,
3442 quic_info
->cipher_algo
, quic_info
->cipher_mode
, pp_state
->next_secret
, &error
, quic_info
->version
)) {
3443 /* This should never be reached, if the parameters were wrong
3444 * before, then it should have set "skip_decryption". */
3445 REPORT_DISSECTOR_BUG("quic_pp_cipher_prepare unexpectedly failed: %s", error
);
3452 *pp_cipher
= pp_state
->pp_ciphers
[key_phase
];
3457 * After success decrypting payload, replaces the previous cipher for this
3458 * phase with the new one, and stores the packet number where this occurred.
3461 quic_set_pp_cipher(quic_pp_cipher
*pp_cipher
, bool key_phase
, quic_info_data_t
*quic_info
, bool from_server
, uint64_t pkn
)
3463 /* Keys were previously not available. */
3464 if (quic_info
->skip_decryption
) {
3468 quic_pp_state_t
*client_pp
= &quic_info
->client_pp
;
3469 quic_pp_state_t
*server_pp
= &quic_info
->server_pp
;
3470 quic_pp_state_t
*pp_state
= !from_server
? client_pp
: server_pp
;
3473 * If the key phase changed, replace the old cipher at this phase
3474 * with the new one, since we succeeded.
3476 * XXX - Perhaps optimally we should have a dynamic array of ciphers,
3477 * and a tree storing the packet numbers at which they changed,
3478 * instead of storing only two ciphers at once. We could even try
3479 * more than one cipher for a given polarity when things are badly
3480 * out of order and missing. (Servers and clients are not supposed
3481 * to switch a second time until they have received acks for the
3482 * previous changes, but there can still be old outstanding packets.
3483 * See RFC 9001 6. Key Update.)
3485 if (key_phase
!= !!pp_state
->key_phase
&& pkn
> pp_state
->changed_in_pkn
) {
3487 /* Verified the cipher, use it from now on and rotate the key. */
3488 /* Note that HP cipher is not touched.
3489 https://tools.ietf.org/html/draft-ietf-quic-tls-32#section-5.4
3490 "The same header protection key is used for the duration of the
3491 connection, with the value not changing after a key update" */
3492 quic_pp_cipher_reset(&pp_state
->pp_ciphers
[key_phase
]);
3493 pp_state
->pp_ciphers
[key_phase
] = *pp_cipher
;
3494 quic_update_key(quic_info
->version
, quic_info
->hash_algo
, pp_state
);
3496 pp_state
->key_phase
= key_phase
;
3497 pp_state
->changed_in_pkn
= pkn
;
3502 * Process (protected) payload, adding the encrypted payload to the tree. If
3503 * decryption is possible, frame dissection is also attempted.
3505 * The given offset must correspond to the end of the QUIC header and begin of
3506 * the (protected) payload. Dissected frames are appended to "tree" and expert
3507 * info is attached to "ti" (the field with the encrypted payload).
3510 quic_process_payload(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, proto_item
*ti
, unsigned offset
,
3511 quic_info_data_t
*quic_info
, quic_packet_info_t
*quic_packet
, bool from_server
,
3512 quic_pp_cipher
*pp_cipher
, uint8_t first_byte
, unsigned pkn_len
)
3514 quic_decrypt_result_t
*decryption
= &quic_packet
->decryption
;
3517 * If no decryption error has occurred yet, try decryption on the first
3518 * pass and store the result for later use.
3520 if (!PINFO_FD_VISITED(pinfo
)) {
3521 if (!quic_packet
->decryption
.error
&& quic_is_pp_cipher_initialized(pp_cipher
)) {
3522 quic_decrypt_message(pp_cipher
, tvb
, offset
, first_byte
, pkn_len
, quic_packet
->packet_number
, &quic_packet
->decryption
, pinfo
);
3526 if (decryption
->error
) {
3527 expert_add_info_format(pinfo
, ti
, &ei_quic_decryption_failed
,
3528 "Decryption failed: %s", decryption
->error
);
3529 } else if (decryption
->data_len
) {
3530 tvbuff_t
*decrypted_tvb
= tvb_new_child_real_data(tvb
, decryption
->data
,
3531 decryption
->data_len
, decryption
->data_len
);
3532 add_new_data_source(pinfo
, decrypted_tvb
, "Decrypted QUIC");
3534 unsigned decrypted_offset
= 0;
3535 while (tvb_reported_length_remaining(decrypted_tvb
, decrypted_offset
) > 0) {
3536 if (quic_info
->version
== 0x51303530 || quic_info
->version
== 0x54303530 || quic_info
->version
== 0x54303531) {
3537 decrypted_offset
= dissect_gquic_frame_type(decrypted_tvb
, pinfo
, tree
, decrypted_offset
, pkn_len
, quic_info
->gquic_info
);
3539 decrypted_offset
= dissect_quic_frame_type(decrypted_tvb
, pinfo
, tree
, decrypted_offset
, quic_info
, quic_packet
, from_server
);
3542 } else if (quic_info
->skip_decryption
) {
3543 expert_add_info_format(pinfo
, ti
, &ei_quic_decryption_failed
,
3544 "Decryption skipped because keys are not available.");
3549 quic_verify_retry_token(tvbuff_t
*tvb
, quic_packet_info_t
*quic_packet
, const quic_cid_t
*odcid
, uint32_t version
)
3552 * Verify the Retry Integrity Tag using the fixed key from
3553 * https://tools.ietf.org/html/draft-ietf-quic-tls-29#section-5.8
3555 static const uint8_t key_v1
[] = {
3556 0xbe, 0x0c, 0x69, 0x0b, 0x9f, 0x66, 0x57, 0x5a,
3557 0x1d, 0x76, 0x6b, 0x54, 0xe3, 0x68, 0xc8, 0x4e
3559 static const uint8_t nonce_v1
[] = {
3560 0x46, 0x15, 0x99, 0xd3, 0x5d, 0x63, 0x2b, 0xf2, 0x23, 0x98, 0x25, 0xbb
3562 static const uint8_t key_draft_29
[] = {
3563 0xcc, 0xce, 0x18, 0x7e, 0xd0, 0x9a, 0x09, 0xd0,
3564 0x57, 0x28, 0x15, 0x5a, 0x6c, 0xb9, 0x6b, 0xe1
3566 static const uint8_t key_v2
[] = {
3567 0x8f, 0xb4, 0xb0, 0x1b, 0x56, 0xac, 0x48, 0xe2,
3568 0x60, 0xfb, 0xcb, 0xce, 0xad, 0x7c, 0xcc, 0x92
3570 static const uint8_t nonce_draft_29
[] = {
3571 0xe5, 0x49, 0x30, 0xf9, 0x7f, 0x21, 0x36, 0xf0, 0x53, 0x0a, 0x8c, 0x1c
3573 static const uint8_t key_draft_25
[] = {
3574 0x4d, 0x32, 0xec, 0xdb, 0x2a, 0x21, 0x33, 0xc8,
3575 0x41, 0xe4, 0x04, 0x3d, 0xf2, 0x7d, 0x44, 0x30,
3577 static const uint8_t nonce_draft_25
[] = {
3578 0x4d, 0x16, 0x11, 0xd0, 0x55, 0x13, 0xa5, 0x52, 0xc5, 0x87, 0xd5, 0x75,
3580 static const uint8_t nonce_v2
[] = {
3581 0xd8, 0x69, 0x69, 0xbc, 0x2d, 0x7c, 0x6d, 0x99, 0x90, 0xef, 0xb0, 0x4a
3583 gcry_cipher_hd_t h
= NULL
;
3585 int pseudo_packet_tail_length
= tvb_reported_length(tvb
) - 16;
3587 DISSECTOR_ASSERT(pseudo_packet_tail_length
> 0);
3589 err
= gcry_cipher_open(&h
, GCRY_CIPHER_AES128
, GCRY_CIPHER_MODE_GCM
, 0);
3590 DISSECTOR_ASSERT_HINT(err
== 0, "create cipher");
3591 if (is_quic_draft_max(version
, 28)) {
3592 err
= gcry_cipher_setkey(h
, key_draft_25
, sizeof(key_draft_25
));
3593 } else if (is_quic_draft_max(version
, 32)) {
3594 err
= gcry_cipher_setkey(h
, key_draft_29
, sizeof(key_draft_29
));
3595 } else if (is_quic_draft_max(version
, 34)) {
3596 err
= gcry_cipher_setkey(h
, key_v1
, sizeof(key_v1
));
3598 err
= gcry_cipher_setkey(h
, key_v2
, sizeof(key_v2
));
3600 DISSECTOR_ASSERT_HINT(err
== 0, "set key");
3601 if (is_quic_draft_max(version
, 28)) {
3602 err
= gcry_cipher_setiv(h
, nonce_draft_25
, sizeof(nonce_draft_25
));
3603 } else if (is_quic_draft_max(version
, 32)) {
3604 err
= gcry_cipher_setiv(h
, nonce_draft_29
, sizeof(nonce_draft_29
));
3605 } else if (is_quic_draft_max(version
, 34)) {
3606 err
= gcry_cipher_setiv(h
, nonce_v1
, sizeof(nonce_v1
));
3608 err
= gcry_cipher_setiv(h
, nonce_v2
, sizeof(nonce_v2
));
3610 DISSECTOR_ASSERT_HINT(err
== 0, "set nonce");
3611 G_STATIC_ASSERT(sizeof(odcid
->len
) == 1);
3612 err
= gcry_cipher_authenticate(h
, odcid
, 1 + odcid
->len
);
3613 DISSECTOR_ASSERT_HINT(err
== 0, "aad1");
3614 err
= gcry_cipher_authenticate(h
, tvb_get_ptr(tvb
, 0, pseudo_packet_tail_length
), pseudo_packet_tail_length
);
3615 DISSECTOR_ASSERT_HINT(err
== 0, "aad2");
3616 // Plaintext is empty, there is no need to call gcry_cipher_encrypt.
3617 err
= gcry_cipher_checktag(h
, tvb_get_ptr(tvb
, pseudo_packet_tail_length
, 16), 16);
3619 quic_packet
->retry_integrity_failure
= true;
3621 quic_packet
->retry_integrity_success
= true;
3623 gcry_cipher_close(h
);
3627 quic_add_connection(packet_info
*pinfo
, quic_cid_t
*cid
)
3629 quic_datagram
*dgram_info
;
3631 dgram_info
= (quic_datagram
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_quic
, 0);
3632 if (dgram_info
&& dgram_info
->conn
) {
3633 quic_connection_add_cid(dgram_info
->conn
, cid
, dgram_info
->from_server
);
3638 quic_add_loss_bits(packet_info
*pinfo
, uint64_t value
)
3640 quic_datagram
*dgram_info
;
3641 quic_info_data_t
*conn
;
3643 dgram_info
= (quic_datagram
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_quic
, 0);
3644 if (dgram_info
&& dgram_info
->conn
) {
3645 conn
= dgram_info
->conn
;
3646 if (dgram_info
->from_server
) {
3647 conn
->server_loss_bits_recv
= true;
3649 conn
->server_loss_bits_send
= true;
3652 conn
->client_loss_bits_recv
= true;
3654 conn
->client_loss_bits_send
= true;
3660 /* Check if "multipath" feature has been negotiated */
3662 quic_multipath_negotiated(quic_info_data_t
*conn
)
3664 if (conn
->client_multipath
!= conn
->server_multipath
)
3667 return conn
->client_multipath
;
3671 quic_add_multipath(packet_info
*pinfo
, unsigned version
)
3673 quic_datagram
*dgram_info
;
3674 quic_info_data_t
*conn
;
3676 dgram_info
= (quic_datagram
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_quic
, 0);
3677 if (dgram_info
&& dgram_info
->conn
) {
3678 conn
= dgram_info
->conn
;
3679 if (dgram_info
->from_server
) {
3680 conn
->server_multipath
= version
;
3682 conn
->client_multipath
= version
;
3688 quic_add_grease_quic_bit(packet_info
*pinfo
)
3690 quic_datagram
*dgram_info
;
3691 quic_info_data_t
*conn
;
3693 dgram_info
= (quic_datagram
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_quic
, 0);
3694 if (dgram_info
&& dgram_info
->conn
) {
3695 conn
= dgram_info
->conn
;
3696 if (dgram_info
->from_server
) {
3697 conn
->server_grease_quic_bit
= true;
3699 conn
->client_grease_quic_bit
= true;
3704 static quic_info_data_t
*
3705 quic_find_stateless_reset_token(packet_info
*pinfo
, tvbuff_t
*tvb
, bool *from_server
)
3707 /* RFC 9000 10.3.1 Detecting a Stateless Reset
3708 * "The endpoint identifies a received datagram as a Stateless
3709 * Reset by comparing the last 16 bytes of the datagram with all
3710 * stateless reset tokens associated with the remote address on
3711 * which the datagram was received." That means we check all QUIC
3712 * connections on the 5-tuple (as when a nonzero Connection ID is
3713 * used there can be more than one.)
3715 quic_info_data_t
* conn
= quic_connection_from_conv(pinfo
);
3716 const quic_cid_item_t
*cids
;
3719 bool conn_from_server
= quic_connection_from_server_endpoint(pinfo
, conn
);
3720 cids
= conn_from_server
? &conn
->server_cids
: &conn
->client_cids
;
3722 const quic_cid_t
*cid
= &cids
->data
;
3723 /* XXX: Ibid., "An endpoint MUST NOT check for any stateless
3724 * reset token associated with connection IDs it has not
3725 * used or for connection IDs that have been retired,"
3726 * so we ideally should track when they are retired.
3728 if (cid
->reset_token_set
&&
3729 !tvb_memeql(tvb
, -16, cid
->reset_token
, 16) ) {
3730 *from_server
= conn_from_server
;
3741 quic_add_stateless_reset_token(packet_info
*pinfo
, tvbuff_t
*tvb
, int offset
, const quic_cid_t
*cid
)
3743 quic_datagram
*dgram_info
;
3744 quic_info_data_t
*conn
;
3745 quic_cid_item_t
*cids
;
3747 dgram_info
= (quic_datagram
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_quic
, 0);
3748 if (dgram_info
&& dgram_info
->conn
) {
3749 conn
= dgram_info
->conn
;
3750 if (dgram_info
->from_server
) {
3751 cids
= &conn
->server_cids
;
3753 cids
= &conn
->client_cids
;
3758 quic_cid_t
*old_cid
= &cids
->data
;
3759 if (quic_connection_equal(old_cid
, cid
) ) {
3760 tvb_memcpy(tvb
, old_cid
->reset_token
, offset
, 16);
3761 old_cid
->reset_token_set
= true;
3767 /* If cid is NULL (this is a Handshake message),
3768 * add it to the most recent cid. (There could
3769 * have been a Retry.)
3771 while (cids
->next
!= NULL
) cids
= cids
->next
;
3772 quic_cid_t
*old_cid
= &cids
->data
;
3773 tvb_memcpy(tvb
, old_cid
->reset_token
, offset
, 16);
3774 old_cid
->reset_token_set
= true;
3778 /* Failed to find cid. */
3783 quic_add_connection_info(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, quic_info_data_t
*conn
)
3788 ctree
= proto_tree_add_subtree(tree
, tvb
, 0, 0, ett_quic_connection_info
, NULL
, "QUIC Connection information");
3790 expert_add_info(pinfo
, ctree
, &ei_quic_connection_unknown
);
3794 /* Set the conversation elements so that TLS and other subdissectors
3795 * calling find_conversation_pinfo() find this QUIC connection and
3796 * not all QUIC connections multiplexed on the same network 5-tuple.
3798 conversation_set_elements_by_id(pinfo
, CONVERSATION_QUIC
, conn
->number
);
3799 pi
= proto_tree_add_uint(ctree
, hf_quic_connection_number
, tvb
, 0, 0, conn
->number
);
3800 proto_item_set_generated(pi
);
3802 proto_tree_add_debug_text(ctree
, "Client CID: %s", cid_to_string(pinfo
->pool
, &conn
->client_cids
.data
));
3803 proto_tree_add_debug_text(ctree
, "Server CID: %s", cid_to_string(pinfo
->pool
, &conn
->server_cids
.data
));
3804 // Note: for Retry, this value has been cleared before.
3805 proto_tree_add_debug_text(ctree
, "InitialCID: %s", cid_to_string(pinfo
->pool
, &conn
->client_dcid_initial
));
3810 * Dissects the common part after the first byte for packets using the Long
3814 dissect_quic_long_header_common(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*quic_tree
,
3815 unsigned offset
, const quic_packet_info_t
*quic_packet _U_
,
3816 quic_cid_t
*dcid
, quic_cid_t
*scid
)
3819 uint32_t dcil
, scil
;
3822 version
= tvb_get_ntohl(tvb
, offset
);
3824 ti
= proto_tree_add_item(quic_tree
, hf_quic_version
, tvb
, offset
, 4, ENC_BIG_ENDIAN
);
3825 if ((version
& 0x0F0F0F0F) == 0x0a0a0a0a) {
3826 proto_item_append_text(ti
, " (Forcing Version Negotiation)");
3830 proto_tree_add_item_ret_uint(quic_tree
, hf_quic_dcil
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &dcil
);
3833 proto_tree_add_item(quic_tree
, hf_quic_dcid
, tvb
, offset
, dcil
, ENC_NA
);
3834 // TODO expert info on CID mismatch with connection
3835 if (dcil
<= QUIC_MAX_CID_LENGTH
) {
3836 tvb_memcpy(tvb
, dcid
->cid
, offset
, dcil
);
3842 proto_tree_add_item_ret_uint(quic_tree
, hf_quic_scil
, tvb
, offset
, 1, ENC_BIG_ENDIAN
, &scil
);
3845 proto_tree_add_item(quic_tree
, hf_quic_scid
, tvb
, offset
, scil
, ENC_NA
);
3846 // TODO expert info on CID mismatch with connection
3847 if (scil
<= QUIC_MAX_CID_LENGTH
) {
3848 tvb_memcpy(tvb
, scid
->cid
, offset
, scil
);
3854 if (dcid
->len
> 0) {
3855 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", DCID=%s", cid_to_string(pinfo
->pool
, dcid
));
3857 if (scid
->len
> 0) {
3858 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", SCID=%s", cid_to_string(pinfo
->pool
, scid
));
3863 /* Retry Packet dissection */
3865 dissect_quic_retry_packet(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*quic_tree
,
3866 quic_datagram
*dgram_info _U_
, quic_packet_info_t
*quic_packet
,
3867 const quic_cid_t
*odcid
, uint32_t version
)
3869 unsigned offset
= 0;
3870 quic_cid_t dcid
= {.len
=0}, scid
= {.len
=0};
3872 unsigned retry_token_len
;
3875 if (is_quic_v2(version
)) {
3876 proto_tree_add_item(quic_tree
, hf_quic_long_packet_type_v2
, tvb
, offset
, 1, ENC_NA
);
3878 proto_tree_add_item(quic_tree
, hf_quic_long_packet_type
, tvb
, offset
, 1, ENC_NA
);
3881 col_set_str(pinfo
->cinfo
, COL_INFO
, "Retry");
3883 offset
= dissect_quic_long_header_common(tvb
, pinfo
, quic_tree
, offset
, quic_packet
, &dcid
, &scid
);
3885 if (is_quic_draft_max(version
, 24)) {
3886 proto_tree_add_item_ret_uint(quic_tree
, hf_quic_odcil
, tvb
, offset
, 1, ENC_NA
, &odcil
);
3888 proto_tree_add_item(quic_tree
, hf_quic_odcid
, tvb
, offset
, odcil
, ENC_NA
);
3892 retry_token_len
= tvb_reported_length_remaining(tvb
, offset
);
3893 // Remove length of Retry Integrity Tag
3894 if (!is_quic_draft_max(version
, 24) && retry_token_len
>= 16) {
3895 retry_token_len
-= 16;
3897 proto_tree_add_item(quic_tree
, hf_quic_retry_token
, tvb
, offset
, retry_token_len
, ENC_NA
);
3898 offset
+= retry_token_len
;
3900 if (!is_quic_draft_max(version
, 24)) {
3901 // Verify the Retry Integrity Tag according to
3902 // https://tools.ietf.org/html/draft-ietf-quic-tls-25#section-5.8
3903 ti
= proto_tree_add_item(quic_tree
, hf_quic_retry_integrity_tag
, tvb
, offset
, 16, ENC_NA
);
3904 if (!PINFO_FD_VISITED(pinfo
) && odcid
) {
3905 // Skip validation if the Initial Packet is unknown, for example due
3906 // to packet loss in the capture file.
3907 quic_verify_retry_token(tvb
, quic_packet
, odcid
, version
);
3909 if (quic_packet
->retry_integrity_failure
) {
3910 expert_add_info(pinfo
, ti
, &ei_quic_bad_retry
);
3911 } else if (!quic_packet
->retry_integrity_success
) {
3912 expert_add_info_format(pinfo
, ti
, &ei_quic_bad_retry
,
3913 "Cannot verify Retry Packet due to unknown ODCID");
3915 proto_item_append_text(ti
, " [verified]");
3924 dissect_quic_long_header(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*quic_tree
,
3925 quic_datagram
*dgram_info
, quic_packet_info_t
*quic_packet
)
3927 unsigned offset
= 0;
3928 uint8_t long_packet_type
;
3930 quic_cid_t dcid
= {.len
=0}, scid
= {.len
=0};
3931 int32_t len_token_length
;
3932 uint64_t token_length
;
3933 int32_t len_payload_length
;
3934 uint64_t payload_length
;
3935 uint8_t first_byte
= 0;
3936 quic_info_data_t
*conn
= dgram_info
->conn
;
3937 const bool from_server
= dgram_info
->from_server
;
3938 quic_ciphers
*ciphers
= NULL
;
3941 quic_extract_header(tvb
, &long_packet_type
, &version
, &dcid
, &scid
);
3942 if (!PINFO_FD_VISITED(pinfo
)) {
3943 quic_packet
->packet_type
= long_packet_type
;
3946 if (long_packet_type
== QUIC_LPT_INITIAL
) {
3947 ciphers
= !from_server
? &conn
->client_initial_ciphers
: &conn
->server_initial_ciphers
;
3948 } else if (long_packet_type
== QUIC_LPT_0RTT
&& !from_server
) {
3949 ciphers
= &conn
->client_0rtt_ciphers
;
3950 } else if (long_packet_type
== QUIC_LPT_HANDSHAKE
) {
3951 ciphers
= !from_server
? &conn
->client_handshake_ciphers
: &conn
->server_handshake_ciphers
;
3954 /* Prepare the Initial/Handshake cipher for header/payload decryption. */
3955 if (!PINFO_FD_VISITED(pinfo
) && conn
&& ciphers
) {
3956 #define DIGEST_MIN_SIZE 32 /* SHA256 */
3957 #define DIGEST_MAX_SIZE 48 /* SHA384 */
3958 const char *error
= NULL
;
3959 char early_data_secret
[DIGEST_MAX_SIZE
];
3960 unsigned early_data_secret_len
= 0;
3961 if (long_packet_type
== QUIC_LPT_INITIAL
&& !from_server
&&
3962 quic_connection_equal(&dcid
, &conn
->client_dcid_initial
)) {
3963 /* Create new decryption context based on the Client Connection
3964 * ID from the *very first* Client Initial packet. */
3965 quic_create_initial_decoders(&dcid
, &error
, conn
);
3966 } else if (long_packet_type
== QUIC_LPT_INITIAL
&& from_server
&&
3967 version
!= conn
->version
) {
3968 /* Compatibile Version Negotiation: the server (probably) updated the connection version.
3969 We need to restart the ciphers since HP depends on version.
3970 If/when updating the ciphers is a bit tricky during Compatible Version Negotiation.
3971 TODO: do we really need to restart all the initial ciphers?
3973 conn
->version
= version
;
3974 quic_ciphers_reset(ciphers
);
3975 quic_create_initial_decoders(&conn
->client_dcid_initial
, &error
, conn
);
3976 } else if (long_packet_type
== QUIC_LPT_0RTT
) {
3977 early_data_secret_len
= tls13_get_quic_secret(pinfo
, false, TLS_SECRET_0RTT_APP
, DIGEST_MIN_SIZE
, DIGEST_MAX_SIZE
, early_data_secret
);
3978 if (early_data_secret_len
== 0) {
3979 error
= "Secrets are not available";
3981 } else if (long_packet_type
== QUIC_LPT_HANDSHAKE
) {
3982 if (!quic_are_ciphers_initialized(ciphers
)) {
3983 quic_create_decoders(pinfo
, conn
, ciphers
, from_server
, TLS_SECRET_HANDSHAKE
, &error
);
3988 int hp_cipher_algo
= long_packet_type
!= QUIC_LPT_INITIAL
&& conn
? conn
->cipher_algo
: GCRY_CIPHER_AES128
;
3989 // PKN is after type(1) + version(4) + DCIL+DCID + SCIL+SCID
3990 unsigned pn_offset
= 1 + 4 + 1 + dcid
.len
+ 1 + scid
.len
;
3991 if (long_packet_type
== QUIC_LPT_INITIAL
) {
3992 pn_offset
+= tvb_get_varint(tvb
, pn_offset
, 8, &token_length
, ENC_VARINT_QUIC
);
3993 pn_offset
+= (unsigned)token_length
;
3995 pn_offset
+= tvb_get_varint(tvb
, pn_offset
, 8, &payload_length
, ENC_VARINT_QUIC
);
3997 // Assume failure unless proven otherwise.
3998 error
= "Header deprotection failed";
3999 if (long_packet_type
!= QUIC_LPT_0RTT
) {
4000 if (quic_decrypt_header(tvb
, pn_offset
, &ciphers
->hp_cipher
, hp_cipher_algo
, &first_byte
, &pkn32
, false)) {
4004 // Cipher is not stored with 0-RTT data or key, perform trial decryption.
4005 for (unsigned i
= 0; quic_create_0rtt_decoder(i
, early_data_secret
, early_data_secret_len
, ciphers
, &hp_cipher_algo
, version
); i
++) {
4006 if (quic_is_hp_cipher_initialized(&ciphers
->hp_cipher
) && quic_decrypt_header(tvb
, pn_offset
, &ciphers
->hp_cipher
, hp_cipher_algo
, &first_byte
, &pkn32
, false)) {
4013 quic_set_full_packet_number(conn
, quic_packet
, dgram_info
->path_id
, from_server
, first_byte
, pkn32
);
4014 quic_packet
->first_byte
= first_byte
;
4018 quic_packet
->decryption
.error
= wmem_strdup(wmem_file_scope(), error
);
4020 } else if (conn
&& quic_packet
->pkn_len
) {
4021 first_byte
= quic_packet
->first_byte
;
4024 proto_tree_add_item(quic_tree
, hf_quic_fixed_bit
, tvb
, offset
, 1, ENC_NA
);
4025 if (is_quic_v2(version
)) {
4026 proto_tree_add_item(quic_tree
, hf_quic_long_packet_type_v2
, tvb
, offset
, 1, ENC_NA
);
4028 proto_tree_add_item(quic_tree
, hf_quic_long_packet_type
, tvb
, offset
, 1, ENC_NA
);
4030 if (quic_packet
->pkn_len
) {
4031 ti
= proto_tree_add_uint(quic_tree
, hf_quic_long_reserved
, tvb
, offset
, 1, first_byte
);
4032 proto_item_set_generated(ti
);
4033 ti
= proto_tree_add_uint(quic_tree
, hf_quic_packet_number_length
, tvb
, offset
, 1, first_byte
);
4034 proto_item_set_generated(ti
);
4037 /* Trick: internal values in `long_packet_type` are always correctly mapped by V1 enum */
4038 col_set_str(pinfo
->cinfo
, COL_INFO
, val_to_str_const(long_packet_type
, quic_v1_long_packet_type_vals
, "Long Header"));
4040 offset
= dissect_quic_long_header_common(tvb
, pinfo
, quic_tree
, offset
, quic_packet
, &dcid
, &scid
);
4042 if (long_packet_type
== QUIC_LPT_INITIAL
) {
4043 ti
= proto_tree_add_item_ret_varint(quic_tree
, hf_quic_token_length
, tvb
, offset
, -1, ENC_VARINT_QUIC
, &token_length
, &len_token_length
);
4044 offset
+= len_token_length
;
4047 proto_tree_add_item(quic_tree
, hf_quic_token
, tvb
, offset
, (uint32_t)token_length
, ENC_NA
);
4048 /* RFC 9287: "A client MAY also set the QUIC Bit to 0 in Initial,
4049 * Handshake, or 0-RTT packets that are sent prior to receiving
4050 * transport parameters from the server. However, a client MUST
4051 * NOT set the QUIC Bit to 0 unless the Initial packets it sends
4052 * include a token provided by the server in a NEW_TOKEN frame,
4053 * received less than 604800 seconds (7 days) prior on a
4054 * connection where the server also included the grease_quic_bit
4055 * transport parameter."
4058 expert_add_info_format(pinfo
, ti
, &ei_quic_protocol_violation
,
4059 "Initial packets sent by the server must set the Token Length field to 0");
4061 /* The client [may] know that the server supports greasing the
4062 * QUIC bit, and perhaps will do so. (We can't really test if
4063 * this token came less than 7 days ago from a server that
4064 * supports it, so we'll assume it might be to be safe.)
4066 conn
->server_grease_quic_bit
= true;
4068 offset
+= (unsigned)token_length
;
4072 proto_tree_add_item_ret_varint(quic_tree
, hf_quic_length
, tvb
, offset
, -1, ENC_VARINT_QUIC
, &payload_length
, &len_payload_length
);
4073 offset
+= len_payload_length
;
4075 if (quic_packet
->decryption
.error
) {
4076 expert_add_info_format(pinfo
, quic_tree
, &ei_quic_decryption_failed
,
4077 "Failed to create decryption context: %s", quic_packet
->decryption
.error
);
4080 if (!conn
|| quic_packet
->pkn_len
== 0) {
4081 // if not part of a connection, the full PKN cannot be reconstructed.
4082 expert_add_info_format(pinfo
, quic_tree
, &ei_quic_decryption_failed
, "Failed to decrypt packet number");
4086 ti
= proto_tree_add_uint64(quic_tree
, hf_quic_packet_number
, tvb
, offset
, quic_packet
->pkn_len
, quic_packet
->packet_number
);
4087 proto_item_set_generated(ti
);
4089 offset
+= quic_packet
->pkn_len
;
4090 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", PKN: %" PRIu64
, quic_packet
->packet_number
);
4093 ti
= proto_tree_add_item(quic_tree
, hf_quic_payload
, tvb
, offset
, -1, ENC_NA
);
4096 quic_process_payload(tvb
, pinfo
, quic_tree
, ti
, offset
,
4097 conn
, quic_packet
, from_server
, &ciphers
->pp_cipher
, first_byte
, quic_packet
->pkn_len
);
4099 if (!PINFO_FD_VISITED(pinfo
) && !quic_packet
->decryption
.error
) {
4100 // Packet number is verified to be valid, remember it.
4101 *quic_max_packet_number(conn
, dgram_info
->path_id
, from_server
, first_byte
) = quic_packet
->packet_number
;
4103 // To be able to understand 0-RTT data sent we need to grab the ALPN the client wanted.
4104 if (long_packet_type
== QUIC_LPT_INITIAL
) {
4105 const char *proto_name
= tls_get_client_alpn(pinfo
);
4107 conn
->zrtt_app_handle
= dissector_get_string_handle(quic_proto_dissector_table
, proto_name
);
4108 // If no specific handle is found, alias "h3-*" to "h3" and "doq-*" to "doq"
4109 if (!conn
->zrtt_app_handle
) {
4110 if (g_str_has_prefix(proto_name
, "h3-")) {
4111 conn
->zrtt_app_handle
= dissector_get_string_handle(quic_proto_dissector_table
, "h3");
4112 } else if (g_str_has_prefix(proto_name
, "doq-")) {
4113 conn
->zrtt_app_handle
= dissector_get_string_handle(quic_proto_dissector_table
, "doq");
4119 offset
+= tvb_reported_length_remaining(tvb
, offset
);
4124 /* Check if "loss bits" feature has been negotiated */
4126 quic_loss_bits_negotiated(quic_info_data_t
*conn
, bool from_server
)
4129 return conn
->client_loss_bits_recv
&& conn
->server_loss_bits_send
;
4131 return conn
->server_loss_bits_recv
&& conn
->client_loss_bits_send
;
4136 dissect_quic_short_header(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*quic_tree
,
4137 quic_datagram
*dgram_info
, quic_packet_info_t
*quic_packet
)
4139 unsigned offset
= 0;
4140 quic_cid_t dcid
= {.len
=0};
4141 uint8_t first_byte
= 0;
4142 bool key_phase
= false;
4144 quic_pp_cipher pp_cipher
= {0};
4145 quic_info_data_t
*conn
= dgram_info
->conn
;
4146 const bool from_server
= dgram_info
->from_server
;
4147 bool loss_bits_negotiated
= false;
4149 proto_item
*pi
= proto_tree_add_item(quic_tree
, hf_quic_short
, tvb
, 0, -1, ENC_NA
);
4150 proto_tree
*hdr_tree
= proto_item_add_subtree(pi
, ett_quic_short_header
);
4151 proto_tree_add_item(hdr_tree
, hf_quic_header_form
, tvb
, 0, 1, ENC_NA
);
4153 if (!PINFO_FD_VISITED(pinfo
)) {
4154 quic_packet
->packet_type
= QUIC_SHORT_PACKET
;
4157 dcid
.len
= from_server
? conn
->client_cids
.data
.len
: conn
->server_cids
.data
.len
;
4158 loss_bits_negotiated
= quic_loss_bits_negotiated(conn
, from_server
);
4160 if (!PINFO_FD_VISITED(pinfo
) && conn
) {
4161 const char *error
= NULL
;
4163 quic_hp_cipher
*hp_cipher
= quic_get_1rtt_hp_cipher(pinfo
, conn
, from_server
, &error
);
4164 if (quic_is_hp_cipher_initialized(hp_cipher
) && quic_decrypt_header(tvb
, 1 + dcid
.len
, hp_cipher
, conn
->cipher_algo
, &first_byte
, &pkn32
, loss_bits_negotiated
)) {
4165 quic_set_full_packet_number(conn
, quic_packet
, dgram_info
->path_id
, from_server
, first_byte
, pkn32
);
4166 quic_packet
->first_byte
= first_byte
;
4169 quic_packet
->decryption
.error
= wmem_strdup(wmem_file_scope(), error
);
4171 } else if (conn
&& quic_packet
->pkn_len
) {
4172 first_byte
= quic_packet
->first_byte
;
4174 proto_tree_add_item(hdr_tree
, hf_quic_fixed_bit
, tvb
, offset
, 1, ENC_NA
);
4175 proto_tree_add_item(hdr_tree
, hf_quic_spin_bit
, tvb
, offset
, 1, ENC_NA
);
4176 /* Q and L bits are not protected by HP cipher */
4177 if (loss_bits_negotiated
) {
4178 proto_tree_add_item(hdr_tree
, hf_quic_q_bit
, tvb
, offset
, 1, ENC_NA
);
4179 proto_tree_add_item(hdr_tree
, hf_quic_l_bit
, tvb
, offset
, 1, ENC_NA
);
4181 if (quic_packet
->pkn_len
) {
4182 key_phase
= (first_byte
& SH_KP
) != 0;
4183 /* No room for reserved bits with "loss bits" feature is enable */
4184 if (!loss_bits_negotiated
) {
4185 ti
= proto_tree_add_uint(hdr_tree
, hf_quic_short_reserved
, tvb
, offset
, 1, first_byte
);
4186 proto_item_set_generated(ti
);
4188 ti
= proto_tree_add_boolean(hdr_tree
, hf_quic_key_phase
, tvb
, offset
, 1, key_phase
<<2);
4189 proto_item_set_generated(ti
);
4190 ti
= proto_tree_add_uint(hdr_tree
, hf_quic_packet_number_length
, tvb
, offset
, 1, first_byte
);
4191 proto_item_set_generated(ti
);
4195 col_clear(pinfo
->cinfo
, COL_INFO
);
4196 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "Protected Payload (KP%u)", key_phase
);
4200 proto_tree_add_item(hdr_tree
, hf_quic_dcid
, tvb
, offset
, dcid
.len
, ENC_NA
);
4201 tvb_memcpy(tvb
, dcid
.cid
, offset
, dcid
.len
);
4203 const char *dcid_str
= cid_to_string(pinfo
->pool
, &dcid
);
4204 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", DCID=%s", dcid_str
);
4205 proto_item_append_text(pi
, " DCID=%s", dcid_str
);
4208 if (quic_packet
->decryption
.error
) {
4209 expert_add_info_format(pinfo
, quic_tree
, &ei_quic_decryption_failed
,
4210 "Failed to create decryption context: %s", quic_packet
->decryption
.error
);
4213 if (!conn
|| conn
->skip_decryption
|| quic_packet
->pkn_len
== 0) {
4218 ti
= proto_tree_add_uint64(hdr_tree
, hf_quic_packet_number
, tvb
, offset
, quic_packet
->pkn_len
, quic_packet
->packet_number
);
4219 proto_item_set_generated(ti
);
4220 offset
+= quic_packet
->pkn_len
;
4221 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ", PKN: %" PRIu64
, quic_packet
->packet_number
);
4222 proto_item_append_text(pi
, " PKN=%" PRIu64
, quic_packet
->packet_number
);
4224 /* Protected Payload */
4225 ti
= proto_tree_add_item(hdr_tree
, hf_quic_protected_payload
, tvb
, offset
, -1, ENC_NA
);
4228 bool phase_change
= false;
4229 if (!PINFO_FD_VISITED(pinfo
)) {
4230 phase_change
= quic_get_pp_cipher(&pp_cipher
, key_phase
, conn
, from_server
, quic_packet
->packet_number
);
4233 quic_process_payload(tvb
, pinfo
, quic_tree
, ti
, offset
,
4234 conn
, quic_packet
, from_server
, &pp_cipher
,
4235 first_byte
, quic_packet
->pkn_len
);
4236 if (!PINFO_FD_VISITED(pinfo
)) {
4237 if (!quic_packet
->decryption
.error
) {
4238 // Packet number is verified to be valid, remember it.
4239 *quic_max_packet_number(conn
, dgram_info
->path_id
, from_server
, first_byte
) = quic_packet
->packet_number
;
4240 // pp cipher is verified to be valid, remember if it new.
4241 quic_set_pp_cipher(&pp_cipher
, key_phase
, conn
, from_server
, quic_packet
->packet_number
);
4242 } else if (phase_change
) {
4243 quic_pp_cipher_reset(&pp_cipher
);
4247 offset
+= tvb_reported_length_remaining(tvb
, offset
);
4253 quic_proto_tree_add_version(tvbuff_t
*tvb
, proto_tree
*tree
, int hfindex
, unsigned offset
)
4258 ti
= proto_tree_add_item_ret_uint(tree
, hfindex
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &version
);
4259 if ((version
& 0x0F0F0F0F) == 0x0a0a0a0a) {
4260 proto_item_append_text(ti
, " (GREASE)");
4265 dissect_quic_version_negotiation(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*quic_tree
, const quic_packet_info_t
*quic_packet
)
4267 unsigned offset
= 0;
4268 quic_cid_t dcid
= {.len
=0}, scid
= {.len
=0};
4270 col_set_str(pinfo
->cinfo
, COL_INFO
, "Version Negotiation");
4272 proto_tree_add_item(quic_tree
, hf_quic_vn_unused
, tvb
, offset
, 1, ENC_NA
);
4275 offset
= dissect_quic_long_header_common(tvb
, pinfo
, quic_tree
, offset
, quic_packet
, &dcid
, &scid
);
4277 /* Supported Version */
4278 while(tvb_reported_length_remaining(tvb
, offset
) > 0){
4279 quic_proto_tree_add_version(tvb
, quic_tree
, hf_quic_supported_version
, offset
);
4287 dissect_quic_forcing_version_negotiation(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*quic_tree
, const quic_packet_info_t
*quic_packet
)
4289 unsigned offset
= 0;
4290 quic_cid_t dcid
= {.len
=0}, scid
= {.len
=0};
4292 col_set_str(pinfo
->cinfo
, COL_INFO
, "Forcing Version Negotiation");
4294 proto_tree_add_item(quic_tree
, hf_quic_vn_unused
, tvb
, offset
, 1, ENC_NA
);
4297 offset
= dissect_quic_long_header_common(tvb
, pinfo
, quic_tree
, offset
, quic_packet
, &dcid
, &scid
);
4302 static unsigned quic_gso_heur_dcid_len
= 8;
4305 quic_get_message_tvb(tvbuff_t
*tvb
, const unsigned offset
, const quic_cid_t
*dcid
)
4307 uint64_t token_length
;
4308 uint64_t payload_length
;
4309 uint8_t packet_type
= tvb_get_uint8(tvb
, offset
);
4310 // Retry and VN packets cannot be coalesced (clarified in draft -14).
4311 if (packet_type
& 0x80) {
4312 unsigned version
= tvb_get_ntohl(tvb
, offset
+ 1);
4313 uint8_t long_packet_type
= quic_get_long_packet_type(packet_type
, version
);
4314 if (long_packet_type
!= QUIC_LPT_RETRY
) {
4315 // long header form, check version
4316 // If this is not a VN packet but a valid long form, extract a subset.
4317 // TODO check for valid QUIC versions as future versions might change the format.
4319 unsigned length
= 5; // flag (1 byte) + version (4 bytes)
4320 length
+= 1 + tvb_get_uint8(tvb
, offset
+ length
); // DCID
4321 length
+= 1 + tvb_get_uint8(tvb
, offset
+ length
); // SCID
4322 if (long_packet_type
== QUIC_LPT_INITIAL
) {
4323 length
+= tvb_get_varint(tvb
, offset
+ length
, 8, &token_length
, ENC_VARINT_QUIC
);
4324 length
+= (unsigned)token_length
;
4326 length
+= tvb_get_varint(tvb
, offset
+ length
, 8, &payload_length
, ENC_VARINT_QUIC
);
4327 length
+= (unsigned)payload_length
;
4328 if (payload_length
<= INT32_MAX
&& length
< (unsigned)tvb_reported_length_remaining(tvb
, offset
)) {
4329 return tvb_new_subset_length(tvb
, offset
, length
);
4334 if (quic_gso_heur_dcid_len
&& (dcid
->len
>= quic_gso_heur_dcid_len
)) {
4335 unsigned dcid_offset
= offset
+ 1;
4336 tvbuff_t
*needle_tvb
= tvb_new_subset_length(tvb
, dcid_offset
, dcid
->len
);
4337 int needle_pos
= tvb_find_tvb(tvb
, needle_tvb
, dcid_offset
+ dcid
->len
);
4338 if (needle_pos
!= -1) {
4339 return tvb_new_subset_length(tvb
, offset
, needle_pos
- offset
- 1);
4344 // short header form, VN or unknown message, return remaining data.
4345 return tvb_new_subset_remaining(tvb
, offset
);
4349 dissect_quic_stateless_reset(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*quic_tree
, const quic_datagram
*dgram_info _U_
)
4353 col_set_str(pinfo
->cinfo
, COL_INFO
, "Stateless Reset");
4355 ti
= proto_tree_add_uint(quic_tree
, hf_quic_packet_length
, tvb
, 0, 0, tvb_reported_length(tvb
));
4356 proto_item_set_generated(ti
);
4357 ti
= proto_tree_add_item(quic_tree
, hf_quic_header_form
, tvb
, 0, 1, ENC_NA
);
4358 if (tvb_get_uint8(tvb
, 0) & 0x80) {
4359 /* RFC 9000 says that endpoints MUST treat any packets ending in a valid
4360 * stateless reset token as a Stateless Reset, even though they MUST
4361 * send them formatted as packets with short headers.
4363 expert_add_info_format(pinfo
, ti
, &ei_quic_protocol_violation
,
4364 "Stateless Reset packets must be formatted as with short header");
4366 proto_tree_add_item(quic_tree
, hf_quic_fixed_bit
, tvb
, 0, 1, ENC_NA
);
4367 proto_tree_add_bits_item(quic_tree
, hf_quic_unpredictable_bits
, tvb
, 2, (tvb_reported_length(tvb
) - 16)*8 - 2, ENC_NA
);
4368 proto_tree_add_item(quic_tree
, hf_quic_stateless_reset_token
, tvb
, tvb_reported_length(tvb
)-16, 16, ENC_NA
);
4370 return tvb_reported_length(tvb
);
4374 * Extracts necessary information from header to find any existing connection.
4375 * There are two special values for "long_packet_type":
4376 * * QUIC_SHORT_PACKET for short header packets;
4377 * * QUIC_LPT_VER_NEG for Version Negotiation packets.
4378 * DCID and SCID are not modified unless available. For short header packets,
4379 * DCID length is unknown, so the caller should truncate it as needed.
4382 quic_extract_header(tvbuff_t
*tvb
, uint8_t *long_packet_type
, uint32_t *version
,
4383 quic_cid_t
*dcid
, quic_cid_t
*scid
)
4385 unsigned offset
= 0;
4387 uint8_t packet_type
= tvb_get_uint8(tvb
, offset
);
4388 bool is_long_header
= packet_type
& 0x80;
4392 if (is_long_header
) {
4394 *version
= tvb_get_ntohl(tvb
, offset
);
4395 *long_packet_type
= quic_get_long_packet_type(packet_type
, *version
);
4397 // short header form, store dummy value that is not a long packet type.
4398 *long_packet_type
= QUIC_SHORT_PACKET
;
4402 if (is_long_header
) {
4403 /* VN packets don't have any real packet type field, even if they have
4404 a long header: use a dummy value */
4405 if (*version
== 0x00000000)
4406 *long_packet_type
= QUIC_LPT_VER_NEG
;
4411 // read DCID and SCID (both are prefixed by a length byte).
4412 uint8_t dcil
= tvb_get_uint8(tvb
, offset
);
4415 if (dcil
&& dcil
<= QUIC_MAX_CID_LENGTH
) {
4416 tvb_memcpy(tvb
, dcid
->cid
, offset
, dcil
);
4421 uint8_t scil
= tvb_get_uint8(tvb
, offset
);
4423 if (scil
&& scil
<= QUIC_MAX_CID_LENGTH
) {
4424 tvb_memcpy(tvb
, scid
->cid
, offset
, scil
);
4428 // Definitely not draft -10, set version to dummy value.
4430 // For short headers, the DCID length is unknown and could be 0 or
4431 // anything from 1 to 20 bytes. Copy the maximum possible and let the
4432 // consumer truncate it as necessary.
4433 tvb_memcpy(tvb
, dcid
->cid
, offset
, QUIC_MAX_CID_LENGTH
);
4434 dcid
->len
= QUIC_MAX_CID_LENGTH
;
4439 * Sanity check on (coalesced) packet.
4440 * https://tools.ietf.org/html/draft-ietf-quic-transport-32#section-12.2
4441 * "Senders MUST NOT coalesce QUIC packets with different connection IDs
4442 * into a single UDP datagram"
4443 * For the first packet of the datagram, we simply save the DCID for later usage (no real check).
4444 * For any subsequent packets, we control if DCID is valid.
4445 * XXX: Generic Segmentation Offload (GSO) captures from Linux create headaches
4446 * here, and even more so with short header packets. (#19109)
4449 check_dcid_on_coalesced_packet(tvbuff_t
*tvb
, const quic_datagram
*dgram_info
,
4450 unsigned offset
, quic_cid_t
*first_packet_dcid
)
4452 bool is_first_packet
= (offset
== 0);
4453 uint8_t first_byte
, dcid_len
;
4454 quic_cid_t dcid
= {.len
=0};
4455 quic_info_data_t
*conn
= dgram_info
->conn
;
4456 bool from_server
= dgram_info
->from_server
;
4457 bool grease_quic_bit
;
4459 first_byte
= tvb_get_uint8(tvb
, offset
);
4461 if (first_byte
& 0x80) {
4462 offset
+= 4; /* Skip version */
4463 dcid_len
= tvb_get_uint8(tvb
, offset
);
4465 if (dcid_len
&& dcid_len
<= QUIC_MAX_CID_LENGTH
) {
4466 dcid
.len
= dcid_len
;
4467 tvb_memcpy(tvb
, dcid
.cid
, offset
, dcid
.len
);
4471 dcid
.len
= from_server
? conn
->client_cids
.data
.len
: conn
->server_cids
.data
.len
;
4473 tvb_memcpy(tvb
, dcid
.cid
, offset
, dcid
.len
);
4476 /* If we don't have a valid quic_info_data_t structure for this flow,
4477 we can't really validate the CID. */
4483 grease_quic_bit
= from_server
? conn
->client_grease_quic_bit
: conn
->server_grease_quic_bit
;
4485 /* Assume we're allowed to grease the Fixed bit if no connection. */
4486 grease_quic_bit
= true;
4489 if (is_first_packet
) {
4490 *first_packet_dcid
= dcid
;
4491 return true; /* Nothing to check */
4494 if (!grease_quic_bit
&& (first_byte
& 0x40) == 0) {
4498 const quic_packet_info_t
*last_packet
= &dgram_info
->first_packet
;
4499 while (last_packet
->next
) {
4500 last_packet
= last_packet
->next
;
4502 /* We should not see any Short Header (1-RTT) packets before the 1-RTT keys
4503 * have been negotiated. Under normal circumstances, that means that if the
4504 * last QUIC packet in the frame before this one is an Initial packet or a
4505 * 0-RTT packet, then this cannot be a SH packet but instead is presumably
4508 if (last_packet
->packet_type
== QUIC_LPT_INITIAL
||
4509 last_packet
->packet_type
== QUIC_LPT_0RTT
) {
4510 if ((first_byte
& 0x80) == 0) {
4516 /* XXX - That seems almost certainly true for Initial packets, but due
4517 * to packet loss, 0-RTT packets might get resent and interleaved with
4518 * Handshake packets, see
4519 * https://www.rfc-editor.org/rfc/rfc9001#section-4.1.4
4520 * If we have a connection, perhaps on the first pass we should check:
4522 if (conn
&& ((first_byte
& 0x80) == 0)) {
4523 quic_ciphers ciphers
= !from_server
? &conn
->client_handshake_ciphers
: &conn
->server_handshake_ciphers
;
4524 if (!quic_are_ciphers_initialized(ciphers
)) {
4528 /* But on the second pass the ciphers would already be initialized from
4529 * later frames so we would need to remember the result from the first pass.
4530 * Or, instead of the DISSECTOR_ASSERT(quic_packet); below, we just assume
4531 * that if there's no quic packet that's because this failed here.
4533 * However, this other solution has issues if the Server Handshake is
4534 * fragmented, the server sends 1-RTT data (as "0.5-RTT" data) after the
4535 * last Handshake fragment, but then is forced to resend an earlier
4536 * Handshake fragment due to not getting an ACK. We need to recognize the
4537 * 1-RTT data when it's first sent, not when the Handshake is reassembled.
4538 * (Or at least store it as potential 1-RTT to handle later, even if it
4539 * turns out to be padding.)
4543 /* Compare the DCID. Note this doesn't help with a 0 length DCID. */
4544 return quic_connection_equal(&dcid
, first_packet_dcid
);
4548 dissect_quic(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
4551 proto_item
*quic_ti
, *ti
;
4552 proto_tree
*quic_tree
;
4553 unsigned offset
= 0;
4554 quic_datagram
*dgram_info
= NULL
;
4555 quic_packet_info_t
*quic_packet
= NULL
;
4556 quic_cid_t real_retry_odcid
= {.len
=0}, *retry_odcid
= NULL
;
4557 quic_cid_t first_packet_dcid
= {.len
=0}; /* DCID of the first packet of the datagram */
4559 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "QUIC");
4561 if (PINFO_FD_VISITED(pinfo
)) {
4562 dgram_info
= (quic_datagram
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_quic
, 0);
4565 dgram_info
= wmem_new0(wmem_file_scope(), quic_datagram
);
4566 p_add_proto_data(wmem_file_scope(), pinfo
, proto_quic
, 0, dgram_info
);
4569 quic_ti
= proto_tree_add_item(tree
, proto_quic
, tvb
, 0, -1, ENC_NA
);
4570 quic_tree
= proto_item_add_subtree(quic_ti
, ett_quic
);
4572 if (!PINFO_FD_VISITED(pinfo
)) {
4573 uint8_t long_packet_type
;
4575 quic_cid_t dcid
= {.len
=0}, scid
= {.len
=0};
4576 bool from_server
= false;
4577 quic_info_data_t
*conn
;
4579 quic_extract_header(tvb
, &long_packet_type
, &version
, &dcid
, &scid
);
4580 conn
= quic_connection_find(pinfo
, long_packet_type
, &dcid
, &from_server
);
4581 if (conn
&& long_packet_type
== QUIC_LPT_RETRY
&& conn
->client_dcid_set
) {
4582 // Save the original client DCID before erasure.
4583 real_retry_odcid
= conn
->client_dcid_initial
;
4584 retry_odcid
= &real_retry_odcid
;
4586 if (!conn
&& tvb_bytes_exist(tvb
, -16, 16) && (conn
= quic_find_stateless_reset_token(pinfo
, tvb
, &from_server
))) {
4587 dgram_info
->stateless_reset
= true;
4589 quic_connection_create_or_update(&conn
, pinfo
, long_packet_type
, version
, &scid
, &dcid
, from_server
);
4591 dgram_info
->conn
= conn
;
4592 dgram_info
->from_server
= from_server
;
4593 /* Senders MUST not coalesce packets with a different Connection ID
4594 * into the same datagram, so we can store the path ID here.
4596 if (conn
&& quic_multipath_negotiated(conn
) == QUIC_MP_NO_PATH_ID
) {
4597 dgram_info
->path_id
= dcid
.seq_num
;
4599 dgram_info
->path_id
= dcid
.path_id
;
4602 proto_tree_add_debug_text(quic_tree
, "Connection: %d %p DCID=%s SCID=%s from_server:%d", pinfo
->num
, dgram_info
->conn
, cid_to_string(pinfo
->pool
, &dcid
), cid_to_string(pinfo
->pool
, &scid
), dgram_info
->from_server
);
4604 proto_tree_add_debug_text(quic_tree
, "Connection: %d %p from_server:%d", pinfo
->num
, dgram_info
->conn
, dgram_info
->from_server
);
4608 quic_add_connection_info(tvb
, pinfo
, quic_tree
, dgram_info
->conn
);
4610 if (dgram_info
->stateless_reset
) {
4611 return dissect_quic_stateless_reset(tvb
, pinfo
, quic_tree
, dgram_info
);
4615 /* Ensure that coalesced QUIC packets end up separated. */
4617 quic_ti
= proto_tree_add_item(tree
, proto_quic
, tvb
, offset
, -1, ENC_NA
);
4618 quic_tree
= proto_item_add_subtree(quic_ti
, ett_quic
);
4621 if (!check_dcid_on_coalesced_packet(tvb
, dgram_info
, offset
, &first_packet_dcid
)) {
4622 /* Coalesced packet with unexpected CID; it probably is some kind
4623 of unencrypted padding data added after the valid QUIC payload */
4624 expert_add_info_format(pinfo
, quic_tree
, &ei_quic_coalesced_padding_data
,
4625 "(Random) padding data appended to the datagram");
4630 quic_packet
= &dgram_info
->first_packet
;
4631 } else if (!PINFO_FD_VISITED(pinfo
)) {
4632 quic_packet
->next
= wmem_new0(wmem_file_scope(), quic_packet_info_t
);
4633 quic_packet
= quic_packet
->next
;
4635 quic_packet
= quic_packet
->next
;
4636 DISSECTOR_ASSERT(quic_packet
);
4639 tvbuff_t
*next_tvb
= quic_get_message_tvb(tvb
, offset
, &first_packet_dcid
);
4641 proto_item_set_len(quic_ti
, tvb_reported_length(next_tvb
));
4642 ti
= proto_tree_add_uint(quic_tree
, hf_quic_packet_length
, next_tvb
, 0, 0, tvb_reported_length(next_tvb
));
4643 proto_item_set_generated(ti
);
4644 unsigned new_offset
= 0;
4645 uint8_t first_byte
= tvb_get_uint8(next_tvb
, 0);
4646 if (first_byte
& 0x80) {
4647 proto_tree_add_item(quic_tree
, hf_quic_header_form
, next_tvb
, 0, 1, ENC_NA
);
4648 uint32_t version
= tvb_get_ntohl(next_tvb
, 1);
4649 uint8_t long_packet_type
= quic_get_long_packet_type(first_byte
, version
);
4650 if ((version
& 0x0F0F0F0F) == 0x0a0a0a0a) {
4651 offset
+= dissect_quic_forcing_version_negotiation(next_tvb
, pinfo
, quic_tree
, quic_packet
);
4652 if (tvb_reported_length_remaining(tvb
, offset
)) {
4653 /* We can't decrypt any remaining data because we don't have a valid version */
4654 expert_add_info_format(pinfo
, quic_tree
, &ei_quic_data_after_forcing_vn
,
4655 "Data appended after a Forcing VN can't be decrypted");
4660 offset
+= dissect_quic_version_negotiation(next_tvb
, pinfo
, quic_tree
, quic_packet
);
4663 if (long_packet_type
== QUIC_LPT_RETRY
) {
4664 new_offset
= dissect_quic_retry_packet(next_tvb
, pinfo
, quic_tree
, dgram_info
, quic_packet
, retry_odcid
, version
);
4666 new_offset
= dissect_quic_long_header(next_tvb
, pinfo
, quic_tree
, dgram_info
, quic_packet
);
4668 } else { /* Note that the "Fixed" bit might have been greased,
4669 so 0x00 is a perfectly valid value as first_byte */
4670 new_offset
= dissect_quic_short_header(next_tvb
, pinfo
, quic_tree
, dgram_info
, quic_packet
);
4672 if (tvb_reported_length_remaining(next_tvb
, new_offset
)) {
4673 // should usually not be present unless decryption is not possible.
4674 proto_tree_add_item(quic_tree
, hf_quic_remaining_payload
, next_tvb
, new_offset
, -1, ENC_NA
);
4676 offset
+= tvb_reported_length(next_tvb
);
4677 } while (tvb_reported_length_remaining(tvb
, offset
));
4683 dissect_quic_short_header_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
4685 // If this capture does not contain QUIC, skip the more expensive checks.
4686 if (quic_cid_lengths
== 0) {
4690 // Is this a SH packet after connection migration? SH (since draft -22):
4691 // Flag (1) + DCID (1-20) + PKN (1/2/4) + encrypted payload (>= 16).
4692 if (tvb_captured_length(tvb
) < 1 + 1 + 1 + 16) {
4696 // DCID length is unknown, so extract the maximum and look for a match.
4697 quic_cid_t dcid
= {.len
= MIN(QUIC_MAX_CID_LENGTH
, tvb_captured_length(tvb
) - 1 - 1 - 16)};
4698 tvb_memcpy(tvb
, dcid
.cid
, 1, dcid
.len
);
4700 if (!quic_connection_find(pinfo
, QUIC_SHORT_PACKET
, &dcid
, &from_server
)) {
4704 conversation_t
*conversation
= find_or_create_conversation(pinfo
);
4705 conversation_set_dissector(conversation
, quic_handle
);
4706 dissect_quic(tvb
, pinfo
, tree
, NULL
);
4710 static bool dissect_quic_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
4714 * Flag (1 byte) + Version (4 bytes) +
4715 * Length (1 byte) + Destination Connection ID (0..255) +
4716 * Length (1 byte) + Source Connection ID (0..255) +
4717 * Payload length (1/2/4/8) + Packet number (1/2/4 bytes) + Payload.
4718 * (absolute minimum: 9 + payload)
4719 * (for Version Negotiation, payload len + PKN + payload is replaced by
4720 * Supported Version (multiple of 4 bytes.)
4722 conversation_t
*conversation
= NULL
;
4724 uint8_t flags
, dcid
, scid
;
4726 bool is_quic
= false;
4728 /* Verify packet size (Flag (1 byte) + Connection ID (8 bytes) + Version (4 bytes)) */
4729 if (tvb_captured_length(tvb
) < 13)
4734 flags
= tvb_get_uint8(tvb
, offset
);
4735 /* Check if long Packet is set */
4736 if((flags
& 0x80) == 0) {
4737 // Perhaps this is a short header, check it.
4738 return dissect_quic_short_header_heur(tvb
, pinfo
, tree
);
4742 // check for draft QUIC version (for draft -11 and newer)
4743 version
= tvb_get_ntohl(tvb
, offset
);
4744 is_quic
= (quic_draft_version(version
) >= 11);
4749 /* Check that CIDs lengths are valid */
4751 dcid
= tvb_get_uint8(tvb
, offset
);
4752 if (dcid
> QUIC_MAX_CID_LENGTH
) {
4756 if (offset
>= (int)tvb_captured_length(tvb
)) {
4759 scid
= tvb_get_uint8(tvb
, offset
);
4760 if (scid
> QUIC_MAX_CID_LENGTH
) {
4765 conversation
= find_or_create_conversation(pinfo
);
4766 conversation_set_dissector(conversation
, quic_handle
);
4767 dissect_quic(tvb
, pinfo
, tree
, data
);
4773 /** Initialize QUIC dissection state for a new capture file. */
4777 quic_connections
= wmem_list_new(wmem_file_scope());
4778 quic_connections_count
= 0;
4779 quic_initial_connections
= wmem_map_new(wmem_file_scope(), quic_connection_hash
, quic_connection_equal
);
4780 quic_client_connections
= wmem_map_new(wmem_file_scope(), quic_connection_hash
, quic_connection_equal
);
4781 quic_server_connections
= wmem_map_new(wmem_file_scope(), quic_connection_hash
, quic_connection_equal
);
4782 quic_cid_lengths
= 0;
4785 /** Release QUIC dissection state on closing a capture file. */
4789 wmem_list_foreach(quic_connections
, quic_connection_destroy
, NULL
);
4790 quic_initial_connections
= NULL
;
4791 quic_client_connections
= NULL
;
4792 quic_server_connections
= NULL
;
4795 /* Follow QUIC Stream functionality {{{ */
4797 quic_streams_add(packet_info
*pinfo
, quic_info_data_t
*quic_info
, uint64_t stream_id
)
4799 /* List: ordered list of Stream IDs in this connection */
4800 if (!quic_info
->streams_list
) {
4801 quic_info
->streams_list
= wmem_list_new(wmem_file_scope());
4803 if (!wmem_list_find(quic_info
->streams_list
, GUINT_TO_POINTER(stream_id
))) {
4804 wmem_list_insert_sorted(quic_info
->streams_list
, GUINT_TO_POINTER(stream_id
),
4808 /* Map: first Stream ID for each UDP payload */
4809 quic_follow_stream
*stream
;
4810 if (!quic_info
->streams_map
) {
4811 quic_info
->streams_map
= wmem_map_new(wmem_file_scope(), g_direct_hash
, g_direct_equal
);
4813 stream
= wmem_map_lookup(quic_info
->streams_map
, GUINT_TO_POINTER(pinfo
->num
));
4815 stream
= wmem_new0(wmem_file_scope(), quic_follow_stream
);
4816 stream
->num
= pinfo
->num
;
4817 stream
->stream_id
= stream_id
;
4818 wmem_map_insert(quic_info
->streams_map
, GUINT_TO_POINTER(stream
->num
), stream
);
4822 static quic_info_data_t
*
4823 get_conn_by_number(unsigned conn_number
)
4825 quic_info_data_t
*conn
;
4826 wmem_list_frame_t
*elem
;
4828 elem
= wmem_list_head(quic_connections
);
4830 conn
= (quic_info_data_t
*)wmem_list_frame_data(elem
);
4831 if (conn
->number
== conn_number
)
4833 elem
= wmem_list_frame_next(elem
);
4839 quic_get_stream_id_le(unsigned streamid
, unsigned sub_stream_id
, unsigned *sub_stream_id_out
)
4841 quic_info_data_t
*quic_info
;
4842 wmem_list_frame_t
*curr_entry
;
4843 unsigned prev_stream_id
;
4845 quic_info
= get_conn_by_number(streamid
);
4849 if (!quic_info
->streams_list
) {
4853 prev_stream_id
= UINT32_MAX
;
4854 curr_entry
= wmem_list_head(quic_info
->streams_list
);
4855 while (curr_entry
) {
4856 if (GPOINTER_TO_UINT(wmem_list_frame_data(curr_entry
)) > sub_stream_id
&&
4857 prev_stream_id
!= UINT32_MAX
) {
4858 *sub_stream_id_out
= (unsigned)prev_stream_id
;
4861 prev_stream_id
= GPOINTER_TO_UINT(wmem_list_frame_data(curr_entry
));
4862 curr_entry
= wmem_list_frame_next(curr_entry
);
4865 if (prev_stream_id
!= UINT32_MAX
) {
4866 *sub_stream_id_out
= prev_stream_id
;
4874 quic_get_stream_id_ge(unsigned streamid
, unsigned sub_stream_id
, unsigned *sub_stream_id_out
)
4876 quic_info_data_t
*quic_info
;
4877 wmem_list_frame_t
*curr_entry
;
4879 quic_info
= get_conn_by_number(streamid
);
4883 if (!quic_info
->streams_list
) {
4887 curr_entry
= wmem_list_head(quic_info
->streams_list
);
4888 while (curr_entry
) {
4889 if (GPOINTER_TO_UINT(wmem_list_frame_data(curr_entry
)) >= sub_stream_id
) {
4890 /* StreamIDs are 64 bits long in QUIC, but "Follow Stream" generic code uses unsigned variables */
4891 *sub_stream_id_out
= GPOINTER_TO_UINT(wmem_list_frame_data(curr_entry
));
4894 curr_entry
= wmem_list_frame_next(curr_entry
);
4901 quic_get_sub_stream_id(unsigned streamid
, unsigned sub_stream_id
, bool le
, unsigned *sub_stream_id_out
)
4904 return quic_get_stream_id_le(streamid
, sub_stream_id
, sub_stream_id_out
);
4906 return quic_get_stream_id_ge(streamid
, sub_stream_id
, sub_stream_id_out
);
4911 quic_follow_conv_filter(epan_dissect_t
*edt _U_
, packet_info
*pinfo
, unsigned *stream
, unsigned *sub_stream
)
4913 quic_datagram
*dgram_info
= (quic_datagram
*)p_get_proto_data(wmem_file_scope(), pinfo
, proto_quic
, 0);
4915 if (!dgram_info
|| !dgram_info
->conn
) {
4919 quic_info_data_t
*conn
= dgram_info
->conn
;
4921 /* First Stream ID in the selected packet */
4922 quic_follow_stream
*s
;
4923 if (conn
->streams_map
) {
4924 s
= wmem_map_lookup(conn
->streams_map
, GUINT_TO_POINTER(pinfo
->num
));
4926 *stream
= conn
->number
;
4927 *sub_stream
= (unsigned)s
->stream_id
;
4928 return ws_strdup_printf("quic.connection.number eq %u and quic.stream.stream_id eq %u", conn
->number
, *sub_stream
);
4936 quic_follow_index_filter(unsigned stream
, unsigned sub_stream
)
4938 return ws_strdup_printf("quic.connection.number eq %u and quic.stream.stream_id eq %u", stream
, sub_stream
);
4941 static tap_packet_status
4942 follow_quic_tap_listener(void *tapdata
, packet_info
*pinfo
, epan_dissect_t
*edt _U_
, const void *data
, tap_flags_t flags _U_
)
4944 follow_record_t
*follow_record
;
4945 follow_info_t
*follow_info
= (follow_info_t
*)tapdata
;
4946 const quic_follow_tap_data_t
*follow_data
= (const quic_follow_tap_data_t
*)data
;
4948 if (follow_info
->substream_id
!= SUBSTREAM_UNUSED
&&
4949 follow_info
->substream_id
!= follow_data
->stream_id
) {
4950 return TAP_PACKET_DONT_REDRAW
;
4953 follow_record
= g_new(follow_record_t
, 1);
4955 // XXX: Ideally, we should also deal with stream retransmission
4956 // and out of order packets in a similar manner to the TCP dissector,
4957 // using the offset, plus ACKs and other information.
4958 follow_record
->data
= g_byte_array_sized_new(tvb_captured_length(follow_data
->tvb
));
4959 follow_record
->data
= g_byte_array_append(follow_record
->data
, tvb_get_ptr(follow_data
->tvb
, 0, -1), tvb_captured_length(follow_data
->tvb
));
4960 follow_record
->packet_num
= pinfo
->fd
->num
;
4961 follow_record
->abs_ts
= pinfo
->fd
->abs_ts
;
4963 /* This sets the address and port information the first time this
4964 * stream is tapped. It will no longer be true after migration, but
4965 * as it seems it's only used for display, using the initial values
4966 * is the best we can do.
4969 if (follow_data
->from_server
) {
4970 follow_record
->is_server
= true;
4971 if (follow_info
->client_port
== 0) {
4972 follow_info
->server_port
= pinfo
->srcport
;
4973 copy_address(&follow_info
->server_ip
, &pinfo
->src
);
4974 follow_info
->client_port
= pinfo
->destport
;
4975 copy_address(&follow_info
->client_ip
, &pinfo
->dst
);
4978 follow_record
->is_server
= false;
4979 if (follow_info
->client_port
== 0) {
4980 follow_info
->client_port
= pinfo
->srcport
;
4981 copy_address(&follow_info
->client_ip
, &pinfo
->src
);
4982 follow_info
->server_port
= pinfo
->destport
;
4983 copy_address(&follow_info
->server_ip
, &pinfo
->dst
);
4987 follow_info
->bytes_written
[follow_record
->is_server
] += follow_record
->data
->len
;
4989 follow_info
->payload
= g_list_prepend(follow_info
->payload
, follow_record
);
4990 return TAP_PACKET_DONT_REDRAW
;
4993 uint32_t get_quic_connections_count(void)
4995 return quic_connections_count
;
4997 /* Follow QUIC Stream functionality }}} */
5000 proto_register_quic(void)
5002 expert_module_t
*expert_quic
;
5003 module_t
*quic_module
;
5005 static hf_register_info hf
[] = {
5006 { &hf_quic_connection_number
,
5007 { "Connection Number", "quic.connection.number",
5008 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
5009 "Connection identifier within this capture file", HFILL
}
5012 { &hf_quic_packet_length
,
5013 { "Packet Length", "quic.packet_length",
5014 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
5015 "Size of the QUIC packet", HFILL
}
5018 { &hf_quic_header_form
,
5019 { "Header Form", "quic.header_form",
5020 FT_UINT8
, BASE_DEC
, VALS(quic_short_long_header_vals
), 0x80,
5021 "The most significant bit (0x80) of the first octet is set to 1 for long headers and 0 for short headers.", HFILL
}
5024 { &hf_quic_long_packet_type
,
5025 { "Packet Type", "quic.long.packet_type",
5026 FT_UINT8
, BASE_DEC
, VALS(quic_v1_long_packet_type_vals
), 0x30,
5027 "Long Header Packet Type", HFILL
}
5029 { &hf_quic_long_packet_type_v2
,
5030 { "Packet Type", "quic.long.packet_type_v2",
5031 FT_UINT8
, BASE_DEC
, VALS(quic_v2_long_packet_type_vals
), 0x30,
5032 "Long Header Packet Type", HFILL
}
5034 { &hf_quic_long_reserved
,
5035 { "Reserved", "quic.long.reserved",
5036 FT_UINT8
, BASE_DEC
, NULL
, 0x0c,
5037 "Reserved bits (protected using header protection)", HFILL
}
5039 { &hf_quic_packet_number_length
,
5040 { "Packet Number Length", "quic.packet_number_length",
5041 FT_UINT8
, BASE_DEC
, VALS(quic_packet_number_lengths
), 0x03,
5042 "Packet Number field length (protected using header protection)", HFILL
}
5045 { "Destination Connection ID", "quic.dcid",
5046 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
5050 { "Source Connection ID", "quic.scid",
5051 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
5055 { "Destination Connection ID Length", "quic.dcil",
5056 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
5060 { "Source Connection ID Length", "quic.scil",
5061 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
5064 { &hf_quic_token_length
,
5065 { "Token Length", "quic.token_length",
5066 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5070 { "Token", "quic.token",
5071 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
5075 { "Length", "quic.length",
5076 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5077 "Length of Packet Number and Payload fields", HFILL
}
5080 { &hf_quic_packet_number
,
5081 { "Packet Number", "quic.packet_number",
5082 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5083 "Decoded packet number", HFILL
}
5086 { "Version", "quic.version",
5087 FT_UINT32
, BASE_RANGE_STRING
| BASE_HEX
, RVALS(quic_version_vals
), 0x0,
5090 { &hf_quic_supported_version
,
5091 { "Supported Version", "quic.supported_version",
5092 FT_UINT32
, BASE_RANGE_STRING
| BASE_HEX
, RVALS(quic_version_vals
), 0x0,
5095 { &hf_quic_vn_unused
,
5096 { "Unused", "quic.vn.unused",
5097 FT_UINT8
, BASE_HEX
, NULL
, 0x7F,
5101 { "QUIC Short Header", "quic.short",
5102 FT_NONE
, BASE_NONE
, NULL
, 0x0,
5105 { &hf_quic_fixed_bit
,
5106 { "Fixed Bit", "quic.fixed_bit",
5107 FT_BOOLEAN
, 8, NULL
, 0x40,
5108 "Must be 1", HFILL
}
5110 { &hf_quic_spin_bit
,
5111 { "Spin Bit", "quic.spin_bit",
5112 FT_BOOLEAN
, 8, NULL
, 0x20,
5113 "Latency Spin Bit", HFILL
}
5117 { &hf_quic_mp_pnci_path_identifier
,
5118 { "Path identifier", "quic.mp_pnci_path_identifier",
5119 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5122 { &hf_quic_mp_rc_path_identifier
,
5123 { "Path identifier", "quic.mp_rc_path_identifier",
5124 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5127 { &hf_quic_mp_path_ack_path_identifier
,
5128 { "Path Identifier", "quic.mp_path_ack_path_identifier",
5129 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5132 { &hf_quic_mp_pa_path_identifier
,
5133 { "Path Identifier", "quic.mp_pa_path_identifier",
5134 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5137 { &hf_quic_mp_pa_error_code
,
5138 { "Error Code", "quic.mp_pa_error_code",
5139 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5142 { &hf_quic_mp_ps_path_identifier
,
5143 { "Path Identifier", "quic.mp_ps_path_identifier",
5144 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5147 { &hf_quic_mp_ps_path_status_sequence_number
,
5148 { "Path Status Sequence Number", "quic.mp_ps_path_status_sequence_number",
5149 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5152 { &hf_quic_mp_ps_path_status
,
5153 { "Path Status", "quic.mp_ps_path_status",
5154 FT_UINT64
, BASE_DEC
| BASE_VAL64_STRING
, VALS64(quic_mp_path_status
), 0x0,
5157 { &hf_quic_mp_maximum_paths
,
5158 { "Maximum Paths", "quic.mp_maximum_paths",
5159 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5162 { &hf_quic_mp_maximum_path_identifier
,
5163 { "Maximum Path identifier", "quic.mp_maximum_path_id",
5164 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5168 { &hf_quic_short_reserved
,
5169 { "Reserved", "quic.short.reserved",
5170 FT_UINT8
, BASE_DEC
, NULL
, 0x18,
5171 "Reserved bits (protected using header protection)", HFILL
}
5174 { "Square Signal Bit (Q)", "quic.q_bit",
5175 FT_BOOLEAN
, 8, NULL
, 0x10,
5176 "Square Signal Bit (used to measure and locate the source of packet loss)", HFILL
}
5179 { "Loss Event Bit (L)", "quic.l_bit",
5180 FT_BOOLEAN
, 8, NULL
, 0x08,
5181 "Loss Event Bit (used to measure and locate the source of packet loss)", HFILL
}
5183 { &hf_quic_key_phase
,
5184 { "Key Phase Bit", "quic.key_phase",
5185 FT_BOOLEAN
, 8, NULL
, SH_KP
,
5186 "Selects the packet protection keys to use (protected using header protection)", HFILL
}
5190 { "Payload", "quic.payload",
5191 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
5192 "(Encrypted) payload of a packet", HFILL
}
5194 { &hf_quic_protected_payload
,
5195 { "Protected Payload", "quic.protected_payload",
5196 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
5197 "1-RTT protected payload", HFILL
}
5199 { &hf_quic_remaining_payload
,
5200 { "Remaining Payload", "quic.remaining_payload",
5201 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
5202 "Remaining payload in a packet (possibly PKN followed by encrypted payload)", HFILL
}
5206 { "Original Destination Connection ID Length", "quic.odcil",
5207 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
5211 { "Original Destination Connection ID", "quic.odcid",
5212 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
5215 { &hf_quic_retry_token
,
5216 { "Retry Token", "quic.retry_token",
5217 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
5220 { &hf_quic_retry_integrity_tag
,
5221 { "Retry Integrity Tag", "quic.retry_integrity_tag",
5222 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
5227 { "Frame", "quic.frame",
5228 FT_NONE
, BASE_NONE
, NULL
, 0x0,
5231 { &hf_quic_frame_type
,
5232 { "Frame Type", "quic.frame_type",
5233 FT_UINT64
, BASE_RANGE_STRING
| BASE_HEX
, RVALS(quic_frame_type_vals
), 0x0,
5238 { &hf_quic_padding_length
,
5239 { "Padding Length", "quic.padding_length",
5240 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
5244 { &hf_quic_ack_largest_acknowledged
,
5245 { "Largest Acknowledged", "quic.ack.largest_acknowledged",
5246 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5247 "Largest packet number the peer is acknowledging in this packet", HFILL
}
5249 { &hf_quic_ack_ack_delay
,
5250 { "ACK Delay", "quic.ack.ack_delay",
5251 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5252 "Time from when the largest acknowledged packet, as indicated in the Largest Acknowledged field, was received by this peer to when this ACK was sent", HFILL
}
5254 { &hf_quic_ack_ack_range_count
,
5255 { "ACK Range Count", "quic.ack.ack_range_count",
5256 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5257 "Number of Gap and ACK Range fields in the frame", HFILL
}
5259 { &hf_quic_ack_first_ack_range
,
5260 { "First ACK Range", "quic.ack.first_ack_range",
5261 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5262 "Number of contiguous packets preceding the Largest Acknowledged that are being acknowledged", HFILL
}
5265 { "Gap", "quic.ack.gap",
5266 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5267 "Number of contiguous unacknowledged packets preceding the packet number one lower than the smallest in the preceding ACK Range", HFILL
}
5269 { &hf_quic_ack_ack_range
,
5270 { "ACK Range", "quic.ack.ack_range",
5271 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5272 "Number of contiguous acknowledged packets preceding the largest packet number, as determined by the preceding Gap", HFILL
}
5274 { &hf_quic_ack_ect0_count
,
5275 { "ECT(0) Count", "quic.ack.ect0_count",
5276 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5277 "Total number of packets received with the ECT(0) codepoint", HFILL
}
5279 { &hf_quic_ack_ect1_count
,
5280 { "ECT(1) Count", "quic.ack.ect1_count",
5281 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5282 "Total number of packets received with the ECT(1) codepoint", HFILL
}
5284 { &hf_quic_ack_ecn_ce_count
,
5285 { "ECN-CE Count", "quic.ack.ecn_ce_count",
5286 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5287 "Total number of packets received with the CE codepoint", HFILL
}
5290 { &hf_quic_rsts_stream_id
,
5291 { "Stream ID", "quic.rsts.stream_id",
5292 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5293 "Stream ID of the stream being terminated", HFILL
}
5295 { &hf_quic_rsts_application_error_code
,
5296 { "Application Error code", "quic.rsts.application_error_code",
5297 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5298 "Indicates why the stream is being closed", HFILL
}
5300 { &hf_quic_rsts_final_size
,
5301 { "Final Size", "quic.rsts.final_size",
5302 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5303 "The final size of the stream by the RESET_STREAM sender (in bytes)", HFILL
}
5306 { &hf_quic_ss_stream_id
,
5307 { "Stream ID", "quic.ss.stream_id",
5308 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5309 "Stream ID of the stream being ignored", HFILL
}
5311 { &hf_quic_ss_application_error_code
,
5312 { "Application Error code", "quic.ss.application_error_code",
5313 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5314 "Indicates why the sender is ignoring the stream", HFILL
}
5317 { &hf_quic_crypto_offset
,
5318 { "Offset", "quic.crypto.offset",
5319 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5320 "Byte offset into the stream", HFILL
}
5322 { &hf_quic_crypto_length
,
5323 { "Length", "quic.crypto.length",
5324 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5325 "Length of the Crypto Data field", HFILL
}
5327 { &hf_quic_crypto_crypto_data
,
5328 { "Crypto Data", "quic.crypto.crypto_data",
5329 FT_NONE
, BASE_NONE
, NULL
, 0x0,
5330 "The cryptographic message data", HFILL
}
5333 { &hf_quic_nt_length
,
5334 { "(Token) Length", "quic.nt.length",
5335 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5336 "Specifying the length of the token", HFILL
}
5338 { &hf_quic_nt_token
,
5339 { "Token", "quic.nt.token",
5340 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
5341 "An opaque blob that the client may use with a future Initial packet", HFILL
}
5344 { &hf_quic_stream_fin
,
5345 { "Fin", "quic.stream.fin",
5346 FT_BOOLEAN
, 8, NULL
, FTFLAGS_STREAM_FIN
,
5349 { &hf_quic_stream_len
,
5350 { "Len(gth)", "quic.stream.len",
5351 FT_BOOLEAN
, 8, NULL
, FTFLAGS_STREAM_LEN
,
5354 { &hf_quic_stream_off
,
5355 { "Off(set)", "quic.stream.off",
5356 FT_BOOLEAN
, 8, NULL
, FTFLAGS_STREAM_OFF
,
5359 { &hf_quic_stream_stream_id
,
5360 { "Stream ID", "quic.stream.stream_id",
5361 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5364 { &hf_quic_stream_initiator
,
5365 { "Stream initiator", "quic.stream.initiator",
5366 FT_UINT64
, BASE_DEC
| BASE_VAL64_STRING
, VALS64(quic_frame_id_initiator
), FTFLAGS_STREAM_INITIATOR
,
5369 { &hf_quic_stream_direction
,
5370 { "Stream direction", "quic.stream.direction",
5371 FT_UINT64
, BASE_DEC
| BASE_VAL64_STRING
, VALS64(quic_frame_id_direction
), FTFLAGS_STREAM_DIRECTION
,
5374 { &hf_quic_stream_offset
,
5375 { "Offset", "quic.stream.offset",
5376 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5379 { &hf_quic_stream_length
,
5380 { "Length", "quic.stream.length",
5381 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5384 { &hf_quic_stream_data
,
5385 { "Stream Data", "quic.stream_data",
5386 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
5391 { &hf_quic_md_maximum_data
,
5392 { "Maximum Data", "quic.md.maximum_data",
5393 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5394 "Indicating the maximum amount of data that can be sent on the entire connection, in units of 1024 octets", HFILL
}
5396 /* MAX_STREAM_DATA */
5397 { &hf_quic_msd_stream_id
,
5398 { "Stream ID", "quic.msd.stream_id",
5399 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5400 "The stream ID of the stream that is affected", HFILL
}
5402 { &hf_quic_msd_maximum_stream_data
,
5403 { "Maximum Stream Data", "quic.msd.maximum_stream_data",
5404 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5405 "Indicating the maximum amount of data that can be sent on the identified stream, in units of octets", HFILL
}
5408 { &hf_quic_ms_max_streams
,
5409 { "Max Streams", "quic.ms.max_streams",
5410 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5411 "A count of the cumulative number of streams of the corresponding type that can be opened over the lifetime of the connection", HFILL
}
5414 { &hf_quic_db_stream_data_limit
,
5415 { "Stream Data Limit", "quic.sb.stream_data_limit",
5416 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5417 "Indicating the connection-level limit at which the blocking occurred", HFILL
}
5419 /* STREAM_DATA_BLOCKED */
5420 { &hf_quic_sdb_stream_id
,
5421 { "Stream ID", "quic.sdb.stream_id",
5422 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5423 "Indicating the stream which is flow control blocked", HFILL
}
5425 { &hf_quic_sdb_stream_data_limit
,
5426 { "Stream Data Limit", "quic.sb.stream_data_limit",
5427 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5428 "Indicating the offset of the stream at which the blocking occurred", HFILL
}
5430 /* STREAMS_BLOCKED */
5431 { &hf_quic_sb_stream_limit
,
5432 { "Stream Limit", "quic.sib.stream_limit",
5433 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5434 "Indicating the stream limit at the time the frame was sent", HFILL
}
5436 /* NEW_CONNECTION_ID */
5437 { &hf_quic_nci_retire_prior_to
,
5438 { "Retire Prior To", "quic.nci.retire_prior_to",
5439 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5440 "A variable-length integer indicating which connection IDs should be retired", HFILL
}
5442 { &hf_quic_nci_sequence
,
5443 { "Sequence", "quic.nci.sequence",
5444 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5445 "Increases by 1 for each connection ID that is provided by the server", HFILL
}
5447 { &hf_quic_nci_connection_id_length
,
5448 { "Connection ID Length", "quic.nci.connection_id.length",
5449 FT_UINT8
, BASE_DEC
, NULL
, 0x0,
5452 { &hf_quic_nci_connection_id
,
5453 { "Connection ID", "quic.nci.connection_id",
5454 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
5457 { &hf_quic_nci_stateless_reset_token
,
5458 { "Stateless Reset Token", "quic.nci.stateless_reset_token",
5459 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
5462 /* RETIRE_CONNECTION_ID */
5463 { &hf_quic_rci_sequence
,
5464 { "Sequence", "quic.rci.sequence",
5465 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5466 "The sequence number of the connection ID being retired", HFILL
}
5468 /* PATH_CHALLENGE */
5469 { &hf_quic_path_challenge_data
,
5470 { "Data", "quic.path_challenge.data",
5471 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
5472 "Arbitrary data that must be matched by a PATH_RESPONSE frame", HFILL
}
5475 { &hf_quic_path_response_data
,
5476 { "Data", "quic.path_response.data",
5477 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
5478 "Arbitrary data that must match a PATH_CHALLENGE frame", HFILL
}
5480 /* CONNECTION_CLOSE */
5481 { &hf_quic_cc_error_code
,
5482 { "Error code", "quic.cc.error_code",
5483 FT_UINT64
, BASE_DEC
|BASE_RANGE_STRING
, RVALS(quic_transport_error_code_vals
), 0x0,
5484 "Indicates the reason for closing this connection", HFILL
}
5486 { &hf_quic_cc_error_code_app
,
5487 { "Application Error code", "quic.cc.error_code.app",
5488 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5489 "Indicates the reason for closing this application", HFILL
}
5491 { &hf_quic_cc_error_code_tls_alert
,
5492 { "TLS Alert Description", "quic.cc.error_code.tls_alert",
5493 FT_UINT8
, BASE_DEC
, VALS(ssl_31_alert_description
), 0x0,
5496 { &hf_quic_cc_frame_type
,
5497 { "Frame Type", "quic.cc.frame_type",
5498 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5499 "The type of frame that triggered the error", HFILL
}
5501 { &hf_quic_cc_reason_phrase_length
,
5502 { "Reason phrase Length", "quic.cc.reason_phrase.length",
5503 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5504 "Specifying the length of the reason phrase", HFILL
}
5506 { &hf_quic_cc_reason_phrase
,
5507 { "Reason phrase", "quic.cc.reason_phrase",
5508 FT_STRING
, BASE_NONE
, NULL
, 0x0,
5509 "A human-readable explanation for why the connection was closed", HFILL
}
5512 { &hf_quic_dg_length
,
5513 { "Datagram Length", "quic.dg.length",
5514 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5515 "Specifies the length of the datagram data in bytes", HFILL
}
5518 { "Datagram", "quic.dg",
5519 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
5520 "The bytes of the datagram to be delivered", HFILL
}
5523 { &hf_quic_af_sequence_number
,
5524 { "Sequence Number", "quic.af.sequence_number",
5525 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5526 "Sequence number assigned to the ACK_FREQUENCY frame by the sender to allow receivers to ignore obsolete frames", HFILL
}
5528 { &hf_quic_af_ack_eliciting_threshold
,
5529 { "Ack-Eliciting Threshold", "quic.af.ack_eliciting_threshold",
5530 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5531 "The maximum number of ack-eliciting packets the recipient of this frame can receive without sending an acknowledgment", HFILL
}
5533 { &hf_quic_af_request_max_ack_delay
,
5534 { "Request Max Ack Delay", "quic.af.request_max_ack_delay",
5535 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5536 "The value to which the endpoint requests the peer update its max_ack_delay", HFILL
}
5538 { &hf_quic_af_reordering_threshold
,
5539 { "Reordering Threshold", "quic.af.reordering_threshold",
5540 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5541 "The value that indicates the maximum packet reordering before eliciting an immediate ACK", HFILL
}
5543 //{ &hf_quic_af_ignore_order,
5544 // { "Ignore Order", "quic.af.ignore_order",
5545 // FT_BOOLEAN, 8, NULL, 0x02,
5546 // "This field is set to true by an endpoint that does not wish to receive an immediate acknowledgement when the peer receives a packet out of order", HFILL }
5548 //{ &hf_quic_af_ignore_ce,
5549 // { "Ignore CE", "quic.af.ignore_ce",
5550 // FT_BOOLEAN, 8, NULL, 0x01,
5551 // "This field is set to true by an endpoint that does not wish to receive an immediate acknowledgement when the peer receives CE-marked packets", HFILL }
5556 { "Time Stamp", "quic.ts",
5557 FT_UINT64
, BASE_DEC
, NULL
, 0x0,
5561 /* STATELESS RESET */
5562 { &hf_quic_unpredictable_bits
,
5563 { "Unpredictable Bits", "quic.unpredictable_bits",
5564 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
5565 "Bytes indistinguishable from random",
5568 { &hf_quic_stateless_reset_token
,
5569 { "Stateless Reset Token", "quic.stateless_reset_token",
5570 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
5574 /* Fields for QUIC Stream data reassembly. */
5575 { &hf_quic_fragment_overlap
,
5576 { "Fragment overlap", "quic.fragment.overlap",
5577 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
5578 "Fragment overlaps with other fragments", HFILL
}
5580 { &hf_quic_fragment_overlap_conflict
,
5581 { "Conflicting data in fragment overlap", "quic.fragment.overlap.conflict",
5582 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
5583 "Overlapping fragments contained conflicting data", HFILL
}
5585 { &hf_quic_fragment_multiple_tails
,
5586 { "Multiple tail fragments found", "quic.fragment.multipletails",
5587 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
5588 "Several tails were found when reassembling the pdu", HFILL
}
5590 { &hf_quic_fragment_too_long_fragment
,
5591 { "Fragment too long", "quic.fragment.toolongfragment",
5592 FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
5593 "Fragment contained data past end of the pdu", HFILL
}
5595 { &hf_quic_fragment_error
,
5596 { "Reassembling error", "quic.fragment.error",
5597 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
5598 "Reassembling error due to illegal fragments", HFILL
}
5600 { &hf_quic_fragment_count
,
5601 { "Fragment count", "quic.fragment.count",
5602 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
5605 { &hf_quic_fragment
,
5606 { "QUIC STREAM Data Fragment", "quic.fragment",
5607 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
5610 { &hf_quic_fragments
,
5611 { "Reassembled QUIC STREAM Data Fragments", "quic.fragments",
5612 FT_NONE
, BASE_NONE
, NULL
, 0x0,
5615 { &hf_quic_reassembled_in
,
5616 { "Reassembled PDU in frame", "quic.reassembled_in",
5617 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
5618 "The PDU that doesn't end in this fragment is reassembled in this frame", HFILL
}
5620 { &hf_quic_reassembled_length
,
5621 { "Reassembled QUIC STREAM Data length", "quic.reassembled.length",
5622 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
5623 "The total length of the reassembled payload", HFILL
}
5625 { &hf_quic_reassembled_data
,
5626 { "Reassembled QUIC STREAM Data", "quic.reassembled.data",
5627 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
5628 "The reassembled payload", HFILL
}
5630 { &hf_quic_crypto_fragment_count
,
5631 { "Fragment count", "quic.crypto.fragment.count",
5632 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
5635 { &hf_quic_crypto_fragment
,
5636 { "QUIC CRYPTO Data Fragment", "quic.crypto.fragment",
5637 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
5640 { &hf_quic_crypto_fragments
,
5641 { "Reassembled QUIC CRYPTO Data Fragments", "quic.crypto.fragments",
5642 FT_NONE
, BASE_NONE
, NULL
, 0x0,
5643 "QUIC STREAM Data Fragments", HFILL
}
5645 { &hf_quic_crypto_reassembled_in
,
5646 { "Reassembled PDU in frame", "quic.crypto.reassembled_in",
5647 FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
5648 "The PDU that doesn't end in this fragment is reassembled in this frame", HFILL
}
5652 static int *ett
[] = {
5655 &ett_quic_short_header
,
5656 &ett_quic_connection_info
,
5660 &ett_quic_fragments
,
5662 &ett_quic_crypto_fragments
,
5663 &ett_quic_crypto_fragment
,
5666 static ei_register_info ei
[] = {
5667 { &ei_quic_connection_unknown
,
5668 { "quic.connection.unknown", PI_PROTOCOL
, PI_NOTE
,
5669 "Unknown QUIC connection. Missing Initial Packet or migrated connection?", EXPFILL
}
5671 { &ei_quic_ft_unknown
,
5672 { "quic.ft.unknown", PI_UNDECODED
, PI_NOTE
,
5673 "Unknown Frame Type", EXPFILL
}
5675 { &ei_quic_decryption_failed
,
5676 { "quic.decryption_failed", PI_DECRYPTION
, PI_WARN
,
5677 "Failed to decrypt handshake", EXPFILL
}
5679 { &ei_quic_protocol_violation
,
5680 { "quic.protocol_violation", PI_PROTOCOL
, PI_WARN
,
5681 "Invalid data according to the protocol", EXPFILL
}
5683 { &ei_quic_bad_retry
,
5684 { "quic.bad_retry", PI_PROTOCOL
, PI_WARN
,
5685 "Retry Integrity Tag verification failure", EXPFILL
}
5687 { &ei_quic_coalesced_padding_data
,
5688 { "quic.coalesced_padding_data", PI_PROTOCOL
, PI_NOTE
,
5689 "Coalesced Padding Data", EXPFILL
}
5691 { &ei_quic_retransmission
,
5692 { "quic.retransmission", PI_SEQUENCE
, PI_NOTE
,
5693 "This QUIC frame has a reused stream offset (retransmission?)", EXPFILL
}
5696 { "quic.overlap", PI_SEQUENCE
, PI_NOTE
,
5697 "This QUIC frame overlaps a previous frame in the stream", EXPFILL
}
5699 { &ei_quic_data_after_forcing_vn
,
5700 { "quic.data_after_forcing_vn", PI_PROTOCOL
, PI_NOTE
,
5701 "Unexpected data on a Forcing Version Negotiation packet", EXPFILL
}
5705 proto_quic
= proto_register_protocol("QUIC IETF", "QUIC", "quic");
5707 proto_register_field_array(proto_quic
, hf
, array_length(hf
));
5708 proto_register_subtree_array(ett
, array_length(ett
));
5710 expert_quic
= expert_register_protocol(proto_quic
);
5711 expert_register_field_array(expert_quic
, ei
, array_length(ei
));
5713 quic_module
= prefs_register_protocol(proto_quic
, NULL
);
5714 prefs_register_bool_preference(quic_module
, "reassemble_crypto_out_of_order",
5715 "Reassemble out-of-order CRYPTO frames",
5716 "Whether out-of-order CRYPTO frames should be buffered and reordered before "
5717 "passing them to the TLS handshake dissector.",
5718 &quic_crypto_out_of_order
);
5720 prefs_register_uint_preference(quic_module
, "gso_heur_min_dcid_len",
5721 "Search for coalesced short header packets at DCID length",
5722 "Heuristically search for coalesced QUIC packets with a short header "
5723 "(e.g., when Generic Segmentation Offload (GSO) or similar is used), "
5724 "if the DCID is at least this many bytes long (0 to disable). ",
5725 10, &quic_gso_heur_dcid_len
);
5727 quic_handle
= register_dissector("quic", dissect_quic
, proto_quic
);
5729 register_init_routine(quic_init
);
5730 register_cleanup_routine(quic_cleanup
);
5732 register_follow_stream(proto_quic
, "quic_follow", quic_follow_conv_filter
, quic_follow_index_filter
, udp_follow_address_filter
,
5733 udp_port_to_display
, follow_quic_tap_listener
, get_quic_connections_count
,
5734 quic_get_sub_stream_id
);
5736 // TODO implement custom reassembly functions that uses the QUIC Connection
5737 // ID instead of address and port numbers.
5738 reassembly_table_register(&quic_reassembly_table
,
5739 &addresses_ports_reassembly_table_functions
);
5741 reassembly_table_register(&quic_crypto_reassembly_table
,
5742 &tcp_reassembly_table_functions
);
5745 * Application protocol. QUIC with TLS uses ALPN.
5746 * https://tools.ietf.org/html/draft-ietf-quic-transport-23#section-7
5747 * This could in theory be an arbitrary octet string with embedded NUL
5748 * bytes, but in practice these do not exist yet.
5750 quic_proto_dissector_table
= register_dissector_table("quic.proto", "QUIC Protocol", proto_quic
, FT_STRING
, STRING_CASE_SENSITIVE
);
5752 quic_follow_tap
= register_tap("quic_follow");
5756 proto_reg_handoff_quic(void)
5758 tls13_handshake_handle
= find_dissector("tls13-handshake");
5759 dissector_add_uint_with_preference("udp.port", 0, quic_handle
);
5760 heur_dissector_add("udp", dissect_quic_heur
, "QUIC", "quic", proto_quic
, HEURISTIC_ENABLE
);
5764 quic_conn_data_get_conn_client_dcid_initial(struct _packet_info
*pinfo
, quic_cid_t
*dcid
)
5766 if (pinfo
== NULL
|| dcid
== NULL
) {
5770 quic_info_data_t
* conn
= quic_connection_from_conv(pinfo
);
5775 dcid
->len
= conn
->client_dcid_initial
.len
;
5776 memset(dcid
->cid
, 0, QUIC_MAX_CID_LENGTH
);
5777 memcpy(dcid
->cid
, conn
->client_dcid_initial
.cid
, dcid
->len
);
5783 * Editor modelines - https://www.wireshark.org/tools/modelines.html
5788 * indent-tabs-mode: nil
5791 * vi: set shiftwidth=4 tabstop=8 expandtab:
5792 * :indentSize=4:tabSize=8:noTabs=true: