2 * Routines for Zero Protocol dissection
3 * Copyright 2016-2017, Alexis La Goutte <alexis.lagoutte at gmail dot com>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
13 * Zero Protocol coming from Facebook and used the same framing like QUIC
14 * (tag-map value) but based on TCP
18 * https://engineering.fb.com/networking-traffic/building-zero-protocol-for-fast-secure-mobile-connections/
20 * for some (not much!) information on it.
22 * It was reverse engineered based off of QUIC dissector functionality
26 #include <epan/packet.h>
28 #include <epan/expert.h>
29 #include <epan/conversation.h>
31 void proto_register_fb_zero(void);
32 void proto_reg_handoff_fb_zero(void);
34 static int proto_fb_zero
;
36 static dissector_handle_t fb_zero_handle
;
38 static int hf_fb_zero_puflags
;
39 static int hf_fb_zero_puflags_vrsn
;
40 static int hf_fb_zero_puflags_unknown
;
41 static int hf_fb_zero_version
;
42 static int hf_fb_zero_length
;
43 static int hf_fb_zero_tag
;
44 static int hf_fb_zero_tags
;
45 static int hf_fb_zero_tag_number
;
46 static int hf_fb_zero_tag_value
;
47 static int hf_fb_zero_tag_type
;
48 static int hf_fb_zero_tag_offset_end
;
49 static int hf_fb_zero_tag_length
;
50 static int hf_fb_zero_tag_sni
;
51 static int hf_fb_zero_tag_vers
;
52 static int hf_fb_zero_tag_sno
;
53 static int hf_fb_zero_tag_aead
;
54 static int hf_fb_zero_tag_scid
;
55 static int hf_fb_zero_tag_time
;
56 static int hf_fb_zero_tag_alpn
;
57 static int hf_fb_zero_tag_pubs
;
58 static int hf_fb_zero_tag_kexs
;
59 static int hf_fb_zero_tag_nonc
;
61 static int hf_fb_zero_tag_unknown
;
63 static int hf_fb_zero_padding
;
64 static int hf_fb_zero_payload
;
65 static int hf_fb_zero_unknown
;
67 static int ett_fb_zero
;
68 static int ett_fb_zero_puflags
;
69 static int ett_fb_zero_prflags
;
70 static int ett_fb_zero_ft
;
71 static int ett_fb_zero_ftflags
;
72 static int ett_fb_zero_tag_value
;
74 static expert_field ei_fb_zero_tag_undecoded
;
75 static expert_field ei_fb_zero_tag_offset_end_invalid
;
76 static expert_field ei_fb_zero_length_invalid
;
78 #define FBZERO_MIN_LENGTH 3
80 #define VERSION_QTV 0x515456
82 /**************************************************************************/
84 /**************************************************************************/
85 #define PUFLAGS_VRSN 0x01
86 #define PUFLAGS_UNKN 0xFE
88 /**************************************************************************/
90 /**************************************************************************/
92 #define MTAG_CHLO 0x43484C4F
93 #define MTAG_SNOM 0x534E4F4D
94 #define MTAG_SHLO 0x53484C4F
95 #define MTAG_REJ 0x52454A00
96 #define MTAG_PRST 0x50525354
98 static const value_string message_tag_vals
[] = {
99 { MTAG_CHLO
, "Client Hello" },
100 { MTAG_SNOM
, "Server NOM??" },
101 { MTAG_SHLO
, "Server Hello" },
102 { MTAG_REJ
, "Rejection" },
103 { MTAG_PRST
, "Public Reset" },
107 /**************************************************************************/
109 /**************************************************************************/
111 #define TAG_SNI 0x534E4900
112 #define TAG_VERS 0x56455253
113 #define TAG_SNO 0x534E4F00
114 #define TAG_AEAD 0x41454144
115 #define TAG_SCID 0x53434944
116 #define TAG_TIME 0x54494d45
117 #define TAG_ALPN 0x414C504E
118 #define TAG_PUBS 0x50554253
119 #define TAG_KEXS 0x4B455853
120 #define TAG_NONC 0x4E4F4E43
122 static const value_string tag_vals
[] = {
123 { TAG_SNI
, "Server Name Indication" },
124 { TAG_VERS
, "Version" },
125 { TAG_SNO
, "Server nonce" },
126 { TAG_AEAD
, "Authenticated encryption algorithms" },
127 { TAG_SCID
, "Server config ID" },
128 { TAG_TIME
, "Time" },
129 { TAG_ALPN
, "ALPN" },
130 { TAG_PUBS
, "Public value" },
131 { TAG_KEXS
, "Key exchange algorithms" },
132 { TAG_NONC
, "Client Nonce" },
137 /**************************************************************************/
139 /**************************************************************************/
141 #define AEAD_AESG 0x41455347
142 #define AEAD_S20P 0x53323050
143 #define AEAD_CC12 0x43433132
145 static const value_string tag_aead_vals
[] = {
146 { AEAD_AESG
, "AES-GCM with a 12-byte tag and IV" },
147 { AEAD_S20P
, "Salsa20 with Poly1305" },
148 { AEAD_CC12
, "ChaCha12 with Poly1305" },
152 /**************************************************************************/
154 /**************************************************************************/
156 #define KEXS_C255 0x43323535
157 #define KEXS_P256 0x50323536
159 static const value_string tag_kexs_vals
[] = {
160 { KEXS_C255
, "Curve25519" },
161 { KEXS_P256
, "P-256" },
167 dissect_fb_zero_tag(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*fb_zero_tree
, unsigned offset
, uint32_t tag_number
){
168 uint32_t tag_offset_start
= offset
+ tag_number
*4*2;
169 uint32_t tag_offset
= 0, total_tag_len
= 0;
171 bool tag_offset_valid
= true;
174 proto_tree
*tag_tree
;
175 proto_item
*ti_tag
, *ti_type
, *ti_offset_len
, *ti_len
;
176 uint32_t offset_end
, tag
;
177 const uint8_t* tag_str
;
180 * This item covers the tag type and end offset; the tag values
181 * are in a separate region following all the type/end offset
184 ti_tag
= proto_tree_add_item(fb_zero_tree
, hf_fb_zero_tags
, tvb
, offset
, 4*2, ENC_NA
);
185 tag_tree
= proto_item_add_subtree(ti_tag
, ett_fb_zero_tag_value
);
186 ti_type
= proto_tree_add_item_ret_string(tag_tree
, hf_fb_zero_tag_type
, tvb
, offset
, 4, ENC_ASCII
|ENC_NA
, pinfo
->pool
, &tag_str
);
187 tag
= tvb_get_ntohl(tvb
, offset
);
188 proto_item_append_text(ti_type
, " (%s)", val_to_str_const(tag
, tag_vals
, "Unknown"));
189 proto_item_append_text(ti_tag
, ": %s (%s)", tag_str
, val_to_str_const(tag
, tag_vals
, "Unknown"));
192 ti_offset_len
= proto_tree_add_item_ret_uint(tag_tree
, hf_fb_zero_tag_offset_end
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &offset_end
);
193 if(offset_end
< tag_offset
){
194 expert_add_info_format(pinfo
, ti_offset_len
, &ei_fb_zero_tag_offset_end_invalid
,
195 "Invalid tag end offset %u < %u",
196 offset_end
, tag_offset
);
198 * We can continue to show the tag type, end offset, and length,
199 * but we can no longer show the values, or subsequent length
200 * values, as the end offset in the tag value region is bogus.
202 tag_offset_valid
= false;
204 tag_len
= offset_end
- tag_offset
;
205 if(!tvb_bytes_exist(tvb
, tag_offset_start
+ tag_offset
, tag_len
)){
206 expert_add_info_format(pinfo
, ti_offset_len
, &ei_fb_zero_tag_offset_end_invalid
,
207 "Invalid tag end offset %u past end of packet",
210 * We can continue to show the tag type, end offset,
211 * and length, but we can no longer show the values,
212 * as the end offset in the tag value region is bogus.
214 * We don't just throw an exception here, because we
215 * want to show all the tag type and end offset values.
217 tag_offset_valid
= false;
219 total_tag_len
+= tag_len
;
220 ti_len
= proto_tree_add_uint(tag_tree
, hf_fb_zero_tag_length
, tvb
, offset
, 4, tag_len
);
221 proto_item_append_text(ti_tag
, " (l=%u)", tag_len
);
222 proto_item_set_generated(ti_len
);
226 if(tag_offset_valid
){
227 proto_tree_add_item(tag_tree
, hf_fb_zero_tag_value
, tvb
, tag_offset_start
+ tag_offset
, tag_len
, ENC_NA
);
232 if(tag_offset_valid
){
233 proto_tree_add_item_ret_string(tag_tree
, hf_fb_zero_tag_sni
, tvb
, tag_offset_start
+ tag_offset
, tag_len
, ENC_ASCII
|ENC_NA
, pinfo
->pool
, &tag_str
);
234 proto_item_append_text(ti_tag
, ": %s", tag_str
);
235 tag_offset
+= tag_len
;
239 if(tag_offset_valid
){
241 expert_add_info_format(pinfo
, fb_zero_tree
, &ei_fb_zero_length_invalid
,
242 "Invalid tag length: %u, should be 4", tag_len
);
243 tag_offset
+= tag_len
;
246 proto_tree_add_item_ret_string(tag_tree
, hf_fb_zero_tag_vers
, tvb
, tag_offset_start
+ tag_offset
, 4, ENC_ASCII
|ENC_NA
, pinfo
->pool
, &tag_str
);
247 proto_item_append_text(ti_tag
, ": %s", tag_str
);
252 if(tag_offset_valid
){
253 proto_tree_add_item(tag_tree
, hf_fb_zero_tag_sno
, tvb
, tag_offset_start
+ tag_offset
, tag_len
, ENC_NA
);
254 tag_offset
+= tag_len
;
258 if(tag_offset_valid
){
259 while(offset_end
- tag_offset
>= 4){
261 ti_aead
= proto_tree_add_item(tag_tree
, hf_fb_zero_tag_aead
, tvb
, tag_offset_start
+ tag_offset
, 4, ENC_ASCII
);
262 proto_item_append_text(ti_aead
, " (%s)", val_to_str_const(tvb_get_ntohl(tvb
, tag_offset_start
+ tag_offset
), tag_aead_vals
, "Unknown"));
263 proto_item_append_text(ti_tag
, ", %s", val_to_str_const(tvb_get_ntohl(tvb
, tag_offset_start
+ tag_offset
), tag_aead_vals
, "Unknown"));
266 if(offset_end
- tag_offset
> 0){
267 expert_add_info_format(pinfo
, fb_zero_tree
, &ei_fb_zero_length_invalid
,
268 "Invalid tag length: %u, should be a multiple of 4", tag_len
);
269 tag_offset
= offset_end
;
274 if(tag_offset_valid
){
275 proto_tree_add_item(tag_tree
, hf_fb_zero_tag_scid
, tvb
, tag_offset_start
+ tag_offset
, tag_len
, ENC_NA
);
276 tag_offset
+= tag_len
;
280 if(tag_offset_valid
){
282 expert_add_info_format(pinfo
, fb_zero_tree
, &ei_fb_zero_length_invalid
,
283 "Invalid tag length: %u, should be 4", tag_len
);
284 tag_offset
+= tag_len
;
287 proto_tree_add_item(tag_tree
, hf_fb_zero_tag_time
, tvb
, tag_offset_start
+ tag_offset
, 4, ENC_LITTLE_ENDIAN
);
288 proto_item_append_text(ti_tag
, ": %u", tvb_get_letohl(tvb
, tag_offset_start
+ tag_offset
));
293 if(tag_offset_valid
){
295 expert_add_info_format(pinfo
, fb_zero_tree
, &ei_fb_zero_length_invalid
,
296 "Invalid tag length: %u, should be 4", tag_len
);
297 tag_offset
+= tag_len
;
300 proto_tree_add_item_ret_string(tag_tree
, hf_fb_zero_tag_alpn
, tvb
, tag_offset_start
+ tag_offset
, 4, ENC_ASCII
|ENC_NA
, pinfo
->pool
, &tag_str
);
301 proto_item_append_text(ti_tag
, ": %s", tag_str
);
306 if(tag_offset_valid
){
307 /*TODO FIX: 24 Length + Pubs key?.. ! */
309 expert_add_info_format(pinfo
, fb_zero_tree
, &ei_fb_zero_length_invalid
,
310 "Invalid tag length: %u, should be >= 2", tag_len
);
311 tag_offset
+= tag_len
;
314 proto_tree_add_item(tag_tree
, hf_fb_zero_tag_pubs
, tvb
, tag_offset_start
+ tag_offset
, 2, ENC_LITTLE_ENDIAN
);
316 while(offset_end
- tag_offset
>= 3){
317 proto_tree_add_item(tag_tree
, hf_fb_zero_tag_pubs
, tvb
, tag_offset_start
+ tag_offset
, 3, ENC_LITTLE_ENDIAN
);
320 if(offset_end
- tag_offset
> 0){
321 expert_add_info_format(pinfo
, fb_zero_tree
, &ei_fb_zero_length_invalid
,
322 "Invalid tag length: %u, should be a multiple of 3", tag_len
);
323 tag_offset
= offset_end
;
328 if(tag_offset_valid
){
329 while(offset_end
- tag_offset
>= 4){
331 ti_kexs
= proto_tree_add_item(tag_tree
, hf_fb_zero_tag_kexs
, tvb
, tag_offset_start
+ tag_offset
, 4, ENC_ASCII
);
332 proto_item_append_text(ti_kexs
, " (%s)", val_to_str_const(tvb_get_ntohl(tvb
, tag_offset_start
+ tag_offset
), tag_kexs_vals
, "Unknown"));
333 proto_item_append_text(ti_tag
, ", %s", val_to_str_const(tvb_get_ntohl(tvb
, tag_offset_start
+ tag_offset
), tag_kexs_vals
, "Unknown"));
336 if(offset_end
- tag_offset
> 0){
337 expert_add_info_format(pinfo
, fb_zero_tree
, &ei_fb_zero_length_invalid
,
338 "Invalid tag length: %u, should be a multiple of 4", tag_len
);
339 tag_offset
= offset_end
;
344 if(tag_offset_valid
){
345 /*TODO: Enhance display: 32 bytes consisting of 4 bytes of timestamp (big-endian, UNIX epoch seconds), 8 bytes of server orbit and 20 bytes of random data. */
347 expert_add_info_format(pinfo
, fb_zero_tree
, &ei_fb_zero_length_invalid
,
348 "Invalid tag length: %u, should be 32", tag_len
);
349 tag_offset
+= tag_len
;
352 proto_tree_add_item(tag_tree
, hf_fb_zero_tag_nonc
, tvb
, tag_offset_start
+ tag_offset
, 32, ENC_NA
);
357 expert_add_info_format(pinfo
, ti_tag
, &ei_fb_zero_tag_undecoded
,
358 "Dissector for FB Zero Tag"
359 " %s (%s) code not implemented, Contact"
360 " Wireshark developers if you want this supported",
361 tvb_get_string_enc(pinfo
->pool
, tvb
, offset
-8, 4, ENC_ASCII
|ENC_NA
), val_to_str_const(tag
, tag_vals
, "Unknown"));
362 if(tag_offset_valid
){
363 proto_tree_add_item(tag_tree
, hf_fb_zero_tag_unknown
, tvb
, tag_offset_start
+ tag_offset
, tag_len
, ENC_NA
);
364 tag_offset
+= tag_len
;
372 /* XXX - can this still occur? */
373 if (offset
+ total_tag_len
<= offset
) {
374 expert_add_info_format(pinfo
, fb_zero_tree
, &ei_fb_zero_length_invalid
,
375 "Invalid total tag length: %u", total_tag_len
);
376 return offset
+ tvb_reported_length_remaining(tvb
, offset
);
378 return offset
+ total_tag_len
;
384 dissect_fb_zero_unencrypt(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*fb_zero_tree
, unsigned offset
, uint8_t len_pkn _U_
){
386 while(tvb_reported_length_remaining(tvb
, offset
) > 0){
388 uint32_t message_tag
, tag_number
, length
;
389 const uint8_t* message_tag_str
;
390 proto_tree_add_item(fb_zero_tree
, hf_fb_zero_unknown
, tvb
, offset
, 1, ENC_NA
);
394 * XXX: in theory, a tagged message could be split between
395 * TCP segments - even the *header containing the length*
396 * could be split - but, from the sequence described in the
397 * Facebook blog post, that's probably unlikely in practice.
399 proto_tree_add_item_ret_uint(fb_zero_tree
, hf_fb_zero_length
, tvb
, offset
, 4, ENC_LITTLE_ENDIAN
, &length
);
402 message_tag
= tvb_get_ntohl(tvb
, offset
);
403 /* check if it is a known message_tag (CHLO, SNOM...) */
404 if(try_val_to_str(message_tag
, message_tag_vals
)){
405 ti
= proto_tree_add_item_ret_string(fb_zero_tree
, hf_fb_zero_tag
, tvb
, offset
, 4, ENC_ASCII
|ENC_NA
, pinfo
->pool
, &message_tag_str
);
407 proto_item_append_text(ti
, ", Type: %s (%s)", message_tag_str
,
408 val_to_str_const(message_tag
, message_tag_vals
, "Unknown Tag"));
409 col_set_str(pinfo
->cinfo
, COL_INFO
, val_to_str_const(message_tag
, message_tag_vals
, "Unknown"));
412 proto_tree_add_item(fb_zero_tree
, hf_fb_zero_tag_number
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
);
413 tag_number
= tvb_get_letohs(tvb
, offset
);
416 proto_tree_add_item(fb_zero_tree
, hf_fb_zero_padding
, tvb
, offset
, 2, ENC_NA
);
419 offset
= dissect_fb_zero_tag(tvb
, pinfo
, fb_zero_tree
, offset
, tag_number
);
421 proto_tree_add_item(fb_zero_tree
, hf_fb_zero_unknown
, tvb
, offset
, length
, ENC_NA
);
431 dissect_fb_zero_common(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
434 proto_item
*ti
, *ti_puflags
;
435 proto_tree
*fb_zero_tree
, *puflags_tree
;
438 uint32_t message_tag
, version
;
440 if (tvb_captured_length(tvb
) < FBZERO_MIN_LENGTH
)
444 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "FB_ZERO");
446 ti
= proto_tree_add_item(tree
, proto_fb_zero
, tvb
, 0, -1, ENC_NA
);
447 fb_zero_tree
= proto_item_add_subtree(ti
, ett_fb_zero
);
450 ti_puflags
= proto_tree_add_item(fb_zero_tree
, hf_fb_zero_puflags
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
451 puflags_tree
= proto_item_add_subtree(ti_puflags
, ett_fb_zero_puflags
);
452 proto_tree_add_item(puflags_tree
, hf_fb_zero_puflags_vrsn
, tvb
, offset
, 1, ENC_NA
);
453 proto_tree_add_item(puflags_tree
, hf_fb_zero_puflags_unknown
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
454 puflags
= tvb_get_uint8(tvb
, offset
);
457 if(puflags
& PUFLAGS_VRSN
){
458 version
= tvb_get_ntoh24(tvb
, offset
);
459 if(version
== VERSION_QTV
){
460 proto_tree_add_item(fb_zero_tree
, hf_fb_zero_version
, tvb
, offset
, 3, ENC_ASCII
);
465 /* Unencrypt Message (Handshake or Connection Close...) */
466 message_tag
= tvb_get_ntohl(tvb
, offset
+5);
467 if (message_tag
== MTAG_CHLO
|| message_tag
== MTAG_SNOM
) {
468 offset
= dissect_fb_zero_unencrypt(tvb
, pinfo
, fb_zero_tree
, offset
, 1);
470 }else { /* Payload... (encrypted... TODO FIX !) */
471 col_set_str(pinfo
->cinfo
, COL_INFO
, "Payload (Encrypted)");
472 proto_tree_add_item(fb_zero_tree
, hf_fb_zero_payload
, tvb
, offset
, -1, ENC_NA
);
479 dissect_fb_zero(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
,
482 return dissect_fb_zero_common(tvb
, pinfo
, tree
, NULL
);
485 static bool dissect_fb_zero_heur(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
)
487 conversation_t
*conversation
= NULL
;
489 uint32_t version
, length
, message_tag
;
490 /* Verify packet size (Flag (1 byte) + Version (3bytes) + Flag (1 byte) + length (4 bytes) + Tag (4 bytes)) */
491 if (tvb_captured_length(tvb
) < 13)
500 version
= tvb_get_ntoh24(tvb
, offset
);
507 length
= tvb_get_letohl(tvb
, offset
);
511 message_tag
= tvb_get_ntohl(tvb
, offset
);
513 if (version
== VERSION_QTV
&& length
<= tvb_reported_length(tvb
) && (message_tag
== MTAG_CHLO
|| message_tag
== MTAG_SNOM
)) {
514 conversation
= find_or_create_conversation(pinfo
);
515 conversation_set_dissector(conversation
, fb_zero_handle
);
516 dissect_fb_zero(tvb
, pinfo
, tree
, data
);
524 proto_register_fb_zero(void)
526 static hf_register_info hf
[] = {
527 { &hf_fb_zero_puflags
,
528 { "Public Flags", "fb_zero.puflags",
529 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
530 "Specifying per-packet public flags", HFILL
}
532 { &hf_fb_zero_puflags_vrsn
,
533 { "Version", "fb_zero.puflags.version",
534 FT_BOOLEAN
, 8, TFS(&tfs_yes_no
), PUFLAGS_VRSN
,
535 "Signifies that this packet also contains the version of the FB Zero protocol", HFILL
}
537 { &hf_fb_zero_puflags_unknown
,
538 { "Unknown", "fb_zero.puflags.unknown",
539 FT_UINT8
, BASE_HEX
, NULL
, PUFLAGS_UNKN
,
543 { &hf_fb_zero_version
,
544 { "Version", "fb_zero.version",
545 FT_STRING
, BASE_NONE
, NULL
, 0x0,
546 "32 bit opaque tag that represents the version of the ZB Zero (Always QTV)", HFILL
}
548 { &hf_fb_zero_length
,
549 { "Length", "fb_zero.length",
550 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
554 { "Tag", "fb_zero.tag",
555 FT_STRING
, BASE_NONE
, NULL
, 0x0,
558 { &hf_fb_zero_tag_number
,
559 { "Tag Number", "fb_zero.tag_number",
560 FT_UINT16
, BASE_DEC
, NULL
, 0x0,
564 { "Tag/value", "fb_zero.tags",
565 FT_NONE
, BASE_NONE
, NULL
, 0x0,
568 { &hf_fb_zero_tag_type
,
569 { "Tag Type", "fb_zero.tag_type",
570 FT_STRING
, BASE_NONE
, NULL
, 0x0,
573 { &hf_fb_zero_tag_offset_end
,
574 { "Tag offset end", "fb_zero.tag_offset_end",
575 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
578 { &hf_fb_zero_tag_length
,
579 { "Tag length", "fb_zero.tag_offset_length",
580 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
583 { &hf_fb_zero_tag_value
,
584 { "Tag/value", "fb_zero.tag_value",
585 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
588 { &hf_fb_zero_tag_sni
,
589 { "Server Name Indication", "fb_zero.tag.sni",
590 FT_STRING
, BASE_NONE
, NULL
, 0x0,
591 "The fully qualified DNS name of the server, canonicalised to lowercase with no trailing period", HFILL
}
593 { &hf_fb_zero_tag_vers
,
594 { "Version", "fb_zero.tag.version",
595 FT_STRING
, BASE_NONE
, NULL
, 0x0,
596 "Version of FB Zero supported", HFILL
}
598 { &hf_fb_zero_tag_sno
,
599 { "Server nonce", "fb_zero.tag.sno",
600 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
603 { &hf_fb_zero_tag_aead
,
604 { "Authenticated encryption algorithms", "fb_zero.tag.aead",
605 FT_STRING
, BASE_NONE
, NULL
, 0x0,
606 "A list of tags, in preference order, specifying the AEAD primitives supported by the server", HFILL
}
608 { &hf_fb_zero_tag_scid
,
609 { "Server Config ID", "fb_zero.tag.scid",
610 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
611 "An opaque, 16-byte identifier for this server config", HFILL
}
613 { &hf_fb_zero_tag_time
,
614 { "Time", "fb_zero.tag.time",
615 FT_UINT32
, BASE_DEC
, NULL
, 0x0,
618 { &hf_fb_zero_tag_alpn
,
619 { "ALPN", "fb_zero.tag.alpn",
620 FT_STRING
, BASE_NONE
, NULL
, 0x0,
621 "Application-Layer Protocol Negotiation supported", HFILL
}
623 { &hf_fb_zero_tag_pubs
,
624 { "Public value", "fb_zero.tag.pubs",
625 FT_UINT24
, BASE_DEC_HEX
, NULL
, 0x0,
626 "A list of public values, 24-bit, little-endian length prefixed", HFILL
}
628 { &hf_fb_zero_tag_kexs
,
629 { "Key exchange algorithms", "fb_zero.tag.kexs",
630 FT_STRING
, BASE_NONE
, NULL
, 0x0,
631 "A list of tags, in preference order, specifying the key exchange algorithms that the server supports", HFILL
}
633 { &hf_fb_zero_tag_nonc
,
634 { "Client nonce", "fb_zero.tag.nonc",
635 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
636 "32 bytes consisting of 4 bytes of timestamp (big-endian, UNIX epoch seconds), 8 bytes of server orbit and 20 bytes of random data", HFILL
}
638 { &hf_fb_zero_tag_unknown
,
639 { "Unknown tag", "fb_zero.tag.unknown",
640 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
643 { &hf_fb_zero_padding
,
644 { "Padding", "fb_zero.padding",
645 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
648 { &hf_fb_zero_payload
,
649 { "Payload", "fb_zero.payload",
650 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
651 "Fb Zero Payload..", HFILL
}
653 { &hf_fb_zero_unknown
,
654 { "Unknown", "fb_zero.unknown",
655 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
656 "Unknown Data", HFILL
}
661 static int *ett
[] = {
663 &ett_fb_zero_puflags
,
664 &ett_fb_zero_prflags
,
666 &ett_fb_zero_ftflags
,
667 &ett_fb_zero_tag_value
670 static ei_register_info ei
[] = {
671 { &ei_fb_zero_tag_undecoded
, { "fb_zero.tag.undecoded", PI_UNDECODED
, PI_NOTE
, "Dissector for FB Zero Tag code not implemented, Contact Wireshark developers if you want this supported", EXPFILL
}},
672 { &ei_fb_zero_tag_offset_end_invalid
, { "fb_zero.offset_end.invalid", PI_PROTOCOL
, PI_ERROR
, "Invalid tag end offset", EXPFILL
}},
673 { &ei_fb_zero_length_invalid
, { "fb_zero.length.invalid", PI_PROTOCOL
, PI_WARN
, "Invalid length", EXPFILL
}},
676 expert_module_t
*expert_fb_zero
;
678 proto_fb_zero
= proto_register_protocol("(Facebook) Zero Protocol", "FBZERO", "fb_zero");
680 fb_zero_handle
= register_dissector("fb_zero", dissect_fb_zero
, proto_fb_zero
);
682 proto_register_field_array(proto_fb_zero
, hf
, array_length(hf
));
683 proto_register_subtree_array(ett
, array_length(ett
));
685 expert_fb_zero
= expert_register_protocol(proto_fb_zero
);
686 expert_register_field_array(expert_fb_zero
, ei
, array_length(ei
));
690 proto_reg_handoff_fb_zero(void)
693 heur_dissector_add("tcp", dissect_fb_zero_heur
, "FBZero (QUIC) over TCP", "fb_zero", proto_fb_zero
, HEURISTIC_ENABLE
);
699 * Editor modelines - https://www.wireshark.org/tools/modelines.html
704 * indent-tabs-mode: nil
707 * vi: set shiftwidth=4 tabstop=8 expandtab:
708 * :indentSize=4:tabSize=8:noTabs=true: