Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-btp-matter.c
blob254d00f82f69342d54eedc3d4ff49ad42111f6d0
1 /* packet-btp-matter.c
2 * Routines for Matter Bluetooth Transport Protocol (BTP) dissection
3 * Copyright 2024, Arkadiusz Bokowy <a.bokowy@samsung.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 * The dissector code is based on Matter Specification Version 1.3, section
14 * 4.18. Bluetooth Transport Protocol (BTP).
16 * The specification is available at:
17 * https://csa-iot.org/wp-content/uploads/2024/05/Matter-1.3-Core-Specification.pdf
20 #include <config.h>
22 #include <epan/packet.h>
23 #include "packet-btatt.h"
25 void proto_register_btatt_matter(void);
26 void proto_reg_handoff_btatt_matter(void);
28 static int proto_matter_btp;
29 static dissector_handle_t matter_btp_handle;
30 static dissector_handle_t matter_tlv_handle;
32 static int hf_matter_btp_flags;
33 static int hf_matter_btp_flags_handshake;
34 static int hf_matter_btp_flags_management;
35 static int hf_matter_btp_flags_acknowledgment;
36 static int hf_matter_btp_flags_ending;
37 static int hf_matter_btp_flags_continuing;
38 static int hf_matter_btp_flags_beginning;
39 static int hf_matter_btp_opcode;
40 static int hf_matter_btp_versions;
41 static int hf_matter_btp_versions_0;
42 static int hf_matter_btp_versions_1;
43 static int hf_matter_btp_versions_2;
44 static int hf_matter_btp_versions_3;
45 static int hf_matter_btp_versions_4;
46 static int hf_matter_btp_versions_5;
47 static int hf_matter_btp_versions_6;
48 static int hf_matter_btp_versions_7;
49 static int hf_matter_btp_version;
50 static int hf_matter_btp_mtu;
51 static int hf_matter_btp_window_size;
52 static int hf_matter_btp_ack;
53 static int hf_matter_btp_seq;
54 static int hf_matter_btp_length;
55 static int hf_matter_btp_payload;
56 static int hf_matter_btp_ad;
57 static int hf_matter_btp_ad_tlv_tag;
59 static int ett_matter_btp;
60 static int ett_matter_btp_flags;
61 static int ett_matter_btp_versions;
62 static int ett_matter_btp_ad;
64 // Section 4.18.2.1
65 #define MATTER_BTP_FLAGS_HANDSHAKE 0x40
66 #define MATTER_BTP_FLAGS_MANAGEMENT 0x20
67 #define MATTER_BTP_FLAGS_ACKNOWLEDGMENT 0x08
68 #define MATTER_BTP_FLAGS_ENDING 0x04
69 #define MATTER_BTP_FLAGS_CONTINUING 0x02
70 #define MATTER_BTP_FLAGS_BEGINNING 0x01
72 // Section 4.18.3.1
73 #define MATTER_BTP_OPCODE_HANDSHAKE 0x6C
75 // Section 5.4.2.4.4
76 #define MATTER_BTP_AD_TAG_ROTATING_ID 0x00
78 // Section 4.18.4.2
79 #define MATTER_GATT_SRV_UUID 0xFFF6
80 // 18EE2EF5-263D-4559-959F-4F9C429F9D11, Client TX Buffer, Write
81 #define MATTER_GATT_CHR_TX_UUID_128 "\x18\xee\x2e\xf5\x26\x3d\x45\x59\x95\x9f\x4f\x9c\x42\x9f\x9d\x11"
82 // 18EE2EF5-263D-4559-959F-4F9C429F9D12, Server RX Buffer, Indication
83 #define MATTER_GATT_CHR_RX_UUID_128 "\x18\xee\x2e\xf5\x26\x3d\x45\x59\x95\x9f\x4f\x9c\x42\x9f\x9d\x12"
84 // 64630238-8772-45F2-B87D-748A83218F04, Additional Data, Read
85 #define MATTER_GATT_CHR_AD_UUID_128 "\x64\x63\x02\x38\x87\x72\x45\xf2\xb8\x7d\x74\x8a\x83\x21\x8f\x04"
87 static const value_string btp_opcode_vals[] = {
88 { MATTER_BTP_OPCODE_HANDSHAKE, "Handshake" },
89 { 0, NULL }
92 static const value_string btp_ad_tag_vals[] = {
93 { MATTER_BTP_AD_TAG_ROTATING_ID, "Rotating Device Identifier" },
94 { 0, NULL }
97 // Dissect the Additional Data characteristic using Matter-defined TLV encoding.
98 static int
99 dissect_matter_chr_ad_tlv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int length)
102 col_append_str(pinfo->cinfo, COL_INFO, " Additional Data");
103 proto_item *item = proto_tree_add_item(tree, hf_matter_btp_ad, tvb, offset, length, ENC_NA);
104 proto_tree *subtree = proto_item_add_subtree(item, ett_matter_btp_ad);
106 call_dissector_with_data(matter_tlv_handle, tvb, pinfo, subtree, &hf_matter_btp_ad_tlv_tag);
108 return length;
111 static int
112 dissect_matter_btp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *btatt_tree, void *data)
114 btatt_data_t *att_data = (btatt_data_t *) data;
115 uint64_t flags = 0;
116 uint32_t opcode = 0;
117 int offset = 0;
119 DISSECTOR_ASSERT(att_data);
120 bluetooth_data_t *bluetooth_data = att_data->bluetooth_data;
121 const uint8_t att_opcode = att_data->opcode;
122 const uint32_t att_handle = att_data->handle;
124 // We are only interested in read, write and indication packets.
125 if (att_opcode != ATT_OPCODE_READ_RESPONSE &&
126 att_opcode != ATT_OPCODE_WRITE_REQUEST &&
127 att_opcode != ATT_OPCODE_HANDLE_VALUE_INDICATION)
128 return 0;
130 /* Get UUID for current ATT handle. */
131 bluetooth_uuid_t uuid = get_gatt_bluetooth_uuid_from_handle(pinfo, att_handle, att_opcode, bluetooth_data);
132 /* Verify that the UUID belongs to the Matter GATT service and bail otherwise. */
133 if (uuid.size != 16 || (
134 memcmp(uuid.data, MATTER_GATT_CHR_TX_UUID_128, 16) != 0 &&
135 memcmp(uuid.data, MATTER_GATT_CHR_RX_UUID_128, 16) != 0 &&
136 memcmp(uuid.data, MATTER_GATT_CHR_AD_UUID_128, 16) != 0))
137 return 0;
139 /* Check that the packet is long enough to contain BTP flags byte. */
140 if (tvb_reported_length(tvb) < 1)
141 return 0;
143 col_set_str(pinfo->cinfo, COL_PROTOCOL, "Matter BTP");
145 switch (pinfo->p2p_dir) {
146 case P2P_DIR_SENT:
147 col_set_str(pinfo->cinfo, COL_INFO, "Sent ");
148 break;
149 case P2P_DIR_RECV:
150 col_set_str(pinfo->cinfo, COL_INFO, "Rcvd ");
151 break;
152 default:
153 col_set_str(pinfo->cinfo, COL_INFO, "UnknownDirection ");
154 break;
157 col_append_str(pinfo->cinfo, COL_INFO, "Matter BTP");
158 col_append_fstr(pinfo->cinfo, COL_INFO, " [Handle: 0x%04x]", att_handle);
160 /* Add Matter Bluetooth Transport Protocol as a root subtree. */
161 proto_item *root = proto_item_get_parent(btatt_tree);
162 proto_item *item = proto_tree_add_item(root, proto_matter_btp, tvb, offset, -1, ENC_NA);
163 proto_tree *tree = proto_item_add_subtree(item, ett_matter_btp);
165 // The payload format of the Additional Data characteristic is different
166 // than the standard BTP packet. It uses Matter-defined TLV encoding.
167 // Section 5.4.2.4.4
168 if (memcmp(uuid.data, MATTER_GATT_CHR_AD_UUID_128, 16) == 0)
169 return dissect_matter_chr_ad_tlv(tvb, pinfo, tree, offset, tvb_reported_length(tvb));
171 static int * const btp_flags[] = {
172 &hf_matter_btp_flags_beginning,
173 &hf_matter_btp_flags_continuing,
174 &hf_matter_btp_flags_ending,
175 &hf_matter_btp_flags_acknowledgment,
176 &hf_matter_btp_flags_management,
177 &hf_matter_btp_flags_handshake,
178 NULL
181 static int * const btp_versions[] = {
182 &hf_matter_btp_versions_0,
183 &hf_matter_btp_versions_1,
184 &hf_matter_btp_versions_2,
185 &hf_matter_btp_versions_3,
186 &hf_matter_btp_versions_4,
187 &hf_matter_btp_versions_5,
188 &hf_matter_btp_versions_6,
189 &hf_matter_btp_versions_7,
190 NULL
193 proto_tree_add_bitmask_ret_uint64(tree, tvb, offset, hf_matter_btp_flags, ett_matter_btp_flags, btp_flags, ENC_NA, &flags);
194 offset += 1;
196 if (flags & MATTER_BTP_FLAGS_MANAGEMENT) {
197 proto_tree_add_item_ret_uint(tree, hf_matter_btp_opcode, tvb, offset, 1, ENC_NA, &opcode);
198 offset += 1;
201 // The handshake packet format is different than standard BTP packets.
202 // Section 4.18.3
203 if (flags & MATTER_BTP_FLAGS_HANDSHAKE) {
205 if (opcode & MATTER_BTP_OPCODE_HANDSHAKE) {
207 // Section 4.18.3.1. BTP Handshake Request
208 if (memcmp(uuid.data, MATTER_GATT_CHR_TX_UUID_128, 16) == 0) {
210 proto_tree_add_bitmask(tree, tvb, offset, hf_matter_btp_versions, ett_matter_btp_versions, btp_versions, ENC_NA);
211 offset += 4;
212 proto_tree_add_item(tree, hf_matter_btp_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN);
213 offset += 2;
214 proto_tree_add_item(tree, hf_matter_btp_window_size, tvb, offset, 1, ENC_NA);
215 offset += 1;
217 col_append_str(pinfo->cinfo, COL_INFO, " Handshake Request");
220 // Section 4.18.3.2. BTP Handshake Response
221 if (memcmp(uuid.data, MATTER_GATT_CHR_RX_UUID_128, 16) == 0) {
223 uint32_t version;
224 proto_tree_add_item_ret_uint(tree, hf_matter_btp_version, tvb, offset, 1, ENC_NA, &version);
225 offset += 1;
227 uint32_t mtu;
228 proto_tree_add_item_ret_uint(tree, hf_matter_btp_mtu, tvb, offset, 2, ENC_LITTLE_ENDIAN, &mtu);
229 offset += 2;
231 uint32_t window_size;
232 proto_tree_add_item_ret_uint(tree, hf_matter_btp_window_size, tvb, offset, 1, ENC_NA, &window_size);
233 offset += 1;
235 col_append_fstr(pinfo->cinfo, COL_INFO, " Handshake Response, Version: %u, MTU: %u, Window Size: %u",
236 version, mtu, window_size);
242 return offset;
245 // Mark the packet as a segment of a BTP Service Data Unit.
246 col_append_str(pinfo->cinfo, COL_INFO, " SDU Segment");
248 if (flags & MATTER_BTP_FLAGS_ACKNOWLEDGMENT) {
249 uint32_t ack;
250 proto_tree_add_item_ret_uint(tree, hf_matter_btp_ack, tvb, offset, 1, ENC_NA, &ack);
251 col_append_fstr(pinfo->cinfo, COL_INFO, ", Ack: %u", ack);
252 offset += 1;
255 // All BTP packets SHALL be sent with sequence numbers.
256 // Section 4.18.4.6
257 if (flags & (MATTER_BTP_FLAGS_BEGINNING | MATTER_BTP_FLAGS_CONTINUING | MATTER_BTP_FLAGS_ENDING)) {
258 uint32_t seq;
259 proto_tree_add_item_ret_uint(tree, hf_matter_btp_seq, tvb, offset, 1, ENC_NA, &seq);
260 col_append_fstr(pinfo->cinfo, COL_INFO, ", Seq: %u", seq);
261 offset += 1;
264 // Message length is an optional field present in the Beginning Segment only.
265 // Section 4.18.2.4
266 if (flags & MATTER_BTP_FLAGS_BEGINNING) {
267 uint32_t length;
268 proto_tree_add_item_ret_uint(tree, hf_matter_btp_length, tvb, offset, 2, ENC_LITTLE_ENDIAN, &length);
269 col_append_fstr(pinfo->cinfo, COL_INFO, ", Length: %u", length);
270 offset += 2;
273 proto_tree_add_item(tree, hf_matter_btp_payload, tvb, offset, -1, ENC_NA);
275 return tvb_captured_length(tvb);
278 void
279 proto_register_btatt_matter(void)
281 static hf_register_info hf[] = {
282 {&hf_matter_btp_flags,
283 {"Flags", "btp-matter.flags",
284 FT_UINT8, BASE_HEX, NULL, 0x0,
285 "Bluetooth Transport Protocol control flags", HFILL}
287 {&hf_matter_btp_flags_handshake,
288 {"Handshake", "btp-matter.flags.handshake",
289 FT_BOOLEAN, 8, NULL, MATTER_BTP_FLAGS_HANDSHAKE,
290 "BTP handshake packet for session establishment", HFILL}
292 {&hf_matter_btp_flags_management,
293 {"Management", "btp-matter.flags.management",
294 FT_BOOLEAN, 8, NULL, MATTER_BTP_FLAGS_MANAGEMENT,
295 "Management message with the opcode field", HFILL}
297 {&hf_matter_btp_flags_acknowledgment,
298 {"Acknowledgment", "btp-matter.flags.ack",
299 FT_BOOLEAN, 8, NULL, MATTER_BTP_FLAGS_ACKNOWLEDGMENT,
300 "Indicates the presence of the ack number field", HFILL}
302 {&hf_matter_btp_flags_ending,
303 {"Ending", "btp-matter.flags.ending",
304 FT_BOOLEAN, 8, NULL, MATTER_BTP_FLAGS_ENDING,
305 "The last segment of a BTP Service Data Unit", HFILL}
307 {&hf_matter_btp_flags_continuing,
308 {"Continuing", "btp-matter.flags.continuing",
309 FT_BOOLEAN, 8, NULL, MATTER_BTP_FLAGS_CONTINUING,
310 "The continuation of a BTP Service Data Unit", HFILL}
312 {&hf_matter_btp_flags_beginning,
313 {"Beginning", "btp-matter.flags.beginning",
314 FT_BOOLEAN, 8, NULL, MATTER_BTP_FLAGS_BEGINNING,
315 "The first segment of a BTP Service Data Unit", HFILL}
317 {&hf_matter_btp_opcode,
318 {"Management Opcode", "btp-matter.opcode",
319 FT_UINT8, BASE_HEX, VALS(btp_opcode_vals), 0x0,
320 NULL, HFILL}
322 {&hf_matter_btp_versions,
323 {"Supported BTP versions", "btp-matter.versions",
324 FT_UINT32, BASE_HEX, NULL, 0x0,
325 "The list of BTP versions supported by the client", HFILL}
327 {&hf_matter_btp_versions_0,
328 {"Version", "btp-matter.versions.0",
329 FT_UINT32, BASE_DEC, NULL, 0x0F000000,
330 NULL, HFILL}
332 {&hf_matter_btp_versions_1,
333 {"Version", "btp-matter.versions.1",
334 FT_UINT32, BASE_DEC, NULL, 0xF0000000,
335 NULL, HFILL}
337 {&hf_matter_btp_versions_2,
338 {"Version", "btp-matter.versions.2",
339 FT_UINT32, BASE_DEC, NULL, 0x000F0000,
340 NULL, HFILL}
342 {&hf_matter_btp_versions_3,
343 {"Version", "btp-matter.versions.3",
344 FT_UINT32, BASE_DEC, NULL, 0x00F00000,
345 NULL, HFILL}
347 {&hf_matter_btp_versions_4,
348 {"Version", "btp-matter.versions.4",
349 FT_UINT32, BASE_DEC, NULL, 0x00000F00,
350 NULL, HFILL}
352 {&hf_matter_btp_versions_5,
353 {"Version", "btp-matter.versions.5",
354 FT_UINT32, BASE_DEC, NULL, 0x0000F000,
355 NULL, HFILL}
357 {&hf_matter_btp_versions_6,
358 {"Version", "btp-matter.versions.6",
359 FT_UINT32, BASE_DEC, NULL, 0x0000000F,
360 NULL, HFILL}
362 {&hf_matter_btp_versions_7,
363 {"Version", "btp-matter.versions.7",
364 FT_UINT32, BASE_DEC, NULL, 0x000000F0,
365 NULL, HFILL}
367 {&hf_matter_btp_version,
368 {"Version", "btp-matter.version",
369 FT_UINT8, BASE_DEC, NULL, 0x0F,
370 "The BTP protocol version selected by the server", HFILL}
372 {&hf_matter_btp_mtu,
373 {"MTU", "btp-matter.mtu",
374 FT_UINT16, BASE_DEC, NULL, 0x0,
375 "Requested or selected MTU for the connection", HFILL}
377 {&hf_matter_btp_window_size,
378 {"Window Size", "btp-matter.window",
379 FT_UINT8, BASE_DEC, NULL, 0x0,
380 "Requested or selected maximum receive window size, in units of BTP packets", HFILL}
382 {&hf_matter_btp_ack,
383 {"Acknowledgment", "btp-matter.ack",
384 FT_UINT8, BASE_DEC, NULL, 0x0,
385 "The acknowledgement of the previous sequence number", HFILL}
387 {&hf_matter_btp_seq,
388 {"Sequence Number", "btp-matter.seq",
389 FT_UINT8, BASE_DEC, NULL, 0x0,
390 "The monotonically increasing sequence number", HFILL}
392 {&hf_matter_btp_length,
393 {"Length", "btp-matter.length",
394 FT_UINT16, BASE_DEC, NULL, 0x0,
395 "The payload length, in bytes", HFILL}
397 {&hf_matter_btp_payload,
398 {"Payload", "btp-matter.payload",
399 FT_BYTES, BASE_NONE, NULL, 0x0,
400 "The segment of the Service Data Unit message", HFILL}
402 {&hf_matter_btp_ad,
403 {"Additional Data", "btp-matter.ad",
404 FT_NONE, BASE_NONE, NULL, 0x0,
405 "Additional commissioning-related data", HFILL}
407 {&hf_matter_btp_ad_tlv_tag,
408 {"Tag", "btp-matter.ad.item",
409 FT_UINT8, BASE_HEX, VALS(btp_ad_tag_vals), 0x0,
410 NULL, HFILL}
414 /* Setup protocol subtree array */
415 static int *ett[] = {
416 &ett_matter_btp,
417 &ett_matter_btp_flags,
418 &ett_matter_btp_versions,
419 &ett_matter_btp_ad,
422 /* Register the protocol name and description */
423 proto_matter_btp = proto_register_protocol("Matter Bluetooth Transport Protocol", "MatterBTP", "btp-matter");
424 matter_btp_handle = register_dissector("btp-matter", dissect_matter_btp, proto_matter_btp);
426 /* Required function calls to register the header fields and subtrees */
427 proto_register_field_array(proto_matter_btp, hf, array_length(hf));
428 proto_register_subtree_array(ett, array_length(ett));
431 void
432 proto_reg_handoff_btatt_matter(void)
434 matter_tlv_handle = find_dissector_add_dependency("matter.tlv", proto_matter_btp);
435 dissector_add_uint("btatt.service", MATTER_GATT_SRV_UUID, matter_btp_handle);