epan/dissectors/pidl/samr/samr.cnf cnf_dissect_lsa_BinaryString => lsarpc_dissect_str...
[wireshark-sm.git] / epan / dissectors / packet-quic.c
blob325fc69c01c64b68e5ad3d2cf17856293b7fed80
1 /* packet-quic.c
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
22 * Extension:
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-10 (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
41 * Limitations:
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
49 #include <config.h>
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>
64 #include <epan/tap.h>
65 #include <epan/follow.h>
66 #include <epan/addr_resolv.h>
68 /* Prototypes */
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;
191 /* multipath*/
192 static int hf_quic_mp_nci_path_identifier;
193 static int hf_quic_mp_rc_path_identifier;
194 static int hf_quic_mp_ack_path_identifier;
195 static int hf_quic_mp_pa_path_identifier;
196 static int hf_quic_mp_ps_path_identifier;
197 static int hf_quic_mp_ps_path_status_sequence_number;
198 static int hf_quic_mp_ps_path_status;
199 static int hf_quic_mp_maximum_paths;
200 static int hf_quic_mp_maximum_path_identifier;
202 static expert_field ei_quic_connection_unknown;
203 static expert_field ei_quic_ft_unknown;
204 static expert_field ei_quic_decryption_failed;
205 static expert_field ei_quic_protocol_violation;
206 static expert_field ei_quic_bad_retry;
207 static expert_field ei_quic_coalesced_padding_data;
208 static expert_field ei_quic_retransmission;
209 static expert_field ei_quic_overlap;
210 static expert_field ei_quic_data_after_forcing_vn;
212 static int ett_quic;
213 static int ett_quic_af;
214 static int ett_quic_short_header;
215 static int ett_quic_connection_info;
216 static int ett_quic_ft;
217 static int ett_quic_ftflags;
218 static int ett_quic_ftid;
219 static int ett_quic_fragments;
220 static int ett_quic_fragment;
221 static int ett_quic_crypto_fragments;
222 static int ett_quic_crypto_fragment;
224 static dissector_handle_t quic_handle;
225 static dissector_handle_t tls13_handshake_handle;
227 static dissector_table_t quic_proto_dissector_table;
229 /* Fields for showing reassembly results for fragments of QUIC stream data. */
230 static const fragment_items quic_stream_fragment_items = {
231 &ett_quic_fragment,
232 &ett_quic_fragments,
233 &hf_quic_fragments,
234 &hf_quic_fragment,
235 &hf_quic_fragment_overlap,
236 &hf_quic_fragment_overlap_conflict,
237 &hf_quic_fragment_multiple_tails,
238 &hf_quic_fragment_too_long_fragment,
239 &hf_quic_fragment_error,
240 &hf_quic_fragment_count,
241 &hf_quic_reassembled_in,
242 &hf_quic_reassembled_length,
243 &hf_quic_reassembled_data,
244 "Fragments"
247 /* Fields for showing reassembly results for fragments of QUIC crypto packets. */
248 static const fragment_items quic_crypto_fragment_items = {
249 &ett_quic_crypto_fragment,
250 &ett_quic_crypto_fragments,
251 &hf_quic_crypto_fragments,
252 &hf_quic_crypto_fragment,
253 &hf_quic_fragment_overlap, /* We can reuse the error fields. */
254 &hf_quic_fragment_overlap_conflict,
255 &hf_quic_fragment_multiple_tails,
256 &hf_quic_fragment_too_long_fragment,
257 &hf_quic_fragment_error,
258 &hf_quic_crypto_fragment_count,
259 &hf_quic_crypto_reassembled_in,
260 NULL, /* length, redundant */
261 NULL, /* data, redundant */
262 "Fragments"
266 * PROTECTED PAYLOAD DECRYPTION (done in first pass)
268 * Long packet types always use a single cipher depending on packet type.
269 * Short packet types always use 1-RTT secrets for packet protection (pp).
271 * Considerations:
272 * - QUIC packets might appear out-of-order (short packets before handshake
273 * message is captured), lost or retransmitted/duplicated.
274 * - During live capture, keys might not be immediately be available. 1-RTT
275 * client keys will be ready while client processes Server Hello (Handshake).
276 * 1-RTT server keys will be ready while server creates Handshake message in
277 * response to Initial Handshake.
278 * - So delay cipher creation until first short packet is received.
280 * Required input from TLS dissector: TLS-Exporter 0-RTT/1-RTT secrets and
281 * cipher/hash algorithms.
283 * QUIC payload decryption requires proper reconstruction of the packet number
284 * which requires proper header decryption. The different states are:
286 * Packet type Packet number space Secrets
287 * Long: Initial Initial Initial secrets
288 * Long: Handshake Handshake Handshake
289 * Long: 0-RTT 0/1-RTT (appdata) 0-RTT
290 * Short header 0/1-RTT (appdata) 1-RTT (KP0 / KP1)
292 * Important to note is that Short Header decryption requires TWO ciphers (one
293 * for each key phase), but that header protection uses only KP0. Total state
294 * needed for each peer (client and server):
295 * - 3 packet number spaces: Initial, Handshake, 0/1-RTT (appdata).
296 * - 4 header protection ciphers: initial, 0-RTT, HS, 1-RTT.
297 * - 5 payload protection ciphers: initial, 0-RTT, HS, 1-RTT (KP0), 1-RTT (KP1).
299 * The multipath draft features introduces separate appdata number spaces for
300 * each Path ID. (prior to draft-07, for each Destination Connection ID.)
303 /* Loss bits feature: https://tools.ietf.org/html/draft-ferrieuxhamchaoui-quic-lossbits-03
304 "The use of the loss bits is negotiated using a transport parameter.
305 [..]
306 When loss_bits parameter is present, the peer is allowed to use
307 reserved bits in the short packet header as loss bits if the peer
308 sends loss_bits=1.
309 When loss_bits is set to 1, the sender will use reserved bits as loss
310 bits if the peer includes the loss_bits transport parameter.
311 [..]
312 Unlike the reserved (R) bits, the loss (Q and L) bits are not
313 protected. When sending loss bits has been negotiated, the first
314 byte of the header protection mask used to protect short packet
315 headers has its five most significant bits masked out instead of
316 three.
319 typedef struct quic_decrypt_result {
320 const unsigned char *error; /**< Error message or NULL for success. */
321 const uint8_t *data; /**< Decrypted result on success (file-scoped). */
322 unsigned data_len; /**< Size of decrypted data. */
323 } quic_decrypt_result_t;
325 /** QUIC decryption context. */
328 typedef struct quic_hp_cipher {
329 gcry_cipher_hd_t hp_cipher; /**< Header protection cipher. */
330 } quic_hp_cipher;
331 typedef struct quic_pp_cipher {
332 gcry_cipher_hd_t pp_cipher; /**< Packet protection cipher. */
333 uint8_t pp_iv[TLS13_AEAD_NONCE_LENGTH];
334 } quic_pp_cipher;
335 typedef struct quic_ciphers {
336 quic_hp_cipher hp_cipher;
337 quic_pp_cipher pp_cipher;
338 } quic_ciphers;
341 * Packet protection state for an endpoint.
343 typedef struct quic_pp_state {
344 uint8_t *next_secret; /**< Next application traffic secret. */
345 quic_pp_cipher pp_ciphers[2]; /**< PP cipher for Key Phase 0/1 */
346 quic_hp_cipher hp_cipher; /**< HP cipher for both Key Phases; it does not change after KeyUpdate */
347 uint64_t changed_in_pkn; /**< Packet number where key change occurred. */
348 bool key_phase : 1; /**< Current key phase. */
349 } quic_pp_state_t;
351 /** Singly-linked list of Connection IDs. */
352 typedef struct quic_cid_item quic_cid_item_t;
353 struct quic_cid_item {
354 struct quic_cid_item *next;
355 quic_cid_t data;
359 * CRYPTO stream state.
362 typedef struct _quic_crypto_state {
363 uint64_t max_contiguous_offset;
364 uint8_t encryption_level; /**< AKA packet type */
365 wmem_tree_t *multisegment_pdus;
366 wmem_map_t *retrans_offsets;
367 } quic_crypto_state;
370 * Per-STREAM state, identified by QUIC Stream ID.
372 * Assume that every QUIC Short Header packet has no STREAM frames that overlap
373 * each other in the same QUIC packet (identified by "frame_num"). Thus, the
374 * Stream ID and offset uniquely identifies the STREAM Frame info in per packet.
376 typedef struct _quic_stream_state {
377 uint64_t stream_id;
378 wmem_tree_t *multisegment_pdus;
379 void *subdissector_private;
380 } quic_stream_state;
383 * Data used to allow "Follow QUIC Stream" functionality
385 typedef struct _quic_follow_stream {
386 uint32_t num;
387 uint64_t stream_id;
388 } quic_follow_stream;
390 typedef struct quic_follow_tap_data {
391 tvbuff_t *tvb;
392 uint64_t stream_id;
393 bool from_server;
394 } quic_follow_tap_data_t;
396 typedef struct quic_endpoint {
397 address server_address;
398 uint16_t server_port;
399 } quic_endpoint_t;
402 * State for a single QUIC connection, identified by one or more Destination
403 * Connection IDs (DCID).
405 typedef struct quic_info_data quic_info_data_t;
406 struct quic_info_data {
407 uint32_t number; /** Similar to "udp.stream", but for identifying QUIC connections across migrations. */
408 uint32_t version;
409 wmem_list_t *server_endpoints; /**< List of server endpoints, primarily used with 0 length DCIDs */
410 bool skip_decryption : 1; /**< Set to 1 if no keys are available. */
411 bool client_dcid_set : 1; /**< Set to 1 if client_dcid_initial is set. */
412 bool client_loss_bits_recv : 1; /**< The client is able to read loss bits info */
413 bool client_loss_bits_send : 1; /**< The client wants to send loss bits info */
414 bool server_loss_bits_recv : 1; /**< The server is able to read loss bits info */
415 bool server_loss_bits_send : 1; /**< The server wants to send loss bits info */
416 unsigned client_multipath : 2; /**< The client supports multipath */
417 unsigned server_multipath : 2; /**< The server supports multipath */
418 bool client_grease_quic_bit : 1; /**< The client supports greasing the Fixed (QUIC) bit */
419 bool server_grease_quic_bit : 1; /**< The server supports greasing the Fixed (QUIC) bit */
420 int hash_algo; /**< Libgcrypt hash algorithm for key derivation. */
421 int cipher_algo; /**< Cipher algorithm for packet number and packet encryption. */
422 int cipher_mode; /**< Cipher mode for packet encryption. */
423 quic_ciphers client_initial_ciphers;
424 quic_ciphers server_initial_ciphers;
425 quic_ciphers client_0rtt_ciphers;
426 quic_ciphers client_handshake_ciphers;
427 quic_ciphers server_handshake_ciphers;
428 quic_pp_state_t client_pp;
429 quic_pp_state_t server_pp;
430 uint64_t max_client_pkn[3]; /**< Packet number spaces for Initial, Handshake and appdata. */
431 uint64_t max_server_pkn[3];
432 wmem_map_t *max_client_mp_pkn; /**< Appdata packet number spaces for multipath, by sequence number. */
433 wmem_map_t *max_server_mp_pkn;
434 quic_cid_item_t client_cids; /**< SCID of client from first Initial Packet. */
435 quic_cid_item_t server_cids; /**< SCID of server from first Retry/Handshake. */
436 quic_cid_t client_dcid_initial; /**< DCID from Initial Packet. */
437 dissector_handle_t app_handle; /**< Application protocol handle (NULL if unknown). */
438 dissector_handle_t zrtt_app_handle; /**< Application protocol handle (NULL if unknown) for 0-RTT data. */
439 wmem_map_t *client_streams; /**< Map from Stream ID -> STREAM info (uint64_t -> quic_stream_state), sent by the client. */
440 wmem_map_t *server_streams; /**< Map from Stream ID -> STREAM info (uint64_t -> quic_stream_state), sent by the server. */
441 wmem_list_t *streams_list; /**< Ordered list of QUIC Stream ID in this connection (both directions). Used by "Follow QUIC Stream" functionality */
442 wmem_map_t *streams_map; /**< Map pinfo->num --> First stream in that frame (unsigned -> quic_follow_stream). Used by "Follow QUIC Stream" functionality */
443 wmem_map_t *client_crypto;
444 wmem_map_t *server_crypto;
445 gquic_info_data_t *gquic_info; /**< GQUIC info for >Q050 flows. */
446 quic_info_data_t *prev; /**< The previous QUIC connection multiplexed on the same network 5-tuple. Used by checking Stateless Reset tokens */
449 typedef struct _quic_crypto_info {
450 const uint64_t packet_number; /**< Reconstructed full packet number. */
451 uint64_t crypto_offset; /**< 62-bit stream offset. */
452 uint32_t offset; /**< Offset within the stream (different for reassembled data). */
453 bool from_server;
454 } quic_crypto_info;
456 /** Per-packet information about QUIC, populated on the first pass. */
457 struct quic_packet_info {
458 struct quic_packet_info *next;
459 uint64_t packet_number; /**< Reconstructed full packet number. */
460 quic_decrypt_result_t decryption;
461 uint8_t pkn_len; /**< Length of PKN (1/2/3/4) or unknown (0). */
462 uint8_t first_byte; /**< Decrypted flag byte, valid only if pkn_len is non-zero. */
463 uint8_t packet_type;
464 bool retry_integrity_failure : 1;
465 bool retry_integrity_success : 1;
467 typedef struct quic_packet_info quic_packet_info_t;
469 /** A UDP datagram contains one or more QUIC packets. */
470 typedef struct quic_datagram {
471 quic_info_data_t *conn;
472 quic_packet_info_t first_packet;
473 uint64_t path_id; /**< Path ID of the connection ID */
474 /* For multipath prior to draft-07, sequence number and path ID are the
475 * same and unique for each CID on the connection.
477 bool from_server : 1;
478 bool stateless_reset : 1;
479 } quic_datagram;
482 * Maps CID (quic_cid_t *) to a QUIC Connection (quic_info_data_t *).
483 * This assumes that the CIDs are not shared between two different connections
484 * (potentially with different versions) as that would break dissection.
486 * These mappings are authoritative. For example, Initial.SCID is stored in
487 * quic_client_connections while Retry.SCID is stored in
488 * quic_server_connections. Retry.DCID should normally correspond to an entry in
489 * quic_client_connections.
491 static wmem_map_t *quic_client_connections, *quic_server_connections;
492 static wmem_map_t *quic_initial_connections; /* Initial.DCID -> connection */
493 static wmem_list_t *quic_connections; /* All unique connections. */
494 static uint32_t quic_cid_lengths; /* Bitmap of CID lengths. */
495 static unsigned quic_connections_count;
497 static unsigned
498 quic_multipath_negotiated(quic_info_data_t *conn);
500 /* Returns the QUIC draft version or 0 if not applicable. */
501 static inline uint8_t quic_draft_version(uint32_t version) {
502 /* IETF Draft versions */
503 if ((version >> 8) == 0xff0000) {
504 return (uint8_t) version;
506 /* Facebook mvfst, based on draft -22. */
507 if (version == 0xfaceb001) {
508 return 22;
510 /* Facebook mvfst, based on draft -27. */
511 if (version == 0xfaceb002 || version == 0xfaceb00e) {
512 return 27;
514 /* GQUIC Q050, T050 and T051: they are not really based on any drafts,
515 * but we must return a sensible value */
516 if (version == 0x51303530 ||
517 version == 0x54303530 ||
518 version == 0x54303531) {
519 return 27;
521 /* https://tools.ietf.org/html/draft-ietf-quic-transport-32#section-15
522 "Versions that follow the pattern 0x?a?a?a?a are reserved for use in
523 forcing version negotiation to be exercised"
524 We can't return a correct draft version because we don't have a real
525 version here! That means that we can't decode any data and we can dissect
526 only the cleartext header.
527 Let's return v1 (any other numbers should be fine, anyway) to only allow
528 the dissection of the (expected) long header */
529 if ((version & 0x0F0F0F0F) == 0x0a0a0a0a) {
530 return 34;
532 /* QUIC (final?) constants for v1 are defined in draft-33, but draft-34 is the
533 final draft version */
534 if (version == 0x00000001) {
535 return 34;
537 /* QUIC Version 2 */
538 if (version == 0x6b3343cf) {
539 return 100;
541 return 0;
544 static inline bool is_quic_v2(uint32_t version) {
545 return version == 0x6b3343cf;
548 static inline bool is_quic_draft_max(uint32_t version, uint8_t max_version) {
549 uint8_t draft_version = quic_draft_version(version);
550 return draft_version && draft_version <= max_version;
553 const range_string quic_version_vals[] = {
554 { 0x00000000, 0x00000000, "Version Negotiation" },
555 { 0x00000001, 0x00000001, "1" },
556 { 0x45474700, 0x454747ff, "Quant" },
557 { 0x50435130, 0x50435131, "Picoquic internal" },
558 { 0x50524f58, 0x50524f58, "Proxied QUIC (PROX)" },
559 /* Versions QXXX < Q050 are dissected by Wireshark as GQUIC and not as QUIC.
560 Nonetheless, some implementations report these values in "Version Negotiation"
561 packets, so decode these fields */
562 { 0x51303433, 0x51303433, "Google Q043" },
563 { 0x51303434, 0x51303434, "Google Q044" },
564 { 0x51303436, 0x51303436, "Google Q046" },
565 { 0x51303530, 0x51303530, "Google Q050" },
566 { 0x51474f00, 0x51474fff, "QGO (QUIC GO)" },
567 { 0x54303530, 0x54303530, "Google T050" },
568 { 0x54303531, 0x54303531, "Google T051" },
569 { 0x91c17000, 0x91c170ff, "Quicly" },
570 { 0xabcd0000, 0xabcd000f, "MsQuic" },
571 { 0xf0f0f0f0, 0xf0f0f0ff, "ETH Zürich (Measurability experiments)" },
572 { 0xf0f0f1f0, 0xf0f0f1ff, "Telecom Italia (Measurability experiments)" },
573 { 0xf123f0c0, 0xf123f0cf, "MozQuic" },
574 { 0xfaceb001, 0xfaceb001, "Facebook mvfst (draft-22)" },
575 { 0xfaceb002, 0xfaceb002, "Facebook mvfst (draft-27)" },
576 { 0xfaceb003, 0xfaceb00d, "Facebook mvfst" },
577 { 0xfaceb00e, 0xfaceb00e, "Facebook mvfst (Experimental)" },
578 { 0xfaceb00f, 0xfaceb00f, "Facebook mvfst" },
579 { 0xff000004, 0xff000004, "draft-04" },
580 { 0xff000005, 0xff000005, "draft-05" },
581 { 0xff000006, 0xff000006, "draft-06" },
582 { 0xff000007, 0xff000007, "draft-07" },
583 { 0xff000008, 0xff000008, "draft-08" },
584 { 0xff000009, 0xff000009, "draft-09" },
585 { 0xff00000a, 0xff00000a, "draft-10" },
586 { 0xff00000b, 0xff00000b, "draft-11" },
587 { 0xff00000c, 0xff00000c, "draft-12" },
588 { 0xff00000d, 0xff00000d, "draft-13" },
589 { 0xff00000e, 0xff00000e, "draft-14" },
590 { 0xff00000f, 0xff00000f, "draft-15" },
591 { 0xff000010, 0xff000010, "draft-16" },
592 { 0xff000011, 0xff000011, "draft-17" },
593 { 0xff000012, 0xff000012, "draft-18" },
594 { 0xff000013, 0xff000013, "draft-19" },
595 { 0xff000014, 0xff000014, "draft-20" },
596 { 0xff000015, 0xff000015, "draft-21" },
597 { 0xff000016, 0xff000016, "draft-22" },
598 { 0xff000017, 0xff000017, "draft-23" },
599 { 0xff000018, 0xff000018, "draft-24" },
600 { 0xff000019, 0xff000019, "draft-25" },
601 { 0xff00001a, 0xff00001a, "draft-26" },
602 { 0xff00001b, 0xff00001b, "draft-27" },
603 { 0xff00001c, 0xff00001c, "draft-28" },
604 { 0xff00001d, 0xff00001d, "draft-29" },
605 { 0xff00001e, 0xff00001e, "draft-30" },
606 { 0xff00001f, 0xff00001f, "draft-31" },
607 { 0xff000020, 0xff000020, "draft-32" },
608 { 0xff000021, 0xff000021, "draft-33" },
609 { 0xff000022, 0xff000022, "draft-34" },
610 /* QUICv2 */
611 { 0xff020000, 0xff020000, "v2-draft-00" }, /* Never used; not really supported */
612 { 0x709A50C4, 0x709A50C4, "v2-draft-01" }, /* Never used; not really supported */
613 { 0x6b3343cf, 0x6b3343cf, "2" },
614 { 0, 0, NULL }
617 static const value_string quic_short_long_header_vals[] = {
618 { 0, "Short Header" },
619 { 1, "Long Header" },
620 { 0, NULL }
623 #define SH_KP 0x04
625 /* Note that these values are "internal-value" used by Wireshark only.
626 Real wire-format values depends on QUIC version */
627 #define QUIC_LPT_INITIAL 0x0
628 #define QUIC_LPT_0RTT 0x1
629 #define QUIC_LPT_HANDSHAKE 0x2
630 #define QUIC_LPT_RETRY 0x3
631 #define QUIC_LPT_VER_NEG 0xfe /* Version Negotiation packets don't have any real packet type */
632 #define QUIC_SHORT_PACKET 0xff /* dummy value that is definitely not LPT */
634 static const value_string quic_v1_long_packet_type_vals[] = {
635 { 0x00, "Initial" },
636 { 0x03, "Retry" },
637 { 0x02, "Handshake" },
638 { 0x01, "0-RTT" },
639 /* Version Negotiation packets never use this mapping, so no need to add QUIC_LPT_VER_NEG */
640 { 0, NULL }
642 static const value_string quic_v2_long_packet_type_vals[] = {
643 { 0x00, "Retry" },
644 { 0x01, "Initial" },
645 { 0x02, "0-RTT" },
646 { 0x03, "Handshake" },
647 /* Version Negotiation packets never use this mapping, so no need to add QUIC_LPT_VER_NEG */
648 { 0, NULL }
651 /* https://github.com/quicwg/base-drafts/wiki/Temporary-IANA-Registry#quic-frame-types */
652 #define FT_PADDING 0x00
653 #define FT_PING 0x01
654 #define FT_ACK 0x02
655 #define FT_ACK_ECN 0x03
656 #define FT_RESET_STREAM 0x04
657 #define FT_STOP_SENDING 0x05
658 #define FT_CRYPTO 0x06
659 #define FT_NEW_TOKEN 0x07
660 #define FT_STREAM_8 0x08
661 #define FT_STREAM_9 0x09
662 #define FT_STREAM_A 0x0a
663 #define FT_STREAM_B 0x0b
664 #define FT_STREAM_C 0x0c
665 #define FT_STREAM_D 0x0d
666 #define FT_STREAM_E 0x0e
667 #define FT_STREAM_F 0x0f
668 #define FT_MAX_DATA 0x10
669 #define FT_MAX_STREAM_DATA 0x11
670 #define FT_MAX_STREAMS_BIDI 0x12
671 #define FT_MAX_STREAMS_UNI 0x13
672 #define FT_DATA_BLOCKED 0x14
673 #define FT_STREAM_DATA_BLOCKED 0x15
674 #define FT_STREAMS_BLOCKED_BIDI 0x16
675 #define FT_STREAMS_BLOCKED_UNI 0x17
676 #define FT_NEW_CONNECTION_ID 0x18
677 #define FT_RETIRE_CONNECTION_ID 0x19
678 #define FT_PATH_CHALLENGE 0x1a
679 #define FT_PATH_RESPONSE 0x1b
680 #define FT_IMMEDIATE_ACK 0x1f
681 #define FT_CONNECTION_CLOSE_TPT 0x1c
682 #define FT_CONNECTION_CLOSE_APP 0x1d
683 #define FT_HANDSHAKE_DONE 0x1e
684 #define FT_DATAGRAM 0x30
685 #define FT_DATAGRAM_LENGTH 0x31
686 #define FT_IMMEDIATE_ACK_DRAFT05 0xac /* ack-frequency-draft-05 */
687 #define FT_ACK_FREQUENCY 0xaf
688 #define FT_MP_ACK 0x15228c00
689 #define FT_MP_ACK_ECN 0x15228c01
690 #define FT_PATH_ABANDON 0x15228c05
691 #define FT_PATH_STATUS 0x15228c06 /* multipath-draft-05 */
692 #define FT_PATH_STANDBY 0x15228c07 /* multipath-draft-06 */
693 #define FT_PATH_AVAILABLE 0x15228c08 /* multipath-draft-06 */
694 #define FT_MP_NEW_CONNECTION_ID 0x15228c09 /* multipath-draft-07 */
695 #define FT_MP_RETIRE_CONNECTION_ID 0x15228c0a /* multipath-draft-07 */
696 #define FT_MAX_PATHS 0x15228c0b /* multipath-draft-07 */
697 #define FT_MAX_PATH_ID 0x15228c0c /* multipath-draft-09 */
698 #define FT_TIME_STAMP 0x02F5
700 static const range_string quic_frame_type_vals[] = {
701 { 0x00, 0x00, "PADDING" },
702 { 0x01, 0x01, "PING" },
703 { 0x02, 0x03, "ACK" },
704 { 0x04, 0x04, "RESET_STREAM" },
705 { 0x05, 0x05, "STOP_SENDING" },
706 { 0x06, 0x06, "CRYPTO" },
707 { 0x07, 0x07, "NEW_TOKEN" },
708 { 0x08, 0x0f, "STREAM" },
709 { 0x10, 0x10, "MAX_DATA" },
710 { 0x11, 0x11, "MAX_STREAM_DATA" },
711 { 0x12, 0x12, "MAX_STREAMS (BIDI)" },
712 { 0x13, 0x13, "MAX_STREAMS (UNI)" },
713 { 0x14, 0x14, "DATA_BLOCKED" },
714 { 0x15, 0x15, "STREAM_DATA_BLOCKED" },
715 { 0x16, 0x16, "STREAMS_BLOCKED (BIDI)" },
716 { 0x16, 0x17, "STREAMS_BLOCKED (UNI)" },
717 { 0x18, 0x18, "NEW_CONNECTION_ID" },
718 { 0x19, 0x19, "RETIRE_CONNECTION_ID" },
719 { 0x1a, 0x1a, "PATH_CHALLENGE" },
720 { 0x1b, 0x1b, "PATH_RESPONSE" },
721 { 0x1c, 0x1c, "CONNECTION_CLOSE (Transport)" },
722 { 0x1d, 0x1d, "CONNECTION_CLOSE (Application)" },
723 { 0x1e, 0x1e, "HANDSHAKE_DONE" },
724 { 0x1f, 0x1f, "IMMEDIATE_ACK" },
725 { 0x30, 0x31, "DATAGRAM" },
726 { 0xac, 0xac, "IMMEDIATE_ACK (draft05)" }, /* ack-frequency-draft-05 */
727 { 0xaf, 0xaf, "ACK_FREQUENCY" },
728 { 0x02f5, 0x02f5, "TIME_STAMP" },
729 { 0xbaba00, 0xbaba01, "ACK_MP" }, /* multipath-draft-04 */
730 { 0xbaba05, 0xbaba05, "PATH_ABANDON" }, /* multipath-draft-04 */
731 { 0xbaba06, 0xbaba06, "PATH_STATUS" }, /* multipath-draft-04 */
732 { 0x15228c00, 0x15228c01, "MP_ACK" }, /* >= multipath-draft-05 */
733 { 0x15228c05, 0x15228c05, "PATH_ABANDON" }, /* >= multipath-draft-05 */
734 { 0x15228c06, 0x15228c06, "PATH_STATUS" }, /* = multipath-draft-05 */
735 { 0x15228c07, 0x15228c07, "PATH_STANDBY" }, /* >= multipath-draft-06 */
736 { 0x15228c08, 0x15228c08, "PATH_AVAILABLE" }, /* >= multipath-draft-06 */
737 { 0x15228c09, 0x15228c09, "MP_NEW_CONNECTION_ID" }, /* >= multipath-draft-07 */
738 { 0x15228c0a, 0x15228c0a, "MP_RETIRE_CONNECTION_ID" }, /* >= multipath-draft-07 */
739 { 0x15228c0b, 0x15228c0b, "MAX_PATHS" }, /* >= multipath-draft-07 */
740 { 0x15228c0c, 0x15228c0c, "MAX_PATH_ID" }, /* >= multipath-draft-09 */
741 { 0, 0, NULL },
745 /* >= draft-08 */
746 #define FTFLAGS_STREAM_FIN 0x01
747 #define FTFLAGS_STREAM_LEN 0x02
748 #define FTFLAGS_STREAM_OFF 0x04
750 #define FTFLAGS_STREAM_INITIATOR 0x01
751 #define FTFLAGS_STREAM_DIRECTION 0x02
753 static const range_string quic_transport_error_code_vals[] = {
754 /* 0x00 - 0x3f Assigned via Standards Action or IESG Review policies. */
755 { 0x0000, 0x0000, "NO_ERROR" },
756 { 0x0001, 0x0001, "INTERNAL_ERROR" },
757 { 0x0002, 0x0002, "CONNECTION_REFUSED" },
758 { 0x0003, 0x0003, "FLOW_CONTROL_ERROR" },
759 { 0x0004, 0x0004, "STREAM_ID_ERROR" },
760 { 0x0005, 0x0005, "STREAM_STATE_ERROR" },
761 { 0x0006, 0x0006, "FINAL_SIZE_ERROR" },
762 { 0x0007, 0x0007, "FRAME_ENCODING_ERROR" },
763 { 0x0008, 0x0008, "TRANSPORT_PARAMETER_ERROR" },
764 { 0x0009, 0x0009, "CONNECTION_ID_LIMIT_ERROR" },
765 { 0x000a, 0x000a, "PROTOCOL_VIOLATION" },
766 { 0x000b, 0x000b, "INVALID_TOKEN" },
767 { 0x000c, 0x000c, "APPLICATION_ERROR" },
768 { 0x000d, 0x000d, "CRYPTO_BUFFER_EXCEEDED" },
769 { 0x000e, 0x000e, "KEY_UPDATE_ERROR" },
770 { 0x000f, 0x000f, "AEAD_LIMIT_REACHED" },
771 { 0x0010, 0x0010, "NO_VIABLE_PATH" },
772 { 0x0011, 0x0011, "VERSION_NEGOTIATION_ERROR" },
773 { 0x0100, 0x01ff, "CRYPTO_ERROR" },
774 /* 0x40 - 0x3fff Assigned via Specification Required policy. */
775 { 0, 0, NULL }
778 static const value_string quic_packet_number_lengths[] = {
779 { 0, "1 bytes" },
780 { 1, "2 bytes" },
781 { 2, "3 bytes" },
782 { 3, "4 bytes" },
783 { 0, NULL }
786 static const val64_string quic_frame_id_initiator[] = {
787 { 0, "Client-initiated" },
788 { 1, "Server-initiated" },
789 { 0, NULL }
792 static const val64_string quic_frame_id_direction[] = {
793 { 0, "Bidirectional" },
794 { 1, "Unidirectional" },
795 { 0, NULL }
798 static const val64_string quic_mp_path_status[] = {
799 { 1, "Standby" },
800 { 2, "Available" },
801 { 0, NULL }
805 static void
806 quic_extract_header(tvbuff_t *tvb, uint8_t *long_packet_type, uint32_t *version,
807 quic_cid_t *dcid, quic_cid_t *scid);
809 static int
810 quic_get_long_packet_type(uint8_t first_byte, uint32_t version)
812 /* Up to V1 */
813 if (!is_quic_v2(version)) {
814 if ((first_byte & 0x30) >> 4 == 0)
815 return QUIC_LPT_INITIAL;
816 if ((first_byte & 0x30) >> 4 == 1)
817 return QUIC_LPT_0RTT;
818 if ((first_byte & 0x30) >> 4 == 2)
819 return QUIC_LPT_HANDSHAKE;
820 return QUIC_LPT_RETRY;
821 } else {
822 if ((first_byte & 0x30) >> 4 == 0)
823 return QUIC_LPT_RETRY;
824 if ((first_byte & 0x30) >> 4 == 1)
825 return QUIC_LPT_INITIAL;
826 if ((first_byte & 0x30) >> 4 == 2)
827 return QUIC_LPT_0RTT;
828 return QUIC_LPT_HANDSHAKE;
832 static void
833 quic_streams_add(packet_info *pinfo, quic_info_data_t *quic_info, uint64_t stream_id);
835 static void
836 quic_hp_cipher_reset(quic_hp_cipher *hp_cipher)
838 gcry_cipher_close(hp_cipher->hp_cipher);
839 memset(hp_cipher, 0, sizeof(*hp_cipher));
841 static void
842 quic_pp_cipher_reset(quic_pp_cipher *pp_cipher)
844 gcry_cipher_close(pp_cipher->pp_cipher);
845 memset(pp_cipher, 0, sizeof(*pp_cipher));
847 static void
848 quic_ciphers_reset(quic_ciphers *ciphers)
850 quic_hp_cipher_reset(&ciphers->hp_cipher);
851 quic_pp_cipher_reset(&ciphers->pp_cipher);
854 static bool
855 quic_is_hp_cipher_initialized(quic_hp_cipher *hp_cipher)
857 return hp_cipher && hp_cipher->hp_cipher;
859 static bool
860 quic_is_pp_cipher_initialized(quic_pp_cipher *pp_cipher)
862 return pp_cipher && pp_cipher->pp_cipher;
864 static bool
865 quic_are_ciphers_initialized(quic_ciphers *ciphers)
867 return ciphers &&
868 quic_is_hp_cipher_initialized(&ciphers->hp_cipher) &&
869 quic_is_pp_cipher_initialized(&ciphers->pp_cipher);
872 /* Inspired from ngtcp2 */
873 static uint64_t quic_pkt_adjust_pkt_num(uint64_t max_pkt_num, uint64_t pkt_num,
874 size_t n) {
875 uint64_t k = max_pkt_num == UINT64_MAX ? max_pkt_num : max_pkt_num + 1;
876 uint64_t u = k & ~((UINT64_C(1) << n) - 1);
877 uint64_t a = u | pkt_num;
878 uint64_t b = (u + (UINT64_C(1) << n)) | pkt_num;
879 uint64_t a1 = k < a ? a - k : k - a;
880 uint64_t b1 = k < b ? b - k : k - b;
882 if (a1 < b1) {
883 return a;
885 return b;
889 * Given a header protection cipher, a buffer and the packet number offset,
890 * return the unmasked first byte and packet number.
891 * If the loss bits feature is enabled, the protected bits in the first byte
892 * are fewer than usual: 3 instead of 5 (on short headers only)
894 static bool
895 quic_decrypt_header(tvbuff_t *tvb, unsigned pn_offset, quic_hp_cipher *hp_cipher, int hp_cipher_algo,
896 uint8_t *first_byte, uint32_t *pn, bool loss_bits_negotiated)
898 if (!hp_cipher->hp_cipher) {
899 // need to know the cipher.
900 return false;
902 gcry_cipher_hd_t h = hp_cipher->hp_cipher;
904 // Sample is always 16 bytes and starts after PKN (assuming length 4).
905 // https://tools.ietf.org/html/draft-ietf-quic-tls-22#section-5.4.2
906 uint8_t sample[16];
907 tvb_memcpy(tvb, sample, pn_offset + 4, 16);
909 uint8_t mask[5] = { 0 };
910 switch (hp_cipher_algo) {
911 case GCRY_CIPHER_AES128:
912 case GCRY_CIPHER_AES256:
913 /* Encrypt in-place with AES-ECB and extract the mask. */
914 if (gcry_cipher_encrypt(h, sample, sizeof(sample), NULL, 0)) {
915 return false;
917 memcpy(mask, sample, sizeof(mask));
918 break;
919 case GCRY_CIPHER_CHACHA20:
920 /* If Gcrypt receives a 16 byte IV, it will assume the buffer to be
921 * counter || nonce (in little endian), as desired. */
922 if (gcry_cipher_setiv(h, sample, 16)) {
923 return false;
925 /* Apply ChaCha20, encrypt in-place five zero bytes. */
926 if (gcry_cipher_encrypt(h, mask, sizeof(mask), NULL, 0)) {
927 return false;
929 break;
930 default:
931 return false;
934 // https://tools.ietf.org/html/draft-ietf-quic-tls-22#section-5.4.1
935 uint8_t packet0 = tvb_get_uint8(tvb, 0);
936 if ((packet0 & 0x80) == 0x80) {
937 // Long header: 4 bits masked
938 packet0 ^= mask[0] & 0x0f;
939 } else {
940 // Short header
941 if (loss_bits_negotiated == false) {
942 // Standard mask: 5 bits masked
943 packet0 ^= mask[0] & 0x1F;
944 } else {
945 // https://tools.ietf.org/html/draft-ferrieuxhamchaoui-quic-lossbits-03#section-5.3
946 packet0 ^= mask[0] & 0x07;
949 unsigned pkn_len = (packet0 & 0x03) + 1;
951 uint8_t pkn_bytes[4];
952 tvb_memcpy(tvb, pkn_bytes, pn_offset, pkn_len);
953 uint32_t pkt_pkn = 0;
954 for (unsigned i = 0; i < pkn_len; i++) {
955 pkt_pkn |= (pkn_bytes[i] ^ mask[1 + i]) << (8 * (pkn_len - 1 - i));
957 *first_byte = packet0;
958 *pn = pkt_pkn;
959 return true;
963 * Retrieve the maximum valid packet number space for a peer.
965 static uint64_t *
966 quic_max_packet_number(quic_info_data_t *quic_info, uint64_t path_id, bool from_server, uint8_t first_byte)
968 int pkn_space;
969 if ((first_byte & 0x80) && quic_get_long_packet_type(first_byte, quic_info->version) == QUIC_LPT_INITIAL) {
970 // Long header, Initial
971 pkn_space = 0;
972 } else if ((first_byte & 0x80) && quic_get_long_packet_type(first_byte, quic_info->version) == QUIC_LPT_HANDSHAKE) {
973 // Long header, Handshake
974 pkn_space = 1;
975 } else {
976 // Long header (0-RTT) or Short Header (1-RTT appdata).
977 pkn_space = 2;
979 if (quic_multipath_negotiated(quic_info) && path_id > 0) {
980 /* The multipath draft states that key negotiation must
981 * happen before 2^32 CID sequence numbers are used, so
982 * possibly we could get away with using GUINT_TO_POINTER
983 * and saving some memory here.
985 wmem_map_t **mp_pkn_map;
986 if (from_server) {
987 if (quic_info->max_server_mp_pkn == NULL) {
988 quic_info->max_server_mp_pkn = wmem_map_new(wmem_file_scope(), wmem_int64_hash, g_int64_equal);
990 mp_pkn_map = &quic_info->max_server_mp_pkn;
991 } else {
992 if (quic_info->max_client_mp_pkn == NULL) {
993 quic_info->max_client_mp_pkn = wmem_map_new(wmem_file_scope(), wmem_int64_hash, g_int64_equal);
995 mp_pkn_map = &quic_info->max_client_mp_pkn;
997 uint64_t *pkt_num = wmem_map_lookup(*mp_pkn_map, &path_id);
998 if (pkt_num == NULL) {
999 uint64_t *path_id_p = wmem_new(wmem_file_scope(), uint64_t);
1000 *path_id_p = path_id;
1001 pkt_num = wmem_new0(wmem_file_scope(), uint64_t);
1002 wmem_map_insert(*mp_pkn_map, path_id_p, pkt_num);
1004 return pkt_num;
1005 } else {
1006 if (from_server) {
1007 return &quic_info->max_server_pkn[pkn_space];
1008 } else {
1009 return &quic_info->max_client_pkn[pkn_space];
1015 * Calculate the full packet number and store it for later use.
1017 static void
1018 quic_set_full_packet_number(quic_info_data_t *quic_info, quic_packet_info_t *quic_packet,
1019 uint64_t path_id, bool from_server,
1020 uint8_t first_byte, uint32_t pkn32)
1022 unsigned pkn_len = (first_byte & 3) + 1;
1023 uint64_t pkn_full;
1024 uint64_t max_pn = *quic_max_packet_number(quic_info, path_id, from_server, first_byte);
1026 /* Sequential first pass, try to reconstruct full packet number. */
1027 pkn_full = quic_pkt_adjust_pkt_num(max_pn, pkn32, 8 * pkn_len);
1028 quic_packet->pkn_len = pkn_len;
1029 quic_packet->packet_number = pkn_full;
1032 static const char *
1033 cid_to_string(wmem_allocator_t *pool, const quic_cid_t *cid)
1035 if (cid->len == 0) {
1036 return "(none)";
1038 char *str = (char *)wmem_alloc0(pool, 2 * cid->len + 1);
1039 bytes_to_hexstr(str, cid->cid, cid->len);
1040 return str;
1043 /* QUIC Connection tracking. {{{ */
1044 static unsigned
1045 quic_connection_hash(const void *key)
1047 const quic_cid_t *cid = (const quic_cid_t *)key;
1049 return wmem_strong_hash((const uint8_t *)cid->cid, cid->len);
1052 /* Note this function intentionally does not consider the reset token. */
1053 static gboolean
1054 quic_connection_equal(const void *a, const void *b)
1056 const quic_cid_t *cid1 = (const quic_cid_t *)a;
1057 const quic_cid_t *cid2 = (const quic_cid_t *)b;
1059 return cid1->len == cid2->len && !memcmp(cid1->cid, cid2->cid, cid1->len);
1062 static gboolean
1063 quic_cids_has_match(const quic_cid_item_t *items, quic_cid_t *raw_cid)
1065 while (items) {
1066 const quic_cid_t *cid = &items->data;
1067 // "raw_cid" potentially has some trailing data that is not part of the
1068 // actual CID, so accept any prefix match against "cid".
1069 // Note that this explicitly matches an empty CID.
1070 if (raw_cid->len >= cid->len && !memcmp(raw_cid->cid, cid->cid, cid->len)) {
1071 raw_cid->seq_num = cid->seq_num;
1072 raw_cid->path_id = cid->path_id;
1073 return true;
1075 items = items->next;
1077 return false;
1080 static void
1081 quic_cids_insert(quic_cid_t *cid, quic_info_data_t *conn, bool from_server)
1083 wmem_map_t *connections = from_server ? quic_server_connections : quic_client_connections;
1084 // Replace any previous CID key with the new one.
1085 wmem_map_remove(connections, cid);
1086 wmem_map_insert(connections, cid, conn);
1087 G_STATIC_ASSERT(QUIC_MAX_CID_LENGTH <= 8 * sizeof(quic_cid_lengths));
1088 quic_cid_lengths |= (1ULL << cid->len);
1091 static inline bool
1092 quic_cids_is_known_length(const quic_cid_t *cid)
1094 return (quic_cid_lengths & (1ULL << cid->len)) != 0;
1098 * Checks if a address and port combination is associated with the server
1099 * side of a connection. This is primarily useful when 0 length Destination
1100 * Connection IDs are used.
1101 * "Clients are responsible for initiating all migrations" (RFC 9000 Section 9),
1102 * so this uses the destination address and port of the packet info.
1104 static bool
1105 quic_connection_from_server_endpoint(packet_info *pinfo, quic_info_data_t *conn)
1107 quic_endpoint_t *server_endpoint;
1108 for (wmem_list_frame_t *frame = wmem_list_head(conn->server_endpoints); frame; frame = wmem_list_frame_next(frame)) {
1110 server_endpoint = wmem_list_frame_data(frame);
1111 if (server_endpoint->server_port == pinfo->srcport &&
1112 addresses_equal(&server_endpoint->server_address, &pinfo->src)) {
1114 return true;
1117 return false;
1121 * Adds a server endpoint to the list of used server endpoints for the address.
1122 * This is most useful when 0 length Destination Connection IDs are used.
1123 * "Clients are responsible for initiating all migrations" (RFC 9000 Section 9),
1124 * so this uses the destination address and port from pinfo as the server.
1126 static void
1127 quic_connection_add_server_endpoint(packet_info *pinfo, quic_info_data_t *conn)
1129 quic_endpoint_t *server_endpoint = wmem_new(wmem_file_scope(), quic_endpoint_t);
1130 copy_address_wmem(wmem_file_scope(), &server_endpoint->server_address, &pinfo->dst);
1131 server_endpoint->server_port = pinfo->destport;
1132 wmem_list_append(conn->server_endpoints, server_endpoint);
1136 * Returns the most recent QUIC connection for the current UDP stream. This may
1137 * return NULL after connection migration if the new UDP association was not
1138 * properly linked via a match based on the Connection ID.
1140 * There may be more than one QUIC connection multiplexed on the same UDP
1141 * 5-tuple; previous connections can be found by looking at the ->prev pointer.
1142 * Per RFC 9000, multiplexed connections with zero-length CIDs will fail.
1144 static quic_info_data_t *
1145 quic_connection_from_conv(packet_info *pinfo)
1147 conversation_t *conv = find_conversation_pinfo(pinfo, 0);
1148 if (conv) {
1149 return (quic_info_data_t *)conversation_get_proto_data(conv, proto_quic);
1151 return NULL;
1155 * Tries to lookup a matching connection (if Connection ID is NULL, the
1156 * most recent connection on the network 5-tuple is returned, if any).
1157 * If connection is found, "from_server" is set accordingly.
1159 static quic_info_data_t *
1160 quic_connection_find_dcid(packet_info *pinfo, quic_cid_t *dcid, bool *from_server)
1162 /* https://tools.ietf.org/html/draft-ietf-quic-transport-22#section-5.2
1164 * "If the packet has a Destination Connection ID corresponding to an
1165 * existing connection, QUIC processes that packet accordingly."
1166 * "If the Destination Connection ID is zero length and the packet matches
1167 * the address/port tuple of a connection where the host did not require
1168 * connection IDs, QUIC processes the packet as part of that connection."
1170 quic_info_data_t *conn = NULL;
1171 const quic_cid_t *original_dcid;
1172 bool check_ports = false;
1174 if (dcid && dcid->len > 0) {
1175 // Optimization: avoid lookup for invalid CIDs.
1176 if (!quic_cids_is_known_length(dcid)) {
1177 return NULL;
1179 if (wmem_map_lookup_extended(quic_client_connections, dcid, (const void**)&original_dcid, (void**)&conn)) {
1180 // DCID recognized by client, so it was from server.
1181 *from_server = true;
1182 // On collision (both client and server choose the same CID), check
1183 // the port to learn about the side.
1184 // This is required for supporting draft -10 which has a single CID.
1185 check_ports = !!wmem_map_lookup(quic_server_connections, dcid);
1186 // Copy the other information, like sequence number and path ID
1187 // (for multipath).
1188 *dcid = *original_dcid;
1189 } else {
1190 if (wmem_map_lookup_extended(quic_server_connections, dcid, (const void**)&original_dcid, (void**)&conn)) {
1191 // DCID recognized by server, so it was from client.
1192 *from_server = false;
1193 // Copy the other information, like sequence number and path ID.
1194 *dcid = *original_dcid;
1197 } else {
1198 conn = quic_connection_from_conv(pinfo);
1199 if (conn) {
1200 check_ports = true;
1204 if (check_ports) {
1205 *from_server = quic_connection_from_server_endpoint(pinfo, conn);
1208 return conn;
1212 * Try to find a QUIC connection based on DCID. For short header packets, DCID
1213 * will be modified in order to find the actual length.
1214 * DCID can be empty, in that case a connection is looked up by address only.
1216 static quic_info_data_t *
1217 quic_connection_find(packet_info *pinfo, uint8_t long_packet_type,
1218 quic_cid_t *dcid, bool *from_server)
1220 bool is_long_packet = long_packet_type != QUIC_SHORT_PACKET;
1221 quic_info_data_t *conn = NULL;
1223 if (long_packet_type == QUIC_LPT_0RTT && dcid->len > 0) {
1224 // The 0-RTT packet always matches the SCID/DCID of the Client Initial
1225 conn = (quic_info_data_t *) wmem_map_lookup(quic_initial_connections, dcid);
1226 *from_server = false;
1227 } else {
1228 // Find a connection for Handshake, Version Negotiation and Server Initial packets by
1229 // matching their DCID against the SCIDs of the original Initial packets
1230 // from the peer. For Client Initial packets, match DCID of the first
1231 // Client Initial (these may contain ACK frames).
1232 conn = quic_connection_find_dcid(pinfo, dcid, from_server);
1233 /* Handle cases where we get a second Client Initial packet before a
1234 * Server Initial packet (so this is not recognized by the server yet),
1235 * e.g. the TLS Client Hello is fragmented in more than one frame.
1237 if (long_packet_type == QUIC_LPT_INITIAL && !conn && dcid->len > 0) {
1238 conn = (quic_info_data_t *) wmem_map_lookup(quic_initial_connections, dcid);
1239 if (conn) {
1240 *from_server = false;
1243 if (long_packet_type == QUIC_LPT_INITIAL && conn && !*from_server && dcid->len > 0 &&
1244 !quic_connection_equal(dcid, &conn->client_dcid_initial) &&
1245 !quic_cids_has_match(&conn->server_cids, dcid)) {
1246 // If the Initial Packet is from the client, it must either match
1247 // the DCID from the first Client Initial, or the DCID that was
1248 // assigned by the server. Otherwise this must be considered a fresh
1249 // Client Initial, for example after the Version Negotiation packet,
1250 // and the connection must be cleared to avoid decryption failure.
1251 conn = NULL;
1255 if (!is_long_packet && !conn) {
1256 // For short packets, first try to find a match based on the address.
1257 // (This is necessary to match a zero-length connection ID - for
1258 // other cases, the second method below also works, and it can vary
1259 // which is faster to try first.)
1260 conn = quic_connection_find_dcid(pinfo, NULL, from_server);
1261 /* Since we don't know the DCID, check all connections multiplexed
1262 * on the same 5-tuple for a match. */
1263 while (conn) {
1264 if ((*from_server && quic_cids_has_match(&conn->client_cids, dcid)) ||
1265 (!*from_server && quic_cids_has_match(&conn->server_cids, dcid))) {
1266 // Connection matches packet.
1267 break;
1269 conn = conn->prev;
1272 // No match found so far, potentially connection migration. Length of
1273 // actual DCID is unknown, so just keep decrementing until found.
1274 while (!conn && dcid->len > 1) {
1275 dcid->len--;
1276 if (quic_cids_is_known_length(dcid)) {
1277 conn = quic_connection_find_dcid(pinfo, dcid, from_server);
1280 if (!conn) {
1281 // No match found, truncate DCID (not really needed, but this
1282 // ensures that debug prints clearly show that DCID is invalid).
1283 dcid->len = 0;
1284 } else if (quic_connection_from_conv(pinfo) == NULL) {
1285 // Connection information might not be attached to the conversation,
1286 // because of connection migration.
1287 conversation_t *conv = find_conversation_pinfo(pinfo, 0);
1288 if (conv) {
1289 // attach the connection information to the conversation.
1290 conversation_add_proto_data(conv, proto_quic, conn);
1291 // Found this connection, but (especially if 0 length DCIDs
1292 // are used for the client) we need to add the server endpoint
1293 // to the list seen.
1294 // XXX - RFC 9000 Section 9 appears to say that the client can
1295 // migrate its own address freely, but should only migrate to
1296 // a server address given in the preferred_address transport
1297 // parameter in the TLS handshake. Should there be an expert
1298 // info if this is an unknown address? (#20165)
1299 quic_connection_add_server_endpoint(pinfo, conn);
1303 return conn;
1306 /** Create a new QUIC Connection based on a Client Initial packet. */
1307 static quic_info_data_t *
1308 quic_connection_create(packet_info *pinfo, uint32_t version)
1310 conversation_t *conv;
1311 quic_info_data_t *prev_conn, *conn = NULL;
1313 conn = wmem_new0(wmem_file_scope(), quic_info_data_t);
1314 wmem_list_append(quic_connections, conn);
1315 conn->number = quic_connections_count++;
1316 conn->version = version;
1317 conn->server_endpoints = wmem_list_new(wmem_file_scope());
1318 quic_connection_add_server_endpoint(pinfo, conn);
1320 // For faster lookups without having to check DCID
1321 conv = find_or_create_conversation(pinfo);
1322 // Check for another connection multiplexed on the 5-tuple
1323 prev_conn = conversation_get_proto_data(conv, proto_quic);
1324 if (prev_conn) {
1325 conn->prev = prev_conn;
1327 conversation_add_proto_data(conv, proto_quic, conn);
1329 conv = find_or_create_conversation_by_id(pinfo, CONVERSATION_QUIC, conn->number);
1330 conversation_add_proto_data(conv, proto_quic, conn);
1332 if (version == 0x51303530 || version == 0x54303530 || version == 0x54303531) {
1333 gquic_info_data_t *gquic_info;
1335 gquic_info = wmem_new(wmem_file_scope(), gquic_info_data_t);
1336 if (version == 0x51303530)
1337 gquic_info->version = 50;
1338 else if (version == 0x54303530)
1339 gquic_info->version = 150;
1340 else
1341 gquic_info->version = 151;
1342 gquic_info->encoding = ENC_BIG_ENDIAN;
1343 gquic_info->version_valid = true;
1344 gquic_info->server_port = pinfo->destport;
1345 conn->gquic_info = gquic_info;
1348 return conn;
1351 /** Update client/server connection identifiers, assuming the information is
1352 * from the Client Initial. */
1353 static void
1354 quic_connection_update_initial(quic_info_data_t *conn, const quic_cid_t *scid, const quic_cid_t *dcid)
1356 // Key connection by Client CID (if provided).
1357 if (scid->len) {
1358 memcpy(&conn->client_cids.data, scid, sizeof(quic_cid_t));
1359 quic_cids_insert(&conn->client_cids.data, conn, false);
1361 if (dcid->len > 0) {
1362 // According to the spec, the Initial Packet DCID MUST be at least 8
1363 // bytes, but non-conforming implementations could exist.
1364 memcpy(&conn->client_dcid_initial, dcid, sizeof(quic_cid_t));
1365 wmem_map_insert(quic_initial_connections, &conn->client_dcid_initial, conn);
1366 conn->client_dcid_set = true;
1371 * Use the new CID as additional identifier for the specified connection and
1372 * remember it for connection tracking.
1374 static void
1375 quic_connection_add_cid(quic_info_data_t *conn, quic_cid_t *new_cid, bool from_server)
1377 DISSECTOR_ASSERT(new_cid->len > 0);
1378 quic_cid_item_t *items = from_server ? &conn->server_cids : &conn->client_cids;
1380 if (quic_cids_has_match(items, new_cid)) {
1381 // CID is already known for this connection.
1382 // XXX: If the same CID is reused with a new sequence number or path
1383 // id and multipath is being used, that's an issue. (Expert info?)
1384 return;
1387 // Insert new CID right after the first known CID (the very first CID cannot
1388 // be overwritten since it might be used as key somewhere else).
1389 quic_cid_item_t *new_item = wmem_new0(wmem_file_scope(), quic_cid_item_t);
1390 new_item->data = *new_cid;
1391 new_item->next = items->next;
1392 items->next = new_item;
1394 quic_cids_insert(&new_item->data, conn, from_server);
1397 /** Create or update a connection. */
1398 static void
1399 quic_connection_create_or_update(quic_info_data_t **conn_p,
1400 packet_info *pinfo, uint32_t long_packet_type,
1401 uint32_t version, const quic_cid_t *scid,
1402 const quic_cid_t *dcid, bool from_server)
1404 quic_info_data_t *conn = *conn_p;
1406 switch (long_packet_type) {
1407 case QUIC_LPT_INITIAL:
1408 if (!from_server) {
1409 if (!conn) {
1410 // The first Initial Packet from the client creates a new connection.
1411 *conn_p = quic_connection_create(pinfo, version);
1412 quic_connection_update_initial(*conn_p, scid, dcid);
1413 } else if (!conn->client_dcid_set && dcid->len) {
1414 // If this client Initial Packet responds to a Retry Packet,
1415 // then remember the new client SCID and initial DCID for the
1416 // new Initial cipher and clear the first server CID such that
1417 // the next server Initial Packet can link the connection with
1418 // that new SCID.
1419 quic_connection_update_initial(conn, scid, dcid);
1420 wmem_map_remove(quic_server_connections, &conn->server_cids.data);
1421 memset(&conn->server_cids, 0, sizeof(quic_cid_t));
1423 break;
1425 /* fallthrough */
1426 case QUIC_LPT_RETRY:
1427 case QUIC_LPT_HANDSHAKE:
1428 // Remember CID from first server Retry/Handshake packet
1429 // (or from the first server Initial packet, since draft -13).
1430 if (from_server && conn) {
1431 if (long_packet_type == QUIC_LPT_RETRY) {
1432 // Retry Packet: the next Initial Packet from the
1433 // client should start a new cryptographic handshake. Erase the
1434 // current "Initial DCID" such that the next client Initial
1435 // packet populates the new value.
1436 wmem_map_remove(quic_initial_connections, &conn->client_dcid_initial);
1437 memset(&conn->client_dcid_initial, 0, sizeof(quic_cid_t));
1438 conn->client_dcid_set = false;
1440 if (conn->server_cids.data.len == 0 && scid->len) {
1441 memcpy(&conn->server_cids.data, scid, sizeof(quic_cid_t));
1442 quic_cids_insert(&conn->server_cids.data, conn, true);
1445 break;
1449 static void
1450 quic_connection_destroy(void *data, void *user_data _U_)
1452 quic_info_data_t *conn = (quic_info_data_t *)data;
1453 quic_ciphers_reset(&conn->client_initial_ciphers);
1454 quic_ciphers_reset(&conn->server_initial_ciphers);
1455 quic_ciphers_reset(&conn->client_handshake_ciphers);
1456 quic_ciphers_reset(&conn->server_handshake_ciphers);
1458 quic_ciphers_reset(&conn->client_0rtt_ciphers);
1460 quic_hp_cipher_reset(&conn->client_pp.hp_cipher);
1461 quic_pp_cipher_reset(&conn->client_pp.pp_ciphers[0]);
1462 quic_pp_cipher_reset(&conn->client_pp.pp_ciphers[1]);
1464 quic_hp_cipher_reset(&conn->server_pp.hp_cipher);
1465 quic_pp_cipher_reset(&conn->server_pp.pp_ciphers[0]);
1466 quic_pp_cipher_reset(&conn->server_pp.pp_ciphers[1]);
1468 /* QUIC Connection tracking. }}} */
1470 /* QUIC Streams tracking and reassembly. {{{ */
1471 static reassembly_table quic_reassembly_table;
1473 /** Perform sequence analysis for STREAM frames. */
1474 static quic_stream_state *
1475 quic_get_stream_state(packet_info *pinfo, quic_info_data_t *quic_info, bool from_server, uint64_t stream_id)
1477 wmem_map_t **streams_p = from_server ? &quic_info->server_streams : &quic_info->client_streams;
1478 wmem_map_t *streams = *streams_p;
1479 quic_stream_state *stream = NULL;
1481 if (PINFO_FD_VISITED(pinfo)) {
1482 DISSECTOR_ASSERT(streams);
1483 stream = (quic_stream_state *)wmem_map_lookup(streams, &stream_id);
1484 DISSECTOR_ASSERT(stream);
1485 return stream;
1488 // Initialize per-connection and per-stream state.
1489 if (!streams) {
1490 streams = wmem_map_new(wmem_file_scope(), wmem_int64_hash, g_int64_equal);
1491 *streams_p = streams;
1492 } else {
1493 stream = (quic_stream_state *)wmem_map_lookup(streams, &stream_id);
1495 if (!stream) {
1496 stream = wmem_new0(wmem_file_scope(), quic_stream_state);
1497 stream->stream_id = stream_id;
1498 stream->multisegment_pdus = wmem_tree_new(wmem_file_scope());
1499 wmem_map_insert(streams, &stream->stream_id, stream);
1501 return stream;
1504 static void
1505 process_quic_stream(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
1506 quic_info_data_t *quic_info, quic_stream_info *stream_info,
1507 const quic_packet_info_t *quic_packet)
1509 if (quic_packet->packet_type != QUIC_LPT_0RTT && quic_info->app_handle) {
1510 tvbuff_t *next_tvb = tvb_new_subset_remaining(tvb, offset);
1511 // Traverse the STREAM frame tree.
1512 proto_tree *top_tree = proto_tree_get_parent_tree(tree);
1513 top_tree = proto_tree_get_parent_tree(top_tree);
1514 // Subdissectors MUST NOT assume that 'stream_info' remains valid after
1515 // returning. Copying the pointer will result in illegal memory access.
1516 call_dissector_with_data(quic_info->app_handle, next_tvb, pinfo, top_tree, stream_info);
1517 } else if (quic_packet->packet_type == QUIC_LPT_0RTT && quic_info->zrtt_app_handle) {
1518 tvbuff_t *next_tvb = tvb_new_subset_remaining(tvb, offset);
1519 proto_tree *top_tree = proto_tree_get_parent_tree(tree);
1520 top_tree = proto_tree_get_parent_tree(top_tree);
1521 call_dissector_with_data(quic_info->zrtt_app_handle, next_tvb, pinfo, top_tree, stream_info);
1526 * Reassemble stream data within a STREAM frame.
1528 static void
1529 desegment_quic_stream(tvbuff_t *tvb, int offset, int length, packet_info *pinfo,
1530 proto_tree *tree, quic_info_data_t *quic_info,
1531 quic_stream_info *stream_info,
1532 quic_stream_state *stream,
1533 const quic_packet_info_t *quic_packet)
1535 fragment_head *fh;
1536 int last_fragment_len;
1537 bool must_desegment;
1538 bool called_dissector;
1539 int another_pdu_follows;
1540 int deseg_offset;
1541 struct tcp_multisegment_pdu *msp;
1542 uint32_t seq = (uint32_t)stream_info->stream_offset;
1543 const uint32_t nxtseq = seq + (uint32_t)length;
1544 uint32_t reassembly_id = 0;
1546 // XXX fix the tvb accessors below such that no new tvb is needed.
1547 tvb = tvb_new_subset_length(tvb, 0, offset + length);
1549 again:
1550 fh = NULL;
1551 last_fragment_len = 0;
1552 must_desegment = false;
1553 called_dissector = false;
1554 another_pdu_follows = 0;
1555 msp = NULL;
1558 * Initialize these to assume no desegmentation.
1559 * If that's not the case, these will be set appropriately
1560 * by the subdissector.
1562 pinfo->desegment_offset = 0;
1563 pinfo->desegment_len = 0;
1566 * Initialize this to assume that this segment will just be
1567 * added to the middle of a desegmented chunk of data, so
1568 * that we should show it all as data.
1569 * If that's not the case, it will be set appropriately.
1571 deseg_offset = offset;
1573 /* Have we seen this PDU before (and is it the start of a multi-
1574 * segment PDU)?
1576 if ((msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32(stream->multisegment_pdus, seq)) &&
1577 nxtseq <= msp->nxtpdu) {
1578 // XXX: This also happens the second time through the data for an MSP normally
1579 // TODO show expert info for retransmission? Additional checks may be
1580 // necessary here to tell a retransmission apart from other (normal?)
1581 // conditions. See also similar code in packet-tcp.c.
1582 #if 0
1583 proto_tree_add_debug_text(tree, "TODO retransmission expert info frame %d stream_id=%" PRIu64 " offset=%d visited=%d reassembly_id=0x%08x",
1584 pinfo->num, stream->stream_id, offset, PINFO_FD_VISITED(pinfo), reassembly_id);
1585 #endif
1586 return;
1588 /* Else, find the most previous PDU starting before this sequence number */
1589 if (!msp && seq > 0) {
1590 msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(stream->multisegment_pdus, seq-1);
1591 /* Unless if we already fully reassembled the msp that covers seq-1
1592 * and seq is beyond the end of that msp. In that case this segment
1593 * will be the start of a new msp.
1595 if (msp && (msp->flags & MSP_FLAGS_GOT_ALL_SEGMENTS) &&
1596 seq >= msp->nxtpdu) {
1597 msp = NULL;
1602 // A single stream can contain multiple fragments (e.g. for HTTP/3
1603 // HEADERS and DATA frames). Let's hope that a single stream within a
1604 // QUIC packet does not contain multiple partial fragments, that would
1605 // result in a reassembly ID collision here. If that collision becomes
1606 // an issue, we would have to replace "msp->first_frame" with a new
1607 // field in "msp" that is initialized with "stream_info->stream_offset".
1608 #if 0
1609 uint64_t reassembly_id_data[2];
1610 reassembly_id_data[0] = stream_info->stream_id;
1611 reassembly_id_data[1] = msp ? msp->first_frame : pinfo->num;
1612 reassembly_id = wmem_strong_hash((const uint8_t *)&reassembly_id_data, sizeof(reassembly_id_data));
1613 #else
1614 // XXX for debug (visibility) purposes, do not use a hash but concatenate
1615 reassembly_id = ((msp ? msp->first_frame : pinfo->num) << 16) | (uint32_t)stream_info->stream_id;
1616 #endif
1619 if (msp && msp->seq <= seq && msp->nxtpdu > seq) {
1620 int len;
1622 if (!PINFO_FD_VISITED(pinfo)) {
1623 msp->last_frame=pinfo->num;
1624 msp->last_frame_time=pinfo->abs_ts;
1627 /* OK, this PDU was found, which means the segment continues
1628 * a higher-level PDU and that we must desegment it.
1630 if (msp->flags & MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT) {
1631 /* The dissector asked for the entire segment */
1632 len = tvb_captured_length_remaining(tvb, offset);
1633 } else {
1634 len = MIN(nxtseq, msp->nxtpdu) - seq;
1636 last_fragment_len = len;
1638 fh = fragment_add(&quic_reassembly_table, tvb, offset,
1639 pinfo, reassembly_id, NULL,
1640 seq - msp->seq, len,
1641 nxtseq < msp->nxtpdu);
1642 if (fh) {
1643 msp->flags |= MSP_FLAGS_GOT_ALL_SEGMENTS;
1645 if (!PINFO_FD_VISITED(pinfo)
1646 && msp->flags & MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT) {
1647 msp->flags &= (~MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT);
1649 /* If we consumed the entire segment there is no
1650 * other pdu starting anywhere inside this segment.
1651 * So update nxtpdu to point at least to the start
1652 * of the next segment.
1653 * (If the subdissector asks for even more data we
1654 * will advance nxtpdu even further later down in
1655 * the code.)
1657 msp->nxtpdu = nxtseq;
1660 if( (msp->nxtpdu < nxtseq)
1661 && (msp->nxtpdu >= seq)
1662 && (len > 0)) {
1663 another_pdu_follows=msp->nxtpdu - seq;
1665 } else {
1666 /* This segment was not found in our table, so it doesn't
1667 * contain a continuation of a higher-level PDU.
1668 * Call the normal subdissector.
1671 stream_info->offset = seq;
1672 process_quic_stream(tvb, offset, pinfo, tree, quic_info, stream_info, quic_packet);
1673 called_dissector = true;
1675 /* Did the subdissector ask us to desegment some more data
1676 * before it could handle the packet?
1677 * If so we'll have to handle that later.
1679 if (pinfo->desegment_len) {
1680 must_desegment = true;
1681 if (!PINFO_FD_VISITED(pinfo)) {
1682 if (msp)
1683 msp->flags &= ~MSP_FLAGS_GOT_ALL_SEGMENTS;
1687 * Set "deseg_offset" to the offset in "tvb"
1688 * of the first byte of data that the
1689 * subdissector didn't process.
1691 deseg_offset = offset + pinfo->desegment_offset;
1694 /* Either no desegmentation is necessary, or this is
1695 * segment contains the beginning but not the end of
1696 * a higher-level PDU and thus isn't completely
1697 * desegmented.
1699 fh = NULL;
1702 /* is it completely desegmented? */
1703 if (fh) {
1705 * Yes, we think it is.
1706 * We only call subdissector for the last segment.
1707 * Note that the last segment may include more than what
1708 * we needed.
1710 if (fh->reassembled_in == pinfo->num) {
1712 * OK, this is the last segment.
1713 * Let's call the subdissector with the desegmented data.
1716 tvbuff_t *next_tvb = tvb_new_chain(tvb, fh->tvb_data);
1717 add_new_data_source(pinfo, next_tvb, "Reassembled QUIC");
1718 stream_info->offset = seq;
1719 process_quic_stream(next_tvb, 0, pinfo, tree, quic_info, stream_info, quic_packet);
1720 called_dissector = true;
1722 int old_len = (int)(tvb_reported_length(next_tvb) - last_fragment_len);
1723 if (pinfo->desegment_len &&
1724 pinfo->desegment_offset <= old_len) {
1726 * "desegment_len" isn't 0, so it needs more
1727 * data for something - and "desegment_offset"
1728 * is before "old_len", so it needs more data
1729 * to dissect the stuff we thought was
1730 * completely desegmented (as opposed to the
1731 * stuff at the beginning being completely
1732 * desegmented, but the stuff at the end
1733 * being a new higher-level PDU that also
1734 * needs desegmentation).
1736 fragment_set_partial_reassembly(&quic_reassembly_table,
1737 pinfo, reassembly_id, NULL);
1739 /* Update msp->nxtpdu to point to the new next
1740 * pdu boundary.
1742 if (pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
1743 /* We want reassembly of at least one
1744 * more segment so set the nxtpdu
1745 * boundary to one byte into the next
1746 * segment.
1747 * This means that the next segment
1748 * will complete reassembly even if it
1749 * is only one single byte in length.
1750 * If this is an OoO segment, then increment the MSP end.
1752 msp->nxtpdu = MAX(seq + tvb_reported_length_remaining(tvb, offset), msp->nxtpdu) + 1;
1753 msp->flags |= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT;
1754 #if 0
1755 } else if (pinfo->desegment_len == DESEGMENT_UNTIL_FIN) {
1756 tcpd->fwd->flags |= TCP_FLOW_REASSEMBLE_UNTIL_FIN;
1757 #endif
1758 } else {
1759 if (seq + last_fragment_len >= msp->nxtpdu) {
1760 /* This is the segment (overlapping) the end of the MSP. */
1761 msp->nxtpdu = seq + last_fragment_len + pinfo->desegment_len;
1762 } else {
1763 /* This is a segment before the end of the MSP, so it
1764 * must be an out-of-order segmented that completed the
1765 * MSP. The requested additional data is relative to
1766 * that end.
1768 msp->nxtpdu += pinfo->desegment_len;
1772 /* Since we need at least some more data
1773 * there can be no pdu following in the
1774 * tail of this segment.
1776 another_pdu_follows = 0;
1777 offset += last_fragment_len;
1778 seq += last_fragment_len;
1779 if (tvb_captured_length_remaining(tvb, offset) > 0)
1780 goto again;
1781 } else {
1782 proto_item *frag_tree_item;
1783 proto_tree *parent_tree = proto_tree_get_parent(tree);
1784 show_fragment_tree(fh, &quic_stream_fragment_items,
1785 parent_tree, pinfo, next_tvb, &frag_tree_item);
1786 // TODO move tree item if needed.
1788 if(pinfo->desegment_len) {
1789 if (!PINFO_FD_VISITED(pinfo)) {
1790 must_desegment = true;
1791 if (msp)
1792 msp->flags &= ~MSP_FLAGS_GOT_ALL_SEGMENTS;
1794 /* See packet-tcp.h for details about this. */
1795 deseg_offset = fh->datalen - pinfo->desegment_offset;
1796 deseg_offset = tvb_reported_length(tvb) - deseg_offset;
1802 if (must_desegment) {
1804 uint32_t deseg_seq = seq + (deseg_offset - offset);
1806 if (!PINFO_FD_VISITED(pinfo)) {
1807 // TODO handle DESEGMENT_UNTIL_FIN if needed, maybe use the FIN bit?
1808 if ((nxtseq - deseg_seq) <= 1024*1024) {
1809 if(pinfo->desegment_len == DESEGMENT_ONE_MORE_SEGMENT) {
1810 /* The subdissector asked to reassemble using the
1811 * entire next segment.
1812 * Just ask reassembly for one more byte
1813 * but set this msp flag so we can pick it up
1814 * above.
1816 msp = pdu_store_sequencenumber_of_next_pdu(pinfo, deseg_seq,
1817 nxtseq+1, stream->multisegment_pdus);
1818 msp->flags |= MSP_FLAGS_REASSEMBLE_ENTIRE_SEGMENT;
1819 } else {
1820 msp = pdu_store_sequencenumber_of_next_pdu(pinfo,
1821 deseg_seq, nxtseq+pinfo->desegment_len, stream->multisegment_pdus);
1824 /* add this segment as the first one for this new pdu */
1825 fragment_add(&quic_reassembly_table, tvb, deseg_offset,
1826 pinfo, reassembly_id, NULL,
1827 0, nxtseq - deseg_seq,
1828 nxtseq < msp->nxtpdu);
1830 } else {
1831 /* If this is not the first time we have seen the packet, then
1832 * the MSP should already be created. Retrieve it to see if we
1833 * know what later frame the PDU is reassembled in.
1835 if (((struct tcp_multisegment_pdu *)wmem_tree_lookup32(stream->multisegment_pdus, deseg_seq))) {
1836 fh = fragment_get(&quic_reassembly_table, pinfo, reassembly_id, NULL);
1841 if (!called_dissector || pinfo->desegment_len != 0) {
1842 if (fh != NULL && fh->reassembled_in != 0 &&
1843 !(fh->flags & FD_PARTIAL_REASSEMBLY)) {
1845 * We know what frame this PDU is reassembled in;
1846 * let the user know.
1848 proto_item *item = proto_tree_add_uint(tree, hf_quic_reassembled_in, tvb, 0,
1849 0, fh->reassembled_in);
1850 proto_item_set_generated(item);
1853 /* TODO: Show what's left in the packet as a raw QUIC "segment", like
1854 * packet-tcp.c does here.
1857 pinfo->can_desegment = 0;
1858 pinfo->desegment_offset = 0;
1859 pinfo->desegment_len = 0;
1861 if (another_pdu_follows) {
1862 /* there was another pdu following this one. */
1863 pinfo->can_desegment = 2;
1864 offset += another_pdu_follows;
1865 seq += another_pdu_follows;
1866 goto again;
1870 static void
1871 dissect_quic_stream_payload(tvbuff_t *tvb, int offset, int length, packet_info *pinfo,
1872 proto_tree *tree, quic_info_data_t *quic_info,
1873 quic_stream_info *stream_info,
1874 quic_stream_state *stream,
1875 const quic_packet_info_t *quic_packet)
1877 /* QUIC application data is most likely not properly dissected when
1878 * reassembly is not enabled. Therefore we do not even offer "desegment"
1879 * preference to disable reassembly.
1882 if (length > 0) {
1883 /* Don't call a subdissector for a zero length segment. It won't
1884 * work for dissection (see #12368), and our methods of determing
1885 * if desegmentation is needed won't work either (#19497). If there
1886 * ever is an app_handle on top of QUIC that needs to be called with
1887 * a zero length segment, revisit this. (Cf. #15159)
1889 pinfo->can_desegment = 2;
1890 desegment_quic_stream(tvb, offset, length, pinfo, tree, quic_info, stream_info, stream, quic_packet);
1893 /* QUIC Streams tracking and reassembly. }}} */
1895 static bool quic_crypto_out_of_order = true;
1897 static reassembly_table quic_crypto_reassembly_table;
1899 typedef struct _quic_crypto_retrans_key {
1900 uint64_t pkt_number; /* QUIC packet number */
1901 int offset;
1902 uint32_t num; /* Frame number in the capture file, pinfo->num */
1903 } quic_crypto_retrans_key;
1905 static unsigned
1906 quic_crypto_retrans_hash(const void *k)
1908 const quic_crypto_retrans_key* key = (const quic_crypto_retrans_key*) k;
1910 #if 0
1911 return wmem_strong_hash((const uint8_t *)key, sizeof(quic_crypto_retrans_key));
1912 #endif
1913 unsigned hash_val;
1915 /* Most of the time the packet number in the capture file suffices. */
1916 hash_val = key->num;
1918 return hash_val;
1921 static int
1922 quic_crypto_retrans_equal(const void *k1, const void *k2)
1924 const quic_crypto_retrans_key* key1 = (const quic_crypto_retrans_key*) k1;
1925 const quic_crypto_retrans_key* key2 = (const quic_crypto_retrans_key*) k2;
1927 return (key1->num == key2->num) &&
1928 (key1->pkt_number == key2->pkt_number) &&
1929 (key1->offset == key2->offset);
1932 static quic_crypto_state *
1933 quic_get_crypto_state(packet_info *pinfo, quic_info_data_t *quic_info, bool from_server, const uint8_t encryption_level)
1935 wmem_map_t **cryptos_p = from_server ? &quic_info->server_crypto : &quic_info->client_crypto;
1936 wmem_map_t *cryptos = *cryptos_p;
1937 quic_crypto_state *crypto = NULL;
1939 if (PINFO_FD_VISITED(pinfo)) {
1940 DISSECTOR_ASSERT(cryptos);
1941 crypto = (quic_crypto_state *)wmem_map_lookup(cryptos, GUINT_TO_POINTER(encryption_level));
1942 DISSECTOR_ASSERT(crypto);
1943 return crypto;
1946 // Initialize per-connection and per-stream state.
1947 if (!cryptos) {
1948 cryptos = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
1949 *cryptos_p = cryptos;
1950 } else {
1951 crypto = (quic_crypto_state *)wmem_map_lookup(cryptos, GUINT_TO_POINTER(encryption_level));
1953 if (!crypto) {
1954 crypto = wmem_new0(wmem_file_scope(), quic_crypto_state);
1955 crypto->multisegment_pdus = wmem_tree_new(wmem_file_scope());
1956 crypto->retrans_offsets = wmem_map_new(wmem_file_scope(),
1957 quic_crypto_retrans_hash, quic_crypto_retrans_equal);
1958 crypto->encryption_level = encryption_level;
1959 wmem_map_insert(cryptos, GUINT_TO_POINTER(encryption_level), crypto);
1962 return crypto;
1965 static void
1966 process_quic_crypto(tvbuff_t *tvb, int offset, int length, packet_info *pinfo,
1967 proto_tree *tree, quic_crypto_info *crypto_info)
1970 tvbuff_t *next_tvb = tvb_new_subset_length(tvb, offset, length);
1971 col_set_writable(pinfo->cinfo, -1, false);
1973 * Dissect TLS handshake record. The Client/Server Hello (CH/SH)
1974 * are contained in the Initial Packet. 0-RTT keys are ready
1975 * after CH. HS + 1-RTT keys are ready after SH.
1976 * (Note: keys captured from the client might become available
1977 * after capturing the packets due to processing delay.)
1978 * These keys will be loaded in the first HS/0-RTT/1-RTT msg.
1980 call_dissector_with_data(tls13_handshake_handle, next_tvb, pinfo, tree, GUINT_TO_POINTER(crypto_info->offset));
1981 col_set_writable(pinfo->cinfo, -1, true);
1985 * Reassemble data within a CRYPTO frame.
1987 * This always gets handed to the TLS handshake dissector, which does its own
1988 * fragmentation handling, so all we do is the Out Of Order handling.
1989 * RFC 9001 4.1.3 "Sending and Receiving Handshake Messages"
1990 * "TLS is responsible for buffering handshake bytes that have arrived in order.
1991 * QUIC is responsible for buffering handshake bytes that arrive out of order or
1992 * for encryption levels that are not yet ready."
1994 * XXX: We are only buffering bytes that arive out of order within an encryption
1995 * level. Buffering for encryption levels that are not yet ready requires
1996 * determining that they are not ready (and they may never be ready from our
1997 * perspective if we don't have the keys.)
2000 static void
2001 desegment_quic_crypto(tvbuff_t *tvb, int offset, int length, packet_info *pinfo,
2002 proto_tree *tree, quic_info_data_t *quic_info _U_,
2003 quic_crypto_info *crypto_info,
2004 quic_crypto_state *crypto)
2006 fragment_head *fh;
2007 bool called_dissector;
2008 bool has_gap;
2009 struct tcp_multisegment_pdu *msp;
2011 /* XXX: There are a few elements in QUIC that can be up to 64 bit
2012 * integers that we're truncating to 32 bit here to re-use current
2013 * code.
2016 uint32_t seq = (uint32_t)crypto_info->crypto_offset;
2017 const uint32_t nxtseq = seq + (uint32_t)length;
2018 uint32_t reassembly_id = 0;
2020 fh = NULL;
2021 called_dissector = false;
2022 has_gap = false;
2023 msp = NULL;
2025 /* Look for retransmissions and overlap and discard them, only handing
2026 * new in order bytes to TLS.
2028 * It's possible to have multiple QUIC packets in the same capture
2029 * file frame, so to really be assured of no collision we need the
2030 * QUIC connection ID, the QUIC packet number space, the QUIC
2031 * packet number, and the offset within the QUIC packet in addition
2032 * to the frame number in the capture file.
2034 * crypto (a quic_crypto_state*) is already unique to the connection
2035 * ID and packet number space, so we need to store the other two
2036 * in its map.
2038 * Alternatively we could have the real offset in the capture
2039 * file frame, but we can't easily get that since the tvb is the
2040 * result of decryption.
2042 quic_crypto_retrans_key *tmp_key = wmem_new(pinfo->pool, quic_crypto_retrans_key);
2043 tmp_key->num = pinfo->num;
2044 tmp_key->offset = offset;
2045 tmp_key->pkt_number = crypto_info->packet_number;
2047 if (!PINFO_FD_VISITED(pinfo)) {
2048 if (crypto_info->crypto_offset + length <= crypto->max_contiguous_offset) {
2049 /* No new data. Remember this. */
2050 proto_tree_add_expert(tree, pinfo, &ei_quic_retransmission, tvb, offset, length);
2051 uint64_t* contiguous_offset = wmem_new(wmem_file_scope(), uint64_t);
2052 *contiguous_offset = crypto->max_contiguous_offset;
2053 quic_crypto_retrans_key *fkey = wmem_new(wmem_file_scope(), quic_crypto_retrans_key);
2054 *fkey = *tmp_key;
2055 wmem_map_insert(crypto->retrans_offsets, fkey, contiguous_offset);
2056 return;
2057 } else if (crypto_info->crypto_offset < crypto->max_contiguous_offset) {
2058 /* XXX: Retrieve the previous data and compare for conflicts? */
2059 proto_tree_add_expert(tree, pinfo, &ei_quic_overlap, tvb, offset, length);
2060 uint64_t overlap = crypto->max_contiguous_offset - crypto_info->crypto_offset;
2061 length -= (int)overlap;
2062 seq = (uint32_t)(crypto->max_contiguous_offset);
2063 offset += (uint32_t)(overlap);
2064 /* Store this offset */
2065 uint64_t* contiguous_offset = wmem_new(wmem_file_scope(), uint64_t);
2066 *contiguous_offset = crypto->max_contiguous_offset;
2067 quic_crypto_retrans_key *fkey = wmem_new(wmem_file_scope(), quic_crypto_retrans_key);
2068 *fkey = *tmp_key;
2069 wmem_map_insert(crypto->retrans_offsets, fkey, contiguous_offset);
2071 } else {
2072 /* Retrieve any per-frame state about retransmitted and overlapping
2073 * data.
2075 uint64_t *contiguous_offset = (uint64_t *)wmem_map_lookup(crypto->retrans_offsets, tmp_key);
2076 if (contiguous_offset != NULL) {
2077 if (crypto_info->crypto_offset + length <= *contiguous_offset) {
2078 proto_tree_add_expert(tree, pinfo, &ei_quic_retransmission, tvb, offset, length);
2079 return;
2080 } else if (crypto_info->crypto_offset < *contiguous_offset) {
2081 /* XXX: Retrieve the previous data and compare for conflicts? */
2082 proto_tree_add_expert(tree, pinfo, &ei_quic_overlap, tvb, offset, length);
2083 uint64_t overlap = *contiguous_offset - crypto_info->crypto_offset;
2084 length -= (int)overlap;
2085 seq = (uint32_t)(*contiguous_offset);
2086 offset += (uint32_t)(overlap);
2087 } else {
2088 DISSECTOR_ASSERT_NOT_REACHED();
2093 /* By doing the above we should not have any retransmissions from in
2094 * order bytes. Retransmission and overlaps in out of order bytes are
2095 * still possible, but those will be handled by adding them to the
2096 * msp fragments. TLS is also going to handle defragmenting (instead
2097 * of returning info about PDU ends via pinfo->desegment_offset and
2098 * pinfo->desegment_len), so we can make this simpler than for payload
2099 * streams or TCP.
2101 * Since TLS doesn't set pinfo->desegment_offset and pinfo->desegment_len,
2102 * we can't align our msps to PDU boundaries, and so we can't skip past
2103 * any missing out of order bytes to send TLS later whole received PDUs.
2106 /* Find the most recent msp that starts before this sequence number. */
2107 msp = (struct tcp_multisegment_pdu *)wmem_tree_lookup32_le(crypto->multisegment_pdus, seq);
2109 /* If we already fully reassembled that msp and seq is beyond its end
2110 * (the latter should always be the case since we're discarding
2111 * retransmitted bytes above), this segment isn't part of the msp.
2113 if (msp && (msp->flags & MSP_FLAGS_GOT_ALL_SEGMENTS) &&
2114 seq >= msp->nxtpdu) {
2115 msp = NULL;
2118 /* The TCP reassembly functions already use msp->seq as a tiebreaker in
2119 * case we do have more than one OOO reassembly in a given frame, which
2120 * happens with Chrome's "Chaos Protection".
2122 * XXX: It would be better to use functions that use the QUIC connection
2123 * instead of addresses and ports, since concurrent connections on the
2124 * same 5 tuple is possible, but using the frame number as well limits
2125 * problems to more unusual encapsulations.
2127 * RFC 9000 9. "Connection Migration": "An endpoint MUST NOT initiate
2128 * connection migration before the handshake is confirmed" so we shouldn't
2129 * have to worry about CRYPTO packets for the same connection being
2130 * fragmented on different 5-tuples. (There may be new CRYPTO packets
2131 * with session tickets later, but we should handle that.)
2133 reassembly_id = ((msp ? msp->first_frame : pinfo->num) << 8) | crypto->encryption_level;
2135 if (!PINFO_FD_VISITED(pinfo)) {
2136 has_gap = crypto->max_contiguous_offset < seq;
2138 if (!has_gap) {
2139 /* No gap, so either this is a standalone in order
2140 * segment, or it's part of our in progress out of
2141 * order MSP and we need to look at the MSP fragments
2142 * to see what the last contiguous offset is.
2143 * Advance the contiguous offset appropriately.
2145 * XXX: A slightly different approach would involve splitting
2146 * the MSP as now done in the TCP dissector. That would send
2147 * any new bytes to TLS sooner and is closer to what RFC 9001
2148 * recommends. It's less important to do so than in TCP, but
2149 * is a possible future improvement.
2151 if (msp) {
2152 fh = fragment_get(&quic_crypto_reassembly_table, pinfo, reassembly_id, msp);
2153 DISSECTOR_ASSERT(fh);
2154 /* The offsets in the fragment list are relative to msp->seq */
2155 uint32_t max = nxtseq - msp->seq;
2156 for (fragment_item *frag = fh->next; frag; frag = frag->next) {
2157 uint32_t frag_end = frag->offset + frag->len;
2158 if (frag->offset <= max && max < frag_end) {
2159 max = frag_end;
2162 crypto->max_contiguous_offset = max + msp->seq;
2163 } else {
2164 crypto->max_contiguous_offset = nxtseq;
2168 /* We always want to hand the entire segment to the TLS dissector.
2169 * So update nxtpdu to point at least to the start of the next segment.
2171 if (msp) {
2172 msp->nxtpdu = MAX(msp->nxtpdu, nxtseq);
2176 if (msp && msp->seq <= seq && msp->nxtpdu > seq) {
2177 if (!PINFO_FD_VISITED(pinfo)) {
2178 msp->last_frame=pinfo->num;
2179 msp->last_frame_time=pinfo->abs_ts;
2182 /* OK, this PDU was found, which means the segment continues
2183 * a higher-level PDU and that we must desegment it.
2185 fragment_reset_tot_len(&quic_crypto_reassembly_table, pinfo, reassembly_id, msp,
2186 MAX(nxtseq, msp->nxtpdu) - msp->seq);
2188 fh = fragment_add(&quic_crypto_reassembly_table, tvb, offset,
2189 pinfo, reassembly_id, msp,
2190 seq - msp->seq, length,
2191 nxtseq < msp->nxtpdu);
2192 if (fh) {
2193 msp->flags |= MSP_FLAGS_GOT_ALL_SEGMENTS;
2194 if (msp->flags & MSP_FLAGS_MISSING_FIRST_SEGMENT) {
2195 msp->first_frame_with_seq = seq; // Overloading this
2196 /* We use "first_frame_with_seq" to mean "the sequence number
2197 * of the fragment that completed the MSP" because many
2198 * CRYPTO frames can be at the same layer, so the normal
2199 * methods of determining the reassembled in fragment don't
2200 * work. (We could store the seq in last_frame instead.)
2202 msp->flags &= (~MSP_FLAGS_MISSING_FIRST_SEGMENT);
2205 } else if (has_gap) {
2206 /* We need to start a new Out of Order MSP on our first visit.
2207 * We shouldn't get here on a second visit.
2209 if (!PINFO_FD_VISITED(pinfo)) {
2210 msp = pdu_store_sequencenumber_of_next_pdu(pinfo, (uint32_t)crypto->max_contiguous_offset, nxtseq, crypto->multisegment_pdus);
2211 msp->flags |= MSP_FLAGS_MISSING_FIRST_SEGMENT;
2212 fh = fragment_add(&quic_crypto_reassembly_table, tvb, offset,
2213 pinfo, reassembly_id, msp,
2214 seq - msp->seq, length,
2215 nxtseq < msp->nxtpdu);
2217 } else {
2218 /* This segment was not found in our table, so it doesn't
2219 * contain a continuation of a higher-level PDU.
2220 * Call the normal subdissector.
2223 crypto_info->offset = seq;
2224 process_quic_crypto(tvb, offset, length, pinfo, tree, crypto_info);
2225 called_dissector = true;
2228 /* is it completely desegmented? */
2229 if (fh) {
2231 * Yes, we think it is.
2232 * We only call TLS for the segment that reassembled it.
2234 if (fh->reassembled_in == pinfo->num && seq == msp->first_frame_with_seq) {
2236 * OK, this is it.
2237 * Let's call the subdissector with the desegmented data.
2240 tvbuff_t *next_tvb = tvb_new_chain(tvb, fh->tvb_data);
2241 add_new_data_source(pinfo, next_tvb, "Reassembled QUIC CRYPTO");
2242 proto_item *frag_tree_item;
2243 /* XXX: Should we use the proto_tree_get_root for these?
2244 * There are PADDING and PINGs after the crypto, so maybe not?
2246 show_fragment_tree(fh, &quic_crypto_fragment_items, tree, pinfo, next_tvb, &frag_tree_item);
2247 crypto_info->offset = seq;
2248 process_quic_crypto(next_tvb, 0, tvb_captured_length(next_tvb), pinfo, tree, crypto_info);
2249 called_dissector = true;
2253 if (!called_dissector) {
2254 if (fh != NULL && fh->reassembled_in != 0 &&
2255 fh->reassembled_in != pinfo->num ) {
2257 * We know what frame this PDU is reassembled in;
2258 * let the user know.
2260 proto_item *item = proto_tree_add_uint(tree, hf_quic_reassembled_in, tvb, 0,
2261 0, fh->reassembled_in);
2262 proto_item_set_generated(item);
2267 static void
2268 dissect_quic_crypto_payload(tvbuff_t *tvb, int offset, int length, packet_info *pinfo,
2269 proto_tree *tree, quic_info_data_t *quic_info,
2270 quic_crypto_info *crypto_info,
2271 quic_crypto_state *crypto)
2273 /* Make sure that TLS can also desegment */
2274 pinfo->can_desegment = 2;
2275 if (quic_crypto_out_of_order) {
2276 desegment_quic_crypto(tvb, offset, length, pinfo, tree, quic_info, crypto_info, crypto);
2277 } else {
2278 crypto_info->offset = (uint32_t)crypto_info->crypto_offset;
2279 process_quic_crypto(tvb, offset, length, pinfo, tree, crypto_info);
2283 void
2284 quic_stream_add_proto_data(packet_info *pinfo, quic_stream_info *stream_info, void *proto_data)
2286 quic_stream_state *stream = quic_get_stream_state(pinfo, stream_info->quic_info, stream_info->from_server, stream_info->stream_id);
2287 stream->subdissector_private = proto_data;
2290 void *quic_stream_get_proto_data(packet_info *pinfo, quic_stream_info *stream_info)
2292 quic_stream_state *stream = quic_get_stream_state(pinfo, stream_info->quic_info, stream_info->from_server, stream_info->stream_id);
2293 return stream->subdissector_private;
2296 static int
2297 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)
2299 proto_item *ti_ft, *ti_ftflags, *ti_ftid, *ti;
2300 proto_tree *ft_tree, *ftflags_tree, *ftid_tree;
2301 uint64_t frame_type;
2302 int32_t lenft;
2303 unsigned orig_offset = offset;
2305 ti_ft = proto_tree_add_item(quic_tree, hf_quic_frame, tvb, offset, 1, ENC_NA);
2306 ft_tree = proto_item_add_subtree(ti_ft, ett_quic_ft);
2308 ti_ftflags = proto_tree_add_item_ret_varint(ft_tree, hf_quic_frame_type, tvb, offset, -1, ENC_VARINT_QUIC, &frame_type, &lenft);
2309 proto_item_set_text(ti_ft, "%s", rval_to_str_const((uint32_t)frame_type, quic_frame_type_vals, "Unknown"));
2310 offset += lenft;
2312 switch(frame_type){
2313 case FT_PADDING:{
2314 uint32_t pad_len;
2316 col_append_str(pinfo->cinfo, COL_INFO, ", PADDING");
2318 /* A padding frame consists of a single zero octet, but for brevity
2319 * sake let's combine multiple zeroes into a single field. */
2320 pad_len = 1 + tvb_skip_uint8(tvb, offset, tvb_reported_length_remaining(tvb, offset), '\0') - offset;
2321 ti = proto_tree_add_uint(ft_tree, hf_quic_padding_length, tvb, offset, 0, pad_len);
2322 proto_item_set_generated(ti);
2323 proto_item_append_text(ti_ft, " Length: %u", pad_len);
2324 offset += pad_len - 1;
2326 break;
2327 case FT_PING:{
2328 col_append_str(pinfo->cinfo, COL_INFO, ", PING");
2330 break;
2331 case FT_ACK:
2332 case FT_ACK_ECN:
2333 case FT_MP_ACK:
2334 case FT_MP_ACK_ECN:{
2335 uint64_t ack_range_count;
2336 int32_t lenvar;
2338 switch(frame_type){
2339 case FT_ACK:
2340 col_append_str(pinfo->cinfo, COL_INFO, ", ACK");
2341 break;
2342 case FT_ACK_ECN:
2343 col_append_str(pinfo->cinfo, COL_INFO, ", ACK_ECN");
2344 break;
2345 case FT_MP_ACK:
2346 col_append_str(pinfo->cinfo, COL_INFO, ", MP_ACK");
2347 proto_tree_add_item_ret_varint(ft_tree, hf_quic_mp_ack_path_identifier, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &lenvar);
2348 offset += lenvar;
2349 break;
2350 case FT_MP_ACK_ECN:
2351 col_append_str(pinfo->cinfo, COL_INFO, ", MP_ACK_ECN");
2352 proto_tree_add_item_ret_varint(ft_tree, hf_quic_mp_ack_path_identifier, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &lenvar);
2353 offset += lenvar;
2354 break;
2357 proto_tree_add_item_ret_varint(ft_tree, hf_quic_ack_largest_acknowledged, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &lenvar);
2358 offset += lenvar;
2360 proto_tree_add_item_ret_varint(ft_tree, hf_quic_ack_ack_delay, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &lenvar);
2361 offset += lenvar;
2363 proto_tree_add_item_ret_varint(ft_tree, hf_quic_ack_ack_range_count, tvb, offset, -1, ENC_VARINT_QUIC, &ack_range_count, &lenvar);
2364 offset += lenvar;
2366 proto_tree_add_item_ret_varint(ft_tree, hf_quic_ack_first_ack_range, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &lenvar);
2367 offset += lenvar;
2369 /* ACK Ranges - Repeated "Ack Range Count" */
2370 while (ack_range_count) {
2372 /* Gap To Next Block */
2373 proto_tree_add_item_ret_varint(ft_tree, hf_quic_ack_gap, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &lenvar);
2374 offset += lenvar;
2376 proto_tree_add_item_ret_varint(ft_tree, hf_quic_ack_ack_range, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &lenvar);
2377 offset += lenvar;
2379 ack_range_count--;
2382 /* ECN Counts. */
2383 if (frame_type == FT_ACK_ECN || frame_type == FT_MP_ACK_ECN ) {
2384 proto_tree_add_item_ret_varint(ft_tree, hf_quic_ack_ect0_count, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &lenvar);
2385 offset += lenvar;
2387 proto_tree_add_item_ret_varint(ft_tree, hf_quic_ack_ect1_count, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &lenvar);
2388 offset += lenvar;
2390 proto_tree_add_item_ret_varint(ft_tree, hf_quic_ack_ecn_ce_count, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &lenvar);
2391 offset += lenvar;
2394 break;
2395 case FT_RESET_STREAM:{
2396 uint64_t stream_id, error_code;
2397 int32_t len_streamid = 0, len_finalsize = 0, len_error_code = 0;
2399 col_append_str(pinfo->cinfo, COL_INFO, ", RS");
2401 proto_tree_add_item_ret_varint(ft_tree, hf_quic_rsts_stream_id, tvb, offset, -1, ENC_VARINT_QUIC, &stream_id, &len_streamid);
2402 offset += len_streamid;
2404 proto_item_append_text(ti_ft, " id=%" PRIu64, stream_id);
2405 col_append_fstr(pinfo->cinfo, COL_INFO, "(%" PRIu64 ")", stream_id);
2407 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);
2408 offset += len_error_code;
2410 proto_tree_add_item_ret_varint(ft_tree, hf_quic_rsts_final_size, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &len_finalsize);
2411 offset += len_finalsize;
2413 proto_item_append_text(ti_ft, " Error code: %#" PRIx64, error_code);
2415 break;
2416 case FT_STOP_SENDING:{
2417 int32_t len_streamid;
2418 uint64_t stream_id, error_code;
2419 int32_t len_error_code = 0;
2421 col_append_str(pinfo->cinfo, COL_INFO, ", SS");
2423 proto_tree_add_item_ret_varint(ft_tree, hf_quic_ss_stream_id, tvb, offset, -1, ENC_VARINT_QUIC, &stream_id, &len_streamid);
2424 offset += len_streamid;
2426 proto_item_append_text(ti_ft, " id=%" PRIu64, stream_id);
2427 col_append_fstr(pinfo->cinfo, COL_INFO, "(%" PRIu64 ")", stream_id);
2429 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);
2430 offset += len_error_code;
2432 proto_item_append_text(ti_ft, " Error code: %#" PRIx64, error_code);
2434 break;
2435 case FT_CRYPTO: {
2436 uint64_t crypto_offset, crypto_length;
2437 int32_t lenvar;
2438 col_append_str(pinfo->cinfo, COL_INFO, ", CRYPTO");
2439 proto_tree_add_item_ret_varint(ft_tree, hf_quic_crypto_offset, tvb, offset, -1, ENC_VARINT_QUIC, &crypto_offset, &lenvar);
2440 offset += lenvar;
2441 proto_tree_add_item_ret_varint(ft_tree, hf_quic_crypto_length, tvb, offset, -1, ENC_VARINT_QUIC, &crypto_length, &lenvar);
2442 offset += lenvar;
2443 proto_tree_add_item(ft_tree, hf_quic_crypto_crypto_data, tvb, offset, (uint32_t)crypto_length, ENC_NA);
2444 quic_crypto_state *crypto = quic_get_crypto_state(pinfo, quic_info, from_server, quic_packet->packet_type);
2445 quic_crypto_info crypto_info = {
2446 .packet_number = quic_packet->packet_number,
2447 .crypto_offset = crypto_offset,
2448 .from_server = from_server,
2450 dissect_quic_crypto_payload(tvb, offset, (int)crypto_length, pinfo, ft_tree, quic_info, &crypto_info, crypto);
2451 offset += (uint32_t)crypto_length;
2453 break;
2454 case FT_NEW_TOKEN: {
2455 uint64_t token_length;
2456 int32_t lenvar;
2458 col_append_str(pinfo->cinfo, COL_INFO, ", NT");
2460 proto_tree_add_item_ret_varint(ft_tree, hf_quic_nt_length, tvb, offset, -1, ENC_VARINT_QUIC, &token_length, &lenvar);
2461 offset += lenvar;
2463 proto_tree_add_item(ft_tree, hf_quic_nt_token, tvb, offset, (uint32_t)token_length, ENC_NA);
2464 offset += (uint32_t)token_length;
2466 break;
2467 case FT_STREAM_8:
2468 case FT_STREAM_9:
2469 case FT_STREAM_A:
2470 case FT_STREAM_B:
2471 case FT_STREAM_C:
2472 case FT_STREAM_D:
2473 case FT_STREAM_E:
2474 case FT_STREAM_F: {
2475 uint64_t stream_id, stream_offset = 0, length;
2476 int32_t lenvar;
2478 offset -= 1;
2480 col_append_str(pinfo->cinfo, COL_INFO, ", STREAM");
2482 ftflags_tree = proto_item_add_subtree(ti_ftflags, ett_quic_ftflags);
2483 proto_tree_add_item(ftflags_tree, hf_quic_stream_fin, tvb, offset, 1, ENC_NA);
2484 proto_tree_add_item(ftflags_tree, hf_quic_stream_len, tvb, offset, 1, ENC_NA);
2485 proto_tree_add_item(ftflags_tree, hf_quic_stream_off, tvb, offset, 1, ENC_NA);
2486 offset += 1;
2488 ti_ftid = proto_tree_add_item_ret_varint(ft_tree, hf_quic_stream_stream_id, tvb, offset, -1, ENC_VARINT_QUIC, &stream_id, &lenvar);
2489 ftid_tree = proto_item_add_subtree(ti_ftid, ett_quic_ftid);
2490 proto_tree_add_item_ret_varint(ftid_tree, hf_quic_stream_initiator, tvb, offset, -1, ENC_VARINT_QUIC, NULL, NULL);
2491 proto_tree_add_item_ret_varint(ftid_tree, hf_quic_stream_direction, tvb, offset, -1, ENC_VARINT_QUIC, NULL, NULL);
2492 offset += lenvar;
2494 proto_item_append_text(ti_ft, " id=%" PRIu64, stream_id);
2495 col_append_fstr(pinfo->cinfo, COL_INFO, "(%" PRIu64 ")", stream_id);
2497 proto_item_append_text(ti_ft, " fin=%d", !!(frame_type & FTFLAGS_STREAM_FIN));
2499 if (!PINFO_FD_VISITED(pinfo)) {
2500 quic_streams_add(pinfo, quic_info, stream_id);
2503 if (frame_type & FTFLAGS_STREAM_OFF) {
2504 proto_tree_add_item_ret_varint(ft_tree, hf_quic_stream_offset, tvb, offset, -1, ENC_VARINT_QUIC, &stream_offset, &lenvar);
2505 offset += lenvar;
2507 proto_item_append_text(ti_ft, " off=%" PRIu64, stream_offset);
2509 if (frame_type & FTFLAGS_STREAM_LEN) {
2510 proto_tree_add_item_ret_varint(ft_tree, hf_quic_stream_length, tvb, offset, -1, ENC_VARINT_QUIC, &length, &lenvar);
2511 offset += lenvar;
2512 } else {
2513 length = tvb_reported_length_remaining(tvb, offset);
2515 proto_item_append_text(ti_ft, " len=%" PRIu64 " dir=%s origin=%s", length,
2516 val64_to_str_const(!!(stream_id & FTFLAGS_STREAM_DIRECTION), quic_frame_id_direction, "unknown"),
2517 val64_to_str_const(!!(stream_id & FTFLAGS_STREAM_INITIATOR), quic_frame_id_initiator, "unknown"));
2519 proto_tree_add_item(ft_tree, hf_quic_stream_data, tvb, offset, (int)length, ENC_NA);
2520 if (have_tap_listener(quic_follow_tap)) {
2521 quic_follow_tap_data_t *follow_data = wmem_new0(pinfo->pool, quic_follow_tap_data_t);
2523 follow_data->tvb = tvb_new_subset_length(tvb, offset, (int)length);
2524 follow_data->stream_id = stream_id;
2525 follow_data->from_server = from_server;
2527 tap_queue_packet(quic_follow_tap, pinfo, follow_data);
2529 quic_stream_state *stream = quic_get_stream_state(pinfo, quic_info, from_server, stream_id);
2530 quic_stream_info stream_info = {
2531 .stream_id = stream_id,
2532 .stream_offset = stream_offset,
2533 .quic_info = quic_info,
2534 .from_server = from_server,
2536 dissect_quic_stream_payload(tvb, offset, (int)length, pinfo, ft_tree, quic_info, &stream_info, stream, quic_packet);
2537 offset += (int)length;
2539 break;
2540 case FT_MAX_DATA:{
2541 int32_t len_maximumdata;
2543 col_append_str(pinfo->cinfo, COL_INFO, ", MD");
2545 proto_tree_add_item_ret_varint(ft_tree, hf_quic_md_maximum_data, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &len_maximumdata);
2546 offset += len_maximumdata;
2548 break;
2549 case FT_MAX_STREAM_DATA:{
2550 int32_t len_streamid, len_maximumstreamdata;
2551 uint64_t stream_id;
2553 col_append_str(pinfo->cinfo, COL_INFO, ", MSD");
2555 proto_tree_add_item_ret_varint(ft_tree, hf_quic_msd_stream_id, tvb, offset, -1, ENC_VARINT_QUIC, &stream_id, &len_streamid);
2556 offset += len_streamid;
2558 proto_item_append_text(ti_ft, " id=%" PRIu64, stream_id);
2559 col_append_fstr(pinfo->cinfo, COL_INFO, "(%" PRIu64 ")", stream_id);
2561 proto_tree_add_item_ret_varint(ft_tree, hf_quic_msd_maximum_stream_data, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &len_maximumstreamdata);
2562 offset += len_maximumstreamdata;
2564 break;
2565 case FT_MAX_STREAMS_BIDI:
2566 case FT_MAX_STREAMS_UNI:{
2567 int32_t len_streamid;
2569 col_append_str(pinfo->cinfo, COL_INFO, ", MS");
2571 proto_tree_add_item_ret_varint(ft_tree, hf_quic_ms_max_streams, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &len_streamid);
2572 offset += len_streamid;
2574 break;
2575 case FT_DATA_BLOCKED:{
2576 int32_t len_offset;
2578 col_append_str(pinfo->cinfo, COL_INFO, ", DB");
2580 proto_tree_add_item_ret_varint(ft_tree, hf_quic_db_stream_data_limit, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &len_offset);
2581 offset += len_offset;
2583 break;
2584 case FT_STREAM_DATA_BLOCKED:{
2585 int32_t len_streamid, len_offset;
2586 uint64_t stream_id;
2588 col_append_str(pinfo->cinfo, COL_INFO, ", SDB");
2590 proto_tree_add_item_ret_varint(ft_tree, hf_quic_sdb_stream_id, tvb, offset, -1, ENC_VARINT_QUIC, &stream_id, &len_streamid);
2591 offset += len_streamid;
2593 proto_item_append_text(ti_ft, " id=%" PRIu64, stream_id);
2594 col_append_fstr(pinfo->cinfo, COL_INFO, "(%" PRIu64 ")", stream_id);
2596 proto_tree_add_item_ret_varint(ft_tree, hf_quic_sdb_stream_data_limit, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &len_offset);
2597 offset += len_offset;
2599 break;
2600 case FT_STREAMS_BLOCKED_BIDI:
2601 case FT_STREAMS_BLOCKED_UNI:{
2602 int32_t len_streamid;
2604 col_append_str(pinfo->cinfo, COL_INFO, ", SB");
2606 proto_tree_add_item_ret_varint(ft_tree, hf_quic_sb_stream_limit, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &len_streamid);
2607 offset += len_streamid;
2609 break;
2610 case FT_NEW_CONNECTION_ID:
2611 case FT_MP_NEW_CONNECTION_ID:{
2612 int32_t len_sequence;
2613 int32_t len_retire_prior_to;
2614 uint64_t seq_num = 0, path_id = 0;
2615 int32_t nci_length;
2616 int32_t lenvar = 0;
2617 bool valid_cid = false;
2619 switch(frame_type){
2620 case FT_NEW_CONNECTION_ID:
2621 col_append_str(pinfo->cinfo, COL_INFO, ", NCI");
2622 break;
2623 case FT_MP_NEW_CONNECTION_ID:
2624 col_append_str(pinfo->cinfo, COL_INFO, ", MP_NCI");
2625 proto_tree_add_item_ret_varint(ft_tree, hf_quic_mp_nci_path_identifier, tvb, offset, -1, ENC_VARINT_QUIC, &path_id, &lenvar);
2626 offset += lenvar;
2627 break;
2630 proto_tree_add_item_ret_varint(ft_tree, hf_quic_nci_sequence, tvb, offset, -1, ENC_VARINT_QUIC, &seq_num, &len_sequence);
2631 offset += len_sequence;
2633 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);
2634 offset += len_retire_prior_to;
2636 ti = proto_tree_add_item_ret_uint(ft_tree, hf_quic_nci_connection_id_length, tvb, offset, 1, ENC_BIG_ENDIAN, &nci_length);
2637 offset++;
2639 valid_cid = nci_length >= 1 && nci_length <= QUIC_MAX_CID_LENGTH;
2640 if (!valid_cid) {
2641 expert_add_info_format(pinfo, ti, &ei_quic_protocol_violation,
2642 "Connection ID Length must be between 1 and %d bytes", QUIC_MAX_CID_LENGTH);
2645 proto_tree_add_item(ft_tree, hf_quic_nci_connection_id, tvb, offset, nci_length, ENC_NA);
2646 quic_cid_t cid = {.len=0};
2647 if (valid_cid && quic_info) {
2648 tvb_memcpy(tvb, cid.cid, offset, nci_length);
2649 cid.len = nci_length;
2650 cid.seq_num = seq_num;
2651 cid.path_id = path_id;
2652 quic_connection_add_cid(quic_info, &cid, from_server);
2654 offset += nci_length;
2656 proto_tree_add_item(ft_tree, hf_quic_nci_stateless_reset_token, tvb, offset, 16, ENC_NA);
2657 if (valid_cid && quic_info) {
2658 quic_add_stateless_reset_token(pinfo, tvb, offset, &cid);
2660 offset += 16;
2662 break;
2663 case FT_RETIRE_CONNECTION_ID:
2664 case FT_MP_RETIRE_CONNECTION_ID:{
2665 int32_t len_sequence;
2666 int32_t lenvar;
2668 switch(frame_type){
2669 case FT_RETIRE_CONNECTION_ID:
2670 col_append_str(pinfo->cinfo, COL_INFO, ", RC");
2671 break;
2672 case FT_MP_RETIRE_CONNECTION_ID:
2673 col_append_str(pinfo->cinfo, COL_INFO, ", MP_RC");
2674 proto_tree_add_item_ret_varint(ft_tree, hf_quic_mp_rc_path_identifier, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &lenvar);
2675 offset += lenvar;
2676 break;
2679 proto_tree_add_item_ret_varint(ft_tree, hf_quic_rci_sequence, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &len_sequence);
2680 offset += len_sequence;
2682 break;
2683 case FT_PATH_CHALLENGE:{
2684 col_append_str(pinfo->cinfo, COL_INFO, ", PC");
2686 proto_tree_add_item(ft_tree, hf_quic_path_challenge_data, tvb, offset, 8, ENC_NA);
2687 offset += 8;
2689 break;
2690 case FT_PATH_RESPONSE:{
2691 col_append_str(pinfo->cinfo, COL_INFO, ", PR");
2693 proto_tree_add_item(ft_tree, hf_quic_path_response_data, tvb, offset, 8, ENC_NA);
2694 offset += 8;
2696 break;
2697 case FT_CONNECTION_CLOSE_TPT:
2698 case FT_CONNECTION_CLOSE_APP:
2699 case FT_PATH_ABANDON:{
2700 int32_t len_reasonphrase, len_frametype, len_error_code;
2701 uint64_t len_reason = 0;
2702 uint64_t error_code;
2703 const char *tls_alert = NULL;
2705 if ( frame_type == FT_PATH_ABANDON) {
2706 int32_t lenvar;
2707 col_append_str(pinfo->cinfo, COL_INFO, ", PA");
2708 proto_tree_add_item_ret_varint(ft_tree, hf_quic_mp_pa_path_identifier, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &lenvar);
2709 offset += lenvar;
2710 } else {
2711 col_append_str(pinfo->cinfo, COL_INFO, ", CC");
2713 if (frame_type == FT_CONNECTION_CLOSE_TPT) {
2714 proto_tree_add_item_ret_varint(ft_tree, hf_quic_cc_error_code, tvb, offset, -1, ENC_VARINT_QUIC, &error_code, &len_error_code);
2715 if ((error_code >> 8) == 1) { // CRYPTO_ERROR (0x1XX)
2716 tls_alert = try_val_to_str(error_code & 0xff, ssl_31_alert_description);
2717 if (tls_alert) {
2718 proto_tree_add_item(ft_tree, hf_quic_cc_error_code_tls_alert, tvb, offset + len_error_code - 1, 1, ENC_BIG_ENDIAN);
2721 offset += len_error_code;
2723 proto_tree_add_item_ret_varint(ft_tree, hf_quic_cc_frame_type, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &len_frametype);
2724 offset += len_frametype;
2725 } else { /* FT_CONNECTION_CLOSE_APP) */
2726 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);
2727 offset += len_error_code;
2731 proto_tree_add_item_ret_varint(ft_tree, hf_quic_cc_reason_phrase_length, tvb, offset, -1, ENC_VARINT_QUIC, &len_reason, &len_reasonphrase);
2732 offset += len_reasonphrase;
2734 proto_tree_add_item(ft_tree, hf_quic_cc_reason_phrase, tvb, offset, (uint32_t)len_reason, ENC_ASCII);
2735 offset += (uint32_t)len_reason;
2737 // Transport Error codes higher than 0x3fff are for Private Use.
2738 if (frame_type == FT_CONNECTION_CLOSE_TPT && error_code <= 0x3fff) {
2739 proto_item_append_text(ti_ft, " Error code: %s", rval_to_str((uint32_t)error_code, quic_transport_error_code_vals, "Unknown (%d)"));
2740 } else {
2741 proto_item_append_text(ti_ft, " Error code: %#" PRIx64, error_code);
2743 if (tls_alert) {
2744 proto_item_append_text(ti_ft, " (%s)", tls_alert);
2747 break;
2748 case FT_HANDSHAKE_DONE:
2749 col_append_str(pinfo->cinfo, COL_INFO, ", DONE");
2750 break;
2751 case FT_DATAGRAM:
2752 case FT_DATAGRAM_LENGTH:{
2753 int32_t dg_length;
2754 uint64_t length;
2755 col_append_str(pinfo->cinfo, COL_INFO, ", DG");
2756 if (frame_type == FT_DATAGRAM_LENGTH) {
2758 proto_tree_add_item_ret_varint(ft_tree, hf_quic_dg_length, tvb, offset, -1, ENC_VARINT_QUIC, &length, &dg_length);
2759 offset += dg_length;
2760 } else {
2761 length = (uint32_t) tvb_reported_length_remaining(tvb, offset);
2763 proto_tree_add_item(ft_tree, hf_quic_dg, tvb, offset, (uint32_t)length, ENC_NA);
2764 offset += (uint32_t)length;
2766 break;
2767 case FT_IMMEDIATE_ACK_DRAFT05:
2768 case FT_IMMEDIATE_ACK:
2769 col_append_str(pinfo->cinfo, COL_INFO, ", IA");
2770 break;
2771 case FT_ACK_FREQUENCY:{
2772 int32_t length;
2774 col_append_str(pinfo->cinfo, COL_INFO, ", AF");
2775 proto_tree_add_item_ret_varint(ft_tree, hf_quic_af_sequence_number, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &length);
2776 offset += (uint32_t)length;
2778 proto_tree_add_item_ret_varint(ft_tree, hf_quic_af_ack_eliciting_threshold, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &length);
2779 offset += (uint32_t)length;
2781 proto_tree_add_item_ret_varint(ft_tree, hf_quic_af_request_max_ack_delay, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &length);
2782 offset += (uint32_t)length;
2784 proto_tree_add_item_ret_varint(ft_tree, hf_quic_af_reordering_threshold, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &length);
2785 offset += (uint32_t)length;
2787 break;
2788 case FT_TIME_STAMP:{
2789 int32_t length;
2791 col_append_str(pinfo->cinfo, COL_INFO, ", TS");
2792 proto_tree_add_item_ret_varint(ft_tree, hf_quic_ts, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &length);
2793 offset += (uint32_t)length;
2796 break;
2797 case FT_PATH_STATUS:
2798 case FT_PATH_STANDBY:
2799 case FT_PATH_AVAILABLE:{
2800 int32_t length;
2802 col_append_str(pinfo->cinfo, COL_INFO, ", PS");
2803 proto_tree_add_item_ret_varint(ft_tree, hf_quic_mp_ps_path_identifier, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &length);
2804 offset += (uint32_t)length;
2806 proto_tree_add_item_ret_varint(ft_tree, hf_quic_mp_ps_path_status_sequence_number, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &length);
2807 offset += (uint32_t)length;
2809 if (frame_type == FT_PATH_STATUS ) {
2810 proto_tree_add_item_ret_varint(ft_tree, hf_quic_mp_ps_path_status, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &length);
2811 offset += (uint32_t)length;
2814 break;
2815 case FT_MAX_PATHS:{
2816 int32_t length;
2818 /* multipath draft-07: "If any of the endpoints does not advertise
2819 * the initial_max_paths transport parameter, then the endpoints
2820 * MUST NOT use any frame or mechanism defined in this document."
2822 * So we do not call quic_add_multipath here, and possibly should
2823 * set a expert info if MP is not supported (similar with other
2824 * MP frames.)
2826 col_append_str(pinfo->cinfo, COL_INFO, ", MP");
2827 proto_tree_add_item_ret_varint(ft_tree, hf_quic_mp_maximum_paths, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &length);
2828 offset += (uint32_t)length;
2830 break;
2831 case FT_MAX_PATH_ID:{
2832 int32_t length;
2834 col_append_str(pinfo->cinfo, COL_INFO, ", MPI");
2835 proto_tree_add_item_ret_varint(ft_tree, hf_quic_mp_maximum_path_identifier, tvb, offset, -1, ENC_VARINT_QUIC, NULL, &length);
2836 offset += (uint32_t)length;
2838 break;
2839 default:
2840 expert_add_info_format(pinfo, ti_ft, &ei_quic_ft_unknown, "Unknown Frame Type %#" PRIx64, frame_type);
2841 break;
2844 proto_item_set_len(ti_ft, offset - orig_offset);
2846 return offset;
2849 static bool
2850 quic_hp_cipher_init(quic_hp_cipher *hp_cipher, int hash_algo, uint8_t key_length, uint8_t *secret, uint32_t version);
2851 static bool
2852 quic_pp_cipher_init(quic_pp_cipher *pp_cipher, int hash_algo, uint8_t key_length, uint8_t *secret, uint32_t version);
2855 * Given a QUIC message (header + non-empty payload), the actual packet number,
2856 * try to decrypt it using the PP cipher.
2857 * As the header points to the original buffer with an encrypted packet number,
2858 * the (encrypted) packet number length is also included.
2860 * The actual packet number must be constructed according to
2861 * https://tools.ietf.org/html/draft-ietf-quic-transport-22#section-12.3
2863 static void
2864 quic_decrypt_message(quic_pp_cipher *pp_cipher, tvbuff_t *head, unsigned header_length,
2865 uint8_t first_byte, unsigned pkn_len, uint64_t packet_number, quic_decrypt_result_t *result, packet_info *pinfo)
2867 gcry_error_t err;
2868 uint8_t *header;
2869 uint8_t nonce[TLS13_AEAD_NONCE_LENGTH];
2870 uint8_t *buffer;
2871 uint8_t atag[16];
2872 unsigned buffer_length;
2873 const unsigned char **error = &result->error;
2874 quic_datagram *dgram_info;
2876 dgram_info = (quic_datagram *)p_get_proto_data(wmem_file_scope(), pinfo, proto_quic, 0);
2878 DISSECTOR_ASSERT(pp_cipher != NULL);
2879 DISSECTOR_ASSERT(pp_cipher->pp_cipher != NULL);
2880 DISSECTOR_ASSERT(pkn_len < header_length);
2881 DISSECTOR_ASSERT(1 <= pkn_len && pkn_len <= 4);
2882 // copy header, but replace encrypted first byte and PKN by plaintext.
2883 header = (uint8_t *)tvb_memdup(pinfo->pool, head, 0, header_length);
2884 header[0] = first_byte;
2885 for (unsigned i = 0; i < pkn_len; i++) {
2886 header[header_length - 1 - i] = (uint8_t)(packet_number >> (8 * i));
2889 /* Input is "header || ciphertext (buffer) || auth tag (16 bytes)" */
2890 buffer_length = tvb_captured_length_remaining(head, header_length + 16);
2891 if (buffer_length == 0) {
2892 *error = "Decryption not possible, ciphertext is too short";
2893 return;
2895 buffer = (uint8_t *)tvb_memdup(wmem_file_scope(), head, header_length, buffer_length);
2896 tvb_memcpy(head, atag, header_length + buffer_length, 16);
2898 memcpy(nonce, pp_cipher->pp_iv, TLS13_AEAD_NONCE_LENGTH);
2899 /* Packet number is left-padded with zeroes and XORed with write_iv */
2900 phton64(nonce + sizeof(nonce) - 8, pntoh64(nonce + sizeof(nonce) - 8) ^ packet_number);
2901 /* QUIC Multipath draft-07 also uses the lower 32 bits of the Path ID
2902 * (CID sequence number prior to draft-07), which MUST NOT go over 2^32
2903 * when multipath is used; also, the nonce must be at least 12 bytes.
2905 if (dgram_info && dgram_info->conn && quic_multipath_negotiated(dgram_info->conn)) {
2906 DISSECTOR_ASSERT_CMPINT(TLS13_AEAD_NONCE_LENGTH, >=, 12);
2907 phton32(nonce + sizeof(nonce) - 12, pntoh32(nonce + sizeof(nonce) - 12) ^ (UINT32_MAX & dgram_info->path_id));
2910 gcry_cipher_reset(pp_cipher->pp_cipher);
2911 err = gcry_cipher_setiv(pp_cipher->pp_cipher, nonce, TLS13_AEAD_NONCE_LENGTH);
2912 if (err) {
2913 *error = wmem_strdup_printf(wmem_file_scope(), "Decryption (setiv) failed: %s", gcry_strerror(err));
2914 return;
2917 /* associated data (A) is the contents of QUIC header */
2918 err = gcry_cipher_authenticate(pp_cipher->pp_cipher, header, header_length);
2919 if (err) {
2920 *error = wmem_strdup_printf(wmem_file_scope(), "Decryption (authenticate) failed: %s", gcry_strerror(err));
2921 return;
2924 /* Output ciphertext (C) */
2925 err = gcry_cipher_decrypt(pp_cipher->pp_cipher, buffer, buffer_length, NULL, 0);
2926 if (err) {
2927 *error = wmem_strdup_printf(wmem_file_scope(), "Decryption (decrypt) failed: %s", gcry_strerror(err));
2928 return;
2931 err = gcry_cipher_checktag(pp_cipher->pp_cipher, atag, 16);
2932 if (err) {
2933 *error = wmem_strdup_printf(wmem_file_scope(), "Decryption (checktag) failed: %s", gcry_strerror(err));
2934 return;
2937 result->error = NULL;
2938 result->data = buffer;
2939 result->data_len = buffer_length;
2942 static bool
2943 quic_hkdf_expand_label(int hash_algo, uint8_t *secret, unsigned secret_len, const char *label, uint8_t *out, unsigned out_len)
2945 const StringInfo secret_si = { secret, secret_len };
2946 unsigned char *out_mem = NULL;
2947 if (tls13_hkdf_expand_label(hash_algo, &secret_si, "tls13 ", label, out_len, &out_mem)) {
2948 memcpy(out, out_mem, out_len);
2949 wmem_free(NULL, out_mem);
2950 return true;
2952 return false;
2956 * Compute the client and server initial secrets given Connection ID "cid".
2958 * On success true is returned and the two initial secrets are set.
2959 * false is returned on error (see "error" parameter for the reason).
2961 static bool
2962 quic_derive_initial_secrets(const quic_cid_t *cid,
2963 uint8_t client_initial_secret[HASH_SHA2_256_LENGTH],
2964 uint8_t server_initial_secret[HASH_SHA2_256_LENGTH],
2965 uint32_t version,
2966 const char **error)
2969 * https://tools.ietf.org/html/draft-ietf-quic-tls-29#section-5.2
2971 * initial_salt = 0xafbfec289993d24c9e9786f19c6111e04390a899
2972 * initial_secret = HKDF-Extract(initial_salt, client_dst_connection_id)
2974 * client_initial_secret = HKDF-Expand-Label(initial_secret,
2975 * "client in", "", Hash.length)
2976 * server_initial_secret = HKDF-Expand-Label(initial_secret,
2977 * "server in", "", Hash.length)
2979 * Hash for handshake packets is SHA-256 (output size 32).
2981 static const uint8_t handshake_salt_draft_22[20] = {
2982 0x7f, 0xbc, 0xdb, 0x0e, 0x7c, 0x66, 0xbb, 0xe9, 0x19, 0x3a,
2983 0x96, 0xcd, 0x21, 0x51, 0x9e, 0xbd, 0x7a, 0x02, 0x64, 0x4a
2985 static const uint8_t handshake_salt_draft_23[20] = {
2986 0xc3, 0xee, 0xf7, 0x12, 0xc7, 0x2e, 0xbb, 0x5a, 0x11, 0xa7,
2987 0xd2, 0x43, 0x2b, 0xb4, 0x63, 0x65, 0xbe, 0xf9, 0xf5, 0x02,
2989 static const uint8_t handshake_salt_draft_29[20] = {
2990 0xaf, 0xbf, 0xec, 0x28, 0x99, 0x93, 0xd2, 0x4c, 0x9e, 0x97,
2991 0x86, 0xf1, 0x9c, 0x61, 0x11, 0xe0, 0x43, 0x90, 0xa8, 0x99
2993 static const uint8_t handshake_salt_v1[20] = {
2994 0x38, 0x76, 0x2c, 0xf7, 0xf5, 0x59, 0x34, 0xb3, 0x4d, 0x17,
2995 0x9a, 0xe6, 0xa4, 0xc8, 0x0c, 0xad, 0xcc, 0xbb, 0x7f, 0x0a
2997 static const uint8_t hanshake_salt_draft_q50[20] = {
2998 0x50, 0x45, 0x74, 0xEF, 0xD0, 0x66, 0xFE, 0x2F, 0x9D, 0x94,
2999 0x5C, 0xFC, 0xDB, 0xD3, 0xA7, 0xF0, 0xD3, 0xB5, 0x6B, 0x45
3001 static const uint8_t hanshake_salt_draft_t50[20] = {
3002 0x7f, 0xf5, 0x79, 0xe5, 0xac, 0xd0, 0x72, 0x91, 0x55, 0x80,
3003 0x30, 0x4c, 0x43, 0xa2, 0x36, 0x7c, 0x60, 0x48, 0x83, 0x10
3005 static const int8_t hanshake_salt_draft_t51[20] = {
3006 0x7a, 0x4e, 0xde, 0xf4, 0xe7, 0xcc, 0xee, 0x5f, 0xa4, 0x50,
3007 0x6c, 0x19, 0x12, 0x4f, 0xc8, 0xcc, 0xda, 0x6e, 0x03, 0x3d
3009 static const uint8_t handshake_salt_v2[20] = {
3010 0x0d, 0xed, 0xe3, 0xde, 0xf7, 0x00, 0xa6, 0xdb, 0x81, 0x93,
3011 0x81, 0xbe, 0x6e, 0x26, 0x9d, 0xcb, 0xf9, 0xbd, 0x2e, 0xd9
3014 gcry_error_t err;
3015 uint8_t secret[HASH_SHA2_256_LENGTH];
3017 if (version == 0x51303530) {
3018 err = hkdf_extract(GCRY_MD_SHA256, hanshake_salt_draft_q50, sizeof(hanshake_salt_draft_q50),
3019 cid->cid, cid->len, secret);
3020 } else if (version == 0x54303530) {
3021 err = hkdf_extract(GCRY_MD_SHA256, hanshake_salt_draft_t50, sizeof(hanshake_salt_draft_t50),
3022 cid->cid, cid->len, secret);
3023 } else if (version == 0x54303531) {
3024 err = hkdf_extract(GCRY_MD_SHA256, hanshake_salt_draft_t51, sizeof(hanshake_salt_draft_t51),
3025 cid->cid, cid->len, secret);
3026 } else if (is_quic_draft_max(version, 22)) {
3027 err = hkdf_extract(GCRY_MD_SHA256, handshake_salt_draft_22, sizeof(handshake_salt_draft_22),
3028 cid->cid, cid->len, secret);
3029 } else if (is_quic_draft_max(version, 28)) {
3030 err = hkdf_extract(GCRY_MD_SHA256, handshake_salt_draft_23, sizeof(handshake_salt_draft_23),
3031 cid->cid, cid->len, secret);
3032 } else if (is_quic_draft_max(version, 32)) {
3033 err = hkdf_extract(GCRY_MD_SHA256, handshake_salt_draft_29, sizeof(handshake_salt_draft_29),
3034 cid->cid, cid->len, secret);
3035 } else if (is_quic_draft_max(version, 34)) {
3036 err = hkdf_extract(GCRY_MD_SHA256, handshake_salt_v1, sizeof(handshake_salt_v1),
3037 cid->cid, cid->len, secret);
3038 } else {
3039 err = hkdf_extract(GCRY_MD_SHA256, handshake_salt_v2, sizeof(handshake_salt_v2),
3040 cid->cid, cid->len, secret);
3042 if (err) {
3043 *error = wmem_strdup_printf(wmem_packet_scope(), "Failed to extract secrets: %s", gcry_strerror(err));
3044 return false;
3047 if (!quic_hkdf_expand_label(GCRY_MD_SHA256, secret, sizeof(secret), "client in",
3048 client_initial_secret, HASH_SHA2_256_LENGTH)) {
3049 *error = "Key expansion (client) failed";
3050 return false;
3053 if (!quic_hkdf_expand_label(GCRY_MD_SHA256, secret, sizeof(secret), "server in",
3054 server_initial_secret, HASH_SHA2_256_LENGTH)) {
3055 *error = "Key expansion (server) failed";
3056 return false;
3059 *error = NULL;
3060 return true;
3064 * Maps a Packet Protection cipher to the Packet Number protection cipher.
3065 * See https://tools.ietf.org/html/draft-ietf-quic-tls-22#section-5.4.3
3067 static bool
3068 quic_get_pn_cipher_algo(int cipher_algo, int *hp_cipher_mode)
3070 switch (cipher_algo) {
3071 case GCRY_CIPHER_AES128:
3072 case GCRY_CIPHER_AES256:
3073 *hp_cipher_mode = GCRY_CIPHER_MODE_ECB;
3074 return true;
3075 case GCRY_CIPHER_CHACHA20:
3076 *hp_cipher_mode = GCRY_CIPHER_MODE_STREAM;
3077 return true;
3078 default:
3079 return false;
3084 * (Re)initialize the PNE/PP ciphers using the given cipher algorithm.
3085 * If the optional base secret is given, then its length MUST match the hash
3086 * algorithm output.
3088 static bool
3089 quic_hp_cipher_prepare(quic_hp_cipher *hp_cipher, int hash_algo, int cipher_algo, uint8_t *secret, const char **error, uint32_t version)
3091 /* Clear previous state (if any). */
3092 quic_hp_cipher_reset(hp_cipher);
3094 int hp_cipher_mode;
3095 if (!quic_get_pn_cipher_algo(cipher_algo, &hp_cipher_mode)) {
3096 *error = "Unsupported cipher algorithm";
3097 return false;
3100 if (gcry_cipher_open(&hp_cipher->hp_cipher, cipher_algo, hp_cipher_mode, 0)) {
3101 quic_hp_cipher_reset(hp_cipher);
3102 *error = "Failed to create HP cipher";
3103 return false;
3106 if (secret) {
3107 unsigned cipher_keylen = (uint8_t) gcry_cipher_get_algo_keylen(cipher_algo);
3108 if (!quic_hp_cipher_init(hp_cipher, hash_algo, cipher_keylen, secret, version)) {
3109 quic_hp_cipher_reset(hp_cipher);
3110 *error = "Failed to derive key material for HP cipher";
3111 return false;
3115 return true;
3117 static bool
3118 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)
3120 /* Clear previous state (if any). */
3121 quic_pp_cipher_reset(pp_cipher);
3123 int hp_cipher_mode;
3124 if (!quic_get_pn_cipher_algo(cipher_algo, &hp_cipher_mode)) {
3125 *error = "Unsupported cipher algorithm";
3126 return false;
3129 if (gcry_cipher_open(&pp_cipher->pp_cipher, cipher_algo, cipher_mode, 0)) {
3130 quic_pp_cipher_reset(pp_cipher);
3131 *error = "Failed to create PP cipher";
3132 return false;
3135 if (secret) {
3136 unsigned cipher_keylen = (uint8_t) gcry_cipher_get_algo_keylen(cipher_algo);
3137 if (!quic_pp_cipher_init(pp_cipher, hash_algo, cipher_keylen, secret, version)) {
3138 quic_pp_cipher_reset(pp_cipher);
3139 *error = "Failed to derive key material for PP cipher";
3140 return false;
3144 return true;
3146 static bool
3147 quic_ciphers_prepare(quic_ciphers *ciphers, int hash_algo, int cipher_algo, int cipher_mode, uint8_t *secret, const char **error, uint32_t version)
3149 return quic_hp_cipher_prepare(&ciphers->hp_cipher, hash_algo, cipher_algo, secret, error, version) &&
3150 quic_pp_cipher_prepare(&ciphers->pp_cipher, hash_algo, cipher_algo, cipher_mode, secret, error, version);
3154 static bool
3155 quic_create_initial_decoders(const quic_cid_t *cid, const char **error, quic_info_data_t *quic_info)
3157 uint8_t client_secret[HASH_SHA2_256_LENGTH];
3158 uint8_t server_secret[HASH_SHA2_256_LENGTH];
3160 if (!quic_derive_initial_secrets(cid, client_secret, server_secret, quic_info->version, error)) {
3161 return false;
3164 /* Packet numbers are protected with AES128-CTR,
3165 * initial packets are protected with AEAD_AES_128_GCM. */
3166 if (!quic_ciphers_prepare(&quic_info->client_initial_ciphers, GCRY_MD_SHA256,
3167 GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_GCM, client_secret, error, quic_info->version) ||
3168 !quic_ciphers_prepare(&quic_info->server_initial_ciphers, GCRY_MD_SHA256,
3169 GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_GCM, server_secret, error, quic_info->version)) {
3170 return false;
3173 return true;
3176 static bool
3177 quic_create_0rtt_decoder(unsigned i, char *early_data_secret, unsigned early_data_secret_len,
3178 quic_ciphers *ciphers, int *cipher_algo, uint32_t version)
3180 static const uint16_t tls13_ciphers[] = {
3181 0x1301, /* TLS_AES_128_GCM_SHA256 */
3182 0x1302, /* TLS_AES_256_GCM_SHA384 */
3183 0x1303, /* TLS_CHACHA20_POLY1305_SHA256 */
3184 0x1304, /* TLS_AES_128_CCM_SHA256 */
3185 0x1305, /* TLS_AES_128_CCM_8_SHA256 */
3187 if (i >= G_N_ELEMENTS(tls13_ciphers)) {
3188 // end of list
3189 return false;
3191 int cipher_mode = 0, hash_algo = 0;
3192 const char *error_ignored = NULL;
3193 if (tls_get_cipher_info(NULL, tls13_ciphers[i], cipher_algo, &cipher_mode, &hash_algo)) {
3194 unsigned hash_len = gcry_md_get_algo_dlen(hash_algo);
3195 if (hash_len == early_data_secret_len && quic_ciphers_prepare(ciphers, hash_algo, *cipher_algo, cipher_mode, early_data_secret, &error_ignored, version)) {
3196 return true;
3199 /* This cipher failed, but there are more to try. */
3200 quic_ciphers_reset(ciphers);
3201 return true;
3204 static bool
3205 quic_create_decoders(packet_info *pinfo, quic_info_data_t *quic_info, quic_ciphers *ciphers,
3206 bool from_server, TLSRecordType type, const char **error)
3208 if (!quic_info->hash_algo) {
3209 if (!tls_get_cipher_info(pinfo, 0, &quic_info->cipher_algo, &quic_info->cipher_mode, &quic_info->hash_algo)) {
3210 *error = "Unable to retrieve cipher information";
3211 return false;
3215 unsigned hash_len = gcry_md_get_algo_dlen(quic_info->hash_algo);
3216 char *secret = (char *)wmem_alloc0(pinfo->pool, hash_len);
3218 if (!tls13_get_quic_secret(pinfo, from_server, type, hash_len, hash_len, secret)) {
3219 *error = "Secrets are not available";
3220 return false;
3223 if (!quic_ciphers_prepare(ciphers, quic_info->hash_algo,
3224 quic_info->cipher_algo, quic_info->cipher_mode, secret, error, quic_info->version)) {
3225 return false;
3228 return true;
3232 * Tries to obtain the QUIC application traffic secrets.
3234 static bool
3235 quic_get_traffic_secret(packet_info *pinfo, int hash_algo, quic_pp_state_t *pp_state, bool from_client)
3237 unsigned hash_len = gcry_md_get_algo_dlen(hash_algo);
3238 char *secret = (char *)wmem_alloc0(pinfo->pool, hash_len);
3239 if (!tls13_get_quic_secret(pinfo, !from_client, TLS_SECRET_APP, hash_len, hash_len, secret)) {
3240 return false;
3242 pp_state->next_secret = (uint8_t *)wmem_memdup(wmem_file_scope(), secret, hash_len);
3243 return true;
3247 * Expands the secret (length MUST be the same as the "hash_algo" digest size)
3248 * and initialize cipher with the new key.
3250 static bool
3251 quic_hp_cipher_init(quic_hp_cipher *hp_cipher, int hash_algo, uint8_t key_length, uint8_t *secret, uint32_t version)
3253 unsigned char hp_key[256/8];
3254 unsigned hash_len = gcry_md_get_algo_dlen(hash_algo);
3255 char *label = !is_quic_v2(version) ? "quic hp" : "quicv2 hp";
3257 if (!quic_hkdf_expand_label(hash_algo, secret, hash_len, label, hp_key, key_length)) {
3258 return false;
3261 return gcry_cipher_setkey(hp_cipher->hp_cipher, hp_key, key_length) == 0;
3263 static bool
3264 quic_pp_cipher_init(quic_pp_cipher *pp_cipher, int hash_algo, uint8_t key_length, uint8_t *secret, uint32_t version)
3266 unsigned char write_key[256/8]; /* Maximum key size is for AES256 cipher. */
3267 unsigned hash_len = gcry_md_get_algo_dlen(hash_algo);
3268 char *key_label = !is_quic_v2(version) ? "quic key" : "quicv2 key";
3269 char *iv_label = !is_quic_v2(version) ? "quic iv" : "quicv2 iv";
3271 if (key_length > sizeof(write_key)) {
3272 return false;
3275 if (!quic_hkdf_expand_label(hash_algo, secret, hash_len, key_label, write_key, key_length) ||
3276 !quic_hkdf_expand_label(hash_algo, secret, hash_len, iv_label, pp_cipher->pp_iv, sizeof(pp_cipher->pp_iv))) {
3277 return false;
3280 return gcry_cipher_setkey(pp_cipher->pp_cipher, write_key, key_length) == 0;
3285 * Updates the packet protection secret to the next one.
3287 static void
3288 quic_update_key(uint32_t version, int hash_algo, quic_pp_state_t *pp_state)
3290 unsigned hash_len = gcry_md_get_algo_dlen(hash_algo);
3291 const char *label = is_quic_draft_max(version, 23) ? "traffic upd" : (is_quic_draft_max(version, 34) ? "quic ku" : "quicv2 ku");
3292 bool ret = quic_hkdf_expand_label(hash_algo, pp_state->next_secret, hash_len,
3293 label, pp_state->next_secret, hash_len);
3294 /* This must always succeed as our hash algorithm was already validated. */
3295 DISSECTOR_ASSERT(ret);
3299 * Retrieves the header protection cipher for short header packets and prepares
3300 * the packet protection cipher. The application layer protocol is also queried.
3302 static quic_hp_cipher *
3303 quic_get_1rtt_hp_cipher(packet_info *pinfo, quic_info_data_t *quic_info, bool from_server, const char **error)
3305 /* Keys were previously not available. */
3306 if (quic_info->skip_decryption) {
3307 return NULL;
3310 quic_pp_state_t *client_pp = &quic_info->client_pp;
3311 quic_pp_state_t *server_pp = &quic_info->server_pp;
3312 quic_pp_state_t *pp_state = !from_server ? client_pp : server_pp;
3314 /* Try to lookup secrets if not available. */
3315 if (!quic_info->client_pp.next_secret) {
3316 /* Query TLS for the cipher suite. */
3317 if (!tls_get_cipher_info(pinfo, 0, &quic_info->cipher_algo, &quic_info->cipher_mode, &quic_info->hash_algo)) {
3318 /* We end up here if:
3319 * no previous TLS handshake is found
3320 * the used ciphers are unsupported
3321 * some (unencrypted) padding is misdetected as SH coalesced packet
3322 Because of the third scenario, we can't set quic_info->skip_decryption
3323 to true; otherwise we will stop decrypting the entire session, even if
3324 we are able to.
3325 Unfortunately, this way, we lost the optimization that allows skipping checks
3326 for future packets in case the capture starts in midst of a
3327 connection where the handshake is not present.
3328 Note that even if we have a basic logic to detect unencrypted padding (via
3329 check_dcid_on_coalesced_packet()), there is not a proper way to detect it
3330 other than checking if the decryption successed
3332 *error = "Missing TLS handshake, unsupported ciphers or padding";
3333 return NULL;
3336 /* XXX: What if this is padding (or anything else) that is falsely
3337 * detected as a SH packet after the TLS handshake in Initial frames
3338 * but before the TLS handshake in the Handshake frames? The most
3339 * likely case is padding that starts with a byte that looks like
3340 * a short header when a 0 length DCID is being used. Then the check
3341 * above won't fail and we will retrieve the wrong TLS information,
3342 * including ALPN.
3345 /* Retrieve secrets for both the client and server. */
3346 if (!quic_get_traffic_secret(pinfo, quic_info->hash_algo, client_pp, true) ||
3347 !quic_get_traffic_secret(pinfo, quic_info->hash_algo, server_pp, false)) {
3348 quic_info->skip_decryption = true;
3349 *error = "Secrets are not available";
3350 return NULL;
3353 // Create initial cipher handles for Key Phase 0 using the 1-RTT keys.
3354 if (!quic_hp_cipher_prepare(&client_pp->hp_cipher, quic_info->hash_algo,
3355 quic_info->cipher_algo, client_pp->next_secret, error, quic_info->version) ||
3356 !quic_pp_cipher_prepare(&client_pp->pp_ciphers[0], quic_info->hash_algo,
3357 quic_info->cipher_algo, quic_info->cipher_mode, client_pp->next_secret, error, quic_info->version) ||
3358 !quic_hp_cipher_prepare(&server_pp->hp_cipher, quic_info->hash_algo,
3359 quic_info->cipher_algo, server_pp->next_secret, error, quic_info->version) ||
3360 !quic_pp_cipher_prepare(&server_pp->pp_ciphers[0], quic_info->hash_algo,
3361 quic_info->cipher_algo, quic_info->cipher_mode, server_pp->next_secret, error, quic_info->version)) {
3362 quic_info->skip_decryption = true;
3363 return NULL;
3365 // Rotate the 1-RTT key for the client and server for the next key update.
3366 quic_update_key(quic_info->version, quic_info->hash_algo, client_pp);
3367 quic_update_key(quic_info->version, quic_info->hash_algo, server_pp);
3369 // For efficiency, look up the application layer protocol once. The
3370 // handshake must have been completed before, so ALPN is known.
3371 const char *proto_name = tls_get_alpn(pinfo);
3372 if (proto_name) {
3373 quic_info->app_handle = dissector_get_string_handle(quic_proto_dissector_table, proto_name);
3374 // If no specific handle is found, alias "h3-*" to "h3" and "doq-*" to "doq"
3375 if (!quic_info->app_handle) {
3376 if (g_str_has_prefix(proto_name, "h3-")) {
3377 quic_info->app_handle = dissector_get_string_handle(quic_proto_dissector_table, "h3");
3378 } else if (g_str_has_prefix(proto_name, "doq-")) {
3379 quic_info->app_handle = dissector_get_string_handle(quic_proto_dissector_table, "doq");
3385 // Note: Header Protect cipher does not change after Key Update.
3386 return &pp_state->hp_cipher;
3390 * Tries to construct the appropriate cipher for the current key phase.
3391 * See also "PROTECTED PAYLOAD DECRYPTION" comment on top of this file.
3392 * Returns true if the cipher was newly created (and needs to be either
3393 * freed or added to the array of ciphers), false if an existing cipher
3394 * was returned.
3396 static bool
3397 quic_get_pp_cipher(quic_pp_cipher *pp_cipher, bool key_phase, quic_info_data_t *quic_info, bool from_server, uint64_t pkn)
3399 const char *error = NULL;
3401 /* Keys were previously not available. */
3402 if (quic_info->skip_decryption) {
3403 return false;
3406 quic_pp_state_t *client_pp = &quic_info->client_pp;
3407 quic_pp_state_t *server_pp = &quic_info->server_pp;
3408 quic_pp_state_t *pp_state = !from_server ? client_pp : server_pp;
3411 * If the key phase changed, try to decrypt the packet using the new cipher.
3412 * However, if the packet number is before we changed to the current phase,
3413 * try the previous cipher instead.
3414 * If that fails, then it is either a malicious packet or out-of-order.
3415 * '!!' is due to key_phase being a signed bitfield, it forces -1 into 1.
3417 if (key_phase != !!pp_state->key_phase && pkn > pp_state->changed_in_pkn) {
3418 memset(pp_cipher, 0, sizeof(quic_pp_cipher));
3419 if (!quic_pp_cipher_prepare(pp_cipher, quic_info->hash_algo,
3420 quic_info->cipher_algo, quic_info->cipher_mode, pp_state->next_secret, &error, quic_info->version)) {
3421 /* This should never be reached, if the parameters were wrong
3422 * before, then it should have set "skip_decryption". */
3423 REPORT_DISSECTOR_BUG("quic_pp_cipher_prepare unexpectedly failed: %s", error);
3424 return false;
3427 return true;
3430 *pp_cipher = pp_state->pp_ciphers[key_phase];
3431 return false;
3435 * After success decrypting payload, replaces the previous cipher for this
3436 * phase with the new one, and stores the packet number where this occurred.
3438 static void
3439 quic_set_pp_cipher(quic_pp_cipher *pp_cipher, bool key_phase, quic_info_data_t *quic_info, bool from_server, uint64_t pkn)
3441 /* Keys were previously not available. */
3442 if (quic_info->skip_decryption) {
3443 return;
3446 quic_pp_state_t *client_pp = &quic_info->client_pp;
3447 quic_pp_state_t *server_pp = &quic_info->server_pp;
3448 quic_pp_state_t *pp_state = !from_server ? client_pp : server_pp;
3451 * If the key phase changed, replace the old cipher at this phase
3452 * with the new one, since we succeeded.
3454 * XXX - Perhaps optimally we should have a dynamic array of ciphers,
3455 * and a tree storing the packet numbers at which they changed,
3456 * instead of storing only two ciphers at once. We could even try
3457 * more than one cipher for a given polarity when things are badly
3458 * out of order and missing. (Servers and clients are not supposed
3459 * to switch a second time until they have received acks for the
3460 * previous changes, but there can still be old outstanding packets.
3461 * See RFC 9001 6. Key Update.)
3463 if (key_phase != !!pp_state->key_phase && pkn > pp_state->changed_in_pkn) {
3465 /* Verified the cipher, use it from now on and rotate the key. */
3466 /* Note that HP cipher is not touched.
3467 https://tools.ietf.org/html/draft-ietf-quic-tls-32#section-5.4
3468 "The same header protection key is used for the duration of the
3469 connection, with the value not changing after a key update" */
3470 quic_pp_cipher_reset(&pp_state->pp_ciphers[key_phase]);
3471 pp_state->pp_ciphers[key_phase] = *pp_cipher;
3472 quic_update_key(quic_info->version, quic_info->hash_algo, pp_state);
3474 pp_state->key_phase = key_phase;
3475 pp_state->changed_in_pkn = pkn;
3480 * Process (protected) payload, adding the encrypted payload to the tree. If
3481 * decryption is possible, frame dissection is also attempted.
3483 * The given offset must correspond to the end of the QUIC header and begin of
3484 * the (protected) payload. Dissected frames are appended to "tree" and expert
3485 * info is attached to "ti" (the field with the encrypted payload).
3487 static void
3488 quic_process_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_item *ti, unsigned offset,
3489 quic_info_data_t *quic_info, quic_packet_info_t *quic_packet, bool from_server,
3490 quic_pp_cipher *pp_cipher, uint8_t first_byte, unsigned pkn_len)
3492 quic_decrypt_result_t *decryption = &quic_packet->decryption;
3495 * If no decryption error has occurred yet, try decryption on the first
3496 * pass and store the result for later use.
3498 if (!PINFO_FD_VISITED(pinfo)) {
3499 if (!quic_packet->decryption.error && quic_is_pp_cipher_initialized(pp_cipher)) {
3500 quic_decrypt_message(pp_cipher, tvb, offset, first_byte, pkn_len, quic_packet->packet_number, &quic_packet->decryption, pinfo);
3504 if (decryption->error) {
3505 expert_add_info_format(pinfo, ti, &ei_quic_decryption_failed,
3506 "Decryption failed: %s", decryption->error);
3507 } else if (decryption->data_len) {
3508 tvbuff_t *decrypted_tvb = tvb_new_child_real_data(tvb, decryption->data,
3509 decryption->data_len, decryption->data_len);
3510 add_new_data_source(pinfo, decrypted_tvb, "Decrypted QUIC");
3512 unsigned decrypted_offset = 0;
3513 while (tvb_reported_length_remaining(decrypted_tvb, decrypted_offset) > 0) {
3514 if (quic_info->version == 0x51303530 || quic_info->version == 0x54303530 || quic_info->version == 0x54303531) {
3515 decrypted_offset = dissect_gquic_frame_type(decrypted_tvb, pinfo, tree, decrypted_offset, pkn_len, quic_info->gquic_info);
3516 } else {
3517 decrypted_offset = dissect_quic_frame_type(decrypted_tvb, pinfo, tree, decrypted_offset, quic_info, quic_packet, from_server);
3520 } else if (quic_info->skip_decryption) {
3521 expert_add_info_format(pinfo, ti, &ei_quic_decryption_failed,
3522 "Decryption skipped because keys are not available.");
3526 static void
3527 quic_verify_retry_token(tvbuff_t *tvb, quic_packet_info_t *quic_packet, const quic_cid_t *odcid, uint32_t version)
3530 * Verify the Retry Integrity Tag using the fixed key from
3531 * https://tools.ietf.org/html/draft-ietf-quic-tls-29#section-5.8
3533 static const uint8_t key_v1[] = {
3534 0xbe, 0x0c, 0x69, 0x0b, 0x9f, 0x66, 0x57, 0x5a,
3535 0x1d, 0x76, 0x6b, 0x54, 0xe3, 0x68, 0xc8, 0x4e
3537 static const uint8_t nonce_v1[] = {
3538 0x46, 0x15, 0x99, 0xd3, 0x5d, 0x63, 0x2b, 0xf2, 0x23, 0x98, 0x25, 0xbb
3540 static const uint8_t key_draft_29[] = {
3541 0xcc, 0xce, 0x18, 0x7e, 0xd0, 0x9a, 0x09, 0xd0,
3542 0x57, 0x28, 0x15, 0x5a, 0x6c, 0xb9, 0x6b, 0xe1
3544 static const uint8_t key_v2[] = {
3545 0x8f, 0xb4, 0xb0, 0x1b, 0x56, 0xac, 0x48, 0xe2,
3546 0x60, 0xfb, 0xcb, 0xce, 0xad, 0x7c, 0xcc, 0x92
3548 static const uint8_t nonce_draft_29[] = {
3549 0xe5, 0x49, 0x30, 0xf9, 0x7f, 0x21, 0x36, 0xf0, 0x53, 0x0a, 0x8c, 0x1c
3551 static const uint8_t key_draft_25[] = {
3552 0x4d, 0x32, 0xec, 0xdb, 0x2a, 0x21, 0x33, 0xc8,
3553 0x41, 0xe4, 0x04, 0x3d, 0xf2, 0x7d, 0x44, 0x30,
3555 static const uint8_t nonce_draft_25[] = {
3556 0x4d, 0x16, 0x11, 0xd0, 0x55, 0x13, 0xa5, 0x52, 0xc5, 0x87, 0xd5, 0x75,
3558 static const uint8_t nonce_v2[] = {
3559 0xd8, 0x69, 0x69, 0xbc, 0x2d, 0x7c, 0x6d, 0x99, 0x90, 0xef, 0xb0, 0x4a
3561 gcry_cipher_hd_t h = NULL;
3562 gcry_error_t err;
3563 int pseudo_packet_tail_length = tvb_reported_length(tvb) - 16;
3565 DISSECTOR_ASSERT(pseudo_packet_tail_length > 0);
3567 err = gcry_cipher_open(&h, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_GCM, 0);
3568 DISSECTOR_ASSERT_HINT(err == 0, "create cipher");
3569 if (is_quic_draft_max(version, 28)) {
3570 err = gcry_cipher_setkey(h, key_draft_25, sizeof(key_draft_25));
3571 } else if (is_quic_draft_max(version, 32)) {
3572 err = gcry_cipher_setkey(h, key_draft_29, sizeof(key_draft_29));
3573 } else if (is_quic_draft_max(version, 34)) {
3574 err = gcry_cipher_setkey(h, key_v1, sizeof(key_v1));
3575 } else {
3576 err = gcry_cipher_setkey(h, key_v2, sizeof(key_v2));
3578 DISSECTOR_ASSERT_HINT(err == 0, "set key");
3579 if (is_quic_draft_max(version, 28)) {
3580 err = gcry_cipher_setiv(h, nonce_draft_25, sizeof(nonce_draft_25));
3581 } else if (is_quic_draft_max(version, 32)) {
3582 err = gcry_cipher_setiv(h, nonce_draft_29, sizeof(nonce_draft_29));
3583 } else if (is_quic_draft_max(version, 34)) {
3584 err = gcry_cipher_setiv(h, nonce_v1, sizeof(nonce_v1));
3585 } else {
3586 err = gcry_cipher_setiv(h, nonce_v2, sizeof(nonce_v2));
3588 DISSECTOR_ASSERT_HINT(err == 0, "set nonce");
3589 G_STATIC_ASSERT(sizeof(odcid->len) == 1);
3590 err = gcry_cipher_authenticate(h, odcid, 1 + odcid->len);
3591 DISSECTOR_ASSERT_HINT(err == 0, "aad1");
3592 err = gcry_cipher_authenticate(h, tvb_get_ptr(tvb, 0, pseudo_packet_tail_length), pseudo_packet_tail_length);
3593 DISSECTOR_ASSERT_HINT(err == 0, "aad2");
3594 // Plaintext is empty, there is no need to call gcry_cipher_encrypt.
3595 err = gcry_cipher_checktag(h, tvb_get_ptr(tvb, pseudo_packet_tail_length, 16), 16);
3596 if (err) {
3597 quic_packet->retry_integrity_failure = true;
3598 } else {
3599 quic_packet->retry_integrity_success = true;
3601 gcry_cipher_close(h);
3604 void
3605 quic_add_connection(packet_info *pinfo, quic_cid_t *cid)
3607 quic_datagram *dgram_info;
3609 dgram_info = (quic_datagram *)p_get_proto_data(wmem_file_scope(), pinfo, proto_quic, 0);
3610 if (dgram_info && dgram_info->conn) {
3611 quic_connection_add_cid(dgram_info->conn, cid, dgram_info->from_server);
3615 void
3616 quic_add_loss_bits(packet_info *pinfo, uint64_t value)
3618 quic_datagram *dgram_info;
3619 quic_info_data_t *conn;
3621 dgram_info = (quic_datagram *)p_get_proto_data(wmem_file_scope(), pinfo, proto_quic, 0);
3622 if (dgram_info && dgram_info->conn) {
3623 conn = dgram_info->conn;
3624 if (dgram_info->from_server) {
3625 conn->server_loss_bits_recv = true;
3626 if (value == 1) {
3627 conn->server_loss_bits_send = true;
3629 } else {
3630 conn->client_loss_bits_recv = true;
3631 if (value == 1) {
3632 conn->client_loss_bits_send = true;
3638 /* Check if "multipath" feature has been negotiated */
3639 static unsigned
3640 quic_multipath_negotiated(quic_info_data_t *conn)
3642 if (conn->client_multipath != conn->server_multipath)
3643 return 0;
3645 return conn->client_multipath;
3648 void
3649 quic_add_multipath(packet_info *pinfo, unsigned version)
3651 quic_datagram *dgram_info;
3652 quic_info_data_t *conn;
3654 dgram_info = (quic_datagram *)p_get_proto_data(wmem_file_scope(), pinfo, proto_quic, 0);
3655 if (dgram_info && dgram_info->conn) {
3656 conn = dgram_info->conn;
3657 if (dgram_info->from_server) {
3658 conn->server_multipath = version;
3659 } else {
3660 conn->client_multipath = version;
3665 void
3666 quic_add_grease_quic_bit(packet_info *pinfo)
3668 quic_datagram *dgram_info;
3669 quic_info_data_t *conn;
3671 dgram_info = (quic_datagram *)p_get_proto_data(wmem_file_scope(), pinfo, proto_quic, 0);
3672 if (dgram_info && dgram_info->conn) {
3673 conn = dgram_info->conn;
3674 if (dgram_info->from_server) {
3675 conn->server_grease_quic_bit = true;
3676 } else {
3677 conn->client_grease_quic_bit = true;
3682 static quic_info_data_t *
3683 quic_find_stateless_reset_token(packet_info *pinfo, tvbuff_t *tvb, bool *from_server)
3685 /* RFC 9000 10.3.1 Detecting a Stateless Reset
3686 * "The endpoint identifies a received datagram as a Stateless
3687 * Reset by comparing the last 16 bytes of the datagram with all
3688 * stateless reset tokens associated with the remote address on
3689 * which the datagram was received." That means we check all QUIC
3690 * connections on the 5-tuple (as when a nonzero Connection ID is
3691 * used there can be more than one.)
3693 quic_info_data_t* conn = quic_connection_from_conv(pinfo);
3694 const quic_cid_item_t *cids;
3696 while (conn) {
3697 bool conn_from_server = quic_connection_from_server_endpoint(pinfo, conn);
3698 cids = conn_from_server ? &conn->server_cids : &conn->client_cids;
3699 while (cids) {
3700 const quic_cid_t *cid = &cids->data;
3701 /* XXX: Ibid., "An endpoint MUST NOT check for any stateless
3702 * reset token associated with connection IDs it has not
3703 * used or for connection IDs that have been retired,"
3704 * so we ideally should track when they are retired.
3706 if (cid->reset_token_set &&
3707 !tvb_memeql(tvb, -16, cid->reset_token, 16) ) {
3708 *from_server = conn_from_server;
3709 return conn;
3711 cids = cids->next;
3713 conn = conn->prev;
3715 return NULL;
3718 void
3719 quic_add_stateless_reset_token(packet_info *pinfo, tvbuff_t *tvb, int offset, const quic_cid_t *cid)
3721 quic_datagram *dgram_info;
3722 quic_info_data_t *conn;
3723 quic_cid_item_t *cids;
3725 dgram_info = (quic_datagram *)p_get_proto_data(wmem_file_scope(), pinfo, proto_quic, 0);
3726 if (dgram_info && dgram_info->conn) {
3727 conn = dgram_info->conn;
3728 if (dgram_info->from_server) {
3729 cids = &conn->server_cids;
3730 } else {
3731 cids = &conn->client_cids;
3734 if (cid) {
3735 while (cids) {
3736 quic_cid_t *old_cid = &cids->data;
3737 if (quic_connection_equal(old_cid, cid) ) {
3738 tvb_memcpy(tvb, old_cid->reset_token, offset, 16);
3739 old_cid->reset_token_set = true;
3740 return;
3742 cids = cids->next;
3744 } else {
3745 /* If cid is NULL (this is a Handshake message),
3746 * add it to the most recent cid. (There could
3747 * have been a Retry.)
3749 while (cids->next != NULL) cids = cids->next;
3750 quic_cid_t *old_cid = &cids->data;
3751 tvb_memcpy(tvb, old_cid->reset_token, offset, 16);
3752 old_cid->reset_token_set = true;
3753 return;
3756 /* Failed to find cid. */
3757 return;
3760 static void
3761 quic_add_connection_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, quic_info_data_t *conn)
3763 proto_tree *ctree;
3764 proto_item *pi;
3766 ctree = proto_tree_add_subtree(tree, tvb, 0, 0, ett_quic_connection_info, NULL, "QUIC Connection information");
3767 if (!conn) {
3768 expert_add_info(pinfo, ctree, &ei_quic_connection_unknown);
3769 return;
3772 /* Set the conversation elements so that TLS and other subdissectors
3773 * calling find_conversation_pinfo() find this QUIC connection and
3774 * not all QUIC connections multiplexed on the same network 5-tuple.
3776 conversation_set_elements_by_id(pinfo, CONVERSATION_QUIC, conn->number);
3777 pi = proto_tree_add_uint(ctree, hf_quic_connection_number, tvb, 0, 0, conn->number);
3778 proto_item_set_generated(pi);
3779 #if 0
3780 proto_tree_add_debug_text(ctree, "Client CID: %s", cid_to_string(pinfo->pool, &conn->client_cids.data));
3781 proto_tree_add_debug_text(ctree, "Server CID: %s", cid_to_string(pinfo->pool, &conn->server_cids.data));
3782 // Note: for Retry, this value has been cleared before.
3783 proto_tree_add_debug_text(ctree, "InitialCID: %s", cid_to_string(pinfo->pool, &conn->client_dcid_initial));
3784 #endif
3788 * Dissects the common part after the first byte for packets using the Long
3789 * Header form.
3791 static int
3792 dissect_quic_long_header_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *quic_tree,
3793 unsigned offset, const quic_packet_info_t *quic_packet _U_,
3794 quic_cid_t *dcid, quic_cid_t *scid)
3796 uint32_t version;
3797 uint32_t dcil, scil;
3798 proto_item *ti;
3800 version = tvb_get_ntohl(tvb, offset);
3802 ti = proto_tree_add_item(quic_tree, hf_quic_version, tvb, offset, 4, ENC_BIG_ENDIAN);
3803 if ((version & 0x0F0F0F0F) == 0x0a0a0a0a) {
3804 proto_item_append_text(ti, " (Forcing Version Negotiation)");
3806 offset += 4;
3808 proto_tree_add_item_ret_uint(quic_tree, hf_quic_dcil, tvb, offset, 1, ENC_BIG_ENDIAN, &dcil);
3809 offset++;
3810 if (dcil) {
3811 proto_tree_add_item(quic_tree, hf_quic_dcid, tvb, offset, dcil, ENC_NA);
3812 // TODO expert info on CID mismatch with connection
3813 if (dcil <= QUIC_MAX_CID_LENGTH) {
3814 tvb_memcpy(tvb, dcid->cid, offset, dcil);
3815 dcid->len = dcil;
3817 offset += dcil;
3820 proto_tree_add_item_ret_uint(quic_tree, hf_quic_scil, tvb, offset, 1, ENC_BIG_ENDIAN, &scil);
3821 offset++;
3822 if (scil) {
3823 proto_tree_add_item(quic_tree, hf_quic_scid, tvb, offset, scil, ENC_NA);
3824 // TODO expert info on CID mismatch with connection
3825 if (scil <= QUIC_MAX_CID_LENGTH) {
3826 tvb_memcpy(tvb, scid->cid, offset, scil);
3827 scid->len = scil;
3829 offset += scil;
3832 if (dcid->len > 0) {
3833 col_append_fstr(pinfo->cinfo, COL_INFO, ", DCID=%s", cid_to_string(pinfo->pool, dcid));
3835 if (scid->len > 0) {
3836 col_append_fstr(pinfo->cinfo, COL_INFO, ", SCID=%s", cid_to_string(pinfo->pool, scid));
3838 return offset;
3841 /* Retry Packet dissection */
3842 static int
3843 dissect_quic_retry_packet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *quic_tree,
3844 quic_datagram *dgram_info _U_, quic_packet_info_t *quic_packet,
3845 const quic_cid_t *odcid, uint32_t version)
3847 unsigned offset = 0;
3848 quic_cid_t dcid = {.len=0}, scid = {.len=0};
3849 uint32_t odcil = 0;
3850 unsigned retry_token_len;
3851 proto_item *ti;
3853 if (is_quic_v2(version)) {
3854 proto_tree_add_item(quic_tree, hf_quic_long_packet_type_v2, tvb, offset, 1, ENC_NA);
3855 } else {
3856 proto_tree_add_item(quic_tree, hf_quic_long_packet_type, tvb, offset, 1, ENC_NA);
3858 offset += 1;
3859 col_set_str(pinfo->cinfo, COL_INFO, "Retry");
3861 offset = dissect_quic_long_header_common(tvb, pinfo, quic_tree, offset, quic_packet, &dcid, &scid);
3863 if (is_quic_draft_max(version, 24)) {
3864 proto_tree_add_item_ret_uint(quic_tree, hf_quic_odcil, tvb, offset, 1, ENC_NA, &odcil);
3865 offset++;
3866 proto_tree_add_item(quic_tree, hf_quic_odcid, tvb, offset, odcil, ENC_NA);
3867 offset += odcil;
3870 retry_token_len = tvb_reported_length_remaining(tvb, offset);
3871 // Remove length of Retry Integrity Tag
3872 if (!is_quic_draft_max(version, 24) && retry_token_len >= 16) {
3873 retry_token_len -= 16;
3875 proto_tree_add_item(quic_tree, hf_quic_retry_token, tvb, offset, retry_token_len, ENC_NA);
3876 offset += retry_token_len;
3878 if (!is_quic_draft_max(version, 24)) {
3879 // Verify the Retry Integrity Tag according to
3880 // https://tools.ietf.org/html/draft-ietf-quic-tls-25#section-5.8
3881 ti = proto_tree_add_item(quic_tree, hf_quic_retry_integrity_tag, tvb, offset, 16, ENC_NA);
3882 if (!PINFO_FD_VISITED(pinfo) && odcid) {
3883 // Skip validation if the Initial Packet is unknown, for example due
3884 // to packet loss in the capture file.
3885 quic_verify_retry_token(tvb, quic_packet, odcid, version);
3887 if (quic_packet->retry_integrity_failure) {
3888 expert_add_info(pinfo, ti, &ei_quic_bad_retry);
3889 } else if (!quic_packet->retry_integrity_success) {
3890 expert_add_info_format(pinfo, ti, &ei_quic_bad_retry,
3891 "Cannot verify Retry Packet due to unknown ODCID");
3892 } else {
3893 proto_item_append_text(ti, " [verified]");
3895 offset += 16;
3898 return offset;
3901 static int
3902 dissect_quic_long_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *quic_tree,
3903 quic_datagram *dgram_info, quic_packet_info_t *quic_packet)
3905 unsigned offset = 0;
3906 uint8_t long_packet_type;
3907 uint32_t version;
3908 quic_cid_t dcid = {.len=0}, scid = {.len=0};
3909 int32_t len_token_length;
3910 uint64_t token_length;
3911 int32_t len_payload_length;
3912 uint64_t payload_length;
3913 uint8_t first_byte = 0;
3914 quic_info_data_t *conn = dgram_info->conn;
3915 const bool from_server = dgram_info->from_server;
3916 quic_ciphers *ciphers = NULL;
3917 proto_item *ti;
3919 quic_extract_header(tvb, &long_packet_type, &version, &dcid, &scid);
3920 if (!PINFO_FD_VISITED(pinfo)) {
3921 quic_packet->packet_type = long_packet_type;
3923 if (conn) {
3924 if (long_packet_type == QUIC_LPT_INITIAL) {
3925 ciphers = !from_server ? &conn->client_initial_ciphers : &conn->server_initial_ciphers;
3926 } else if (long_packet_type == QUIC_LPT_0RTT && !from_server) {
3927 ciphers = &conn->client_0rtt_ciphers;
3928 } else if (long_packet_type == QUIC_LPT_HANDSHAKE) {
3929 ciphers = !from_server ? &conn->client_handshake_ciphers : &conn->server_handshake_ciphers;
3932 /* Prepare the Initial/Handshake cipher for header/payload decryption. */
3933 if (!PINFO_FD_VISITED(pinfo) && conn && ciphers) {
3934 #define DIGEST_MIN_SIZE 32 /* SHA256 */
3935 #define DIGEST_MAX_SIZE 48 /* SHA384 */
3936 const char *error = NULL;
3937 char early_data_secret[DIGEST_MAX_SIZE];
3938 unsigned early_data_secret_len = 0;
3939 if (long_packet_type == QUIC_LPT_INITIAL && !from_server &&
3940 quic_connection_equal(&dcid, &conn->client_dcid_initial)) {
3941 /* Create new decryption context based on the Client Connection
3942 * ID from the *very first* Client Initial packet. */
3943 quic_create_initial_decoders(&dcid, &error, conn);
3944 } else if (long_packet_type == QUIC_LPT_INITIAL && from_server &&
3945 version != conn->version) {
3946 /* Compatibile Version Negotiation: the server (probably) updated the connection version.
3947 We need to restart the ciphers since HP depends on version.
3948 If/when updating the ciphers is a bit tricky during Compatible Version Negotiation.
3949 TODO: do we really need to restart all the initial ciphers?
3951 conn->version = version;
3952 quic_ciphers_reset(ciphers);
3953 quic_create_initial_decoders(&conn->client_dcid_initial, &error, conn);
3954 } else if (long_packet_type == QUIC_LPT_0RTT) {
3955 early_data_secret_len = tls13_get_quic_secret(pinfo, false, TLS_SECRET_0RTT_APP, DIGEST_MIN_SIZE, DIGEST_MAX_SIZE, early_data_secret);
3956 if (early_data_secret_len == 0) {
3957 error = "Secrets are not available";
3959 } else if (long_packet_type == QUIC_LPT_HANDSHAKE) {
3960 if (!quic_are_ciphers_initialized(ciphers)) {
3961 quic_create_decoders(pinfo, conn, ciphers, from_server, TLS_SECRET_HANDSHAKE, &error);
3964 if (!error) {
3965 uint32_t pkn32 = 0;
3966 int hp_cipher_algo = long_packet_type != QUIC_LPT_INITIAL && conn ? conn->cipher_algo : GCRY_CIPHER_AES128;
3967 // PKN is after type(1) + version(4) + DCIL+DCID + SCIL+SCID
3968 unsigned pn_offset = 1 + 4 + 1 + dcid.len + 1 + scid.len;
3969 if (long_packet_type == QUIC_LPT_INITIAL) {
3970 pn_offset += tvb_get_varint(tvb, pn_offset, 8, &token_length, ENC_VARINT_QUIC);
3971 pn_offset += (unsigned)token_length;
3973 pn_offset += tvb_get_varint(tvb, pn_offset, 8, &payload_length, ENC_VARINT_QUIC);
3975 // Assume failure unless proven otherwise.
3976 error = "Header deprotection failed";
3977 if (long_packet_type != QUIC_LPT_0RTT) {
3978 if (quic_decrypt_header(tvb, pn_offset, &ciphers->hp_cipher, hp_cipher_algo, &first_byte, &pkn32, false)) {
3979 error = NULL;
3981 } else {
3982 // Cipher is not stored with 0-RTT data or key, perform trial decryption.
3983 for (unsigned i = 0; quic_create_0rtt_decoder(i, early_data_secret, early_data_secret_len, ciphers, &hp_cipher_algo, version); i++) {
3984 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)) {
3985 error = NULL;
3986 break;
3990 if (!error) {
3991 quic_set_full_packet_number(conn, quic_packet, dgram_info->path_id, from_server, first_byte, pkn32);
3992 quic_packet->first_byte = first_byte;
3995 if (error) {
3996 quic_packet->decryption.error = wmem_strdup(wmem_file_scope(), error);
3998 } else if (conn && quic_packet->pkn_len) {
3999 first_byte = quic_packet->first_byte;
4002 proto_tree_add_item(quic_tree, hf_quic_fixed_bit, tvb, offset, 1, ENC_NA);
4003 if (is_quic_v2(version)) {
4004 proto_tree_add_item(quic_tree, hf_quic_long_packet_type_v2, tvb, offset, 1, ENC_NA);
4005 } else {
4006 proto_tree_add_item(quic_tree, hf_quic_long_packet_type, tvb, offset, 1, ENC_NA);
4008 if (quic_packet->pkn_len) {
4009 ti = proto_tree_add_uint(quic_tree, hf_quic_long_reserved, tvb, offset, 1, first_byte);
4010 proto_item_set_generated(ti);
4011 ti = proto_tree_add_uint(quic_tree, hf_quic_packet_number_length, tvb, offset, 1, first_byte);
4012 proto_item_set_generated(ti);
4014 offset += 1;
4015 /* Trick: internal values in `long_packet_type` are always correctly mapped by V1 enum */
4016 col_set_str(pinfo->cinfo, COL_INFO, val_to_str_const(long_packet_type, quic_v1_long_packet_type_vals, "Long Header"));
4018 offset = dissect_quic_long_header_common(tvb, pinfo, quic_tree, offset, quic_packet, &dcid, &scid);
4020 if (long_packet_type == QUIC_LPT_INITIAL) {
4021 ti = proto_tree_add_item_ret_varint(quic_tree, hf_quic_token_length, tvb, offset, -1, ENC_VARINT_QUIC, &token_length, &len_token_length);
4022 offset += len_token_length;
4024 if (token_length) {
4025 proto_tree_add_item(quic_tree, hf_quic_token, tvb, offset, (uint32_t)token_length, ENC_NA);
4026 /* RFC 9287: "A client MAY also set the QUIC Bit to 0 in Initial,
4027 * Handshake, or 0-RTT packets that are sent prior to receiving
4028 * transport parameters from the server. However, a client MUST
4029 * NOT set the QUIC Bit to 0 unless the Initial packets it sends
4030 * include a token provided by the server in a NEW_TOKEN frame,
4031 * received less than 604800 seconds (7 days) prior on a
4032 * connection where the server also included the grease_quic_bit
4033 * transport parameter."
4035 if (from_server) {
4036 expert_add_info_format(pinfo, ti, &ei_quic_protocol_violation,
4037 "Initial packets sent by the server must set the Token Length field to 0");
4038 } else if (conn) {
4039 /* The client [may] know that the server supports greasing the
4040 * QUIC bit, and perhaps will do so. (We can't really test if
4041 * this token came less than 7 days ago from a server that
4042 * supports it, so we'll assume it might be to be safe.)
4044 conn->server_grease_quic_bit = true;
4046 offset += (unsigned)token_length;
4050 proto_tree_add_item_ret_varint(quic_tree, hf_quic_length, tvb, offset, -1, ENC_VARINT_QUIC, &payload_length, &len_payload_length);
4051 offset += len_payload_length;
4053 if (quic_packet->decryption.error) {
4054 expert_add_info_format(pinfo, quic_tree, &ei_quic_decryption_failed,
4055 "Failed to create decryption context: %s", quic_packet->decryption.error);
4056 return offset;
4058 if (!conn || quic_packet->pkn_len == 0) {
4059 // if not part of a connection, the full PKN cannot be reconstructed.
4060 expert_add_info_format(pinfo, quic_tree, &ei_quic_decryption_failed, "Failed to decrypt packet number");
4061 return offset;
4064 ti = proto_tree_add_uint64(quic_tree, hf_quic_packet_number, tvb, offset, quic_packet->pkn_len, quic_packet->packet_number);
4065 proto_item_set_generated(ti);
4067 offset += quic_packet->pkn_len;
4068 col_append_fstr(pinfo->cinfo, COL_INFO, ", PKN: %" PRIu64, quic_packet->packet_number);
4070 /* Payload */
4071 ti = proto_tree_add_item(quic_tree, hf_quic_payload, tvb, offset, -1, ENC_NA);
4073 if (conn) {
4074 quic_process_payload(tvb, pinfo, quic_tree, ti, offset,
4075 conn, quic_packet, from_server, &ciphers->pp_cipher, first_byte, quic_packet->pkn_len);
4077 if (!PINFO_FD_VISITED(pinfo) && !quic_packet->decryption.error) {
4078 // Packet number is verified to be valid, remember it.
4079 *quic_max_packet_number(conn, dgram_info->path_id, from_server, first_byte) = quic_packet->packet_number;
4081 // To be able to understand 0-RTT data sent we need to grab the ALPN the client wanted.
4082 if (long_packet_type == QUIC_LPT_INITIAL) {
4083 const char *proto_name = tls_get_client_alpn(pinfo);
4084 if (proto_name) {
4085 conn->zrtt_app_handle = dissector_get_string_handle(quic_proto_dissector_table, proto_name);
4086 // If no specific handle is found, alias "h3-*" to "h3" and "doq-*" to "doq"
4087 if (!conn->zrtt_app_handle) {
4088 if (g_str_has_prefix(proto_name, "h3-")) {
4089 conn->zrtt_app_handle = dissector_get_string_handle(quic_proto_dissector_table, "h3");
4090 } else if (g_str_has_prefix(proto_name, "doq-")) {
4091 conn->zrtt_app_handle = dissector_get_string_handle(quic_proto_dissector_table, "doq");
4097 offset += tvb_reported_length_remaining(tvb, offset);
4099 return offset;
4102 /* Check if "loss bits" feature has been negotiated */
4103 static bool
4104 quic_loss_bits_negotiated(quic_info_data_t *conn, bool from_server)
4106 if (from_server) {
4107 return conn->client_loss_bits_recv && conn->server_loss_bits_send;
4108 } else {
4109 return conn->server_loss_bits_recv && conn->client_loss_bits_send;
4113 static int
4114 dissect_quic_short_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *quic_tree,
4115 quic_datagram *dgram_info, quic_packet_info_t *quic_packet)
4117 unsigned offset = 0;
4118 quic_cid_t dcid = {.len=0};
4119 uint8_t first_byte = 0;
4120 bool key_phase = false;
4121 proto_item *ti;
4122 quic_pp_cipher pp_cipher = {0};
4123 quic_info_data_t *conn = dgram_info->conn;
4124 const bool from_server = dgram_info->from_server;
4125 bool loss_bits_negotiated = false;
4127 proto_item *pi = proto_tree_add_item(quic_tree, hf_quic_short, tvb, 0, -1, ENC_NA);
4128 proto_tree *hdr_tree = proto_item_add_subtree(pi, ett_quic_short_header);
4129 proto_tree_add_item(hdr_tree, hf_quic_header_form, tvb, 0, 1, ENC_NA);
4131 if (!PINFO_FD_VISITED(pinfo)) {
4132 quic_packet->packet_type = QUIC_SHORT_PACKET;
4134 if (conn) {
4135 dcid.len = from_server ? conn->client_cids.data.len : conn->server_cids.data.len;
4136 loss_bits_negotiated = quic_loss_bits_negotiated(conn, from_server);
4138 if (!PINFO_FD_VISITED(pinfo) && conn) {
4139 const char *error = NULL;
4140 uint32_t pkn32 = 0;
4141 quic_hp_cipher *hp_cipher = quic_get_1rtt_hp_cipher(pinfo, conn, from_server, &error);
4142 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)) {
4143 quic_set_full_packet_number(conn, quic_packet, dgram_info->path_id, from_server, first_byte, pkn32);
4144 quic_packet->first_byte = first_byte;
4146 if (error) {
4147 quic_packet->decryption.error = wmem_strdup(wmem_file_scope(), error);
4149 } else if (conn && quic_packet->pkn_len) {
4150 first_byte = quic_packet->first_byte;
4152 proto_tree_add_item(hdr_tree, hf_quic_fixed_bit, tvb, offset, 1, ENC_NA);
4153 proto_tree_add_item(hdr_tree, hf_quic_spin_bit, tvb, offset, 1, ENC_NA);
4154 /* Q and L bits are not protected by HP cipher */
4155 if (loss_bits_negotiated) {
4156 proto_tree_add_item(hdr_tree, hf_quic_q_bit, tvb, offset, 1, ENC_NA);
4157 proto_tree_add_item(hdr_tree, hf_quic_l_bit, tvb, offset, 1, ENC_NA);
4159 if (quic_packet->pkn_len) {
4160 key_phase = (first_byte & SH_KP) != 0;
4161 /* No room for reserved bits with "loss bits" feature is enable */
4162 if (!loss_bits_negotiated) {
4163 ti = proto_tree_add_uint(hdr_tree, hf_quic_short_reserved, tvb, offset, 1, first_byte);
4164 proto_item_set_generated(ti);
4166 ti = proto_tree_add_boolean(hdr_tree, hf_quic_key_phase, tvb, offset, 1, key_phase<<2);
4167 proto_item_set_generated(ti);
4168 ti = proto_tree_add_uint(hdr_tree, hf_quic_packet_number_length, tvb, offset, 1, first_byte);
4169 proto_item_set_generated(ti);
4171 offset += 1;
4173 col_clear(pinfo->cinfo, COL_INFO);
4174 col_append_fstr(pinfo->cinfo, COL_INFO, "Protected Payload (KP%u)", key_phase);
4176 /* Connection ID */
4177 if (dcid.len > 0) {
4178 proto_tree_add_item(hdr_tree, hf_quic_dcid, tvb, offset, dcid.len, ENC_NA);
4179 tvb_memcpy(tvb, dcid.cid, offset, dcid.len);
4180 offset += dcid.len;
4181 const char *dcid_str = cid_to_string(pinfo->pool, &dcid);
4182 col_append_fstr(pinfo->cinfo, COL_INFO, ", DCID=%s", dcid_str);
4183 proto_item_append_text(pi, " DCID=%s", dcid_str);
4186 if (quic_packet->decryption.error) {
4187 expert_add_info_format(pinfo, quic_tree, &ei_quic_decryption_failed,
4188 "Failed to create decryption context: %s", quic_packet->decryption.error);
4189 return offset;
4191 if (!conn || conn->skip_decryption || quic_packet->pkn_len == 0) {
4192 return offset;
4195 /* Packet Number */
4196 ti = proto_tree_add_uint64(hdr_tree, hf_quic_packet_number, tvb, offset, quic_packet->pkn_len, quic_packet->packet_number);
4197 proto_item_set_generated(ti);
4198 offset += quic_packet->pkn_len;
4199 col_append_fstr(pinfo->cinfo, COL_INFO, ", PKN: %" PRIu64, quic_packet->packet_number);
4200 proto_item_append_text(pi, " PKN=%" PRIu64, quic_packet->packet_number);
4202 /* Protected Payload */
4203 ti = proto_tree_add_item(hdr_tree, hf_quic_protected_payload, tvb, offset, -1, ENC_NA);
4205 if (conn) {
4206 bool phase_change = false;
4207 if (!PINFO_FD_VISITED(pinfo)) {
4208 phase_change = quic_get_pp_cipher(&pp_cipher, key_phase, conn, from_server, quic_packet->packet_number);
4211 quic_process_payload(tvb, pinfo, quic_tree, ti, offset,
4212 conn, quic_packet, from_server, &pp_cipher,
4213 first_byte, quic_packet->pkn_len);
4214 if (!PINFO_FD_VISITED(pinfo)) {
4215 if (!quic_packet->decryption.error) {
4216 // Packet number is verified to be valid, remember it.
4217 *quic_max_packet_number(conn, dgram_info->path_id, from_server, first_byte) = quic_packet->packet_number;
4218 // pp cipher is verified to be valid, remember if it new.
4219 quic_set_pp_cipher(&pp_cipher, key_phase, conn, from_server, quic_packet->packet_number);
4220 } else if (phase_change) {
4221 quic_pp_cipher_reset(&pp_cipher);
4225 offset += tvb_reported_length_remaining(tvb, offset);
4227 return offset;
4230 void
4231 quic_proto_tree_add_version(tvbuff_t *tvb, proto_tree *tree, int hfindex, unsigned offset)
4233 uint32_t version;
4234 proto_item *ti;
4236 ti = proto_tree_add_item_ret_uint(tree, hfindex, tvb, offset, 4, ENC_BIG_ENDIAN, &version);
4237 if ((version & 0x0F0F0F0F) == 0x0a0a0a0a) {
4238 proto_item_append_text(ti, " (GREASE)");
4242 static int
4243 dissect_quic_version_negotiation(tvbuff_t *tvb, packet_info *pinfo, proto_tree *quic_tree, const quic_packet_info_t *quic_packet)
4245 unsigned offset = 0;
4246 quic_cid_t dcid = {.len=0}, scid = {.len=0};
4248 col_set_str(pinfo->cinfo, COL_INFO, "Version Negotiation");
4250 proto_tree_add_item(quic_tree, hf_quic_vn_unused, tvb, offset, 1, ENC_NA);
4251 offset += 1;
4253 offset = dissect_quic_long_header_common(tvb, pinfo, quic_tree, offset, quic_packet, &dcid, &scid);
4255 /* Supported Version */
4256 while(tvb_reported_length_remaining(tvb, offset) > 0){
4257 quic_proto_tree_add_version(tvb, quic_tree, hf_quic_supported_version, offset);
4258 offset += 4;
4261 return offset;
4264 static int
4265 dissect_quic_forcing_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, "Forcing Version Negotiation");
4272 proto_tree_add_item(quic_tree, hf_quic_vn_unused, tvb, offset, 1, ENC_NA);
4273 offset += 1;
4275 offset = dissect_quic_long_header_common(tvb, pinfo, quic_tree, offset, quic_packet, &dcid, &scid);
4277 return offset;
4280 static unsigned quic_gso_heur_dcid_len = 8;
4282 static tvbuff_t *
4283 quic_get_message_tvb(tvbuff_t *tvb, const unsigned offset, const quic_cid_t *dcid)
4285 uint64_t token_length;
4286 uint64_t payload_length;
4287 uint8_t packet_type = tvb_get_uint8(tvb, offset);
4288 // Retry and VN packets cannot be coalesced (clarified in draft -14).
4289 if (packet_type & 0x80) {
4290 unsigned version = tvb_get_ntohl(tvb, offset + 1);
4291 uint8_t long_packet_type = quic_get_long_packet_type(packet_type, version);
4292 if (long_packet_type != QUIC_LPT_RETRY) {
4293 // long header form, check version
4294 // If this is not a VN packet but a valid long form, extract a subset.
4295 // TODO check for valid QUIC versions as future versions might change the format.
4296 if (version != 0) {
4297 unsigned length = 5; // flag (1 byte) + version (4 bytes)
4298 length += 1 + tvb_get_uint8(tvb, offset + length); // DCID
4299 length += 1 + tvb_get_uint8(tvb, offset + length); // SCID
4300 if (long_packet_type == QUIC_LPT_INITIAL) {
4301 length += tvb_get_varint(tvb, offset + length, 8, &token_length, ENC_VARINT_QUIC);
4302 length += (unsigned)token_length;
4304 length += tvb_get_varint(tvb, offset + length, 8, &payload_length, ENC_VARINT_QUIC);
4305 length += (unsigned)payload_length;
4306 if (payload_length <= INT32_MAX && length < (unsigned)tvb_reported_length_remaining(tvb, offset)) {
4307 return tvb_new_subset_length(tvb, offset, length);
4311 } else {
4312 if (quic_gso_heur_dcid_len && (dcid->len >= quic_gso_heur_dcid_len)) {
4313 unsigned dcid_offset = offset + 1;
4314 tvbuff_t *needle_tvb = tvb_new_subset_length(tvb, dcid_offset, dcid->len);
4315 int needle_pos = tvb_find_tvb(tvb, needle_tvb, dcid_offset + dcid->len);
4316 if (needle_pos != -1) {
4317 return tvb_new_subset_length(tvb, offset, needle_pos - offset - 1);
4322 // short header form, VN or unknown message, return remaining data.
4323 return tvb_new_subset_remaining(tvb, offset);
4326 static int
4327 dissect_quic_stateless_reset(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *quic_tree, const quic_datagram *dgram_info _U_)
4329 proto_item *ti;
4331 col_set_str(pinfo->cinfo, COL_INFO, "Stateless Reset");
4333 ti = proto_tree_add_uint(quic_tree, hf_quic_packet_length, tvb, 0, 0, tvb_reported_length(tvb));
4334 proto_item_set_generated(ti);
4335 ti = proto_tree_add_item(quic_tree, hf_quic_header_form, tvb, 0, 1, ENC_NA);
4336 if (tvb_get_uint8(tvb, 0) & 0x80) {
4337 /* RFC 9000 says that endpoints MUST treat any packets ending in a valid
4338 * stateless reset token as a Stateless Reset, even though they MUST
4339 * send them formatted as packets with short headers.
4341 expert_add_info_format(pinfo, ti, &ei_quic_protocol_violation,
4342 "Stateless Reset packets must be formatted as with short header");
4344 proto_tree_add_item(quic_tree, hf_quic_fixed_bit, tvb, 0, 1, ENC_NA);
4345 proto_tree_add_bits_item(quic_tree, hf_quic_unpredictable_bits, tvb, 2, (tvb_reported_length(tvb) - 16)*8 - 2, ENC_NA);
4346 proto_tree_add_item(quic_tree, hf_quic_stateless_reset_token, tvb, tvb_reported_length(tvb)-16, 16, ENC_NA);
4348 return tvb_reported_length(tvb);
4352 * Extracts necessary information from header to find any existing connection.
4353 * There are two special values for "long_packet_type":
4354 * * QUIC_SHORT_PACKET for short header packets;
4355 * * QUIC_LPT_VER_NEG for Version Negotiation packets.
4356 * DCID and SCID are not modified unless available. For short header packets,
4357 * DCID length is unknown, so the caller should truncate it as needed.
4359 static void
4360 quic_extract_header(tvbuff_t *tvb, uint8_t *long_packet_type, uint32_t *version,
4361 quic_cid_t *dcid, quic_cid_t *scid)
4363 unsigned offset = 0;
4365 uint8_t packet_type = tvb_get_uint8(tvb, offset);
4366 bool is_long_header = packet_type & 0x80;
4368 offset++;
4370 if (is_long_header) {
4371 // long header form
4372 *version = tvb_get_ntohl(tvb, offset);
4373 *long_packet_type = quic_get_long_packet_type(packet_type, *version);
4374 } else {
4375 // short header form, store dummy value that is not a long packet type.
4376 *long_packet_type = QUIC_SHORT_PACKET;
4380 if (is_long_header) {
4381 /* VN packets don't have any real packet type field, even if they have
4382 a long header: use a dummy value */
4383 if (*version == 0x00000000)
4384 *long_packet_type = QUIC_LPT_VER_NEG;
4386 // skip version
4387 offset += 4;
4389 // read DCID and SCID (both are prefixed by a length byte).
4390 uint8_t dcil = tvb_get_uint8(tvb, offset);
4391 offset++;
4393 if (dcil && dcil <= QUIC_MAX_CID_LENGTH) {
4394 tvb_memcpy(tvb, dcid->cid, offset, dcil);
4395 dcid->len = dcil;
4397 offset += dcil;
4399 uint8_t scil = tvb_get_uint8(tvb, offset);
4400 offset++;
4401 if (scil && scil <= QUIC_MAX_CID_LENGTH) {
4402 tvb_memcpy(tvb, scid->cid, offset, scil);
4403 scid->len = scil;
4405 } else {
4406 // Definitely not draft -10, set version to dummy value.
4407 *version = 0;
4408 // For short headers, the DCID length is unknown and could be 0 or
4409 // anything from 1 to 20 bytes. Copy the maximum possible and let the
4410 // consumer truncate it as necessary.
4411 tvb_memcpy(tvb, dcid->cid, offset, QUIC_MAX_CID_LENGTH);
4412 dcid->len = QUIC_MAX_CID_LENGTH;
4417 * Sanity check on (coalesced) packet.
4418 * https://tools.ietf.org/html/draft-ietf-quic-transport-32#section-12.2
4419 * "Senders MUST NOT coalesce QUIC packets with different connection IDs
4420 * into a single UDP datagram"
4421 * For the first packet of the datagram, we simply save the DCID for later usage (no real check).
4422 * For any subsequent packets, we control if DCID is valid.
4423 * XXX: Generic Segmentation Offload (GSO) captures from Linux create headaches
4424 * here, and even more so with short header packets. (#19109)
4426 static bool
4427 check_dcid_on_coalesced_packet(tvbuff_t *tvb, const quic_datagram *dgram_info,
4428 unsigned offset, quic_cid_t *first_packet_dcid)
4430 bool is_first_packet = (offset == 0);
4431 uint8_t first_byte, dcid_len;
4432 quic_cid_t dcid = {.len=0};
4433 quic_info_data_t *conn = dgram_info->conn;
4434 bool from_server = dgram_info->from_server;
4435 bool grease_quic_bit;
4437 first_byte = tvb_get_uint8(tvb, offset);
4438 offset++;
4439 if (first_byte & 0x80) {
4440 offset += 4; /* Skip version */
4441 dcid_len = tvb_get_uint8(tvb, offset);
4442 offset++;
4443 if (dcid_len && dcid_len <= QUIC_MAX_CID_LENGTH) {
4444 dcid.len = dcid_len;
4445 tvb_memcpy(tvb, dcid.cid, offset, dcid.len);
4447 } else {
4448 if (conn) {
4449 dcid.len = from_server ? conn->client_cids.data.len : conn->server_cids.data.len;
4450 if (dcid.len) {
4451 tvb_memcpy(tvb, dcid.cid, offset, dcid.len);
4453 } else {
4454 /* If we don't have a valid quic_info_data_t structure for this flow,
4455 we can't really validate the CID. */
4456 return true;
4460 if (conn) {
4461 grease_quic_bit = from_server ? conn->client_grease_quic_bit : conn->server_grease_quic_bit;
4462 } else {
4463 /* Assume we're allowed to grease the Fixed bit if no connection. */
4464 grease_quic_bit = true;
4467 if (is_first_packet) {
4468 *first_packet_dcid = dcid;
4469 return true; /* Nothing to check */
4472 if (!grease_quic_bit && (first_byte & 0x40) == 0) {
4473 return false;
4476 const quic_packet_info_t *last_packet = &dgram_info->first_packet;
4477 while (last_packet->next) {
4478 last_packet = last_packet->next;
4480 /* We should not see any Short Header (1-RTT) packets before the 1-RTT keys
4481 * have been negotiated. Under normal circumstances, that means that if the
4482 * last QUIC packet in the frame before this one is an Initial packet or a
4483 * 0-RTT packet, then this cannot be a SH packet but instead is presumably
4484 * padding data.
4486 if (last_packet->packet_type == QUIC_LPT_INITIAL ||
4487 last_packet->packet_type == QUIC_LPT_0RTT) {
4488 if ((first_byte & 0x80) == 0) {
4489 return false;
4493 #if 0
4494 /* XXX - That seems almost certainly true for Initial packets, but due
4495 * to packet loss, 0-RTT packets might get resent and interleaved with
4496 * Handshake packets, see
4497 * https://www.rfc-editor.org/rfc/rfc9001#section-4.1.4
4498 * If we have a connection, perhaps on the first pass we should check:
4500 if (conn && ((first_byte & 0x80) == 0)) {
4501 quic_ciphers ciphers = !from_server ? &conn->client_handshake_ciphers : &conn->server_handshake_ciphers;
4502 if (!quic_are_ciphers_initialized(ciphers)) {
4503 return false;
4506 /* But on the second pass the ciphers would already be initialized from
4507 * later frames so we would need to remember the result from the first pass.
4508 * Or, instead of the DISSECTOR_ASSERT(quic_packet); below, we just assume
4509 * that if there's no quic packet that's because this failed here.
4511 * However, this other solution has issues if the Server Handshake is
4512 * fragmented, the server sends 1-RTT data (as "0.5-RTT" data) after the
4513 * last Handshake fragment, but then is forced to resend an earlier
4514 * Handshake fragment due to not getting an ACK. We need to recognize the
4515 * 1-RTT data when it's first sent, not when the Handshake is reassembled.
4516 * (Or at least store it as potential 1-RTT to handle later, even if it
4517 * turns out to be padding.)
4519 #endif
4521 /* Compare the DCID. Note this doesn't help with a 0 length DCID. */
4522 return quic_connection_equal(&dcid, first_packet_dcid);
4525 static int
4526 dissect_quic(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
4527 void *data _U_)
4529 proto_item *quic_ti, *ti;
4530 proto_tree *quic_tree;
4531 unsigned offset = 0;
4532 quic_datagram *dgram_info = NULL;
4533 quic_packet_info_t *quic_packet = NULL;
4534 quic_cid_t real_retry_odcid = {.len=0}, *retry_odcid = NULL;
4535 quic_cid_t first_packet_dcid = {.len=0}; /* DCID of the first packet of the datagram */
4537 col_set_str(pinfo->cinfo, COL_PROTOCOL, "QUIC");
4539 if (PINFO_FD_VISITED(pinfo)) {
4540 dgram_info = (quic_datagram *)p_get_proto_data(wmem_file_scope(), pinfo, proto_quic, 0);
4542 if (!dgram_info) {
4543 dgram_info = wmem_new0(wmem_file_scope(), quic_datagram);
4544 p_add_proto_data(wmem_file_scope(), pinfo, proto_quic, 0, dgram_info);
4547 quic_ti = proto_tree_add_item(tree, proto_quic, tvb, 0, -1, ENC_NA);
4548 quic_tree = proto_item_add_subtree(quic_ti, ett_quic);
4550 if (!PINFO_FD_VISITED(pinfo)) {
4551 uint8_t long_packet_type;
4552 uint32_t version;
4553 quic_cid_t dcid = {.len=0}, scid = {.len=0};
4554 bool from_server = false;
4555 quic_info_data_t *conn;
4557 quic_extract_header(tvb, &long_packet_type, &version, &dcid, &scid);
4558 conn = quic_connection_find(pinfo, long_packet_type, &dcid, &from_server);
4559 if (conn && long_packet_type == QUIC_LPT_RETRY && conn->client_dcid_set) {
4560 // Save the original client DCID before erasure.
4561 real_retry_odcid = conn->client_dcid_initial;
4562 retry_odcid = &real_retry_odcid;
4564 if (!conn && tvb_bytes_exist(tvb, -16, 16) && (conn = quic_find_stateless_reset_token(pinfo, tvb, &from_server))) {
4565 dgram_info->stateless_reset = true;
4566 } else {
4567 quic_connection_create_or_update(&conn, pinfo, long_packet_type, version, &scid, &dcid, from_server);
4569 dgram_info->conn = conn;
4570 dgram_info->from_server = from_server;
4571 /* Senders MUST not coalesce packets with a different Connection ID
4572 * into the same datagram, so we can store the path ID here.
4574 if (conn && quic_multipath_negotiated(conn) == QUIC_MP_NO_PATH_ID) {
4575 dgram_info->path_id = dcid.seq_num;
4576 } else {
4577 dgram_info->path_id = dcid.path_id;
4579 #if 0
4580 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);
4581 } else {
4582 proto_tree_add_debug_text(quic_tree, "Connection: %d %p from_server:%d", pinfo->num, dgram_info->conn, dgram_info->from_server);
4583 #endif
4586 quic_add_connection_info(tvb, pinfo, quic_tree, dgram_info->conn);
4588 if (dgram_info->stateless_reset) {
4589 return dissect_quic_stateless_reset(tvb, pinfo, quic_tree, dgram_info);
4592 do {
4593 /* Ensure that coalesced QUIC packets end up separated. */
4594 if (offset > 0) {
4595 quic_ti = proto_tree_add_item(tree, proto_quic, tvb, offset, -1, ENC_NA);
4596 quic_tree = proto_item_add_subtree(quic_ti, ett_quic);
4599 if (!check_dcid_on_coalesced_packet(tvb, dgram_info, offset, &first_packet_dcid)) {
4600 /* Coalesced packet with unexpected CID; it probably is some kind
4601 of unencrypted padding data added after the valid QUIC payload */
4602 expert_add_info_format(pinfo, quic_tree, &ei_quic_coalesced_padding_data,
4603 "(Random) padding data appended to the datagram");
4604 break;
4607 if (!quic_packet) {
4608 quic_packet = &dgram_info->first_packet;
4609 } else if (!PINFO_FD_VISITED(pinfo)) {
4610 quic_packet->next = wmem_new0(wmem_file_scope(), quic_packet_info_t);
4611 quic_packet = quic_packet->next;
4612 } else {
4613 quic_packet = quic_packet->next;
4614 DISSECTOR_ASSERT(quic_packet);
4617 tvbuff_t *next_tvb = quic_get_message_tvb(tvb, offset, &first_packet_dcid);
4619 proto_item_set_len(quic_ti, tvb_reported_length(next_tvb));
4620 ti = proto_tree_add_uint(quic_tree, hf_quic_packet_length, next_tvb, 0, 0, tvb_reported_length(next_tvb));
4621 proto_item_set_generated(ti);
4622 unsigned new_offset = 0;
4623 uint8_t first_byte = tvb_get_uint8(next_tvb, 0);
4624 if (first_byte & 0x80) {
4625 proto_tree_add_item(quic_tree, hf_quic_header_form, next_tvb, 0, 1, ENC_NA);
4626 uint32_t version = tvb_get_ntohl(next_tvb, 1);
4627 uint8_t long_packet_type = quic_get_long_packet_type(first_byte, version);
4628 if ((version & 0x0F0F0F0F) == 0x0a0a0a0a) {
4629 offset += dissect_quic_forcing_version_negotiation(next_tvb, pinfo, quic_tree, quic_packet);
4630 if (tvb_reported_length_remaining(tvb, offset)) {
4631 /* We can't decrypt any remaining data because we don't have a valid version */
4632 expert_add_info_format(pinfo, quic_tree, &ei_quic_data_after_forcing_vn,
4633 "Data appended after a Forcing VN can't be decrypted");
4635 break;
4637 if (version == 0) {
4638 offset += dissect_quic_version_negotiation(next_tvb, pinfo, quic_tree, quic_packet);
4639 break;
4641 if (long_packet_type == QUIC_LPT_RETRY) {
4642 new_offset = dissect_quic_retry_packet(next_tvb, pinfo, quic_tree, dgram_info, quic_packet, retry_odcid, version);
4643 } else {
4644 new_offset = dissect_quic_long_header(next_tvb, pinfo, quic_tree, dgram_info, quic_packet);
4646 } else { /* Note that the "Fixed" bit might have been greased,
4647 so 0x00 is a perfectly valid value as first_byte */
4648 new_offset = dissect_quic_short_header(next_tvb, pinfo, quic_tree, dgram_info, quic_packet);
4650 if (tvb_reported_length_remaining(next_tvb, new_offset)) {
4651 // should usually not be present unless decryption is not possible.
4652 proto_tree_add_item(quic_tree, hf_quic_remaining_payload, next_tvb, new_offset, -1, ENC_NA);
4654 offset += tvb_reported_length(next_tvb);
4655 } while (tvb_reported_length_remaining(tvb, offset));
4657 return offset;
4660 static bool
4661 dissect_quic_short_header_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
4663 // If this capture does not contain QUIC, skip the more expensive checks.
4664 if (quic_cid_lengths == 0) {
4665 return false;
4668 // Is this a SH packet after connection migration? SH (since draft -22):
4669 // Flag (1) + DCID (1-20) + PKN (1/2/4) + encrypted payload (>= 16).
4670 if (tvb_captured_length(tvb) < 1 + 1 + 1 + 16) {
4671 return false;
4674 // DCID length is unknown, so extract the maximum and look for a match.
4675 quic_cid_t dcid = {.len = MIN(QUIC_MAX_CID_LENGTH, tvb_captured_length(tvb) - 1 - 1 - 16)};
4676 tvb_memcpy(tvb, dcid.cid, 1, dcid.len);
4677 bool from_server;
4678 if (!quic_connection_find(pinfo, QUIC_SHORT_PACKET, &dcid, &from_server)) {
4679 return false;
4682 conversation_t *conversation = find_or_create_conversation(pinfo);
4683 conversation_set_dissector(conversation, quic_handle);
4684 dissect_quic(tvb, pinfo, tree, NULL);
4685 return true;
4688 static bool dissect_quic_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
4691 * Since draft -22:
4692 * Flag (1 byte) + Version (4 bytes) +
4693 * Length (1 byte) + Destination Connection ID (0..255) +
4694 * Length (1 byte) + Source Connection ID (0..255) +
4695 * Payload length (1/2/4/8) + Packet number (1/2/4 bytes) + Payload.
4696 * (absolute minimum: 9 + payload)
4697 * (for Version Negotiation, payload len + PKN + payload is replaced by
4698 * Supported Version (multiple of 4 bytes.)
4700 conversation_t *conversation = NULL;
4701 int offset = 0;
4702 uint8_t flags, dcid, scid;
4703 uint32_t version;
4704 bool is_quic = false;
4706 /* Verify packet size (Flag (1 byte) + Connection ID (8 bytes) + Version (4 bytes)) */
4707 if (tvb_captured_length(tvb) < 13)
4709 return false;
4712 flags = tvb_get_uint8(tvb, offset);
4713 /* Check if long Packet is set */
4714 if((flags & 0x80) == 0) {
4715 // Perhaps this is a short header, check it.
4716 return dissect_quic_short_header_heur(tvb, pinfo, tree);
4718 offset += 1;
4720 // check for draft QUIC version (for draft -11 and newer)
4721 version = tvb_get_ntohl(tvb, offset);
4722 is_quic = (quic_draft_version(version) >= 11);
4723 if (!is_quic) {
4724 return false;
4727 /* Check that CIDs lengths are valid */
4728 offset += 4;
4729 dcid = tvb_get_uint8(tvb, offset);
4730 if (dcid > QUIC_MAX_CID_LENGTH) {
4731 return false;
4733 offset += 1 + dcid;
4734 if (offset >= (int)tvb_captured_length(tvb)) {
4735 return false;
4737 scid = tvb_get_uint8(tvb, offset);
4738 if (scid > QUIC_MAX_CID_LENGTH) {
4739 return false;
4742 /* Ok! */
4743 conversation = find_or_create_conversation(pinfo);
4744 conversation_set_dissector(conversation, quic_handle);
4745 dissect_quic(tvb, pinfo, tree, data);
4747 return true;
4751 /** Initialize QUIC dissection state for a new capture file. */
4752 static void
4753 quic_init(void)
4755 quic_connections = wmem_list_new(wmem_file_scope());
4756 quic_connections_count = 0;
4757 quic_initial_connections = wmem_map_new(wmem_file_scope(), quic_connection_hash, quic_connection_equal);
4758 quic_client_connections = wmem_map_new(wmem_file_scope(), quic_connection_hash, quic_connection_equal);
4759 quic_server_connections = wmem_map_new(wmem_file_scope(), quic_connection_hash, quic_connection_equal);
4760 quic_cid_lengths = 0;
4763 /** Release QUIC dissection state on closing a capture file. */
4764 static void
4765 quic_cleanup(void)
4767 wmem_list_foreach(quic_connections, quic_connection_destroy, NULL);
4768 quic_initial_connections = NULL;
4769 quic_client_connections = NULL;
4770 quic_server_connections = NULL;
4773 /* Follow QUIC Stream functionality {{{ */
4774 static void
4775 quic_streams_add(packet_info *pinfo, quic_info_data_t *quic_info, uint64_t stream_id)
4777 /* List: ordered list of Stream IDs in this connection */
4778 if (!quic_info->streams_list) {
4779 quic_info->streams_list = wmem_list_new(wmem_file_scope());
4781 if (!wmem_list_find(quic_info->streams_list, GUINT_TO_POINTER(stream_id))) {
4782 wmem_list_insert_sorted(quic_info->streams_list, GUINT_TO_POINTER(stream_id),
4783 wmem_compare_uint);
4786 /* Map: first Stream ID for each UDP payload */
4787 quic_follow_stream *stream;
4788 if (!quic_info->streams_map) {
4789 quic_info->streams_map = wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);
4791 stream = wmem_map_lookup(quic_info->streams_map, GUINT_TO_POINTER(pinfo->num));
4792 if (!stream) {
4793 stream = wmem_new0(wmem_file_scope(), quic_follow_stream);
4794 stream->num = pinfo->num;
4795 stream->stream_id = stream_id;
4796 wmem_map_insert(quic_info->streams_map, GUINT_TO_POINTER(stream->num), stream);
4800 static quic_info_data_t *
4801 get_conn_by_number(unsigned conn_number)
4803 quic_info_data_t *conn;
4804 wmem_list_frame_t *elem;
4806 elem = wmem_list_head(quic_connections);
4807 while (elem) {
4808 conn = (quic_info_data_t *)wmem_list_frame_data(elem);
4809 if (conn->number == conn_number)
4810 return conn;
4811 elem = wmem_list_frame_next(elem);
4813 return NULL;
4816 bool
4817 quic_get_stream_id_le(unsigned streamid, unsigned sub_stream_id, unsigned *sub_stream_id_out)
4819 quic_info_data_t *quic_info;
4820 wmem_list_frame_t *curr_entry;
4821 unsigned prev_stream_id;
4823 quic_info = get_conn_by_number(streamid);
4824 if (!quic_info) {
4825 return false;
4827 if (!quic_info->streams_list) {
4828 return false;
4831 prev_stream_id = UINT32_MAX;
4832 curr_entry = wmem_list_head(quic_info->streams_list);
4833 while (curr_entry) {
4834 if (GPOINTER_TO_UINT(wmem_list_frame_data(curr_entry)) > sub_stream_id &&
4835 prev_stream_id != UINT32_MAX) {
4836 *sub_stream_id_out = (unsigned)prev_stream_id;
4837 return true;
4839 prev_stream_id = GPOINTER_TO_UINT(wmem_list_frame_data(curr_entry));
4840 curr_entry = wmem_list_frame_next(curr_entry);
4843 if (prev_stream_id != UINT32_MAX) {
4844 *sub_stream_id_out = prev_stream_id;
4845 return true;
4848 return false;
4851 bool
4852 quic_get_stream_id_ge(unsigned streamid, unsigned sub_stream_id, unsigned *sub_stream_id_out)
4854 quic_info_data_t *quic_info;
4855 wmem_list_frame_t *curr_entry;
4857 quic_info = get_conn_by_number(streamid);
4858 if (!quic_info) {
4859 return false;
4861 if (!quic_info->streams_list) {
4862 return false;
4865 curr_entry = wmem_list_head(quic_info->streams_list);
4866 while (curr_entry) {
4867 if (GPOINTER_TO_UINT(wmem_list_frame_data(curr_entry)) >= sub_stream_id) {
4868 /* StreamIDs are 64 bits long in QUIC, but "Follow Stream" generic code uses unsigned variables */
4869 *sub_stream_id_out = GPOINTER_TO_UINT(wmem_list_frame_data(curr_entry));
4870 return true;
4872 curr_entry = wmem_list_frame_next(curr_entry);
4875 return false;
4878 static bool
4879 quic_get_sub_stream_id(unsigned streamid, unsigned sub_stream_id, bool le, unsigned *sub_stream_id_out)
4881 if (le) {
4882 return quic_get_stream_id_le(streamid, sub_stream_id, sub_stream_id_out);
4883 } else {
4884 return quic_get_stream_id_ge(streamid, sub_stream_id, sub_stream_id_out);
4888 static char *
4889 quic_follow_conv_filter(epan_dissect_t *edt _U_, packet_info *pinfo, unsigned *stream, unsigned *sub_stream)
4891 quic_datagram *dgram_info = (quic_datagram *)p_get_proto_data(wmem_file_scope(), pinfo, proto_quic, 0);
4893 if (!dgram_info || !dgram_info->conn) {
4894 return NULL;
4897 quic_info_data_t *conn = dgram_info->conn;
4899 /* First Stream ID in the selected packet */
4900 quic_follow_stream *s;
4901 if (conn->streams_map) {
4902 s = wmem_map_lookup(conn->streams_map, GUINT_TO_POINTER(pinfo->num));
4903 if (s) {
4904 *stream = conn->number;
4905 *sub_stream = (unsigned)s->stream_id;
4906 return ws_strdup_printf("quic.connection.number eq %u and quic.stream.stream_id eq %u", conn->number, *sub_stream);
4910 return NULL;
4913 static char *
4914 quic_follow_index_filter(unsigned stream, unsigned sub_stream)
4916 return ws_strdup_printf("quic.connection.number eq %u and quic.stream.stream_id eq %u", stream, sub_stream);
4919 static tap_packet_status
4920 follow_quic_tap_listener(void *tapdata, packet_info *pinfo, epan_dissect_t *edt _U_, const void *data, tap_flags_t flags _U_)
4922 follow_record_t *follow_record;
4923 follow_info_t *follow_info = (follow_info_t *)tapdata;
4924 const quic_follow_tap_data_t *follow_data = (const quic_follow_tap_data_t *)data;
4926 if (follow_info->substream_id != SUBSTREAM_UNUSED &&
4927 follow_info->substream_id != follow_data->stream_id) {
4928 return TAP_PACKET_DONT_REDRAW;
4931 follow_record = g_new(follow_record_t, 1);
4933 // XXX: Ideally, we should also deal with stream retransmission
4934 // and out of order packets in a similar manner to the TCP dissector,
4935 // using the offset, plus ACKs and other information.
4936 follow_record->data = g_byte_array_sized_new(tvb_captured_length(follow_data->tvb));
4937 follow_record->data = g_byte_array_append(follow_record->data, tvb_get_ptr(follow_data->tvb, 0, -1), tvb_captured_length(follow_data->tvb));
4938 follow_record->packet_num = pinfo->fd->num;
4939 follow_record->abs_ts = pinfo->fd->abs_ts;
4941 /* This sets the address and port information the first time this
4942 * stream is tapped. It will no longer be true after migration, but
4943 * as it seems it's only used for display, using the initial values
4944 * is the best we can do.
4947 if (follow_data->from_server) {
4948 follow_record->is_server = true;
4949 if (follow_info->client_port == 0) {
4950 follow_info->server_port = pinfo->srcport;
4951 copy_address(&follow_info->server_ip, &pinfo->src);
4952 follow_info->client_port = pinfo->destport;
4953 copy_address(&follow_info->client_ip, &pinfo->dst);
4955 } else {
4956 follow_record->is_server = false;
4957 if (follow_info->client_port == 0) {
4958 follow_info->client_port = pinfo->srcport;
4959 copy_address(&follow_info->client_ip, &pinfo->src);
4960 follow_info->server_port = pinfo->destport;
4961 copy_address(&follow_info->server_ip, &pinfo->dst);
4965 follow_info->bytes_written[follow_record->is_server] += follow_record->data->len;
4967 follow_info->payload = g_list_prepend(follow_info->payload, follow_record);
4968 return TAP_PACKET_DONT_REDRAW;
4971 uint32_t get_quic_connections_count(void)
4973 return quic_connections_count;
4975 /* Follow QUIC Stream functionality }}} */
4977 void
4978 proto_register_quic(void)
4980 expert_module_t *expert_quic;
4981 module_t *quic_module;
4983 static hf_register_info hf[] = {
4984 { &hf_quic_connection_number,
4985 { "Connection Number", "quic.connection.number",
4986 FT_UINT32, BASE_DEC, NULL, 0x0,
4987 "Connection identifier within this capture file", HFILL }
4990 { &hf_quic_packet_length,
4991 { "Packet Length", "quic.packet_length",
4992 FT_UINT32, BASE_DEC, NULL, 0x0,
4993 "Size of the QUIC packet", HFILL }
4996 { &hf_quic_header_form,
4997 { "Header Form", "quic.header_form",
4998 FT_UINT8, BASE_DEC, VALS(quic_short_long_header_vals), 0x80,
4999 "The most significant bit (0x80) of the first octet is set to 1 for long headers and 0 for short headers.", HFILL }
5002 { &hf_quic_long_packet_type,
5003 { "Packet Type", "quic.long.packet_type",
5004 FT_UINT8, BASE_DEC, VALS(quic_v1_long_packet_type_vals), 0x30,
5005 "Long Header Packet Type", HFILL }
5007 { &hf_quic_long_packet_type_v2,
5008 { "Packet Type", "quic.long.packet_type_v2",
5009 FT_UINT8, BASE_DEC, VALS(quic_v2_long_packet_type_vals), 0x30,
5010 "Long Header Packet Type", HFILL }
5012 { &hf_quic_long_reserved,
5013 { "Reserved", "quic.long.reserved",
5014 FT_UINT8, BASE_DEC, NULL, 0x0c,
5015 "Reserved bits (protected using header protection)", HFILL }
5017 { &hf_quic_packet_number_length,
5018 { "Packet Number Length", "quic.packet_number_length",
5019 FT_UINT8, BASE_DEC, VALS(quic_packet_number_lengths), 0x03,
5020 "Packet Number field length (protected using header protection)", HFILL }
5022 { &hf_quic_dcid,
5023 { "Destination Connection ID", "quic.dcid",
5024 FT_BYTES, BASE_NONE, NULL, 0x0,
5025 NULL, HFILL }
5027 { &hf_quic_scid,
5028 { "Source Connection ID", "quic.scid",
5029 FT_BYTES, BASE_NONE, NULL, 0x0,
5030 NULL, HFILL }
5032 { &hf_quic_dcil,
5033 { "Destination Connection ID Length", "quic.dcil",
5034 FT_UINT8, BASE_DEC, NULL, 0x0,
5035 NULL, HFILL }
5037 { &hf_quic_scil,
5038 { "Source Connection ID Length", "quic.scil",
5039 FT_UINT8, BASE_DEC, NULL, 0x0,
5040 NULL, HFILL }
5042 { &hf_quic_token_length,
5043 { "Token Length", "quic.token_length",
5044 FT_UINT64, BASE_DEC, NULL, 0x0,
5045 NULL, HFILL }
5047 { &hf_quic_token,
5048 { "Token", "quic.token",
5049 FT_BYTES, BASE_NONE, NULL, 0x0,
5050 NULL, HFILL }
5052 { &hf_quic_length,
5053 { "Length", "quic.length",
5054 FT_UINT64, BASE_DEC, NULL, 0x0,
5055 "Length of Packet Number and Payload fields", HFILL }
5058 { &hf_quic_packet_number,
5059 { "Packet Number", "quic.packet_number",
5060 FT_UINT64, BASE_DEC, NULL, 0x0,
5061 "Decoded packet number", HFILL }
5063 { &hf_quic_version,
5064 { "Version", "quic.version",
5065 FT_UINT32, BASE_RANGE_STRING | BASE_HEX, RVALS(quic_version_vals), 0x0,
5066 NULL, HFILL }
5068 { &hf_quic_supported_version,
5069 { "Supported Version", "quic.supported_version",
5070 FT_UINT32, BASE_RANGE_STRING | BASE_HEX, RVALS(quic_version_vals), 0x0,
5071 NULL, HFILL }
5073 { &hf_quic_vn_unused,
5074 { "Unused", "quic.vn.unused",
5075 FT_UINT8, BASE_HEX, NULL, 0x7F,
5076 NULL, HFILL }
5078 { &hf_quic_short,
5079 { "QUIC Short Header", "quic.short",
5080 FT_NONE, BASE_NONE, NULL, 0x0,
5081 NULL, HFILL }
5083 { &hf_quic_fixed_bit,
5084 { "Fixed Bit", "quic.fixed_bit",
5085 FT_BOOLEAN, 8, NULL, 0x40,
5086 "Must be 1", HFILL }
5088 { &hf_quic_spin_bit,
5089 { "Spin Bit", "quic.spin_bit",
5090 FT_BOOLEAN, 8, NULL, 0x20,
5091 "Latency Spin Bit", HFILL }
5094 /* multipath */
5095 { &hf_quic_mp_nci_path_identifier,
5096 { "Path identifier", "quic.mp_nci_path_identifier",
5097 FT_UINT64, BASE_DEC, NULL, 0x0,
5098 NULL, HFILL }
5100 { &hf_quic_mp_rc_path_identifier,
5101 { "Path identifier", "quic.mp_rc_path_identifier",
5102 FT_UINT64, BASE_DEC, NULL, 0x0,
5103 NULL, HFILL }
5105 { &hf_quic_mp_ack_path_identifier,
5106 { "Path Identifier", "quic.mp_ack_path_identifier",
5107 FT_UINT64, BASE_DEC, NULL, 0x0,
5108 NULL, HFILL }
5110 { &hf_quic_mp_pa_path_identifier,
5111 { "Path Identifier", "quic.mp_pa_path_identifier",
5112 FT_UINT64, BASE_DEC, NULL, 0x0,
5113 NULL, HFILL }
5115 { &hf_quic_mp_ps_path_identifier,
5116 { "Path Identifier", "quic.mp_ps_path_identifier",
5117 FT_UINT64, BASE_DEC, NULL, 0x0,
5118 NULL, HFILL }
5120 { &hf_quic_mp_ps_path_status_sequence_number,
5121 { "Path Status Sequence Number", "quic.mp_ps_path_status_sequence_number",
5122 FT_UINT64, BASE_DEC, NULL, 0x0,
5123 NULL, HFILL }
5125 { &hf_quic_mp_ps_path_status,
5126 { "Path Status", "quic.mp_ps_path_status",
5127 FT_UINT64, BASE_DEC | BASE_VAL64_STRING, VALS64(quic_mp_path_status), 0x0,
5128 NULL, HFILL }
5130 { &hf_quic_mp_maximum_paths,
5131 { "Maximum Paths", "quic.mp_maximum_paths",
5132 FT_UINT64, BASE_DEC, NULL, 0x0,
5133 NULL, HFILL }
5135 { &hf_quic_mp_maximum_path_identifier,
5136 { "Maximum Path identifier", "quic.mp_maximum_path_id",
5137 FT_UINT64, BASE_DEC, NULL, 0x0,
5138 NULL, HFILL }
5141 { &hf_quic_short_reserved,
5142 { "Reserved", "quic.short.reserved",
5143 FT_UINT8, BASE_DEC, NULL, 0x18,
5144 "Reserved bits (protected using header protection)", HFILL }
5146 { &hf_quic_q_bit,
5147 { "Square Signal Bit (Q)", "quic.q_bit",
5148 FT_BOOLEAN, 8, NULL, 0x10,
5149 "Square Signal Bit (used to measure and locate the source of packet loss)", HFILL }
5151 { &hf_quic_l_bit,
5152 { "Loss Event Bit (L)", "quic.l_bit",
5153 FT_BOOLEAN, 8, NULL, 0x08,
5154 "Loss Event Bit (used to measure and locate the source of packet loss)", HFILL }
5156 { &hf_quic_key_phase,
5157 { "Key Phase Bit", "quic.key_phase",
5158 FT_BOOLEAN, 8, NULL, SH_KP,
5159 "Selects the packet protection keys to use (protected using header protection)", HFILL }
5162 { &hf_quic_payload,
5163 { "Payload", "quic.payload",
5164 FT_BYTES, BASE_NONE, NULL, 0x0,
5165 "(Encrypted) payload of a packet", HFILL }
5167 { &hf_quic_protected_payload,
5168 { "Protected Payload", "quic.protected_payload",
5169 FT_BYTES, BASE_NONE, NULL, 0x0,
5170 "1-RTT protected payload", HFILL }
5172 { &hf_quic_remaining_payload,
5173 { "Remaining Payload", "quic.remaining_payload",
5174 FT_BYTES, BASE_NONE, NULL, 0x0,
5175 "Remaining payload in a packet (possibly PKN followed by encrypted payload)", HFILL }
5178 { &hf_quic_odcil,
5179 { "Original Destination Connection ID Length", "quic.odcil",
5180 FT_UINT8, BASE_DEC, NULL, 0x0,
5181 NULL, HFILL }
5183 { &hf_quic_odcid,
5184 { "Original Destination Connection ID", "quic.odcid",
5185 FT_BYTES, BASE_NONE, NULL, 0x0,
5186 NULL, HFILL }
5188 { &hf_quic_retry_token,
5189 { "Retry Token", "quic.retry_token",
5190 FT_BYTES, BASE_NONE, NULL, 0x0,
5191 NULL, HFILL }
5193 { &hf_quic_retry_integrity_tag,
5194 { "Retry Integrity Tag", "quic.retry_integrity_tag",
5195 FT_BYTES, BASE_NONE, NULL, 0x0,
5196 NULL, HFILL }
5199 { &hf_quic_frame,
5200 { "Frame", "quic.frame",
5201 FT_NONE, BASE_NONE, NULL, 0x0,
5202 NULL, HFILL }
5204 { &hf_quic_frame_type,
5205 { "Frame Type", "quic.frame_type",
5206 FT_UINT64, BASE_RANGE_STRING | BASE_HEX, RVALS(quic_frame_type_vals), 0x0,
5207 NULL, HFILL }
5210 /* PADDING */
5211 { &hf_quic_padding_length,
5212 { "Padding Length", "quic.padding_length",
5213 FT_UINT32, BASE_DEC, NULL, 0x0,
5214 NULL, HFILL }
5216 /* ACK */
5217 { &hf_quic_ack_largest_acknowledged,
5218 { "Largest Acknowledged", "quic.ack.largest_acknowledged",
5219 FT_UINT64, BASE_DEC, NULL, 0x0,
5220 "Largest packet number the peer is acknowledging in this packet", HFILL }
5222 { &hf_quic_ack_ack_delay,
5223 { "ACK Delay", "quic.ack.ack_delay",
5224 FT_UINT64, BASE_DEC, NULL, 0x0,
5225 "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 }
5227 { &hf_quic_ack_ack_range_count,
5228 { "ACK Range Count", "quic.ack.ack_range_count",
5229 FT_UINT64, BASE_DEC, NULL, 0x0,
5230 "Number of Gap and ACK Range fields in the frame", HFILL }
5232 { &hf_quic_ack_first_ack_range,
5233 { "First ACK Range", "quic.ack.first_ack_range",
5234 FT_UINT64, BASE_DEC, NULL, 0x0,
5235 "Number of contiguous packets preceding the Largest Acknowledged that are being acknowledged", HFILL }
5237 { &hf_quic_ack_gap,
5238 { "Gap", "quic.ack.gap",
5239 FT_UINT64, BASE_DEC, NULL, 0x0,
5240 "Number of contiguous unacknowledged packets preceding the packet number one lower than the smallest in the preceding ACK Range", HFILL }
5242 { &hf_quic_ack_ack_range,
5243 { "ACK Range", "quic.ack.ack_range",
5244 FT_UINT64, BASE_DEC, NULL, 0x0,
5245 "Number of contiguous acknowledged packets preceding the largest packet number, as determined by the preceding Gap", HFILL }
5247 { &hf_quic_ack_ect0_count,
5248 { "ECT(0) Count", "quic.ack.ect0_count",
5249 FT_UINT64, BASE_DEC, NULL, 0x0,
5250 "Total number of packets received with the ECT(0) codepoint", HFILL }
5252 { &hf_quic_ack_ect1_count,
5253 { "ECT(1) Count", "quic.ack.ect1_count",
5254 FT_UINT64, BASE_DEC, NULL, 0x0,
5255 "Total number of packets received with the ECT(1) codepoint", HFILL }
5257 { &hf_quic_ack_ecn_ce_count,
5258 { "ECN-CE Count", "quic.ack.ecn_ce_count",
5259 FT_UINT64, BASE_DEC, NULL, 0x0,
5260 "Total number of packets received with the CE codepoint", HFILL }
5262 /* RESET_STREAM */
5263 { &hf_quic_rsts_stream_id,
5264 { "Stream ID", "quic.rsts.stream_id",
5265 FT_UINT64, BASE_DEC, NULL, 0x0,
5266 "Stream ID of the stream being terminated", HFILL }
5268 { &hf_quic_rsts_application_error_code,
5269 { "Application Error code", "quic.rsts.application_error_code",
5270 FT_UINT64, BASE_DEC, NULL, 0x0,
5271 "Indicates why the stream is being closed", HFILL }
5273 { &hf_quic_rsts_final_size,
5274 { "Final Size", "quic.rsts.final_size",
5275 FT_UINT64, BASE_DEC, NULL, 0x0,
5276 "The final size of the stream by the RESET_STREAM sender (in bytes)", HFILL }
5278 /* STOP_SENDING */
5279 { &hf_quic_ss_stream_id,
5280 { "Stream ID", "quic.ss.stream_id",
5281 FT_UINT64, BASE_DEC, NULL, 0x0,
5282 "Stream ID of the stream being ignored", HFILL }
5284 { &hf_quic_ss_application_error_code,
5285 { "Application Error code", "quic.ss.application_error_code",
5286 FT_UINT64, BASE_DEC, NULL, 0x0,
5287 "Indicates why the sender is ignoring the stream", HFILL }
5289 /* CRYPTO */
5290 { &hf_quic_crypto_offset,
5291 { "Offset", "quic.crypto.offset",
5292 FT_UINT64, BASE_DEC, NULL, 0x0,
5293 "Byte offset into the stream", HFILL }
5295 { &hf_quic_crypto_length,
5296 { "Length", "quic.crypto.length",
5297 FT_UINT64, BASE_DEC, NULL, 0x0,
5298 "Length of the Crypto Data field", HFILL }
5300 { &hf_quic_crypto_crypto_data,
5301 { "Crypto Data", "quic.crypto.crypto_data",
5302 FT_NONE, BASE_NONE, NULL, 0x0,
5303 "The cryptographic message data", HFILL }
5305 /* NEW_TOKEN */
5306 { &hf_quic_nt_length,
5307 { "(Token) Length", "quic.nt.length",
5308 FT_UINT64, BASE_DEC, NULL, 0x0,
5309 "Specifying the length of the token", HFILL }
5311 { &hf_quic_nt_token,
5312 { "Token", "quic.nt.token",
5313 FT_BYTES, BASE_NONE, NULL, 0x0,
5314 "An opaque blob that the client may use with a future Initial packet", HFILL }
5316 /* STREAM */
5317 { &hf_quic_stream_fin,
5318 { "Fin", "quic.stream.fin",
5319 FT_BOOLEAN, 8, NULL, FTFLAGS_STREAM_FIN,
5320 NULL, HFILL }
5322 { &hf_quic_stream_len,
5323 { "Len(gth)", "quic.stream.len",
5324 FT_BOOLEAN, 8, NULL, FTFLAGS_STREAM_LEN,
5325 NULL, HFILL }
5327 { &hf_quic_stream_off,
5328 { "Off(set)", "quic.stream.off",
5329 FT_BOOLEAN, 8, NULL, FTFLAGS_STREAM_OFF,
5330 NULL, HFILL }
5332 { &hf_quic_stream_stream_id,
5333 { "Stream ID", "quic.stream.stream_id",
5334 FT_UINT64, BASE_DEC, NULL, 0x0,
5335 NULL, HFILL }
5337 { &hf_quic_stream_initiator,
5338 { "Stream initiator", "quic.stream.initiator",
5339 FT_UINT64, BASE_DEC | BASE_VAL64_STRING, VALS64(quic_frame_id_initiator), FTFLAGS_STREAM_INITIATOR,
5340 NULL, HFILL }
5342 { &hf_quic_stream_direction,
5343 { "Stream direction", "quic.stream.direction",
5344 FT_UINT64, BASE_DEC | BASE_VAL64_STRING, VALS64(quic_frame_id_direction), FTFLAGS_STREAM_DIRECTION,
5345 NULL, HFILL }
5347 { &hf_quic_stream_offset,
5348 { "Offset", "quic.stream.offset",
5349 FT_UINT64, BASE_DEC, NULL, 0x0,
5350 NULL, HFILL }
5352 { &hf_quic_stream_length,
5353 { "Length", "quic.stream.length",
5354 FT_UINT64, BASE_DEC, NULL, 0x0,
5355 NULL, HFILL }
5357 { &hf_quic_stream_data,
5358 { "Stream Data", "quic.stream_data",
5359 FT_BYTES, BASE_NONE, NULL, 0x0,
5360 NULL, HFILL }
5363 /* MAX_DATA */
5364 { &hf_quic_md_maximum_data,
5365 { "Maximum Data", "quic.md.maximum_data",
5366 FT_UINT64, BASE_DEC, NULL, 0x0,
5367 "Indicating the maximum amount of data that can be sent on the entire connection, in units of 1024 octets", HFILL }
5369 /* MAX_STREAM_DATA */
5370 { &hf_quic_msd_stream_id,
5371 { "Stream ID", "quic.msd.stream_id",
5372 FT_UINT64, BASE_DEC, NULL, 0x0,
5373 "The stream ID of the stream that is affected", HFILL }
5375 { &hf_quic_msd_maximum_stream_data,
5376 { "Maximum Stream Data", "quic.msd.maximum_stream_data",
5377 FT_UINT64, BASE_DEC, NULL, 0x0,
5378 "Indicating the maximum amount of data that can be sent on the identified stream, in units of octets", HFILL }
5380 /* MAX_STREAMS */
5381 { &hf_quic_ms_max_streams,
5382 { "Max Streams", "quic.ms.max_streams",
5383 FT_UINT64, BASE_DEC, NULL, 0x0,
5384 "A count of the cumulative number of streams of the corresponding type that can be opened over the lifetime of the connection", HFILL }
5386 /* DATA_BLOCKED */
5387 { &hf_quic_db_stream_data_limit,
5388 { "Stream Data Limit", "quic.sb.stream_data_limit",
5389 FT_UINT64, BASE_DEC, NULL, 0x0,
5390 "Indicating the connection-level limit at which the blocking occurred", HFILL }
5392 /* STREAM_DATA_BLOCKED */
5393 { &hf_quic_sdb_stream_id,
5394 { "Stream ID", "quic.sdb.stream_id",
5395 FT_UINT64, BASE_DEC, NULL, 0x0,
5396 "Indicating the stream which is flow control blocked", HFILL }
5398 { &hf_quic_sdb_stream_data_limit,
5399 { "Stream Data Limit", "quic.sb.stream_data_limit",
5400 FT_UINT64, BASE_DEC, NULL, 0x0,
5401 "Indicating the offset of the stream at which the blocking occurred", HFILL }
5403 /* STREAMS_BLOCKED */
5404 { &hf_quic_sb_stream_limit,
5405 { "Stream Limit", "quic.sib.stream_limit",
5406 FT_UINT64, BASE_DEC, NULL, 0x0,
5407 "Indicating the stream limit at the time the frame was sent", HFILL }
5409 /* NEW_CONNECTION_ID */
5410 { &hf_quic_nci_retire_prior_to,
5411 { "Retire Prior To", "quic.nci.retire_prior_to",
5412 FT_UINT64, BASE_DEC, NULL, 0x0,
5413 "A variable-length integer indicating which connection IDs should be retired", HFILL }
5415 { &hf_quic_nci_sequence,
5416 { "Sequence", "quic.nci.sequence",
5417 FT_UINT64, BASE_DEC, NULL, 0x0,
5418 "Increases by 1 for each connection ID that is provided by the server", HFILL }
5420 { &hf_quic_nci_connection_id_length,
5421 { "Connection ID Length", "quic.nci.connection_id.length",
5422 FT_UINT8, BASE_DEC, NULL, 0x0,
5423 NULL, HFILL }
5425 { &hf_quic_nci_connection_id,
5426 { "Connection ID", "quic.nci.connection_id",
5427 FT_BYTES, BASE_NONE, NULL, 0x0,
5428 NULL, HFILL }
5430 { &hf_quic_nci_stateless_reset_token,
5431 { "Stateless Reset Token", "quic.nci.stateless_reset_token",
5432 FT_BYTES, BASE_NONE, NULL, 0x0,
5433 NULL, HFILL }
5435 /* RETIRE_CONNECTION_ID */
5436 { &hf_quic_rci_sequence,
5437 { "Sequence", "quic.rci.sequence",
5438 FT_UINT64, BASE_DEC, NULL, 0x0,
5439 "The sequence number of the connection ID being retired", HFILL }
5441 /* PATH_CHALLENGE */
5442 { &hf_quic_path_challenge_data,
5443 { "Data", "quic.path_challenge.data",
5444 FT_BYTES, BASE_NONE, NULL, 0x0,
5445 "Arbitrary data that must be matched by a PATH_RESPONSE frame", HFILL }
5447 /* PATH_RESPONSE */
5448 { &hf_quic_path_response_data,
5449 { "Data", "quic.path_response.data",
5450 FT_BYTES, BASE_NONE, NULL, 0x0,
5451 "Arbitrary data that must match a PATH_CHALLENGE frame", HFILL }
5453 /* CONNECTION_CLOSE */
5454 { &hf_quic_cc_error_code,
5455 { "Error code", "quic.cc.error_code",
5456 FT_UINT64, BASE_DEC|BASE_RANGE_STRING, RVALS(quic_transport_error_code_vals), 0x0,
5457 "Indicates the reason for closing this connection", HFILL }
5459 { &hf_quic_cc_error_code_app,
5460 { "Application Error code", "quic.cc.error_code.app",
5461 FT_UINT64, BASE_DEC, NULL, 0x0,
5462 "Indicates the reason for closing this application", HFILL }
5464 { &hf_quic_cc_error_code_tls_alert,
5465 { "TLS Alert Description", "quic.cc.error_code.tls_alert",
5466 FT_UINT8, BASE_DEC, VALS(ssl_31_alert_description), 0x0,
5467 NULL, HFILL }
5469 { &hf_quic_cc_frame_type,
5470 { "Frame Type", "quic.cc.frame_type",
5471 FT_UINT64, BASE_DEC, NULL, 0x0,
5472 "The type of frame that triggered the error", HFILL }
5474 { &hf_quic_cc_reason_phrase_length,
5475 { "Reason phrase Length", "quic.cc.reason_phrase.length",
5476 FT_UINT64, BASE_DEC, NULL, 0x0,
5477 "Specifying the length of the reason phrase", HFILL }
5479 { &hf_quic_cc_reason_phrase,
5480 { "Reason phrase", "quic.cc.reason_phrase",
5481 FT_STRING, BASE_NONE, NULL, 0x0,
5482 "A human-readable explanation for why the connection was closed", HFILL }
5484 /* DATAGRAM */
5485 { &hf_quic_dg_length,
5486 { "Datagram Length", "quic.dg.length",
5487 FT_UINT64, BASE_DEC, NULL, 0x0,
5488 "Specifies the length of the datagram data in bytes", HFILL }
5490 { &hf_quic_dg,
5491 { "Datagram", "quic.dg",
5492 FT_BYTES, BASE_NONE, NULL, 0x0,
5493 "The bytes of the datagram to be delivered", HFILL }
5495 /* ACK-FREQUENCY */
5496 { &hf_quic_af_sequence_number,
5497 { "Sequence Number", "quic.af.sequence_number",
5498 FT_UINT64, BASE_DEC, NULL, 0x0,
5499 "Sequence number assigned to the ACK_FREQUENCY frame by the sender to allow receivers to ignore obsolete frames", HFILL }
5501 { &hf_quic_af_ack_eliciting_threshold,
5502 { "Ack-Eliciting Threshold", "quic.af.ack_eliciting_threshold",
5503 FT_UINT64, BASE_DEC, NULL, 0x0,
5504 "The maximum number of ack-eliciting packets the recipient of this frame can receive without sending an acknowledgment", HFILL }
5506 { &hf_quic_af_request_max_ack_delay,
5507 { "Request Max Ack Delay", "quic.af.request_max_ack_delay",
5508 FT_UINT64, BASE_DEC, NULL, 0x0,
5509 "The value to which the endpoint requests the peer update its max_ack_delay", HFILL }
5511 { &hf_quic_af_reordering_threshold,
5512 { "Reordering Threshold", "quic.af.reordering_threshold",
5513 FT_UINT64, BASE_DEC, NULL, 0x0,
5514 "The value that indicates the maximum packet reordering before eliciting an immediate ACK", HFILL }
5516 //{ &hf_quic_af_ignore_order,
5517 // { "Ignore Order", "quic.af.ignore_order",
5518 // FT_BOOLEAN, 8, NULL, 0x02,
5519 // "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 }
5520 //},
5521 //{ &hf_quic_af_ignore_ce,
5522 // { "Ignore CE", "quic.af.ignore_ce",
5523 // FT_BOOLEAN, 8, NULL, 0x01,
5524 // "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 }
5525 //},
5527 /* TIME STAMP */
5528 { &hf_quic_ts,
5529 { "Time Stamp", "quic.ts",
5530 FT_UINT64, BASE_DEC, NULL, 0x0,
5531 NULL, HFILL }
5534 /* STATELESS RESET */
5535 { &hf_quic_unpredictable_bits,
5536 { "Unpredictable Bits", "quic.unpredictable_bits",
5537 FT_BYTES, BASE_NONE, NULL, 0x0,
5538 "Bytes indistinguishable from random",
5539 HFILL }
5541 { &hf_quic_stateless_reset_token,
5542 { "Stateless Reset Token", "quic.stateless_reset_token",
5543 FT_BYTES, BASE_NONE, NULL, 0x0,
5544 NULL, HFILL }
5547 /* Fields for QUIC Stream data reassembly. */
5548 { &hf_quic_fragment_overlap,
5549 { "Fragment overlap", "quic.fragment.overlap",
5550 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
5551 "Fragment overlaps with other fragments", HFILL }
5553 { &hf_quic_fragment_overlap_conflict,
5554 { "Conflicting data in fragment overlap", "quic.fragment.overlap.conflict",
5555 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
5556 "Overlapping fragments contained conflicting data", HFILL }
5558 { &hf_quic_fragment_multiple_tails,
5559 { "Multiple tail fragments found", "quic.fragment.multipletails",
5560 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
5561 "Several tails were found when reassembling the pdu", HFILL }
5563 { &hf_quic_fragment_too_long_fragment,
5564 { "Fragment too long", "quic.fragment.toolongfragment",
5565 FT_BOOLEAN, BASE_NONE, NULL, 0x0,
5566 "Fragment contained data past end of the pdu", HFILL }
5568 { &hf_quic_fragment_error,
5569 { "Reassembling error", "quic.fragment.error",
5570 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
5571 "Reassembling error due to illegal fragments", HFILL }
5573 { &hf_quic_fragment_count,
5574 { "Fragment count", "quic.fragment.count",
5575 FT_UINT32, BASE_DEC, NULL, 0x0,
5576 NULL, HFILL }
5578 { &hf_quic_fragment,
5579 { "QUIC STREAM Data Fragment", "quic.fragment",
5580 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
5581 NULL, HFILL }
5583 { &hf_quic_fragments,
5584 { "Reassembled QUIC STREAM Data Fragments", "quic.fragments",
5585 FT_NONE, BASE_NONE, NULL, 0x0,
5586 NULL, HFILL }
5588 { &hf_quic_reassembled_in,
5589 { "Reassembled PDU in frame", "quic.reassembled_in",
5590 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
5591 "The PDU that doesn't end in this fragment is reassembled in this frame", HFILL }
5593 { &hf_quic_reassembled_length,
5594 { "Reassembled QUIC STREAM Data length", "quic.reassembled.length",
5595 FT_UINT32, BASE_DEC, NULL, 0x0,
5596 "The total length of the reassembled payload", HFILL }
5598 { &hf_quic_reassembled_data,
5599 { "Reassembled QUIC STREAM Data", "quic.reassembled.data",
5600 FT_BYTES, BASE_NONE, NULL, 0x0,
5601 "The reassembled payload", HFILL }
5603 { &hf_quic_crypto_fragment_count,
5604 { "Fragment count", "quic.crypto.fragment.count",
5605 FT_UINT32, BASE_DEC, NULL, 0x0,
5606 NULL, HFILL }
5608 { &hf_quic_crypto_fragment,
5609 { "QUIC CRYPTO Data Fragment", "quic.crypto.fragment",
5610 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
5611 NULL, HFILL }
5613 { &hf_quic_crypto_fragments,
5614 { "Reassembled QUIC CRYPTO Data Fragments", "quic.crypto.fragments",
5615 FT_NONE, BASE_NONE, NULL, 0x0,
5616 "QUIC STREAM Data Fragments", HFILL }
5618 { &hf_quic_crypto_reassembled_in,
5619 { "Reassembled PDU in frame", "quic.crypto.reassembled_in",
5620 FT_FRAMENUM, BASE_NONE, NULL, 0x0,
5621 "The PDU that doesn't end in this fragment is reassembled in this frame", HFILL }
5625 static int *ett[] = {
5626 &ett_quic,
5627 &ett_quic_af,
5628 &ett_quic_short_header,
5629 &ett_quic_connection_info,
5630 &ett_quic_ft,
5631 &ett_quic_ftflags,
5632 &ett_quic_ftid,
5633 &ett_quic_fragments,
5634 &ett_quic_fragment,
5635 &ett_quic_crypto_fragments,
5636 &ett_quic_crypto_fragment,
5639 static ei_register_info ei[] = {
5640 { &ei_quic_connection_unknown,
5641 { "quic.connection.unknown", PI_PROTOCOL, PI_NOTE,
5642 "Unknown QUIC connection. Missing Initial Packet or migrated connection?", EXPFILL }
5644 { &ei_quic_ft_unknown,
5645 { "quic.ft.unknown", PI_UNDECODED, PI_NOTE,
5646 "Unknown Frame Type", EXPFILL }
5648 { &ei_quic_decryption_failed,
5649 { "quic.decryption_failed", PI_DECRYPTION, PI_WARN,
5650 "Failed to decrypt handshake", EXPFILL }
5652 { &ei_quic_protocol_violation,
5653 { "quic.protocol_violation", PI_PROTOCOL, PI_WARN,
5654 "Invalid data according to the protocol", EXPFILL }
5656 { &ei_quic_bad_retry,
5657 { "quic.bad_retry", PI_PROTOCOL, PI_WARN,
5658 "Retry Integrity Tag verification failure", EXPFILL }
5660 { &ei_quic_coalesced_padding_data,
5661 { "quic.coalesced_padding_data", PI_PROTOCOL, PI_NOTE,
5662 "Coalesced Padding Data", EXPFILL }
5664 { &ei_quic_retransmission,
5665 { "quic.retransmission", PI_SEQUENCE, PI_NOTE,
5666 "This QUIC frame has a reused stream offset (retransmission?)", EXPFILL }
5668 { &ei_quic_overlap,
5669 { "quic.overlap", PI_SEQUENCE, PI_NOTE,
5670 "This QUIC frame overlaps a previous frame in the stream", EXPFILL }
5672 { &ei_quic_data_after_forcing_vn,
5673 { "quic.data_after_forcing_vn", PI_PROTOCOL, PI_NOTE,
5674 "Unexpected data on a Forcing Version Negotiation packet", EXPFILL }
5678 proto_quic = proto_register_protocol("QUIC IETF", "QUIC", "quic");
5680 proto_register_field_array(proto_quic, hf, array_length(hf));
5681 proto_register_subtree_array(ett, array_length(ett));
5683 expert_quic = expert_register_protocol(proto_quic);
5684 expert_register_field_array(expert_quic, ei, array_length(ei));
5686 quic_module = prefs_register_protocol(proto_quic, NULL);
5687 prefs_register_bool_preference(quic_module, "reassemble_crypto_out_of_order",
5688 "Reassemble out-of-order CRYPTO frames",
5689 "Whether out-of-order CRYPTO frames should be buffered and reordered before "
5690 "passing them to the TLS handshake dissector.",
5691 &quic_crypto_out_of_order);
5693 prefs_register_uint_preference(quic_module, "gso_heur_min_dcid_len",
5694 "Search for coalesced short header packets at DCID length",
5695 "Heuristically search for coalesced QUIC packets with a short header "
5696 "(e.g., when Generic Segmentation Offload (GSO) or similar is used), "
5697 "if the DCID is at least this many bytes long (0 to disable). ",
5698 10, &quic_gso_heur_dcid_len);
5700 quic_handle = register_dissector("quic", dissect_quic, proto_quic);
5702 register_init_routine(quic_init);
5703 register_cleanup_routine(quic_cleanup);
5705 register_follow_stream(proto_quic, "quic_follow", quic_follow_conv_filter, quic_follow_index_filter, udp_follow_address_filter,
5706 udp_port_to_display, follow_quic_tap_listener, get_quic_connections_count,
5707 quic_get_sub_stream_id);
5709 // TODO implement custom reassembly functions that uses the QUIC Connection
5710 // ID instead of address and port numbers.
5711 reassembly_table_register(&quic_reassembly_table,
5712 &addresses_ports_reassembly_table_functions);
5714 reassembly_table_register(&quic_crypto_reassembly_table,
5715 &tcp_reassembly_table_functions);
5718 * Application protocol. QUIC with TLS uses ALPN.
5719 * https://tools.ietf.org/html/draft-ietf-quic-transport-23#section-7
5720 * This could in theory be an arbitrary octet string with embedded NUL
5721 * bytes, but in practice these do not exist yet.
5723 quic_proto_dissector_table = register_dissector_table("quic.proto", "QUIC Protocol", proto_quic, FT_STRING, STRING_CASE_SENSITIVE);
5725 quic_follow_tap = register_tap("quic_follow");
5728 void
5729 proto_reg_handoff_quic(void)
5731 tls13_handshake_handle = find_dissector("tls13-handshake");
5732 dissector_add_uint_with_preference("udp.port", 0, quic_handle);
5733 heur_dissector_add("udp", dissect_quic_heur, "QUIC", "quic", proto_quic, HEURISTIC_ENABLE);
5736 bool
5737 quic_conn_data_get_conn_client_dcid_initial(struct _packet_info *pinfo, quic_cid_t *dcid)
5739 if (pinfo == NULL || dcid == NULL) {
5740 return false;
5743 quic_info_data_t * conn = quic_connection_from_conv(pinfo);
5744 if (conn == NULL) {
5745 return false;
5748 dcid->len = conn->client_dcid_initial.len;
5749 memset(dcid->cid, 0, QUIC_MAX_CID_LENGTH);
5750 memcpy(dcid->cid, conn->client_dcid_initial.cid, dcid->len);
5752 return true;
5756 * Editor modelines - https://www.wireshark.org/tools/modelines.html
5758 * Local variables:
5759 * c-basic-offset: 4
5760 * tab-width: 8
5761 * indent-tabs-mode: nil
5762 * End:
5764 * vi: set shiftwidth=4 tabstop=8 expandtab:
5765 * :indentSize=4:tabSize=8:noTabs=true: