1 /* packet-nordic_ble.c
2  * Routines for nRF Sniffer for Bluetooth LE dissection
3  *
4  * Copyright (c) 2016-2018 Nordic Semiconductor.
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * SPDX-License-Identifier: GPL-2.0-or-later
11  */
12 
13 /* nRF Sniffer for Bluetooth LE packet format: BoardID + Header + Payload
14  *
15  *  +--------+--------+--------+--------+--------+--------+--------+--------+
16  *  |                           BoardID  (1 byte)                           |
17  *  +--------+--------+--------+--------+--------+--------+--------+--------+
18  *
19  * Header version 0 (legacy):
20  *  +--------+--------+--------+--------+--------+--------+--------+--------+
21  *  |                          Packet ID  (1 byte)                          |
22  *  +--------+--------+--------+--------+--------+--------+--------+--------+
23  *  |                         Packet counter (LSB)                          |
24  *  |                               (2 bytes)                               |
25  *  +--------+--------+--------+--------+--------+--------+--------+--------+
26  *  |                                Unused                                 |
27  *  |                               (2 bytes)                               |
28  *  +--------+--------+--------+--------+--------+--------+--------+--------+
29  *  |                      Length of payload  (1 byte)                      |
30  *  +--------+--------+--------+--------+--------+--------+--------+--------+
31  *
32  * Header version 1:
33  *  +--------+--------+--------+--------+--------+--------+--------+--------+
34  *  |                      Length of header  (1 byte)                       |
35  *  +--------+--------+--------+--------+--------+--------+--------+--------+
36  *  |                      Length of payload  (1 byte)                      |
37  *  +--------+--------+--------+--------+--------+--------+--------+--------+
38  *  |                      Protocol version  (1 byte)                       |
39  *  +--------+--------+--------+--------+--------+--------+--------+--------+
40  *  |                         Packet counter (LSB)                          |
41  *  |                               (2 bytes)                               |
42  *  +--------+--------+--------+--------+--------+--------+--------+--------+
43  *  |                          Packet ID  (1 byte)                          |
44  *  +--------+--------+--------+--------+--------+--------+--------+--------+
45  *
46  * Header version > 1:
47  *  +--------+--------+--------+--------+--------+--------+--------+--------+
48  *  |                   Length of payload (little endian)                   |
49  *  |                               (2 bytes)                               |
50  *  +--------+--------+--------+--------+--------+--------+--------+--------+
51  *  |                      Protocol version  (1 byte)                       |
52  *  +--------+--------+--------+--------+--------+--------+--------+--------+
53  *  |                    Packet counter (little endian)                     |
54  *  |                               (2 bytes)                               |
55  *  +--------+--------+--------+--------+--------+--------+--------+--------+
56  *  |                          Packet ID  (1 byte)                          |
57  *  +--------+--------+--------+--------+--------+--------+--------+--------+
58  *
59  *  Packet ID:
60  *   0x00 = REQ_FOLLOW
61  *          Host tells the Sniffer to scan for Advertising from a specific
62  *          address and follow all communication it has with other devices.
63  *
64  *   0x01 = EVENT_FOLLOW
65  *          Sniffer tells the Host that it has entered the FOLLOW state.
66  *
67  *   0x02 = EVENT_PACKET_ADVERTISING
68  *          Sniffer tells the Host that it has received an advertising physical
69  *          channel PDU.
70  *
71  *   0x05 = EVENT_CONNECT
72  *          Sniffer tells the Host that someone has connected to the unit we
73  *          are following.
74  *
75  *   0x06 = EVENT_PACKET_DATA
76  *   Protocol version < 3:
77  *          Sniffer tells the host that it has received a packet on any physical
78  *          channel.
79  *          Access address == 0x8e89bed6 Advertising physical channel PDU
80  *          Access address != 0x8e89bed6 Data physical channel PDU
81  *   Protocol version 3:
82  *          Sniffer tells the Host that it has received a data physical
83  *          channel PDU.
84  *
85  *   0x07 = REQ_SCAN_CONT
86  *          Host tells the Sniffer to scan continuously for any advertising
87  *          physical channel PDUs and send all packets received.
88  *
89  *   0x09 = EVENT_DISCONNECT
90  *          Sniffer tells the Host that the connected address we were following
91  *          has received a disconnect packet.
92  *
93  *   0x0C = SET_TEMPORARY_KEY
94  *          Specify a temporary key (TK) to use on encryption.
95  *          Only used for Legacy OOB and Legacy passkey pairing.
96  *
97  *   0x0D = PING_REQ
98  *
99  *   0x0E = PING_RESP
100  *
101  *   0x13 = SWITCH_BAUD_RATE_REQ
102  *
103  *   0x14 = SWITCH_BAUD_RATE_RESP
104  *
105  *   0x17 = SET_ADV_CHANNEL_HOP_SEQ
106  *          Host tells the Sniffer which order to cycle through the channels
107  *          when following an advertiser.
108  *
109  *   0xFE = GO_IDLE
110  *          Host tell the Sniffer to stop sending UART traffic and listen for
111  *          new commands.
112  *
113  * Payloads:
114  *
115  *  Protocol version < 3:
116  *  EVENT_PACKET             (ID 0x06)
117  *
118  *  Protocol version 3:
119  *  EVENT_PACKET_ADVERTISING (ID 0x02)
120  *  EVENT_PACKET_DATA        (ID 0x06)
121  *  +--------+--------+--------+--------+--------+--------+--------+--------+
122  *  |                   Length of payload data  (1 byte)                    |
123  *  +--------+--------+--------+--------+--------+--------+--------+--------+
124  *  |                            Flags  (1 byte)                            |
125  *  +--------+--------+--------+--------+--------+--------+--------+--------+
126  *  |                           Channel  (1 byte)                           |
127  *  +--------+--------+--------+--------+--------+--------+--------+--------+
128  *  |                      RSSISample (dBm)  (1 byte)                       |
129  *  +--------+--------+--------+--------+--------+--------+--------+--------+
130  *  |                             Event counter                             |
131  *  |                               (2 bytes)                               |
132  *  +--------+--------+--------+--------+--------+--------+--------+--------+
133  *  |  Protocol version < 3:    Delta time (us end to start)                |
134  *  |                                    (4 bytes)                          |
135  *  |  Protocol version 3:      Firmware  Timestamp (us)                    |
136  *  |                                    (4 bytes)                          |
137  *  +--------+--------+--------+--------+--------+--------+--------+--------+
138  *
139  *  +--------+--------+--------+--------+--------+--------+--------+--------+
140  *  |                                                                       |
141  *  |      Bluetooth Low Energy Link Layer Packet (excluding preamble)      |
142  *  |                                  ...                                  |
143  *  |                                                                       |
144  *  +--------+--------+--------+--------+--------+--------+--------+--------+
145  *
146  *  Flags EVENT_PACKET_ADVERTISING (0x02)
147  *   0000000x = CRC       (0 = Incorrect, 1 = OK)
148  *   000000x0 = RFU
149  *   00000x00 = RFU
150  *   00000xx0 = AUX_TYPE  (channel < 37: 0 = AUX_ADV_IND, 1 = AUX_CHAIN_IND,
151  *                                       2 = AUX_SYNC_IND, 3 = AUX_SCAN_RSP)
152  *   0000x000 = RFU
153  *   0xxx0000 = PHY       (0 = 1M, 1 = 2M, 2 = Coded, rest unused)
154  *   x0000000 = RFU
155  *
156  *  Flags EVENT_PACKET_DATA (0x06)
157  *   0000000x = CRC       (0 = Incorrect, 1 = OK)
158  *   000000x0 = Direction (0 = Slave -> Master, 1 = Master -> Slave)
159  *   00000x00 = Encrypted (0 = No, 1 = Yes)
160  *   0000x000 = MIC       (0 = Incorrect, 1 = OK)
161  *   0xxx0000 = PHY       (0 = 1M, 1 = 2M, 2 = Coded, rest unused)
162  *   x0000000 = RFU
163  *
164  *  Channel:
165  *   The channel index being used.
166  *
167  * RSSIsample:
168  *   RSSI sample raw value. The value of this register is read as a
169  *   positive value while the actual received signal strength is a
170  *   negative value. Actual received signal strength is therefore
171  *   as follows: rssi = -RSSISAMPLE dBm
172  *
173  *  Delta time:
174  *   This is the time in microseconds from the end of the previous received
175  *   packet to the beginning of this packet.
176  *
177  *  Firmware timestamp:
178  *    Timestamp of the start of the received packet captured by the firmware
179  *    timer with microsecond resolution.
180  */
181 
182 #include "config.h"
183 
184 #include <epan/packet.h>
185 #include <epan/expert.h>
186 #include <epan/proto_data.h>
187 
188 #include <wsutil/utf8_entities.h>
189 #include <wiretap/wtap.h>
190 
191 #include "packet-btle.h"
192 
193 /* Size of various UART Packet header fields */
194 #define UART_HEADER_LEN      6
195 #define EVENT_PACKET_LEN    10
196 
197 #define US_PER_BYTE_1M_PHY   8
198 #define US_PER_BYTE_2M_PHY   4
199 
200 #define US_PER_BYTE_CODED_PHY_S8 64
201 #define US_PER_BYTE_CODED_PHY_S2 16
202 
203 #define PREAMBLE_LEN_1M_PHY  1
204 #define PREAMBLE_LEN_2M_PHY  2
205 
206 /* Preamble + Access Address + CI + TERM1 */
207 #define FEC1_BLOCK_S8_US (80 + 256 + 16 + 24)
208 #define TERM2_S8_US      24
209 #define TERM2_S2_US       6
210 
211 void proto_reg_handoff_nordic_ble(void);
212 void proto_register_nordic_ble(void);
213 
214 /* Initialize the protocol and registered fields */
215 static int proto_nordic_ble = -1;
216 
217 /* Initialize the subtree pointers */
218 static gint ett_nordic_ble = -1;
219 static gint ett_packet_header = -1;
220 static gint ett_flags = -1;
221 
222 static int hf_nordic_ble_board_id = -1;
223 static int hf_nordic_ble_legacy_marker = -1;
224 static int hf_nordic_ble_header = -1;
225 static int hf_nordic_ble_header_length = -1;
226 static int hf_nordic_ble_payload_length = -1;
227 static int hf_nordic_ble_protover = -1;
228 static int hf_nordic_ble_packet_counter = -1;
229 static int hf_nordic_ble_packet_id = -1;
230 static int hf_nordic_ble_packet_length = -1;
231 static int hf_nordic_ble_flags = -1;
232 static int hf_nordic_ble_crcok = -1;
233 static int hf_nordic_ble_encrypted = -1;
234 static int hf_nordic_ble_micok = -1;
235 static int hf_nordic_ble_mic_not_relevant = -1;
236 static int hf_nordic_ble_aux_type = -1;
237 static int hf_nordic_ble_flag_reserved1 = -1;
238 static int hf_nordic_ble_flag_reserved2 = -1;
239 static int hf_nordic_ble_address_resolved = -1;
240 static int hf_nordic_ble_flag_reserved7 = -1;
241 static int hf_nordic_ble_le_phy = -1;
242 static int hf_nordic_ble_direction = -1;
243 static int hf_nordic_ble_channel = -1;
244 static int hf_nordic_ble_rssi = -1;
245 static int hf_nordic_ble_event_counter = -1;
246 static int hf_nordic_ble_time = -1;
247 static int hf_nordic_ble_delta_time = -1;
248 static int hf_nordic_ble_delta_time_ss = -1;
249 static int hf_nordic_ble_packet_time = -1;
250 
251 static expert_field ei_nordic_ble_bad_crc = EI_INIT;
252 static expert_field ei_nordic_ble_bad_mic = EI_INIT;
253 static expert_field ei_nordic_ble_bad_length = EI_INIT;
254 static expert_field ei_nordic_ble_unknown_version = EI_INIT;
255 
256 static const true_false_string direction_tfs =
257 {
258     "Master -> Slave",
259     "Slave -> Master"
260 };
261 
262 static const value_string le_phys[] =
263 {
264     { 0, "LE 1M"    },
265     { 1, "LE 2M"    },
266     { 2, "LE Coded" },
267     { 3, "Reserved" },
268     { 4, "Reserved" },
269     { 5, "Reserved" },
270     { 6, "Reserved" },
271     { 7, "Reserved" },
272     { 0, NULL }
273 };
274 
275 #define CI_S8 0
276 #define CI_S2 1
277 
278 static const value_string le_aux_ext_adv[] = {
279     { 0, "AUX_ADV_IND" },
280     { 1, "AUX_CHAIN_IND" },
281     { 2, "AUX_SYNC_IND" },
282     { 3, "AUX_SCAN_RSP" },
283     { 0, NULL }
284 };
285 
286 typedef struct {
287     guint8 protover;
288     guint8 phy;
289     gboolean bad_length;
290     guint16 payload_length;
291     guint16 event_packet_length;
292 } nordic_ble_context_t;
293 
294 /* next dissector */
295 static dissector_handle_t btle_dissector_handle = NULL;
296 static dissector_handle_t debug_handle = NULL;
297 
298 static gint
dissect_lengths(tvbuff_t * tvb,gint offset,packet_info * pinfo,proto_tree * tree,nordic_ble_context_t * nordic_ble_context)299 dissect_lengths(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree, nordic_ble_context_t *nordic_ble_context)
300 {
301     guint32 hlen, plen;
302     proto_item* item;
303 
304     switch (nordic_ble_context->protover) {
305     case 0:  /* Legacy version */
306         hlen = 2 + UART_HEADER_LEN; /* 2 bytes legacy marker + UART header */
307         item = proto_tree_add_item_ret_uint(tree, hf_nordic_ble_payload_length, tvb, offset, 1, ENC_NA, &plen);
308         offset += 1;
309         break;
310 
311     case 1:
312         proto_tree_add_item_ret_uint(tree, hf_nordic_ble_header_length, tvb, offset, 1, ENC_NA, &hlen);
313         hlen += 1; /* Add one byte for board id */
314         offset += 1;
315 
316         item = proto_tree_add_item_ret_uint(tree, hf_nordic_ble_payload_length, tvb, offset, 1, ENC_NA, &plen);
317         offset += 1;
318         break;
319 
320     default: /* Starting from version 2 */
321         hlen = 1 + UART_HEADER_LEN; /* Board ID + UART header */
322         item = proto_tree_add_item_ret_uint(tree, hf_nordic_ble_payload_length, tvb, offset, 2, ENC_LITTLE_ENDIAN, &plen);
323         offset += 2;
324         break;
325     }
326 
327     if ((hlen + plen) != tvb_captured_length(tvb)) {
328         expert_add_info(pinfo, item, &ei_nordic_ble_bad_length);
329         nordic_ble_context->bad_length = TRUE;
330     }
331 
332     nordic_ble_context->payload_length = plen;
333 
334     return offset;
335 }
336 
337 static gint
dissect_flags(tvbuff_t * tvb,gint offset,packet_info * pinfo,proto_tree * tree,nordic_ble_context_t * nordic_ble_context,btle_context_t * context)338 dissect_flags(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree, nordic_ble_context_t *nordic_ble_context, btle_context_t *context)
339 {
340     guint8 flags, channel;
341     gboolean dir;
342     proto_item *flags_item, *item;
343     proto_tree *flags_tree;
344 
345     flags = tvb_get_guint8(tvb, offset);
346     channel = tvb_get_guint8(tvb, offset + 1);
347 
348     if (nordic_ble_context->protover < 3) {
349         guint32 access_address;
350 
351         access_address = tvb_get_letohl(tvb, offset + nordic_ble_context->event_packet_length - 1);
352         context->pdu_type = access_address == ACCESS_ADDRESS_ADVERTISING ? BTLE_PDU_TYPE_ADVERTISING : BTLE_PDU_TYPE_DATA;
353     }
354 
355     context->crc_checked_at_capture = 1;
356     context->crc_valid_at_capture = !!(flags & 1);
357 
358     if (context->pdu_type == BTLE_PDU_TYPE_DATA) {
359         dir = !!(flags & 2);
360         context->mic_checked_at_capture = !!(flags & 4);
361         if (context->mic_checked_at_capture) {
362             context->mic_valid_at_capture = !!(flags & 8);
363         }
364     }
365 
366     nordic_ble_context->phy = (flags >> 4) & 7;
367     context->phy = nordic_ble_context->phy;
368 
369     if (context->pdu_type == BTLE_PDU_TYPE_DATA) {
370         if (dir) {
371             set_address(&pinfo->src, AT_STRINGZ, 7, "Master");
372             set_address(&pinfo->dst, AT_STRINGZ, 6, "Slave");
373             context->direction = BTLE_DIR_MASTER_SLAVE;
374             pinfo->p2p_dir = P2P_DIR_SENT;
375         } else {
376             set_address(&pinfo->src, AT_STRINGZ, 6, "Slave");
377             set_address(&pinfo->dst, AT_STRINGZ, 7, "Master");
378             context->direction = BTLE_DIR_SLAVE_MASTER;
379             pinfo->p2p_dir = P2P_DIR_RECV;
380         }
381     }
382 
383     flags_item = proto_tree_add_item(tree, hf_nordic_ble_flags, tvb, offset, 1, ENC_NA);
384     flags_tree = proto_item_add_subtree(flags_item, ett_flags);
385     item = proto_tree_add_item(flags_tree, hf_nordic_ble_crcok, tvb, offset, 1, ENC_NA);
386     if (!context->crc_valid_at_capture) {
387         /* CRC is bad */
388         expert_add_info(pinfo, item, &ei_nordic_ble_bad_crc);
389     }
390 
391     if (context->pdu_type == BTLE_PDU_TYPE_DATA) {
392         proto_tree_add_item(flags_tree, hf_nordic_ble_direction, tvb, offset, 1, ENC_NA);
393         proto_tree_add_item(flags_tree, hf_nordic_ble_encrypted, tvb, offset, 1, ENC_NA);
394         if (context->mic_checked_at_capture) {
395             item = proto_tree_add_item(flags_tree, hf_nordic_ble_micok, tvb, offset, 1, ENC_NA);
396             if (!context->mic_valid_at_capture) {
397                 /* MIC is bad */
398                 expert_add_info(pinfo, item, &ei_nordic_ble_bad_mic);
399             }
400         } else {
401             proto_tree_add_item(flags_tree, hf_nordic_ble_mic_not_relevant, tvb, offset, 1, ENC_NA);
402         }
403     } else {
404         if (channel < 37) {
405             guint32 aux_pdu_type;
406 
407             proto_tree_add_item_ret_uint(flags_tree, hf_nordic_ble_aux_type, tvb, offset, 1, ENC_NA, &aux_pdu_type);
408             context->aux_pdu_type = aux_pdu_type;
409             context->aux_pdu_type_valid = TRUE;
410         } else {
411             proto_tree_add_item(flags_tree, hf_nordic_ble_flag_reserved1, tvb, offset, 1, ENC_NA);
412             proto_tree_add_item(flags_tree, hf_nordic_ble_flag_reserved2, tvb, offset, 1, ENC_NA);
413         }
414         proto_tree_add_item(flags_tree, hf_nordic_ble_address_resolved, tvb, offset, 1, ENC_NA);
415     }
416 
417     proto_tree_add_item(flags_tree, hf_nordic_ble_le_phy, tvb, offset, 1, ENC_NA);
418     proto_tree_add_item(flags_tree, hf_nordic_ble_flag_reserved7, tvb, offset, 1, ENC_NA);
419 
420     offset++;
421 
422     return offset;
423 }
424 
packet_time_get(nordic_ble_context_t * nordic_ble_context,guint8 ci)425 static guint16 packet_time_get(nordic_ble_context_t *nordic_ble_context, guint8 ci)
426 {
427     /* Calculate packet time according to this packets PHY */
428     guint16 ble_payload_length = nordic_ble_context->payload_length - nordic_ble_context->event_packet_length;
429 
430     switch (nordic_ble_context->phy) {
431         case LE_1M_PHY:
432             return  US_PER_BYTE_1M_PHY * (PREAMBLE_LEN_1M_PHY + ble_payload_length);
433         case LE_2M_PHY:
434             return US_PER_BYTE_2M_PHY * (PREAMBLE_LEN_2M_PHY + ble_payload_length);
435         case LE_CODED_PHY:
436         {
437             /* Subtract Access address and CI */
438             guint16 fec2_block_len = ble_payload_length - 4 - 1;
439 
440             switch (ci) {
441                 case CI_S8:
442                     return FEC1_BLOCK_S8_US + fec2_block_len * US_PER_BYTE_CODED_PHY_S8 + TERM2_S8_US;
443                 case CI_S2:
444                     return FEC1_BLOCK_S8_US + fec2_block_len * US_PER_BYTE_CODED_PHY_S2 + TERM2_S2_US;
445             }
446         }
447         /* Fallthrough */
448         default:
449             return 0; /* Unknown */
450     }
451 }
452 
453 typedef struct
454 {
455     guint32 packet_start_time;
456     guint32 packet_end_time;
457 } packet_times_t;
458 
459 typedef struct {
460     gboolean first_frame_seen;
461     /* Time information about previous packet times to calculate delta times */
462     guint32 packet_time;
463     guint32 packet_start_time;
464     guint32 packet_end_time;
465 } packet_time_context_t;
466 
467 static wmem_tree_t *packet_time_context_tree;
468 
packet_times_get(packet_info * pinfo)469 static packet_time_context_t *packet_times_get(packet_info *pinfo)
470 {
471     guint32 interface_id = (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID) ? pinfo->rec->rec_header.packet_header.interface_id: HCI_INTERFACE_DEFAULT;
472     wmem_tree_t *wmem_tree;
473     wmem_tree_key_t keys[2];
474 
475     keys[0].length = 1;
476     keys[0].key = &interface_id;
477     keys[1].length = 0;
478     keys[1].key = NULL;
479 
480     wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(packet_time_context_tree, keys);
481     if (wmem_tree) {
482         return (packet_time_context_t *) wmem_tree_lookup32_le(wmem_tree, 0);
483     }
484 
485     return NULL;
486 }
487 
packet_times_insert(packet_info * pinfo)488 static packet_time_context_t *packet_times_insert(packet_info *pinfo)
489 {
490     guint32 interface_id = (pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID) ? pinfo->rec->rec_header.packet_header.interface_id: HCI_INTERFACE_DEFAULT;
491     guint32 key = 0;
492     wmem_tree_key_t keys[3];
493     packet_time_context_t *packet_times;
494 
495     keys[0].length = 1;
496     keys[0].key = &interface_id;
497     keys[1].length = 1;
498     keys[1].key = &key;
499     keys[2].length = 0;
500     keys[2].key = NULL;
501     packet_times = wmem_new0(wmem_file_scope(), packet_time_context_t);
502     wmem_tree_insert32_array(packet_time_context_tree, keys, packet_times);
503 
504     return packet_times;
505 }
506 
507 static gint
dissect_ble_delta_time(tvbuff_t * tvb,gint offset,packet_info * pinfo,proto_tree * tree,nordic_ble_context_t * nordic_ble_context)508 dissect_ble_delta_time(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree, nordic_ble_context_t *nordic_ble_context)
509 {
510     guint32 delta_time, delta_time_ss, prev_packet_time, packet_time;
511     proto_item *pi;
512     packet_time_context_t *packet_times_context;
513 
514     packet_times_context = packet_times_get(pinfo);
515     if (!packet_times_context) {
516         packet_times_context = packet_times_insert(pinfo);
517     }
518 
519     /* end-to-start */
520     proto_tree_add_item_ret_uint(tree, hf_nordic_ble_delta_time, tvb, offset, 4, ENC_LITTLE_ENDIAN, &delta_time);
521 
522     if (!pinfo->fd->visited) {
523         /* First time visiting this packet, store previous BLE packet time */
524         p_add_proto_data(wmem_file_scope(), pinfo, proto_nordic_ble, 0, GUINT_TO_POINTER(packet_times_context->packet_time));
525         prev_packet_time = packet_times_context->packet_time;
526     } else {
527         prev_packet_time = GPOINTER_TO_UINT(p_get_proto_data(wmem_file_scope(), pinfo, proto_nordic_ble, 0));
528     }
529 
530     if (!packet_times_context->first_frame_seen) {
531         delta_time_ss = prev_packet_time + delta_time;
532         pi = proto_tree_add_uint(tree, hf_nordic_ble_delta_time_ss, tvb, offset, 4, delta_time_ss);
533         proto_item_set_generated(pi);
534     }
535 
536     packet_time = packet_time_get(nordic_ble_context, 0 /* This version never supported Coded PHY */);
537     pi = proto_tree_add_uint(tree, hf_nordic_ble_packet_time, tvb, offset, 4, packet_time);
538     proto_item_set_generated(pi);
539 
540     offset += 4;
541 
542     if (!pinfo->fd->visited) {
543         packet_times_context->packet_time = packet_time;
544         packet_times_context->first_frame_seen = TRUE;
545     }
546 
547     return offset;
548 }
549 
550 static gint
dissect_ble_timestamp(tvbuff_t * tvb,gint offset,packet_info * pinfo,proto_tree * tree,nordic_ble_context_t * nordic_ble_context)551 dissect_ble_timestamp(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree, nordic_ble_context_t *nordic_ble_context)
552 {
553     guint32 delta_time, delta_time_ss, packet_time;
554     guint32 timestamp, last_packet_end_time, last_packet_start_time;
555     proto_item *item;
556     packet_time_context_t *packet_times_context;
557 
558     packet_times_context = packet_times_get(pinfo);
559     if (!packet_times_context) {
560         packet_times_context = packet_times_insert(pinfo);
561     }
562 
563     proto_tree_add_item_ret_uint(tree, hf_nordic_ble_time, tvb, offset, 4, ENC_LITTLE_ENDIAN, &timestamp);
564 
565     if (!pinfo->fd->visited) {
566         packet_times_t *saved_packet_times = wmem_new0(wmem_file_scope(), packet_times_t);
567 
568         saved_packet_times->packet_end_time = packet_times_context->packet_end_time;
569         saved_packet_times->packet_start_time = packet_times_context->packet_start_time;
570         p_add_proto_data(wmem_file_scope(), pinfo, proto_nordic_ble, 0, saved_packet_times);
571 
572         /* First time visiting this packet, store previous BLE packet time */
573         last_packet_end_time = packet_times_context->packet_end_time;
574         last_packet_start_time = packet_times_context->packet_start_time;
575     } else {
576         packet_times_t* saved_packet_times = (packet_times_t *)p_get_proto_data(wmem_file_scope(), pinfo, proto_nordic_ble, 0);
577 
578         last_packet_end_time = saved_packet_times->packet_end_time;
579         last_packet_start_time = saved_packet_times->packet_start_time;
580     }
581 
582     guint8 ci = tvb_get_guint8(tvb, offset + 4 + 4);
583     packet_time = packet_time_get(nordic_ble_context, ci);
584     item = proto_tree_add_uint(tree, hf_nordic_ble_packet_time, tvb, offset, 4, packet_time);
585     proto_item_set_generated(item);
586 
587     if (pinfo->num > 1) {
588         /* Calculated delta times are not valid for the first packet because we don't have the last packet times. */
589         delta_time = timestamp - last_packet_end_time;
590         item = proto_tree_add_uint(tree, hf_nordic_ble_delta_time, tvb, offset, 4, delta_time);
591         proto_item_set_generated(item);
592 
593         delta_time_ss = timestamp - last_packet_start_time;
594         item = proto_tree_add_uint(tree, hf_nordic_ble_delta_time_ss, tvb, offset, 4, delta_time_ss);
595         proto_item_set_generated(item);
596     }
597 
598     if (!pinfo->fd->visited) {
599 
600         packet_times_context->packet_start_time = timestamp;
601         packet_times_context->packet_end_time = timestamp + packet_time;
602         packet_times_context->first_frame_seen = TRUE;
603     }
604 
605     offset += 4;
606 
607     return offset;
608 }
609 
610 static gint
dissect_packet_counter(tvbuff_t * tvb,gint offset,proto_item * item,proto_tree * tree)611 dissect_packet_counter(tvbuff_t *tvb, gint offset, proto_item *item, proto_tree *tree)
612 {
613     proto_item_append_text(item, ", Packet counter: %u", tvb_get_guint16(tvb, offset, ENC_LITTLE_ENDIAN));
614     proto_tree_add_item(tree, hf_nordic_ble_packet_counter, tvb, offset, 2, ENC_LITTLE_ENDIAN);
615     offset += 2;
616 
617     return offset;
618 }
619 
620 static gint
dissect_packet_header(tvbuff_t * tvb,gint offset,packet_info * pinfo,proto_tree * tree,nordic_ble_context_t * nordic_ble_context,btle_context_t * context)621 dissect_packet_header(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree, nordic_ble_context_t *nordic_ble_context, btle_context_t *context)
622 {
623     proto_item *ti;
624     proto_tree *header_tree;
625     gint start_offset = offset;
626 
627     ti = proto_tree_add_item(tree, hf_nordic_ble_header, tvb, offset, -1, ENC_NA);
628     header_tree = proto_item_add_subtree(ti, ett_packet_header);
629     proto_item_append_text(ti, " Version: %u", nordic_ble_context->protover);
630 
631     if (nordic_ble_context->protover == 0) {
632         proto_item *item = proto_tree_add_uint(header_tree, hf_nordic_ble_protover, tvb, 0, 0, 0);
633         proto_item_set_generated(item);
634 
635         proto_tree_add_item(header_tree, hf_nordic_ble_packet_id, tvb, offset, 1, ENC_NA);
636         offset += 1;
637 
638         offset = dissect_packet_counter(tvb, offset, ti, header_tree);
639 
640         offset += 2; // Two unused bytes
641     }
642 
643     offset = dissect_lengths(tvb, offset, pinfo, header_tree, nordic_ble_context);
644 
645     if (nordic_ble_context->protover != 0) {
646         proto_item *item = proto_tree_add_item(header_tree, hf_nordic_ble_protover, tvb, offset, 1, ENC_NA);
647         offset += 1;
648         if (nordic_ble_context->protover > 3) {
649             expert_add_info(pinfo, item, &ei_nordic_ble_unknown_version);
650         }
651 
652         offset = dissect_packet_counter(tvb, offset, ti, header_tree);
653 
654         proto_tree_add_item(header_tree, hf_nordic_ble_packet_id, tvb, offset, 1, ENC_NA);
655 
656         if (nordic_ble_context->protover > 2) {
657             guint8 id = tvb_get_guint8(tvb, offset);
658 
659             context->pdu_type = id == 0x06 ? BTLE_PDU_TYPE_DATA :
660                                 id == 0x02 ? BTLE_PDU_TYPE_ADVERTISING :
661                                              BTLE_PDU_TYPE_UNKNOWN;
662         }
663 
664         offset += 1;
665     }
666 
667     proto_item_set_len(ti, offset - start_offset);
668 
669     return offset;
670 }
671 
672 static gint
dissect_packet(tvbuff_t * tvb,gint offset,packet_info * pinfo,proto_tree * tree,nordic_ble_context_t * nordic_ble_context,btle_context_t * context)673 dissect_packet(tvbuff_t *tvb, gint offset, packet_info *pinfo, proto_tree *tree, nordic_ble_context_t *nordic_ble_context, btle_context_t *context)
674 {
675     gint32 rssi;
676     guint32 channel, event_counter;
677 
678     if (nordic_ble_context->protover == 0) {
679         // Event packet length is fixed for the legacy version
680         nordic_ble_context->event_packet_length = EVENT_PACKET_LEN;
681     } else {
682         guint32 plen;
683         proto_tree_add_item_ret_uint(tree, hf_nordic_ble_packet_length, tvb, offset, 1, ENC_NA, &plen);
684         nordic_ble_context->event_packet_length = plen;
685         offset += 1;
686     }
687 
688     offset = dissect_flags(tvb, offset, pinfo, tree, nordic_ble_context, context);
689 
690     proto_tree_add_item_ret_uint(tree, hf_nordic_ble_channel, tvb, offset, 1, ENC_NA, &channel);
691     offset += 1;
692 
693     context->channel = channel;
694 
695     rssi = (-1)*((gint32)tvb_get_guint8(tvb, offset));
696     proto_tree_add_int(tree, hf_nordic_ble_rssi, tvb, offset, 1, rssi);
697     offset += 1;
698 
699     proto_tree_add_item_ret_uint(tree, hf_nordic_ble_event_counter, tvb, offset, 2, ENC_LITTLE_ENDIAN, &event_counter);
700     offset += 2;
701 
702     context->event_counter = event_counter;
703     context->event_counter_valid = 1;
704 
705     if (nordic_ble_context->protover < 3) {
706         offset = dissect_ble_delta_time(tvb, offset, pinfo, tree, nordic_ble_context);
707     } else {
708         offset = dissect_ble_timestamp(tvb, offset, pinfo, tree, nordic_ble_context);
709     }
710 
711     return offset;
712 }
713 
714 static gint
dissect_header(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,btle_context_t * context,gboolean * bad_length)715 dissect_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, btle_context_t *context, gboolean *bad_length)
716 {
717     proto_item *ti;
718     proto_tree *nordic_ble_tree;
719     gint offset = 0;
720     nordic_ble_context_t nordic_ble_context;
721 
722     memset(&nordic_ble_context, 0, sizeof(nordic_ble_context));
723 
724     ti = proto_tree_add_item(tree, proto_nordic_ble, tvb, 0, -1, ENC_NA);
725     nordic_ble_tree = proto_item_add_subtree(ti, ett_nordic_ble);
726 
727     if (tvb_get_guint16(tvb, 0, ENC_BIG_ENDIAN) == 0xBEEF) {
728         proto_tree_add_item(nordic_ble_tree, hf_nordic_ble_legacy_marker, tvb, 0, 2, ENC_BIG_ENDIAN);
729         offset += 2;
730 
731         nordic_ble_context.protover = 0; /* Legacy Version */
732     } else {
733         proto_tree_add_item(nordic_ble_tree, hf_nordic_ble_board_id, tvb, 0, 1, ENC_NA);
734         offset += 1;
735 
736         nordic_ble_context.protover = tvb_get_guint8(tvb, offset + 2);
737     }
738 
739     offset = dissect_packet_header(tvb, offset, pinfo, nordic_ble_tree, &nordic_ble_context, context);
740     offset = dissect_packet(tvb, offset, pinfo, nordic_ble_tree, &nordic_ble_context, context);
741 
742     proto_item_set_len(ti, offset);
743     *bad_length = nordic_ble_context.bad_length;
744 
745     return offset;
746 }
747 
748 /* Main entry point for sniffer */
749 static int
dissect_nordic_ble(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)750 dissect_nordic_ble(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_)
751 {
752     tvbuff_t          *payload_tvb;
753     btle_context_t    *context;
754     gint               offset;
755     gboolean           bad_length = FALSE;
756 
757     context = wmem_new0(pinfo->pool, btle_context_t);
758 
759     offset = dissect_header(tvb, pinfo, tree, context, &bad_length);
760     payload_tvb = tvb_new_subset_length_caplen(tvb, offset, -1, tvb_captured_length(tvb) - offset);
761 
762     if (!bad_length) {
763         call_dissector_with_data(btle_dissector_handle, payload_tvb, pinfo, tree, context);
764     }
765 
766     if ((context->mic_checked_at_capture) && (!context->mic_valid_at_capture)) {
767         col_set_str(pinfo->cinfo, COL_INFO, "Encrypted packet decrypted incorrectly");
768         if (!context->crc_valid_at_capture) {
769             /* CRC is bad */
770             col_append_str(pinfo->cinfo, COL_INFO, " (bad CRC)");
771         } else {
772             col_append_str(pinfo->cinfo, COL_INFO, " (bad MIC)");
773         }
774     }
775 
776     if (debug_handle) {
777         call_dissector(debug_handle, payload_tvb, pinfo, tree);
778     }
779 
780     return offset;
781 }
782 
783 void
proto_register_nordic_ble(void)784 proto_register_nordic_ble(void)
785 {
786     static hf_register_info hf[] = {
787         { &hf_nordic_ble_board_id,
788             { "Board", "nordic_ble.board_id",
789                 FT_UINT8, BASE_DEC, NULL, 0x0,
790                 NULL, HFILL }
791         },
792         { &hf_nordic_ble_legacy_marker,
793             { "Legacy marker", "nordic_ble.legacy_marker",
794                 FT_UINT16, BASE_HEX, NULL, 0x0,
795                 NULL, HFILL }
796         },
797         { &hf_nordic_ble_header,
798             { "Header", "nordic_ble.header",
799                 FT_NONE, BASE_NONE, NULL, 0x0,
800                 NULL, HFILL }
801         },
802         { &hf_nordic_ble_header_length,
803             { "Length of header", "nordic_ble.hlen",
804                 FT_UINT8, BASE_DEC, NULL, 0x0,
805                 NULL, HFILL }
806         },
807         { &hf_nordic_ble_payload_length,
808             { "Length of payload", "nordic_ble.plen",
809                 FT_UINT16, BASE_DEC, NULL, 0x0,
810                 "Payload length", HFILL }
811         },
812         { &hf_nordic_ble_protover,
813             { "Protocol version", "nordic_ble.protover",
814                 FT_UINT8, BASE_DEC, NULL, 0x0,
815                 NULL, HFILL }
816         },
817         { &hf_nordic_ble_packet_counter,
818             { "Packet counter", "nordic_ble.packet_counter",
819                 FT_UINT16, BASE_DEC, NULL, 0x0,
820                 "Global packet counter for packets sent on UART", HFILL }
821         },
822         { &hf_nordic_ble_packet_id,
823             { "Packet ID", "nordic_ble.packet_id",
824                 FT_UINT8, BASE_DEC, NULL, 0x0,
825                 NULL, HFILL }
826         },
827         { &hf_nordic_ble_packet_length,
828             { "Length of packet", "nordic_ble.len",
829                 FT_UINT16, BASE_DEC, NULL, 0x0,
830                 NULL, HFILL }
831         },
832         { &hf_nordic_ble_flags,
833             { "Flags", "nordic_ble.flags",
834                 FT_UINT8, BASE_HEX, NULL, 0x0,
835                 NULL, HFILL }
836         },
837         { &hf_nordic_ble_crcok,
838             { "CRC", "nordic_ble.crcok",
839                 FT_BOOLEAN, 8, TFS(&tfs_ok_error), 0x01,
840                 "Cyclic Redundancy Check state", HFILL }
841         },
842         { &hf_nordic_ble_direction,
843             { "Direction", "nordic_ble.direction",
844                 FT_BOOLEAN, 8, TFS(&direction_tfs), 0x02,
845                 NULL, HFILL }
846         },
847         { &hf_nordic_ble_flag_reserved1,
848             { "Reserved", "nordic_ble.flag_reserved1",
849                 FT_UINT8, BASE_DEC, NULL, 0x02,
850                 NULL, HFILL }
851         },
852         { &hf_nordic_ble_encrypted,
853             { "Encrypted", "nordic_ble.encrypted",
854                 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x04,
855                 "Was the packet encrypted", HFILL }
856         },
857         { &hf_nordic_ble_flag_reserved2,
858             { "Reserved", "nordic_ble.flag_reserved2",
859                 FT_UINT8, BASE_DEC, NULL, 0x04,
860                 NULL, HFILL }
861         },
862         { &hf_nordic_ble_aux_type,
863             { "Aux Type", "nordic_ble.aux_type",
864                 FT_UINT8, BASE_DEC, VALS(le_aux_ext_adv), 0x06,
865                 NULL, HFILL }
866         },
867         { &hf_nordic_ble_micok,
868             { "MIC", "nordic_ble.micok",
869                 FT_BOOLEAN, 8, TFS(&tfs_ok_error), 0x08,
870                 "Message Integrity Check state", HFILL }
871         },
872         { &hf_nordic_ble_mic_not_relevant,
873             { "MIC (not relevant)", "nordic_ble.mic_not_relevant",
874                 FT_UINT8, BASE_DEC, NULL, 0x08,
875                 "Message Integrity Check state is only relevant when encrypted", HFILL }
876         },
877         { &hf_nordic_ble_address_resolved,
878             { "Address Resolved", "nordic_ble.address_resolved",
879                 FT_BOOLEAN, 8, TFS(&tfs_yes_no), 0x08,
880                 NULL, HFILL }
881         },
882         { &hf_nordic_ble_le_phy,
883             { "PHY", "nordic_ble.phy",
884                 FT_UINT8, BASE_DEC, VALS(le_phys), 0x70,
885                 "Physical Layer", HFILL }
886         },
887         { &hf_nordic_ble_flag_reserved7,
888             { "Reserved", "nordic_ble.flag_reserved7",
889                 FT_UINT8, BASE_DEC, NULL, 0x80,
890                 "Reserved for Future Use", HFILL }
891         },
892         { &hf_nordic_ble_channel,
893             { "Channel Index", "nordic_ble.channel",
894                 FT_UINT8, BASE_DEC, NULL, 0x0,
895                 NULL, HFILL }
896         },
897         { &hf_nordic_ble_rssi,
898             { "RSSI", "nordic_ble.rssi",
899                 FT_INT8, BASE_DEC | BASE_UNIT_STRING, &units_dbm, 0x0,
900                 "Received Signal Strength Indicator", HFILL }
901         },
902         { &hf_nordic_ble_event_counter,
903             { "Event counter", "nordic_ble.event_counter",
904                 FT_UINT16, BASE_DEC, NULL, 0x0,
905                 NULL, HFILL }
906         },
907         { &hf_nordic_ble_time,
908             { "Timestamp", "nordic_ble.time",
909                 FT_UINT32, BASE_DEC | BASE_UNIT_STRING, &units_microseconds, 0x0,
910                 "Firmware timestamp", HFILL }
911         },
912         { &hf_nordic_ble_delta_time,
913             { "Delta time (end to start)", "nordic_ble.delta_time",
914                 FT_UINT32, BASE_DEC | BASE_UNIT_STRING, &units_microseconds, 0x0,
915                 "Time since end of last reported packet", HFILL }
916         },
917         { &hf_nordic_ble_delta_time_ss,
918             { "Delta time (start to start)", "nordic_ble.delta_time_ss",
919                 FT_UINT32, BASE_DEC | BASE_UNIT_STRING, &units_microseconds, 0x0,
920                 "Time since start of last reported packet", HFILL }
921         },
922         { &hf_nordic_ble_packet_time,
923             { "Packet time (start to end)", "nordic_ble.packet_time",
924                 FT_UINT32, BASE_DEC | BASE_UNIT_STRING, &units_microseconds, 0x0,
925                 "Time of packet", HFILL }
926         },
927     };
928 
929     static gint *ett[] = {
930         &ett_nordic_ble,
931         &ett_packet_header,
932         &ett_flags
933     };
934 
935     static ei_register_info ei[] = {
936         { &ei_nordic_ble_bad_crc, { "nordic_ble.crc.bad", PI_CHECKSUM, PI_ERROR, "CRC is bad", EXPFILL }},
937         { &ei_nordic_ble_bad_mic, { "nordic_ble.mic.bad", PI_CHECKSUM, PI_ERROR, "MIC is bad", EXPFILL }},
938         { &ei_nordic_ble_bad_length, { "nordic_ble.length.bad", PI_MALFORMED, PI_ERROR, "Length is incorrect", EXPFILL }},
939         { &ei_nordic_ble_unknown_version, { "nordic_ble.protover.bad", PI_PROTOCOL, PI_ERROR, "Unknown version", EXPFILL }},
940     };
941 
942     expert_module_t *expert_nordic_ble;
943 
944     packet_time_context_tree = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
945 
946     proto_nordic_ble = proto_register_protocol("nRF Sniffer for Bluetooth LE", "NORDIC_BLE", "nordic_ble");
947 
948     register_dissector("nordic_ble", dissect_nordic_ble, proto_nordic_ble);
949 
950     expert_nordic_ble = expert_register_protocol(proto_nordic_ble);
951     expert_register_field_array(expert_nordic_ble, ei, array_length(ei));
952 
953     proto_register_field_array(proto_nordic_ble, hf, array_length(hf));
954     proto_register_subtree_array(ett, array_length(ett));
955 }
956 
957 void
proto_reg_handoff_nordic_ble(void)958 proto_reg_handoff_nordic_ble(void)
959 {
960     dissector_handle_t nordic_ble_handle;
961 
962     nordic_ble_handle = create_dissector_handle(dissect_nordic_ble, proto_nordic_ble);
963 
964     btle_dissector_handle = find_dissector("btle");
965     debug_handle = find_dissector("nordic_debug");
966 
967     dissector_add_for_decode_as_with_preference("udp.port", nordic_ble_handle);
968     dissector_add_uint("wtap_encap", WTAP_ENCAP_NORDIC_BLE, nordic_ble_handle);
969 }
970 
971 
972 /*
973  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
974  *
975  * Local variables:
976  * c-basic-offset: 4
977  * tab-width: 8
978  * indent-tabs-mode: nil
979  * End:
980  *
981  * vi: set shiftwidth =4 tabstop =8 expandtab:
982  * :indentSize =4:tabSize =8:noTabs =true:
983  */
984