1 /* packet-zbee-direct.c
2 * Dissector routines for the ZigBee Direct
3 * Copyright 2021 DSR Corporation, http://dsr-wireless.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
15 #include <epan/packet.h>
16 #include <epan/expert.h>
19 #include "packet-zbee-security.h"
20 #include "packet-bluetooth.h"
21 #include "packet-ieee802154.h"
22 #include "packet-zbee-nwk.h"
23 #include "packet-zbee-tlv.h"
24 #include "packet-zbee-direct.h"
26 /*-------------------------------------
27 * Dissector Function Prototypes
28 *-------------------------------------
31 static int dissect_zb_direct_dump_info(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
);
32 static int dissect_zb_direct_secur_common(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
, unsigned offset
, unsigned msg_id
);
33 static int dissect_zb_direct_secur_c25519_aesmmo(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
);
34 static int dissect_zb_direct_secur_c25519_sha256(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
);
35 static int dissect_zb_direct_secur_p256(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
);
36 static int dissect_zb_direct_formation(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
);
37 static int dissect_zb_direct_status(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
);
38 static int dissect_zb_direct_join(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
);
39 static int dissect_zb_direct_permit_join(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
);
40 static int dissect_zb_direct_leave(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
);
41 static int dissect_zb_direct_manage_joiners(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
);
42 static int dissect_zb_direct_identify(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
);
43 static int dissect_zb_direct_finding_binding(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
);
44 static int dissect_zb_direct_tunneling(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void *data
);
46 static int dissect_zb_direct_common(tvbuff_t
**tvb
, packet_info
*pinfo
, proto_tree
**tree
, void *data
, unsigned offset
, const uint8_t *serv_uuid
, const uint8_t *char_uuid
);
49 static dissector_handle_t zbee_nwk_handle
;
51 /* TLV Node-elements */
52 static int proto_zb_direct
;
55 static int hf_zb_direct_info_type
;
56 static int hf_zb_direct_info_key
;
57 static int hf_zb_direct_info_zdd_ieee
;
58 static int hf_zb_direct_info_zvd_ieee
;
59 static int hf_zb_direct_info_encryption
;
60 static int hf_zb_direct_msg_type
;
63 static int hf_zb_direct_comm_permit_time
;
64 static int hf_zb_direct_comm_rejoin
;
65 static int hf_zb_direct_comm_rm_children
;
66 static int hf_zb_direct_comm_identify_time
;
67 static int hf_zb_direct_comm_fb_endpoint
;
68 static int hf_zb_direct_comm_fb_initiator
;
70 /* Markers (also leafs) */
71 static int hf_zb_direct_unrecognized_msg
;
72 static int hf_zb_direct_char_info
;
73 static int hf_zb_direct_char_c25519_aesmmo
;
74 static int hf_zb_direct_char_c25519_sha256
;
75 static int hf_zb_direct_char_p256
;
76 static int hf_zb_direct_char_form
;
77 static int hf_zb_direct_char_status
;
78 static int hf_zb_direct_char_join
;
79 static int hf_zb_direct_char_permit_join
;
80 static int hf_zb_direct_char_leave
;
81 static int hf_zb_direct_char_manage_joiners
;
82 static int hf_zb_direct_char_identify
;
83 static int hf_zb_direct_char_finding_binding
;
84 static int hf_zb_direct_char_tunneling
;
87 static expert_field ei_zb_direct_crypt_error
;
90 static int ett_zb_direct
;
92 static const uint8_t serv_secur_uuid
[] = { 0xe3, 0x29, 0xb4, 0x99, 0x02, 0x6d, 0xe9, 0xbf,
93 0x81, 0x44, 0x00, 0x00, 0xf4, 0x4a, 0x14, 0x29 };
94 static const uint8_t char_p256_uuid
[] = { 0xe3, 0x29, 0xb4, 0x99, 0x02, 0x6d, 0xe9, 0xbf,
95 0x81, 0x44, 0x03, 0x00, 0xf4, 0x4a, 0x14, 0x29 };
96 static const uint8_t char_c25519_aesmmo_uuid
[] = { 0xe3, 0x29, 0xb4, 0x99, 0x02, 0x6d, 0xe9, 0xbf,
97 0x81, 0x44, 0x01, 0x00, 0xf4, 0x4a, 0x14, 0x29 };
98 static const uint8_t char_c25519_sha256_uuid
[] = { 0xe3, 0x29, 0xb4, 0x99, 0x02, 0x6d, 0xe9, 0xbf,
99 0x81, 0x44, 0x02, 0x00, 0xf4, 0x4a, 0x14, 0x29 };
100 static const uint8_t serv_comm_uuid
[] = { 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
101 0x00, 0x10, 0x00, 0x00, 0xf7, 0xff, 0x00, 0x00 };
102 static const uint8_t char_form_uuid
[] = { 0x61, 0x3a, 0x33, 0x27, 0x1c, 0x49, 0x63, 0xb1,
103 0x1c, 0x42, 0x01, 0x00, 0x7d, 0x37, 0x72, 0x70 };
104 static const uint8_t char_join_uuid
[] = { 0x61, 0x3a, 0x33, 0x27, 0x1c, 0x49, 0x63, 0xb1,
105 0x1c, 0x42, 0x02, 0x00, 0x7d, 0x37, 0x72, 0x70 };
106 static const uint8_t char_permit_uuid
[] = { 0x61, 0x3a, 0x33, 0x27, 0x1c, 0x49, 0x63, 0xb1,
107 0x1c, 0x42, 0x03, 0x00, 0x7d, 0x37, 0x72, 0x70 };
108 static const uint8_t char_leave_uuid
[] = { 0x61, 0x3a, 0x33, 0x27, 0x1c, 0x49, 0x63, 0xb1,
109 0x1c, 0x42, 0x04, 0x00, 0x7d, 0x37, 0x72, 0x70 };
110 static const uint8_t char_status_uuid
[] = { 0x61, 0x3a, 0x33, 0x27, 0x1c, 0x49, 0x63, 0xb1,
111 0x1c, 0x42, 0x05, 0x00, 0x7d, 0x37, 0x72, 0x70 };
112 static const uint8_t char_identify_uuid
[] = { 0x61, 0x3a, 0x33, 0x27, 0x1c, 0x49, 0x63, 0xb1,
113 0x1c, 0x42, 0x07, 0x00, 0x7d, 0x37, 0x72, 0x70 };
114 static const uint8_t char_manage_joiners_uuid
[] = { 0x61, 0x3a, 0x33, 0x27, 0x1c, 0x49, 0x63, 0xb1,
115 0x1c, 0x42, 0x06, 0x00, 0x7d, 0x37, 0x72, 0x70 };
116 static const uint8_t char_finding_binding_uuid
[] = { 0x61, 0x3a, 0x33, 0x27, 0x1c, 0x49, 0x63, 0xb1,
117 0x1c, 0x42, 0x08, 0x00, 0x7d, 0x37, 0x72, 0x70 };
118 static const uint8_t serv_tunnel_uuid
[] = { 0x3f, 0x31, 0xd5, 0x8b, 0x37, 0xb2, 0x20, 0x81,
119 0xf4, 0x45, 0x00, 0x00, 0xfd, 0x78, 0xd1, 0x8b };
120 static const uint8_t char_tunnel_uuid
[] = { 0x3f, 0x31, 0xd5, 0x8b, 0x37, 0xb2, 0x20, 0x81,
121 0xf4, 0x45, 0x01, 0x00, 0xfd, 0x78, 0xd1, 0x8b };
122 #define ZIGBEE_DIRECT_MAX_ATT_SIZE 248
123 #define ZIGBEE_DIRECT_AUTH_STR_SIZE (16 + 1 + 16 + 1)
124 #define ZIGBEE_DIRECT_SECUR_CONTROL 0x05
130 #define MAX_CONNECTIONS 2
132 /*****************************************************************************/
133 /******************************** Static Data ********************************/
134 /*****************************************************************************/
136 static uat_t
*zbd_secur_key_table_uat
;
138 /* Values in the key rings. */
144 uint8_t key
[KEY_LEN
];
146 } zb_direct_key_record_t
;
149 typedef struct uat_key_record_s
157 UAT_CSTRING_CB_DEF(uat_key_records
, zdd_ieee
, uat_key_record_t
)
158 UAT_CSTRING_CB_DEF(uat_key_records
, zvd_ieee
, uat_key_record_t
)
159 UAT_CSTRING_CB_DEF(uat_key_records
, key
, uat_key_record_t
)
160 UAT_CSTRING_CB_DEF(uat_key_records
, label
, uat_key_record_t
)
162 static GSList
*zbee_pc_keyring
;
163 static uat_key_record_t
*uat_key_records
;
164 static unsigned num_uat_key_records
;
167 static uint8_t g_conn_id
;
169 static bool ignore_late_keys
= true;
176 DUMP_INFO_ENCRYPTION_STATUS
179 static const value_string info_type_str
[] =
181 { DUMP_INFO_KEY_DEL
, "Delete CCM* key" },
182 { DUMP_INFO_KEY_SET
, "Set CCM* key" },
183 { DUMP_INFO_ENCRYPTION_STATUS
, "Set encryption status" },
196 static const value_string msg_type_str
[] =
198 { MSG_SE1
, "Message SE1" },
199 { MSG_SE2
, "Message SE2" },
200 { MSG_SE3
, "Message SE3" },
201 { MSG_SE4
, "Message SE4" },
205 #define BOOLSTR(b) ((b) ? "TRUE" : "FALSE")
207 /* "Cast" GSList node to zb_direct_key_record_t* */
208 #define keyrec(node) ((zb_direct_key_record_t*)((node)->data))
211 * Like memcpy, but in reverse order.
213 * @param dst pointer to destination (copy to)
214 * @param src pointer to source (copy from)
215 * @param len number of bytes
217 static inline void memcpy_reverse(uint8_t *dst
, const uint8_t *src
, size_t len
)
221 for (size_t i
= 0; i
<= len
; ++i
)
223 dst
[i
] = src
[len
- i
];
227 /*****************************************************************************/
228 /************************************ UAT ************************************/
229 /*****************************************************************************/
232 * Parses a hex string into bytes.
234 * @param str pointer to a hex string
235 * @param buf pointer to buffer, where to place result
236 * @param bytes_num number of bytes to retrive from the string
239 static bool zbd_parse_uat_hexline(const char *str
,
245 bool string_mode
= false;
248 memset(buf
, 0, bytes_num
);
255 * Attempt to parse the hex string. The hex string must
256 * be at least 16 pairs of hexidecimal digits with the
257 * following optional separators: ':', '-', " ", or 16
258 * alphanumeric characters after a double-quote.
260 if ((temp
= *str
++) == '"')
267 for (i
= bytes_num
- 1; i
>= 0; i
--)
271 if (g_ascii_isprint(temp
))
283 /* If this character is a separator, skip it. */
284 if (temp
== ':' || temp
== '-' || temp
== ' ')
289 /* Process a nibble. */
290 if (g_ascii_isxdigit(temp
))
292 buf
[j
] = g_ascii_xdigit_value(temp
) << 4;
299 /* Get the next nibble. */
302 /* Process another nibble. */
303 if (g_ascii_isxdigit(temp
))
305 buf
[j
] |= g_ascii_xdigit_value(temp
);
312 /* Get the next nibble. */
316 /* Move buf pointer */
320 /* If we get this far, then the key was good. */
327 * @param n pointer to new uat_kkey_record_t
328 * @param o pointer to old uat_key_record_t
331 static void *uat_key_record_copy_cb(void *n
, const void *o
, size_t size _U_
)
333 uat_key_record_t
*new_key
= (uat_key_record_t
*)n
;
334 const uat_key_record_t
*old_key
= (const uat_key_record_t
*)o
;
336 new_key
->zdd_ieee
= g_strdup(old_key
->zdd_ieee
);
337 new_key
->zvd_ieee
= g_strdup(old_key
->zvd_ieee
);
338 new_key
->key
= g_strdup(old_key
->key
);
339 new_key
->label
= g_strdup(old_key
->label
);
345 * UAT Update callback.
347 * @param r pointer to uat_kkey_record_t
348 * @param err pointer to error pointer
351 static bool uat_key_record_update_cb(void *r
, char **err
)
353 uat_key_record_t
*rec
= (uat_key_record_t
*)r
;
356 uint8_t key
[KEY_LEN
];
360 if (rec
->zdd_ieee
== NULL
)
362 *err
= g_strdup("ZDD IEEE can't be blank");
366 if (rec
->zvd_ieee
== NULL
)
368 *err
= g_strdup("ZVD IEEE can't be blank");
372 if (rec
->key
== NULL
)
374 *err
= g_strdup("Key can't be blank");
378 g_strstrip(rec
->zdd_ieee
);
379 g_strstrip(rec
->zvd_ieee
);
380 g_strstrip(rec
->key
);
382 if (rec
->zdd_ieee
[0] == 0)
384 *err
= g_strdup("ZDD IEEE can't be blank");
388 if (rec
->zvd_ieee
[0] == 0)
390 *err
= g_strdup("ZVD IEEE can't be blank");
394 if (rec
->key
[0] == 0)
396 *err
= g_strdup("Key can't be blank");
400 if (!zbd_parse_uat_hexline(rec
->zdd_ieee
, zdd_ieee
, 8))
402 *err
= g_strdup_printf("Expecting %d hexadecimal bytes or a %d character double-quoted string", 8, 8);
406 if (!zbd_parse_uat_hexline(rec
->zvd_ieee
, zvd_ieee
, 8))
408 *err
= g_strdup_printf("Expecting %d hexadecimal bytes or a %d character double-quoted string", 8, 8);
412 if (!zbd_parse_uat_hexline(rec
->key
, key
, 16))
414 *err
= g_strdup_printf("Expecting %d hexadecimal bytes or a %d character double-quoted string", 16, 16);
424 * @param r pointer to a uat_key_record_t
426 static void uat_key_record_free_cb(void *r
)
428 uat_key_record_t
*key
= (uat_key_record_t
*)r
;
430 g_free(key
->zdd_ieee
);
431 g_free(key
->zvd_ieee
);
437 * Frees zb_direct_key_record_t.
439 * @param ptr pointer to a zb_direct_key_record_t
441 static void zbd_free_key_record(void *ptr
)
443 zb_direct_key_record_t
*k
= (zb_direct_key_record_t
*)ptr
;
450 * Deletes all existing keys in zbee_pc_keyrig and adds new ones
451 * from uat_key_records.
453 static void uat_key_record_post_update(void)
455 zb_direct_key_record_t key_record
;
458 uint8_t key
[KEY_LEN
];
461 GSList
*element
= zbee_pc_keyring
;
463 /* Find where UAT table keys begin */
464 while (element
&& keyrec(element
)->frame_num
> 0)
466 element
= g_slist_next(element
);
469 /* Delete all UAT keys */
472 GSList
*next
= element
->next
;
474 zbee_pc_keyring
= g_slist_remove_link(zbee_pc_keyring
, element
);
476 g_slist_free_full(element
, zbd_free_key_record
);
480 /* Load the pre-configured slist from the UAT */
481 for (unsigned i
= 0U; uat_key_records
&& i
< num_uat_key_records
; i
++)
483 bool success
= (int)zbd_parse_uat_hexline(uat_key_records
[i
].zdd_ieee
, zdd_ieee
, sizeof(zdd_ieee
))
484 | (int)zbd_parse_uat_hexline(uat_key_records
[i
].zvd_ieee
, zvd_ieee
, sizeof(zvd_ieee
))
485 | (int)zbd_parse_uat_hexline(uat_key_records
[i
].key
, key
, sizeof(key
));
489 key_record
.frame_num
= 0; /* means it's a user PC key */
490 key_record
.label
= g_strdup(uat_key_records
[i
].label
);
492 memcpy_reverse(key_record
.zdd_ieee
, zdd_ieee
, 8);
493 memcpy_reverse(key_record
.zvd_ieee
, zvd_ieee
, 8);
494 memcpy(key_record
.key
, key
, KEY_LEN
);
496 /* Add UAT keys to the end */
497 zbee_pc_keyring
= g_slist_append(zbee_pc_keyring
, g_memdup2(&key_record
, sizeof(key_record
)));
502 /*****************************************************************************/
503 /******************************** Decryption *********************************/
504 /*****************************************************************************/
506 #define MAX_CRYPT_TOGGLES 4096
508 typedef struct encryption_states_handler_s
510 /* How many toggles were performed */
512 /* Even entries point, where encryption enabled region starts, odd ones point, where they end */
513 uint32_t states
[MAX_CRYPT_TOGGLES
];
514 } encryption_states_handler_t
;
516 static encryption_states_handler_t enc_h
[MAX_CONNECTIONS
];
519 * Enables encryption for packet_info if possible.
521 * @param pinfo pointer to packet
523 static void zb_direct_encryption_enable(packet_info
*pinfo
)
525 encryption_states_handler_t
*h
= &enc_h
[g_conn_id
];
527 /* If currently enabled && was not disabled previously, exit */
528 if (h
->counter
% 2 == 1)
533 /* If this packet was already handled, exit */
534 if (h
->counter
!= 0 && pinfo
->num
<= h
->states
[h
->counter
- 1])
539 if (h
->counter
>= MAX_CRYPT_TOGGLES
)
545 h
->states
[h
->counter
++] = pinfo
->num
;
549 * Disables encryption for packet_info if possible.
551 * @param pinfo pointer to packet
553 static void zb_direct_encryption_disable(packet_info
*pinfo
)
555 encryption_states_handler_t
*h
= &enc_h
[g_conn_id
];
557 /* If currently enabled && was not disabled previously */
558 if (h
->counter
% 2 == 0)
563 if (pinfo
->num
<= h
->states
[h
->counter
- 1])
569 h
->states
[h
->counter
++] = pinfo
->num
;
573 * Checks if the packet must be decrypted.
575 * @param pinfo pointer to packet
576 * @return true, if decryption is needed, false, otherwise
578 static bool zb_direct_decryption_needed(packet_info
*pinfo
)
580 encryption_states_handler_t
*h
= &enc_h
[g_conn_id
];
582 for (int i
= 0; i
< h
->counter
; i
+= 2)
584 if (h
->states
[i
] < pinfo
->num
)
586 /* If the packet is before the beginning of current crypted block, shutdown the search */
587 if (pinfo
->num
< h
->states
[i
])
592 /* If encrypted block was opened and not closed till now, or closed after current packet */
593 if (i
== h
->counter
- 1 || pinfo
->num
< h
->states
[i
+ 1])
603 static bool decrypt_data(const uint8_t *serv_uuid
,
604 const uint8_t *char_uuid
,
611 uint8_t key
[KEY_LEN
]);
614 * Tries to decrypt packet payload as ZDD and ZVD.
616 * @param serv_uuid service UUID
617 * @param char_uuid characteristic UUID
618 * @param in pointer to encrypted payload
619 * @param out pointer to buffer for the result
620 * @param len pointer to the length of payload, outputs length of out
621 * @param zdd_ieee ZDD IEEE
622 * @param zvd_ieee ZVD IEEE
623 * @param key key for decryption
626 static bool try_decrypt(const uint8_t *serv_uuid
,
627 const uint8_t *char_uuid
,
633 uint8_t key
[KEY_LEN
])
635 /* As there is no reliable way known to determine,
636 * if the packet is from zdd or zvd, try both cases */
638 uint16_t len_buf
= *len
;
639 bool success
= decrypt_data(serv_uuid
, char_uuid
,
643 zdd_ieee
, zvd_ieee
, key
);
648 success
= decrypt_data(serv_uuid
, char_uuid
,
652 zdd_ieee
, zvd_ieee
, key
);
659 * @brief Generates IEEE address from BLE MAC.
661 * @param mac_address BLE MAC in BE
662 * @param ieee generated IEEE in BE
664 static void zb_direct_ieee_from_mac(const uint8_t *mac_address
, uint8_t *ieee
)
666 ieee
[0] = mac_address
[0] ^ 0x02;
667 ieee
[1] = mac_address
[1];
668 ieee
[2] = mac_address
[2];
671 ieee
[5] = mac_address
[3];
672 ieee
[6] = mac_address
[4];
673 ieee
[7] = mac_address
[5];
677 * @brief Get BLE MAC address of the device which sent current packet from the packet data.
679 * @param pinfo packet info
680 * @param mac BLE MAC (bd_addr) corresponding to current packet sender
682 static void zb_direct_bd_addr_from_packet_data(const packet_info
*pinfo
,
685 (void)address_to_bytes(&pinfo
->dl_src
, mac
, 6);
689 * @brief Get IEEE address of the device which generated current packet from the packet data.
691 * @param pinfo packet info
692 * @param ieee calculated IEEE in BE
694 static void zb_direct_ieee_from_packet_data(const packet_info
*pinfo
,
698 zb_direct_bd_addr_from_packet_data(pinfo
, mac
);
699 zb_direct_ieee_from_mac(mac
, ieee
);
703 * Decrypts ZB Direct packets.
705 * @param tvb pointer to buffer containing raw packet
706 * @param pinfo pointer to packet information fields
707 * @param tree pointer to the command subtree
708 * @param data raw packet private data
709 * @param offset offset into the tvb to begin dissection
710 * @param serv_uuid service UUID
711 * @param char_uuid characteristic UUID
712 * @return offset after command dissection
714 static int zb_direct_decrypt(tvbuff_t
**tvb
,
719 const uint8_t *serv_uuid
,
720 const uint8_t *char_uuid
)
722 if (zb_direct_decryption_needed(pinfo
))
725 bool success
= false;
726 uint16_t size
= tvb_reported_length_remaining(*tvb
, offset
);
727 uint8_t *decrypted
= (uint8_t *)wmem_alloc(pinfo
->pool
, 512);
729 GSList
*i
= zbee_pc_keyring
;
730 uint16_t init_size
= size
;
732 zb_direct_ieee_from_packet_data(pinfo
, ieee
);
734 if (ignore_late_keys
)
736 /* Skip all keys, which were reported after current package */
737 while (i
&& (keyrec(i
)->frame_num
> pinfo
->num
))
743 /* Try potential keys from preconfigured table and dump info packets */
744 while (i
&& !success
)
746 success
= try_decrypt(serv_uuid
,
748 tvb_get_ptr(*tvb
, offset
, size
),
762 /* Retrieve all pan-specific nwk keyrings from the hash table */
763 if (!success
&& zbee_table_nwk_keyring
)
765 pan_keyring
= (GList
*)g_hash_table_get_values(zbee_table_nwk_keyring
);
767 while (!success
&& pan_keyring
)
769 i
= *((GSList
**)pan_keyring
->data
);
771 /* Iterate over keys in the keyring */
772 while (!success
&& i
)
774 if (!ignore_late_keys
|| ((key_record_t
*)i
->data
)->frame_num
> pinfo
->num
)
776 success
= decrypt_data(serv_uuid
, char_uuid
, false,
777 tvb_get_ptr(*tvb
, offset
, size
),
779 ieee
, NULL
, ((key_record_t
*)i
->data
)->key
);
788 pan_keyring
= g_list_next(i
);
794 /* On decryption success: replace the tvb, make offset point to its beginning */
795 *tvb
= tvb_new_child_real_data(*tvb
, decrypted
, size
, size
);
796 add_new_data_source(pinfo
, *tvb
, "CCM* decrypted payload");
801 /* On decryption error: make offset point to the end of original tvb */
802 offset
= tvb_reported_length(*tvb
);
803 expert_add_info(pinfo
, tree
, &ei_zb_direct_crypt_error
);
810 /* 6.4.3. CCM Nonce */
812 #if defined(_MSC_VER)
813 # pragma pack(push, 1)
815 __attribute__((__packed__
))
819 uint8_t source_address
[8];
820 uint32_t frame_counter
;
821 uint8_t secur_control
;
822 } zb_secur_ccm_nonce_t
;
828 * Creates an auth string.
830 * @param serv_uuid service UUID
831 * @param char_uuid characteristic UUID
832 * @param auth_string output buffer
834 static void create_auth_string(const uint8_t serv_uuid
[16],
835 const uint8_t char_uuid
[16],
836 uint8_t auth_string
[ZIGBEE_DIRECT_AUTH_STR_SIZE
])
838 /* 6.4.5. Unique address */
839 memcpy_reverse(auth_string
, serv_uuid
, 16);
841 memcpy_reverse(&auth_string
[17], char_uuid
, 16);
846 * Decrypts packet payload as ZDD and ZVD.
848 * @param serv_uuid service UUID
849 * @param char_uuid characteristic UUID
850 * @param to_zdd true if packet ws sent to zdd, false if to zvd (needed for nonce formation)
851 * @param in pointer to encrypted payload
852 * @param out pointer to buffer for the result
853 * @param len pointer to the length of payload, outputs length of out
854 * @param zdd_ieee ZDD IEEE
855 * @param zvd_ieee ZVD IEEE
856 * @param key key for decryption
859 static bool decrypt_data(const uint8_t *serv_uuid
,
860 const uint8_t *char_uuid
,
867 uint8_t key
[KEY_LEN
])
870 uint8_t auth_str
[ZIGBEE_DIRECT_AUTH_STR_SIZE
];
871 uint8_t decrypted_data
[ZIGBEE_DIRECT_MAX_ATT_SIZE
+ 16];
872 uint16_t decrypted_data_len
= sizeof(decrypted_data
);
874 /* Remove 32-bit counter from the beginning */
875 const uint8_t *encrypted_data
= in
+ sizeof(uint32_t);
876 uint16_t encrypted_data_len
= *len
- sizeof(uint32_t);
879 zb_secur_ccm_nonce_t nonce
= (zb_secur_ccm_nonce_t
)
881 .secur_control
= ZIGBEE_DIRECT_SECUR_CONTROL
884 /* Fetch counter from the packet (don't check) */
885 memcpy(&nonce
.frame_counter
, in
, sizeof(uint32_t));
886 memcpy(&nonce
.source_address
, to_zdd
? zvd_ieee
: zdd_ieee
, 8);
888 if (*len
< 8) return false;
890 create_auth_string(serv_uuid
, char_uuid
, auth_str
);
892 success
= zbee_sec_ccm_decrypt(key
,
898 encrypted_data_len
- ZB_CCM_M
,
904 decrypted_data_len
= encrypted_data_len
- ZB_CCM_M
;
905 memcpy(out
, decrypted_data
, decrypted_data_len
);
906 *len
= decrypted_data_len
;
916 /*****************************************************************************/
917 /***************************** Dissectors Common *****************************/
918 /*****************************************************************************/
921 * Common helper dissector.
923 * @param tvb pointer to buffer containing raw packet
924 * @param pinfo pointer to packet information fields
925 * @param tree pointer to the command subtree
926 * @param data pointer to packet data
927 * @param offset offset into the tvb to begin dissection
928 * @param serv_uuid service UUID
929 * @param char_uuid characteristic UUID
930 * @return offset after command dissection
932 static int dissect_zb_direct_common(tvbuff_t
**tvb
,
937 const uint8_t *serv_uuid
,
938 const uint8_t *char_uuid
)
942 /** TODO: find a way to detect direct (master/slave) and particular connection from data, passed from Bluetooth dissector */
944 /* Set basic columns (proto, src, dst) */
945 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "ZBD");
948 * Actually should think of better way to know
950 * (probably try fetch BLE data: indication would reveal ZDD for example)
952 /* Add ZB Direct subtree */
953 ti
= proto_tree_add_item(*tree
, proto_zb_direct
, *tvb
, 0, -1, ENC_LITTLE_ENDIAN
);
954 *tree
= proto_item_add_subtree(ti
, ett_zb_direct
);
958 proto_item_append_text(ti
, " (Connection ID: %d)", (int)g_conn_id
);
960 /* NULL uuid is for chars, which do not have to be encrypted at all (dump info) */
961 if (char_uuid
!= NULL
&& serv_uuid
!= NULL
&& memcmp(serv_uuid
, serv_secur_uuid
, sizeof(serv_secur_uuid
)))
963 offset
= zb_direct_decrypt(tvb
, pinfo
, *tree
, data
, offset
, serv_uuid
, char_uuid
);
969 /*****************************************************************************/
970 /**************************** Dump Info Dissector ****************************/
971 /*****************************************************************************/
973 typedef enum zb_dump_info_e
975 /* Clear current used key */
976 ZB_DUMP_INFO_CCM_KEY_DELETE
,
977 /* Replace current key with a new one */
978 ZB_DUMP_INFO_CCM_KEY_SET
,
979 /* Specify, if encryption is needed or not */
980 ZB_DUMP_INFO_ENCRYPTION_STATUS
984 * Dump Info dissector.
986 * @param tvb pointer to buffer containing raw packet
987 * @param pinfo pointer to packet information fields
988 * @param tree pointer to the command subtree
989 * @param data raw packet private data
990 * @return offset after command dissection
992 static int dissect_zb_direct_dump_info(tvbuff_t
*tvb
,
1001 offset
= dissect_zb_direct_common(&tvb
, pinfo
, &tree
, data
, offset
, NULL
, NULL
);
1002 col_set_str(pinfo
->cinfo
, COL_INFO
, "Dump info");
1004 ti
= proto_tree_add_item(tree
, hf_zb_direct_char_info
, tvb
, offset
, 0, ENC_NA
);
1005 proto_item_set_generated(ti
);
1007 proto_tree_add_item_ret_uint(tree
, hf_zb_direct_info_type
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
, &type
);
1012 case ZB_DUMP_INFO_CCM_KEY_DELETE
:
1013 /* Obsolete option */
1016 case ZB_DUMP_INFO_CCM_KEY_SET
:
1018 zb_direct_key_record_t key_record
;
1019 col_append_str(pinfo
->cinfo
, COL_INFO
, ": update key");
1022 * From the Wireshark Developer's Guide:
1024 * Wireshark performs a first pass of dissecting all packets as they are loaded from the file.
1025 * All packets are dissected sequentially...
1027 * So, we can assume that keys are coming in order they will be used in file
1030 proto_tree_add_item(tree
, hf_zb_direct_info_key
, tvb
, offset
, KEY_LEN
, ENC_NA
);
1031 tvb_memcpy(tvb
, key_record
.key
, offset
, KEY_LEN
);
1034 proto_tree_add_item(tree
, hf_zb_direct_info_zdd_ieee
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
1035 tvb_memcpy(tvb
, key_record
.zdd_ieee
, offset
, sizeof(key_record
.zdd_ieee
));
1038 proto_tree_add_item(tree
, hf_zb_direct_info_zvd_ieee
, tvb
, offset
, 8, ENC_LITTLE_ENDIAN
);
1039 tvb_memcpy(tvb
, key_record
.zvd_ieee
, offset
, sizeof(key_record
.zdd_ieee
));
1042 key_record
.frame_num
= pinfo
->num
;
1043 key_record
.label
= g_strdup_printf("Key reported over air in packet #%d", pinfo
->num
);
1045 /* Check if this key was already added */
1046 if (zbee_pc_keyring
== NULL
|| keyrec(zbee_pc_keyring
)->frame_num
< pinfo
->num
)
1048 /* store the keys in order: latest <- ... <- first <- (UAT: top <- ... <- bottom) */
1049 zbee_pc_keyring
= g_slist_prepend(zbee_pc_keyring
,
1050 g_memdup2(&key_record
, sizeof(zb_direct_key_record_t
)));
1055 case ZB_DUMP_INFO_ENCRYPTION_STATUS
:
1057 bool is_enabled
= tvb_get_uint8(tvb
, offset
);
1061 zb_direct_encryption_enable(pinfo
);
1065 zb_direct_encryption_disable(pinfo
);
1068 proto_tree_add_item(tree
,
1069 hf_zb_direct_info_encryption
,
1078 col_append_str(pinfo
->cinfo
, COL_INFO
, ": encryption ON");
1082 col_append_str(pinfo
->cinfo
, COL_INFO
, ": encryption OFF");
1090 /*****************************************************************************/
1091 /********* Zigbee Direct Security Service Characteristics Dissectors *********/
1092 /*****************************************************************************/
1095 * Dissector for the security packets.
1097 * @param tvb pointer to buffer containing raw packet
1098 * @param pinfo pointer to packet information fields
1099 * @param tree pointer to the command subtree
1100 * @param data raw packet private data
1101 * @param offset offset into the tvb to begin dissection.
1102 * @param msg_id ZB Direct local Message ID
1103 * @return offset after command dissection
1105 static int dissect_zb_direct_secur_common(tvbuff_t
*tvb
,
1112 unsigned cap_len
= tvb_captured_length(tvb
);
1115 const uint8_t *decrypt_char_uuid
;
1119 case ZB_DIRECT_MSG_ID_SECUR_C25519_AESMMO
:
1120 decrypt_char_uuid
= char_c25519_aesmmo_uuid
;
1123 case ZB_DIRECT_MSG_ID_SECUR_C25519_SHA256
:
1124 decrypt_char_uuid
= char_c25519_sha256_uuid
;
1127 case ZB_DIRECT_MSG_ID_SECUR_P256
:
1128 decrypt_char_uuid
= char_p256_uuid
;
1132 DISSECTOR_ASSERT(false);
1136 offset
= dissect_zb_direct_common(&tvb
, pinfo
, &tree
, data
, offset
,
1137 serv_secur_uuid
, decrypt_char_uuid
);
1141 case ZB_DIRECT_MSG_ID_SECUR_C25519_AESMMO
:
1142 ti
= proto_tree_add_item(tree
, hf_zb_direct_char_c25519_aesmmo
, tvb
, offset
, 0, ENC_NA
);
1145 case ZB_DIRECT_MSG_ID_SECUR_C25519_SHA256
:
1146 ti
= proto_tree_add_item(tree
, hf_zb_direct_char_c25519_sha256
, tvb
, offset
, 0, ENC_NA
);
1149 case ZB_DIRECT_MSG_ID_SECUR_P256
:
1150 ti
= proto_tree_add_item(tree
, hf_zb_direct_char_p256
, tvb
, offset
, 0, ENC_NA
);
1154 DISSECTOR_ASSERT(false);
1158 proto_item_set_generated(ti
);
1160 /* Discover type of the message */
1161 uint8_t msg_type
= tvb_get_uint8(tvb
, offset
);
1163 proto_tree_add_item(tree
, hf_zb_direct_msg_type
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
);
1166 if (msg_type
== MSG_SE1
)
1168 zb_direct_encryption_disable(pinfo
);
1170 else if (msg_type
== MSG_SE4
)
1172 zb_direct_encryption_enable(pinfo
);
1175 offset
= dissect_zbee_tlvs(tvb
, pinfo
, tree
, offset
, data
,
1176 ZBEE_TLV_SRC_TYPE_ZB_DIRECT
, msg_id
);
1178 if (msg_type
>= MSG_SE1
&& msg_type
<= MSG_SE4
)
1180 size_t msg_type_idx
= msg_type
- MSG_SE1
;
1181 col_set_str(pinfo
->cinfo
, COL_INFO
, msg_type_str
[msg_type_idx
].strptr
);
1185 proto_tree_add_item(tree
, hf_zb_direct_unrecognized_msg
, tvb
, 0, cap_len
, ENC_NA
);
1188 col_set_str(pinfo
->cinfo
, COL_INFO
, "Unrecognized SE message");
1195 * Dissector for security packets authenticated with Curve25519/AESMMO.
1197 * @param tvb pointer to buffer containing raw packet
1198 * @param pinfo pointer to packet information fields
1199 * @param tree pointer to the command subtree
1200 * @param data raw packet private data
1201 * @return offset after command dissection
1203 static int dissect_zb_direct_secur_c25519_aesmmo(tvbuff_t
*tvb
,
1208 return dissect_zb_direct_secur_common(tvb
, pinfo
, tree
, data
, 0U, ZB_DIRECT_MSG_ID_SECUR_C25519_AESMMO
);
1212 * Dissector for security packets authenticated with Curve25519/SHA256.
1214 * @param tvb pointer to buffer containing raw packet
1215 * @param pinfo pointer to packet information fields
1216 * @param tree pointer to the command subtree
1217 * @param data raw packet private data
1218 * @return offset after command dissection
1220 static int dissect_zb_direct_secur_c25519_sha256(tvbuff_t
*tvb
,
1225 return dissect_zb_direct_secur_common(tvb
, pinfo
, tree
, data
, 0U, ZB_DIRECT_MSG_ID_SECUR_C25519_SHA256
);
1229 * Dissector for security packets authenticated with curve P-256.
1231 * @param tvb pointer to buffer containing raw packet
1232 * @param pinfo pointer to packet information fields
1233 * @param tree pointer to the command subtree
1234 * @param data raw packet private data
1235 * @return offset after command dissection
1237 static int dissect_zb_direct_secur_p256(tvbuff_t
*tvb
,
1242 return dissect_zb_direct_secur_common(tvb
, pinfo
, tree
, data
, 0U, ZB_DIRECT_MSG_ID_SECUR_P256
);
1245 /*****************************************************************************/
1246 /****************** BLE Service Characteristics Dissectors *******************/
1247 /*****************************************************************************/
1250 * Dissector for Form Network.
1252 * @param tvb pointer to buffer containing raw packet
1253 * @param pinfo pointer to packet information fields
1254 * @param tree pointer to subtree
1255 * @param data raw packet private data
1256 * @return offset after dissection
1258 static int dissect_zb_direct_formation(tvbuff_t
*tvb
,
1264 unsigned offset
= 0;
1266 offset
= dissect_zb_direct_common(&tvb
, pinfo
, &tree
, data
, offset
, serv_comm_uuid
, char_form_uuid
);
1267 ti
= proto_tree_add_item(tree
, hf_zb_direct_char_form
, tvb
, offset
, 0, ENC_NA
);
1268 proto_item_set_generated(ti
);
1270 col_set_str(pinfo
->cinfo
, COL_INFO
, "FORM Request");
1274 offset
= dissect_zbee_tlvs(tvb
, pinfo
, tree
, offset
, data
,
1275 ZBEE_TLV_SRC_TYPE_ZB_DIRECT
,
1276 ZB_DIRECT_MSG_ID_FORMATION
);
1283 * Dissector for Commissioning Status.
1285 * @param tvb pointer to buffer containing raw packet
1286 * @param pinfo pointer to packet information fields
1287 * @param tree pointer to subtree
1288 * @param data raw packet private data
1289 * @return offset after dissection
1291 static int dissect_zb_direct_status(tvbuff_t
*tvb
,
1297 unsigned offset
= 0;
1298 offset
= dissect_zb_direct_common(&tvb
, pinfo
, &tree
, data
, offset
, serv_comm_uuid
, char_status_uuid
);
1299 ti
= proto_tree_add_item(tree
, hf_zb_direct_char_status
, tvb
, offset
, 0, ENC_NA
);
1300 proto_item_set_generated(ti
);
1302 col_set_str(pinfo
->cinfo
, COL_INFO
, "COMM STATUS Notification");
1304 offset
= dissect_zbee_tlvs(tvb
, pinfo
, tree
, offset
, data
,
1305 ZBEE_TLV_SRC_TYPE_ZB_DIRECT
,
1306 ZB_DIRECT_MSG_ID_STATUS
);
1312 * Dissector for Join Network.
1314 * @param tvb pointer to buffer containing raw packet
1315 * @param pinfo pointer to packet information fields
1316 * @param tree pointer to subtree
1317 * @param data raw packet private data
1318 * @return offset after dissection
1320 static int dissect_zb_direct_join(tvbuff_t
*tvb
,
1326 unsigned offset
= 0;
1328 offset
= dissect_zb_direct_common(&tvb
, pinfo
, &tree
, data
, offset
, serv_comm_uuid
, char_join_uuid
);
1329 ti
= proto_tree_add_item(tree
, hf_zb_direct_char_join
, tvb
, offset
, 0, ENC_NA
);
1330 proto_item_set_generated(ti
);
1332 col_set_str(pinfo
->cinfo
, COL_INFO
, "JOIN Request");
1336 offset
= dissect_zbee_tlvs(tvb
, pinfo
, tree
, offset
, data
,
1337 ZBEE_TLV_SRC_TYPE_ZB_DIRECT
,
1338 ZB_DIRECT_MSG_ID_JOIN
);
1345 * Dissector for Permit Joining.
1347 * @param tvb pointer to buffer containing raw packet
1348 * @param pinfo pointer to packet information fields
1349 * @param tree pointer to subtree
1350 * @param data raw packet private data
1351 * @return offset after dissection
1353 static int dissect_zb_direct_permit_join(tvbuff_t
*tvb
,
1359 unsigned offset
= 0;
1361 offset
= dissect_zb_direct_common(&tvb
, pinfo
, &tree
, data
, offset
, serv_comm_uuid
, char_permit_uuid
);
1362 ti
= proto_tree_add_item(tree
, hf_zb_direct_char_permit_join
, tvb
, offset
, 0, ENC_NA
);
1363 proto_item_set_generated(ti
);
1365 col_set_str(pinfo
->cinfo
, COL_INFO
, "PERMIT JOIN Request");
1367 if (offset
< tvb_reported_length(tvb
))
1369 uint32_t parent_time
;
1371 proto_tree_add_item_ret_uint(tree
, hf_zb_direct_comm_permit_time
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
, &parent_time
);
1374 if (parent_time
> 0)
1376 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ": open for %us", parent_time
);
1380 col_append_str(pinfo
->cinfo
, COL_INFO
, ": close");
1388 * Dissector for Leave Networ.
1390 * @param tvb pointer to buffer containing raw packet
1391 * @param pinfo pointer to packet information fields
1392 * @param tree pointer to subtree
1393 * @param data raw packet private data
1394 * @return offset after dissection
1396 static int dissect_zb_direct_leave(tvbuff_t
*tvb
,
1402 unsigned offset
= 0;
1404 offset
= dissect_zb_direct_common(&tvb
, pinfo
, &tree
, data
, offset
, serv_comm_uuid
, char_leave_uuid
);
1405 ti
= proto_tree_add_item(tree
, hf_zb_direct_char_leave
, tvb
, offset
, 0, ENC_NA
);
1406 proto_item_set_generated(ti
);
1408 col_set_str(pinfo
->cinfo
, COL_INFO
, "LEAVE Request");
1410 if (offset
< tvb_reported_length(tvb
))
1415 proto_tree_add_item_ret_boolean(tree
, hf_zb_direct_comm_rm_children
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
, &rm_children
);
1418 proto_tree_add_item_ret_boolean(tree
, hf_zb_direct_comm_rejoin
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
, &rejoin
);
1421 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (remove children: %s, rejoin: %s)", BOOLSTR(rm_children
), BOOLSTR(rejoin
));
1428 * Dissector for Manage Joiners.
1430 * @param tvb pointer to buffer containing raw packet
1431 * @param pinfo pointer to packet information fields
1432 * @param tree pointer to subtree
1433 * @param data raw packet private data
1434 * @return offset after dissection
1436 static int dissect_zb_direct_manage_joiners(tvbuff_t
*tvb
,
1442 unsigned offset
= 0;
1444 offset
= dissect_zb_direct_common(&tvb
, pinfo
, &tree
, data
, offset
, serv_comm_uuid
, char_manage_joiners_uuid
);
1445 ti
= proto_tree_add_item(tree
, hf_zb_direct_char_manage_joiners
, tvb
, offset
, 0, ENC_NA
);
1446 proto_item_set_generated(ti
);
1448 col_set_str(pinfo
->cinfo
, COL_INFO
, "MANAGE JOINERS Request");
1452 offset
= dissect_zbee_tlvs(tvb
, pinfo
, tree
, offset
, data
,
1453 ZBEE_TLV_SRC_TYPE_ZB_DIRECT
,
1454 ZB_DIRECT_MSG_ID_MANAGE_JOINERS
);
1461 * Dissector for Indentify.
1463 * @param tvb pointer to buffer containing raw packet
1464 * @param pinfo pointer to packet information fields
1465 * @param tree pointer to subtree
1466 * @param data raw packet private data
1467 * @return offset after dissection
1469 static int dissect_zb_direct_identify(tvbuff_t
*tvb
,
1475 unsigned offset
= 0;
1476 offset
= dissect_zb_direct_common(&tvb
, pinfo
, &tree
, data
, offset
, serv_comm_uuid
, char_identify_uuid
);
1477 ti
= proto_tree_add_item(tree
, hf_zb_direct_char_identify
, tvb
, offset
, 0, ENC_NA
);
1478 proto_item_set_generated(ti
);
1480 col_set_str(pinfo
->cinfo
, COL_INFO
, "IDENTIFY Request");
1482 if (offset
< tvb_reported_length(tvb
))
1484 uint32_t parent_time
;
1486 proto_tree_add_item_ret_uint(tree
, hf_zb_direct_comm_identify_time
, tvb
, offset
, 2, ENC_LITTLE_ENDIAN
, &parent_time
);
1489 if (parent_time
> 0)
1491 col_append_fstr(pinfo
->cinfo
, COL_INFO
, ": start for %us", parent_time
);
1495 col_append_str(pinfo
->cinfo
, COL_INFO
, ": stop");
1503 * Dissector for Finding & Binding.
1505 * @param tvb pointer to buffer containing raw packet
1506 * @param pinfo pointer to packet information fields
1507 * @param tree pointer to subtree
1508 * @param data raw packet private data
1509 * @return offset after dissection
1511 static int dissect_zb_direct_finding_binding(tvbuff_t
*tvb
,
1517 unsigned offset
= 0;
1519 offset
= dissect_zb_direct_common(&tvb
, pinfo
, &tree
, data
, offset
, serv_comm_uuid
, char_finding_binding_uuid
);
1520 ti
= proto_tree_add_item(tree
, hf_zb_direct_char_finding_binding
, tvb
, offset
, 0, ENC_NA
);
1521 proto_item_set_generated(ti
);
1523 col_set_str(pinfo
->cinfo
, COL_INFO
, "FINDING & BINDING Request");
1525 if (offset
< tvb_reported_length(tvb
))
1530 proto_tree_add_item_ret_uint(tree
, hf_zb_direct_comm_fb_endpoint
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
, &endpoint
);
1532 proto_tree_add_item_ret_boolean(tree
, hf_zb_direct_comm_fb_initiator
, tvb
, offset
, 1, ENC_LITTLE_ENDIAN
, &initiator
);
1535 col_append_fstr(pinfo
->cinfo
, COL_INFO
, " (endpoint: %u, initiator: %s)", endpoint
, BOOLSTR(initiator
));
1542 * Helper dissector for Tunneling.
1544 * @param tvb pointer to buffer containing raw packet
1545 * @param pinfo pointer to packet information fields
1546 * @param tree pointer to subtree
1547 * @param data raw packet private data
1548 * @return offset after dissection
1550 static int dissect_zb_direct_tunneling(tvbuff_t
*tvb
,
1556 unsigned offset
= 0;
1558 offset
= dissect_zb_direct_common(&tvb
,
1567 ti
= proto_tree_add_item(tree
, hf_zb_direct_char_tunneling
, tvb
, offset
, 0, ENC_NA
);
1568 proto_item_set_generated(ti
);
1570 offset
= dissect_zbee_tlvs(tvb
, pinfo
, tree
, offset
, data
,
1571 ZBEE_TLV_SRC_TYPE_ZB_DIRECT
,
1572 ZB_DIRECT_MSG_ID_TUNNELING
);
1577 /*****************************************************************************/
1578 /******************************* Registration ********************************/
1579 /*****************************************************************************/
1582 * ZigBee Direct initialization routine.
1584 static void zb_direct_init(void)
1586 for (int i
= 0; i
< MAX_CONNECTIONS
; i
++)
1588 enc_h
[i
].counter
= 0;
1590 for (int j
= 0; j
< MAX_CRYPT_TOGGLES
&& enc_h
[i
].states
[j
] != 0; j
++)
1592 enc_h
[i
].states
[j
] = 0;
1598 * ZigBee Direct clean routine.
1600 static void zb_direct_cleanup(void)
1602 /* Empty temporary keys */
1603 while (zbee_pc_keyring
&& keyrec(zbee_pc_keyring
)->frame_num
> 0)
1605 GSList
*element
= zbee_pc_keyring
;
1607 zbee_pc_keyring
= g_slist_delete_link(zbee_pc_keyring
, element
);
1612 * ZigBee Direct registration routine.
1614 void proto_register_zb_direct(void)
1616 static hf_register_info hf
[] =
1618 { &hf_zb_direct_unrecognized_msg
,
1619 { "Unrecognized message", "zbd.unrecognized",
1620 FT_BYTES
, SEP_SPACE
,
1624 { &hf_zb_direct_info_type
,
1625 { "Type", "zbd.dump_info.type",
1627 VALS(info_type_str
), 0x0,
1630 { &hf_zb_direct_info_key
,
1632 FT_BYTES
, SEP_SPACE
,
1636 { &hf_zb_direct_info_zdd_ieee
,
1637 { "ZDD IEEE Address", "zbd.dump_info.zdd_addr",
1638 FT_UINT64
, BASE_HEX
,
1642 { &hf_zb_direct_info_zvd_ieee
,
1643 { "ZVD IEEE Address", "zbd.dump_info.zvd_addr",
1644 FT_UINT64
, BASE_HEX
,
1648 { &hf_zb_direct_info_encryption
,
1649 { "Encryption enabled", "zbd.encryption_status",
1650 FT_BOOLEAN
, BASE_NONE
,
1655 { &hf_zb_direct_msg_type
,
1656 { "Message type", "zbd.secur.msg_type",
1658 VALS(msg_type_str
), 0x0,
1663 { &hf_zb_direct_char_info
,
1664 { "Dump info", "zbd.dump_info",
1669 { &hf_zb_direct_char_c25519_aesmmo
,
1670 { "Characteristic: Security / C25519-AES-MMO", "zbd.secur.c25519_aesmmo",
1675 { &hf_zb_direct_char_c25519_sha256
,
1676 { "Characteristic: Security / C25519-SHA-256", "zbd.secur.c25519_sha256",
1681 { &hf_zb_direct_char_p256
,
1682 { "Characteristic: Security / P-256", "zbd.secur.p256",
1687 { &hf_zb_direct_char_form
,
1688 { "Characteristic: Commissioning / Formation", "zbd.comm.form",
1693 { &hf_zb_direct_char_status
,
1694 { "Characteristic: Commissioning / Status", "zbd.comm.status",
1699 { &hf_zb_direct_char_join
,
1700 { "Characteristic: Commissioning / Join", "zbd.comm.join",
1705 { &hf_zb_direct_char_permit_join
,
1706 { "Characteristic: Commissioning / Permit Join", "zbd.comm.permit_join",
1711 { &hf_zb_direct_char_leave
,
1712 { "Characteristic: Commissioning / Leave", "zbd.comm.leave",
1717 { &hf_zb_direct_char_manage_joiners
,
1718 { "Characteristic: Commissioning / Manage Joiners", "zbd.comm.manage_joiners",
1723 { &hf_zb_direct_char_identify
,
1724 { "Characteristic: Commissioning / Identify", "zbd.comm.identify",
1729 { &hf_zb_direct_char_finding_binding
,
1730 { "Characteristic: Commissioning / Finding & Binding", "zbd.comm.finding_binding",
1735 { &hf_zb_direct_char_tunneling
,
1736 { "Characteristic: Tunneling", "zbd.comm.tunneling",
1742 /* Subtrees elements */
1743 { &hf_zb_direct_comm_permit_time
,
1744 { "Permit time interval (sec)", "zbd.comm.permit_time",
1749 { &hf_zb_direct_comm_rejoin
,
1750 { "Rejoin", "zbd.comm.rejoin",
1751 FT_BOOLEAN
, BASE_NONE
,
1755 { &hf_zb_direct_comm_rm_children
,
1756 { "Remove children", "zbd.comm.rm_children",
1757 FT_BOOLEAN
, BASE_NONE
,
1761 { &hf_zb_direct_comm_identify_time
,
1762 { "Identify time", "zbd.comm.identify_time",
1763 FT_UINT16
, BASE_DEC
,
1767 { &hf_zb_direct_comm_fb_endpoint
,
1768 { "Endpoint", "zbd.comm.fb_endpoint",
1773 { &hf_zb_direct_comm_fb_initiator
,
1774 { "Initiator", "zbd.comm.fb_initiator",
1775 FT_BOOLEAN
, BASE_NONE
,
1781 static ei_register_info ei
[] = {
1782 { &ei_zb_direct_crypt_error
,
1783 { "zbd.error.decryption", PI_UNDECODED
, PI_WARN
,
1789 /* Setup protocol subtree array */
1795 expert_module_t
*expert_zb_direct
;
1797 proto_zb_direct
= proto_register_protocol("ZigBee Direct", /* name */
1798 "ZBD", /* short_name */
1799 "zbd"); /* filter_name */
1801 proto_register_field_array(proto_zb_direct
, hf
, array_length(hf
));
1802 proto_register_subtree_array(ett
, array_length(ett
));
1804 expert_zb_direct
= expert_register_protocol(proto_zb_direct
);
1805 expert_register_field_array(expert_zb_direct
, ei
, array_length(ei
));
1807 register_init_routine(zb_direct_init
);
1808 register_cleanup_routine(zb_direct_cleanup
);
1810 module_t
*zbd_prefs
= prefs_register_protocol(proto_zb_direct
, NULL
);
1812 static uat_field_t key_uat_fields
[] =
1814 UAT_FLD_CSTRING(uat_key_records
, zdd_ieee
, "ZDD IEEE",
1815 "A 8-byte address of ZDD in hexadecimal with optional "
1816 "dash-, colon-, or space-separator characters, "
1818 UAT_FLD_CSTRING(uat_key_records
, zvd_ieee
, "ZVD IEEE",
1819 "A 8-byte address of ZVD in hexadecimal with optional "
1820 "dash-, colon-, or space-separator characters, "
1822 UAT_FLD_CSTRING(uat_key_records
, key
, "Key",
1823 "A 16-byte session key in hexadecimal with optional "
1824 "dash-, colon-, or space-separator characters, "
1827 UAT_FLD_CSTRING(uat_key_records
, label
, "Label", "User comment"),
1831 /* Affects dissection of packets, but not set of named fields */
1832 unsigned uat_flags
= UAT_AFFECTS_DISSECTION
;
1834 zbd_secur_key_table_uat
= uat_new("Pre-configured Keys",
1835 sizeof(uat_key_record_t
),
1836 "zigbee_direct_pc_keys",
1839 &num_uat_key_records
,
1841 NULL
, /** TODO: ptr to help manual? */
1842 uat_key_record_copy_cb
,
1843 uat_key_record_update_cb
,
1844 uat_key_record_free_cb
,
1845 uat_key_record_post_update
,
1849 prefs_register_uat_preference(zbd_prefs
,
1851 "Pre-configured Keys",
1852 "Pre-configured session keys",
1853 zbd_secur_key_table_uat
);
1855 prefs_register_bool_preference(zbd_prefs
,
1858 "Whether or not dissector shall ignore keys, "
1859 "which were provided after current packet "
1860 "during decryption",
1865 * ZigBee Direct handoff routine.
1867 void proto_reg_handoff_zb_direct(void)
1871 const char * const uuid
;
1872 char * const description
;
1873 dissector_t dissector
;
1874 } zb_direct_service_t
;
1876 static zb_direct_service_t services
[] =
1878 { "29144af4-00ff-4481-bfe9-6d0299b429e3", "ZBD Dump Info", dissect_zb_direct_dump_info
},
1880 /* 6.5.1. Zigbee Direct Security Service characteristic */
1881 { "29144af4-0001-4481-bfe9-6d0299b429e3", "ZBD Authenticate SPEKE/Curve25519/AES-MMO-128/HMAC-AES-MMO-128", dissect_zb_direct_secur_c25519_aesmmo
},
1882 { "29144af4-0002-4481-bfe9-6d0299b429e3", "ZBD Authenticate SPEKE/Curve25519/SHA-256/HMAC-SHA-256-128", dissect_zb_direct_secur_c25519_sha256
},
1883 { "29144af4-0003-4481-bfe9-6d0299b429e3", "ZBD Authenticate ECDHE-PSK/P-256/SHA-256/HMAC-SHA-256-128", dissect_zb_direct_secur_p256
},
1885 /* 7.7.2.3. Zigbee Direct Commissioning Service characteristics */
1886 { "7072377d-0001-421c-b163-491c27333a61", "ZBD Form Network", dissect_zb_direct_formation
},
1887 { "7072377d-0002-421c-b163-491c27333a61", "ZBD Join Network", dissect_zb_direct_join
},
1888 { "7072377d-0003-421c-b163-491c27333a61", "ZBD Permit Joining", dissect_zb_direct_permit_join
},
1889 { "7072377d-0004-421c-b163-491c27333a61", "ZBD Leave Network", dissect_zb_direct_leave
},
1890 { "7072377d-0005-421c-b163-491c27333a61", "ZBD Commissioning Status", dissect_zb_direct_status
},
1891 { "7072377d-0006-421c-b163-491c27333a61", "ZBD Manage Joiners", dissect_zb_direct_manage_joiners
},
1892 { "7072377d-0007-421c-b163-491c27333a61", "ZBD Identify", dissect_zb_direct_identify
},
1893 { "7072377d-0008-421c-b163-491c27333a61", "ZBD Finding & Binding", dissect_zb_direct_finding_binding
},
1895 /* 7.7.3.3. Zigbee Direct Tunnel Service characteristics */
1896 { "8bd178fd-0001-45f4-8120-b2378bd5313f", "ZBD Tunnel Service NPDU", dissect_zb_direct_tunneling
},
1897 { NULL
, NULL
, NULL
},
1900 for (size_t i
= 0; services
[i
].uuid
; i
++)
1902 wmem_tree_insert_string(bluetooth_uuids
, services
[i
].uuid
, services
[i
].description
, 0);
1904 dissector_handle_t handle
= create_dissector_handle_with_name_and_description(
1905 services
[i
].dissector
, proto_zb_direct
,
1906 NULL
, services
[i
].description
);
1907 dissector_add_string("bluetooth.uuid", services
[i
].uuid
, handle
);
1910 zbee_nwk_handle
= find_dissector("zbee_nwk");
1914 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1919 * indent-tabs-mode: nil
1922 * vi: set shiftwidth=4 tabstop=8 expandtab:
1923 * :indentSize=4:tabSize=8:noTabs=true: