1 /* Routines for LTE PDCP
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31 #include <epan/packet.h>
32 #include <epan/prefs.h>
33 #include <epan/expert.h>
34 #include <epan/addr_resolv.h>
35 #include <epan/wmem/wmem.h>
40 #include <wsutil/wsgcrypt.h>
41 #endif /* HAVE_LIBGCRYPT */
43 /* Define this symbol if you have a working implementation of SNOW3G f8() and f9() available */
44 /* #define HAVE_SNOW3G */
46 #include <epan/snow3g_algorithm.h>
49 #include "packet-rlc-lte.h"
50 #include "packet-pdcp-lte.h"
52 void proto_register_pdcp(void);
53 void proto_reg_handoff_pdcp_lte(void);
56 * 3GPP TS 36.323 Evolved Universal Terrestrial Radio Access (E-UTRA)
57 * Packet Data Convergence Protocol (PDCP) specification v11.0.0
62 - More deciphering. Next steps are:
63 - Verify MAC authentication bytes for supported protocol(s)?
64 - code that doesn't quite work against gcrypt 1.6 is #if 0'd out...
65 - Add Relay Node user plane data PDU dissection
69 /* Initialize the protocol and registered fields. */
70 int proto_pdcp_lte = -1;
72 extern int proto_rlc_lte;
74 /* Configuration (info known outside of PDU) */
75 static int hf_pdcp_lte_configuration = -1;
76 static int hf_pdcp_lte_direction = -1;
77 static int hf_pdcp_lte_ueid = -1;
78 static int hf_pdcp_lte_channel_type = -1;
79 static int hf_pdcp_lte_channel_id = -1;
81 static int hf_pdcp_lte_rohc_compression = -1;
82 static int hf_pdcp_lte_rohc_mode = -1;
83 static int hf_pdcp_lte_rohc_rnd = -1;
84 static int hf_pdcp_lte_rohc_udp_checksum_present = -1;
85 static int hf_pdcp_lte_rohc_profile = -1;
87 static int hf_pdcp_lte_no_header_pdu = -1;
88 static int hf_pdcp_lte_plane = -1;
89 static int hf_pdcp_lte_seqnum_length = -1;
90 static int hf_pdcp_lte_cid_inclusion_info = -1;
91 static int hf_pdcp_lte_large_cid_present = -1;
93 /* PDCP header fields */
94 static int hf_pdcp_lte_control_plane_reserved = -1;
95 static int hf_pdcp_lte_seq_num_5 = -1;
96 static int hf_pdcp_lte_seq_num_7 = -1;
97 static int hf_pdcp_lte_reserved3 = -1;
98 static int hf_pdcp_lte_seq_num_12 = -1;
99 static int hf_pdcp_lte_seq_num_15 = -1;
100 static int hf_pdcp_lte_signalling_data = -1;
101 static int hf_pdcp_lte_mac = -1;
102 static int hf_pdcp_lte_data_control = -1;
103 static int hf_pdcp_lte_user_plane_data = -1;
104 static int hf_pdcp_lte_control_pdu_type = -1;
105 static int hf_pdcp_lte_fms = -1;
106 static int hf_pdcp_lte_reserved4 = -1;
107 static int hf_pdcp_lte_fms2 = -1;
108 static int hf_pdcp_lte_bitmap = -1;
111 /* Sequence Analysis */
112 static int hf_pdcp_lte_sequence_analysis = -1;
113 static int hf_pdcp_lte_sequence_analysis_ok = -1;
114 static int hf_pdcp_lte_sequence_analysis_previous_frame = -1;
115 static int hf_pdcp_lte_sequence_analysis_next_frame = -1;
116 static int hf_pdcp_lte_sequence_analysis_expected_sn = -1;
118 static int hf_pdcp_lte_sequence_analysis_repeated = -1;
119 static int hf_pdcp_lte_sequence_analysis_skipped = -1;
121 /* Security Settings */
122 static int hf_pdcp_lte_security = -1;
123 static int hf_pdcp_lte_security_setup_frame = -1;
124 static int hf_pdcp_lte_security_integrity_algorithm = -1;
125 static int hf_pdcp_lte_security_ciphering_algorithm = -1;
127 static int hf_pdcp_lte_security_bearer = -1;
128 static int hf_pdcp_lte_security_direction = -1;
129 static int hf_pdcp_lte_security_count = -1;
130 static int hf_pdcp_lte_security_cipher_key = -1;
131 static int hf_pdcp_lte_security_integrity_key = -1;
135 /* Protocol subtree. */
136 static int ett_pdcp = -1;
137 static int ett_pdcp_configuration = -1;
138 static int ett_pdcp_packet = -1;
139 static int ett_pdcp_lte_sequence_analysis = -1;
140 static int ett_pdcp_report_bitmap = -1;
141 static int ett_pdcp_security = -1;
143 static expert_field ei_pdcp_lte_sequence_analysis_wrong_sequence_number = EI_INIT;
144 static expert_field ei_pdcp_lte_reserved_bits_not_zero = EI_INIT;
145 static expert_field ei_pdcp_lte_sequence_analysis_sn_repeated = EI_INIT;
146 static expert_field ei_pdcp_lte_sequence_analysis_sn_missing = EI_INIT;
147 static expert_field ei_pdcp_lte_digest_wrong = EI_INIT;
149 /*-------------------------------------
151 *-------------------------------------
153 /* UAT entry structure. */
156 gchar *rrcCipherKeyString;
157 gchar *upCipherKeyString;
158 gchar *rrcIntegrityKeyString;
160 guint8 rrcCipherBinaryKey[16];
161 gboolean rrcCipherKeyOK;
162 guint8 upCipherBinaryKey[16];
163 gboolean upCipherKeyOK;
164 guint8 rrcIntegrityBinaryKey[16];
165 gboolean rrcIntegrityKeyOK;
166 } uat_ue_keys_record_t;
168 static uat_ue_keys_record_t *uat_ue_keys_records = NULL;
170 static uat_t * ue_keys_uat = NULL;
171 static guint num_ue_keys_uat = 0;
173 /* Convert an ascii hex character into a digit. Should only be given valid
174 hex ascii characters */
175 static guchar hex_ascii_to_binary(gchar c)
177 if ((c >= '0') && (c <= '9')) {
180 else if ((c >= 'a') && (c <= 'f')) {
183 else if ((c >= 'A') && (c <= 'F')) {
191 static void* uat_ue_keys_record_copy_cb(void* n, const void* o, size_t siz _U_) {
192 uat_ue_keys_record_t* new_rec = (uat_ue_keys_record_t *)n;
193 const uat_ue_keys_record_t* old_rec = (const uat_ue_keys_record_t *)o;
195 new_rec->ueid = old_rec->ueid;
196 new_rec->rrcCipherKeyString = (old_rec->rrcCipherKeyString) ? g_strdup(old_rec->rrcCipherKeyString) : NULL;
197 new_rec->upCipherKeyString = (old_rec->upCipherKeyString) ? g_strdup(old_rec->upCipherKeyString) : NULL;
198 new_rec->rrcIntegrityKeyString = (old_rec->rrcIntegrityKeyString) ? g_strdup(old_rec->rrcIntegrityKeyString) : NULL;
204 static gboolean check_valid_key_sring(const char* raw_string, char* checked_string)
208 guint length = (gint)strlen(raw_string);
210 /* Can't be valid if not long enough. */
215 for (n=0; (n < length) && (written < 32); n++) {
216 char c = raw_string[n];
218 /* Skipping past allowed 'padding' characters */
219 if ((c == ' ') || (c == '-')) {
223 /* Other characters must be hex digits, otherwise string is invalid */
224 if (((c >= '0') && (c <= '9')) ||
225 ((c >= 'a') && (c <= 'f')) ||
226 ((c >= 'A') && (c <= 'F'))) {
227 checked_string[written++] = c;
234 /* Must have found exactly 32 hex ascii chars for 16-byte key */
235 return (written == 32);
238 static void uat_ue_keys_record_update_cb(void* record, const char** error _U_) {
239 uat_ue_keys_record_t* rec = (uat_ue_keys_record_t *)record;
241 char cleanString[32];
243 /* Check and convert RRC key */
244 if (!check_valid_key_sring(rec->rrcCipherKeyString, cleanString)) {
245 rec->rrcCipherKeyOK = FALSE;
248 for (n=0; n < 32; n += 2) {
249 rec->rrcCipherBinaryKey[n/2] = (hex_ascii_to_binary(cleanString[n]) << 4) +
250 hex_ascii_to_binary(cleanString[n+1]);
252 rec->rrcCipherKeyOK = TRUE;
255 /* Check and convert User-plane key */
256 if (!check_valid_key_sring(rec->upCipherKeyString, cleanString)) {
257 rec->upCipherKeyOK = FALSE;
260 for (n=0; n < 32; n += 2) {
261 rec->upCipherBinaryKey[n/2] = (hex_ascii_to_binary(cleanString[n]) << 4) +
262 hex_ascii_to_binary(cleanString[n+1]);
264 rec->upCipherKeyOK = TRUE;
267 /* Check and convert Integrity key */
268 if (!check_valid_key_sring(rec->rrcIntegrityKeyString, cleanString)) {
269 rec->rrcIntegrityKeyOK = FALSE;
272 for (n=0; n < 32; n += 2) {
273 rec->rrcIntegrityBinaryKey[n/2] = (hex_ascii_to_binary(cleanString[n]) << 4) +
274 hex_ascii_to_binary(cleanString[n+1]);
276 rec->rrcIntegrityKeyOK = TRUE;
281 static void uat_ue_keys_record_free_cb(void*r) {
282 uat_ue_keys_record_t* rec = (uat_ue_keys_record_t*)r;
284 g_free(rec->rrcCipherKeyString);
285 g_free(rec->upCipherKeyString);
286 g_free(rec->rrcIntegrityKeyString);
289 UAT_DEC_CB_DEF(uat_ue_keys_records, ueid, uat_ue_keys_record_t)
290 UAT_CSTRING_CB_DEF(uat_ue_keys_records, rrcCipherKeyString, uat_ue_keys_record_t)
291 UAT_CSTRING_CB_DEF(uat_ue_keys_records, upCipherKeyString, uat_ue_keys_record_t)
292 UAT_CSTRING_CB_DEF(uat_ue_keys_records, rrcIntegrityKeyString, uat_ue_keys_record_t)
294 static gboolean global_pdcp_decipher_signalling = FALSE;
295 static gboolean global_pdcp_decipher_userplane = FALSE;
296 static gboolean global_pdcp_check_integrity = FALSE;
298 static const value_string direction_vals[] =
300 { DIRECTION_UPLINK, "Uplink"},
301 { DIRECTION_DOWNLINK, "Downlink"},
306 static const value_string pdcp_plane_vals[] = {
307 { SIGNALING_PLANE, "Signalling" },
308 { USER_PLANE, "User" },
312 static const value_string logical_channel_vals[] = {
313 { Channel_DCCH, "DCCH"},
314 { Channel_BCCH, "BCCH"},
315 { Channel_CCCH, "CCCH"},
316 { Channel_PCCH, "PCCH"},
320 static const value_string rohc_mode_vals[] = {
321 { UNIDIRECTIONAL, "Unidirectional" },
322 { OPTIMISTIC_BIDIRECTIONAL, "Optimistic Bidirectional" },
323 { RELIABLE_BIDIRECTIONAL, "Reliable Bidirectional" },
328 /* Values taken from:
329 http://www.iana.org/assignments/rohc-pro-ids/rohc-pro-ids.txt */
330 static const value_string rohc_profile_vals[] = {
331 { 0x0000, "ROHC uncompressed" }, /* [RFC5795] */
332 { 0x0001, "ROHC RTP" }, /* [RFC3095] */
333 { 0x0101, "ROHCv2 RTP" }, /* [RFC5225] */
334 { 0x0002, "ROHC UDP" }, /* [RFC3095] */
335 { 0x0102, "ROHCv2 UDP" }, /* [RFC5225] */
336 { 0x0003, "ROHC ESP" }, /* [RFC3095] */
337 { 0x0103, "ROHCv2 ESP" }, /* [RFC5225] */
338 { 0x0004, "ROHC IP" }, /* [RFC3843] */
339 { 0x0104, "ROHCv2 IP" }, /* [RFC5225] */
340 { 0x0005, "ROHC LLA" }, /* [RFC4362] */
341 { 0x0105, "ROHC LLA with R-mode" }, /* [RFC3408] */
342 { 0x0006, "ROHC TCP" }, /* [RFC4996] */
343 { 0x0007, "ROHC RTP/UDP-Lite" }, /* [RFC4019] */
344 { 0x0107, "ROHCv2 RTP/UDP-Lite" }, /* [RFC5225] */
345 { 0x0008, "ROHC UDP-Lite" }, /* [RFC4019] */
346 { 0x0108, "ROHCv2 UDP-Lite" }, /* [RFC5225] */
350 static const value_string pdu_type_vals[] = {
351 { 0, "Control PDU" },
356 static const value_string control_pdu_type_vals[] = {
357 { 0, "PDCP Status report" },
358 { 1, "Header Compression Feedback Information" },
362 static const value_string integrity_algorithm_vals[] = {
369 static const value_string ciphering_algorithm_vals[] = {
377 static dissector_handle_t ip_handle;
378 static dissector_handle_t ipv6_handle;
379 static dissector_handle_t rohc_handle;
380 static dissector_handle_t data_handle;
383 #define SEQUENCE_ANALYSIS_RLC_ONLY 1
384 #define SEQUENCE_ANALYSIS_PDCP_ONLY 2
386 /* Preference variables */
387 static gboolean global_pdcp_dissect_user_plane_as_ip = TRUE;
388 static gboolean global_pdcp_dissect_signalling_plane_as_rrc = TRUE;
389 static gint global_pdcp_check_sequence_numbers = TRUE;
390 static gboolean global_pdcp_dissect_rohc = FALSE;
392 /* Which layer info to show in the info column */
394 ShowRLCLayer, ShowPDCPLayer, ShowTrafficLayer
396 static gint global_pdcp_lte_layer_to_show = (gint)ShowRLCLayer;
400 /**************************************************/
401 /* Sequence number analysis */
406 /* Using bit fields to fit into 32 bits, so avoiding the need to allocate
407 heap memory for these structs */
413 } pdcp_channel_hash_key;
418 guint16 previousSequenceNumber;
419 guint32 previousFrameNum;
421 } pdcp_channel_status;
423 /* The sequence analysis channel hash table.
424 Maps key -> status */
425 static GHashTable *pdcp_sequence_analysis_channel_hash = NULL;
428 static gint pdcp_channel_equal(gconstpointer v, gconstpointer v2)
430 /* Key fits in 4 bytes, so just compare pointers! */
434 /* Compute a hash value for a given key. */
435 static guint pdcp_channel_hash_func(gconstpointer v)
437 /* Just use pointer, as the fields are all in this value */
438 return GPOINTER_TO_UINT(v);
442 /* Hash table types & functions for frame reports */
448 guint32 channelId: 5;
449 guint32 direction: 1;
451 } pdcp_result_hash_key;
453 static gint pdcp_result_hash_equal(gconstpointer v, gconstpointer v2)
455 const pdcp_result_hash_key* val1 = (const pdcp_result_hash_key *)v;
456 const pdcp_result_hash_key* val2 = (const pdcp_result_hash_key *)v2;
458 /* All fields must match */
459 return (memcmp(val1, val2, sizeof(pdcp_result_hash_key)) == 0);
462 /* Compute a hash value for a given key. */
463 static guint pdcp_result_hash_func(gconstpointer v)
465 const pdcp_result_hash_key* val1 = (const pdcp_result_hash_key *)v;
467 /* TODO: This is a bit random. */
468 return val1->frameNumber + (val1->channelId<<13) +
471 (val1->direction<<9);
474 /* pdcp_channel_hash_key fits into the pointer, so just copy the value into
475 a guint, cast to apointer and return that as the key */
476 static gpointer get_channel_hash_key(pdcp_channel_hash_key *key)
479 /* TODO: assert that sizeof(pdcp_channel_hash_key) <= sizeof(guint) ? */
480 memcpy(&asInt, key, sizeof(pdcp_channel_hash_key));
481 return GUINT_TO_POINTER(asInt);
484 /* Convenience function to get a pointer for the hash_func to work with */
485 static gpointer get_report_hash_key(guint16 SN, guint32 frameNumber,
486 pdcp_lte_info *p_pdcp_lte_info,
489 static pdcp_result_hash_key key;
490 pdcp_result_hash_key *p_key;
492 /* Only allocate a struct when will be adding entry */
494 p_key = wmem_new(wmem_file_scope(), pdcp_result_hash_key);
497 memset(&key, 0, sizeof(pdcp_result_hash_key));
501 /* Fill in details, and return pointer */
502 p_key->frameNumber = frameNumber;
504 p_key->plane = (guint8)p_pdcp_lte_info->plane;
505 p_key->channelId = p_pdcp_lte_info->channelId;
506 p_key->direction = p_pdcp_lte_info->direction;
513 /* Info to attach to frame when first read, recording what to show about sequence */
516 SN_OK, SN_Repeated, SN_MAC_Retx, SN_Retx, SN_Missing
520 gboolean sequenceExpectedCorrect;
521 guint16 sequenceExpected;
522 guint32 previousFrameNum;
523 guint32 nextFrameNum;
529 sequence_state state;
530 } pdcp_sequence_report_in_frame;
532 /* The sequence analysis frame report hash table.
533 Maps pdcp_result_hash_key* -> pdcp_sequence_report_in_frame* */
534 static GHashTable *pdcp_lte_sequence_analysis_report_hash = NULL;
536 /* Gather together security settings in order to be able to do deciphering */
537 typedef struct pdu_security_settings_t
539 enum security_ciphering_algorithm_e ciphering;
540 enum security_integrity_algorithm_e integrity;
542 guint8* integrityKey;
543 gboolean cipherKeyValid;
544 gboolean integrityKeyValid;
548 } pdu_security_settings_t;
551 /* Add to the tree values associated with sequence analysis for this frame */
552 static void addChannelSequenceInfo(pdcp_sequence_report_in_frame *p,
553 pdcp_lte_info *p_pdcp_lte_info,
554 guint16 sequenceNumber,
555 packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb,
556 proto_tree *security_tree,
557 pdu_security_settings_t *pdu_security)
559 proto_tree *seqnum_tree;
560 proto_item *seqnum_ti;
561 proto_item *ti_expected_sn;
565 seqnum_ti = proto_tree_add_string_format(tree,
566 hf_pdcp_lte_sequence_analysis,
568 "", "Sequence Analysis");
569 seqnum_tree = proto_item_add_subtree(seqnum_ti,
570 ett_pdcp_lte_sequence_analysis);
571 PROTO_ITEM_SET_GENERATED(seqnum_ti);
574 /* Previous channel frame */
575 if (p->previousFrameNum != 0) {
576 proto_tree_add_uint(seqnum_tree, hf_pdcp_lte_sequence_analysis_previous_frame,
577 tvb, 0, 0, p->previousFrameNum);
580 /* Expected sequence number */
581 ti_expected_sn = proto_tree_add_uint(seqnum_tree, hf_pdcp_lte_sequence_analysis_expected_sn,
582 tvb, 0, 0, p->sequenceExpected);
583 PROTO_ITEM_SET_GENERATED(ti_expected_sn);
585 /* Make sure we have recognised SN length */
586 switch (p_pdcp_lte_info->seqnum_length) {
587 case PDCP_SN_LENGTH_5_BITS:
588 case PDCP_SN_LENGTH_7_BITS:
589 case PDCP_SN_LENGTH_12_BITS:
590 case PDCP_SN_LENGTH_15_BITS:
593 DISSECTOR_ASSERT_NOT_REACHED();
599 PROTO_ITEM_SET_HIDDEN(ti_expected_sn);
600 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_ok,
602 PROTO_ITEM_SET_GENERATED(ti);
603 proto_item_append_text(seqnum_ti, " - OK");
605 /* Link to next SN in channel (if known) */
606 if (p->nextFrameNum != 0) {
607 proto_tree_add_uint(seqnum_tree, hf_pdcp_lte_sequence_analysis_next_frame,
608 tvb, 0, 0, p->nextFrameNum);
611 /* May also be able to add key inputs to security tree here */
612 if ((pdu_security->ciphering != eea0) ||
613 (pdu_security->integrity != eia0)) {
614 guint32 hfn_multiplier;
616 gchar *cipher_key = NULL;
617 gchar *integrity_key = NULL;
621 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_bearer,
622 tvb, 0, 0, p_pdcp_lte_info->channelId-1);
623 PROTO_ITEM_SET_GENERATED(ti);
624 pdu_security->bearer = p_pdcp_lte_info->channelId-1;
627 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_direction,
628 tvb, 0, 0, p_pdcp_lte_info->direction);
629 PROTO_ITEM_SET_GENERATED(ti);
631 /* COUNT (HFN * snLength^2 + SN) */
632 switch (p_pdcp_lte_info->seqnum_length) {
633 case PDCP_SN_LENGTH_5_BITS:
636 case PDCP_SN_LENGTH_7_BITS:
637 hfn_multiplier = 128;
639 case PDCP_SN_LENGTH_12_BITS:
640 hfn_multiplier = 2048;
642 case PDCP_SN_LENGTH_15_BITS:
643 hfn_multiplier = 32768;
646 DISSECTOR_ASSERT_NOT_REACHED();
649 count = (p->hfn * hfn_multiplier) + sequenceNumber;
650 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_count,
652 PROTO_ITEM_SET_GENERATED(ti);
653 pdu_security->count = count;
655 /* KEY. Look this UE up among UEs that have keys configured */
656 for (record_id=0; record_id < num_ue_keys_uat; record_id++) {
657 if (uat_ue_keys_records[record_id].ueid == p_pdcp_lte_info->ueid) {
658 if (p_pdcp_lte_info->plane == SIGNALING_PLANE) {
659 /* Get RRC ciphering key */
660 if (uat_ue_keys_records[record_id].rrcCipherKeyOK) {
661 cipher_key = uat_ue_keys_records[record_id].rrcCipherKeyString;
662 pdu_security->cipherKey = &(uat_ue_keys_records[record_id].rrcCipherBinaryKey[0]);
663 pdu_security->cipherKeyValid = TRUE;
665 /* Get RRC integrity key */
666 if (uat_ue_keys_records[record_id].rrcIntegrityKeyOK) {
667 integrity_key = uat_ue_keys_records[record_id].rrcIntegrityKeyString;
668 pdu_security->integrityKey = &(uat_ue_keys_records[record_id].rrcIntegrityBinaryKey[0]);
669 pdu_security->integrityKeyValid = TRUE;
673 /* Get userplane ciphering key */
674 if (uat_ue_keys_records[record_id].upCipherKeyOK) {
675 cipher_key = uat_ue_keys_records[record_id].upCipherKeyString;
676 pdu_security->cipherKey = &(uat_ue_keys_records[record_id].upCipherBinaryKey[0]);
677 pdu_security->cipherKeyValid = TRUE;
681 /* Show keys where known and valid */
682 if (cipher_key != NULL) {
683 ti = proto_tree_add_string(security_tree, hf_pdcp_lte_security_cipher_key,
684 tvb, 0, 0, cipher_key);
685 PROTO_ITEM_SET_GENERATED(ti);
687 if (integrity_key != NULL) {
688 ti = proto_tree_add_string(security_tree, hf_pdcp_lte_security_integrity_key,
689 tvb, 0, 0, integrity_key);
690 PROTO_ITEM_SET_GENERATED(ti);
695 pdu_security->direction = p_pdcp_lte_info->direction;
700 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_ok,
702 PROTO_ITEM_SET_GENERATED(ti);
703 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_skipped,
705 PROTO_ITEM_SET_GENERATED(ti);
706 if (p->lastSN != p->firstSN) {
707 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_sequence_analysis_sn_missing,
708 "PDCP SNs (%u to %u) missing for %s on UE %u (%s-%u)",
709 p->firstSN, p->lastSN,
710 val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
711 p_pdcp_lte_info->ueid,
712 val_to_str_const(p_pdcp_lte_info->channelType, logical_channel_vals, "Unknown"),
713 p_pdcp_lte_info->channelId);
714 proto_item_append_text(seqnum_ti, " - SNs missing (%u to %u)",
715 p->firstSN, p->lastSN);
718 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_sequence_analysis_sn_missing,
719 "PDCP SN (%u) missing for %s on UE %u (%s-%u)",
721 val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
722 p_pdcp_lte_info->ueid,
723 val_to_str_const(p_pdcp_lte_info->channelType, logical_channel_vals, "Unknown"),
724 p_pdcp_lte_info->channelId);
725 proto_item_append_text(seqnum_ti, " - SN missing (%u)",
731 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_ok,
733 PROTO_ITEM_SET_GENERATED(ti);
734 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_repeated,
736 PROTO_ITEM_SET_GENERATED(ti);
737 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_sequence_analysis_sn_repeated,
738 "PDCP SN (%u) repeated for %s for UE %u (%s-%u)",
740 val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
741 p_pdcp_lte_info->ueid,
742 val_to_str_const(p_pdcp_lte_info->channelType, logical_channel_vals, "Unknown"),
743 p_pdcp_lte_info->channelId);
744 proto_item_append_text(seqnum_ti, "- SN %u Repeated",
749 /* Incorrect sequence number */
750 expert_add_info_format(pinfo, ti_expected_sn, &ei_pdcp_lte_sequence_analysis_wrong_sequence_number,
751 "Wrong Sequence Number for %s on UE %u (%s-%u) - got %u, expected %u",
752 val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
753 p_pdcp_lte_info->ueid,
754 val_to_str_const(p_pdcp_lte_info->channelType, logical_channel_vals, "Unknown"),
755 p_pdcp_lte_info->channelId,
756 sequenceNumber, p->sequenceExpected);
762 /* Update the channel status and set report for this frame */
763 static void checkChannelSequenceInfo(packet_info *pinfo, tvbuff_t *tvb,
764 pdcp_lte_info *p_pdcp_lte_info,
765 guint16 sequenceNumber,
767 proto_tree *security_tree,
768 pdu_security_settings_t *pdu_security)
770 pdcp_channel_hash_key channel_key;
771 pdcp_channel_status *p_channel_status;
772 pdcp_sequence_report_in_frame *p_report_in_frame = NULL;
773 gboolean createdChannel = FALSE;
774 guint16 expectedSequenceNumber = 0;
777 /* If find stat_report_in_frame already, use that and get out */
778 if (pinfo->fd->flags.visited) {
780 (pdcp_sequence_report_in_frame*)g_hash_table_lookup(pdcp_lte_sequence_analysis_report_hash,
781 get_report_hash_key(sequenceNumber,
783 p_pdcp_lte_info, FALSE));
784 if (p_report_in_frame != NULL) {
785 addChannelSequenceInfo(p_report_in_frame, p_pdcp_lte_info,
787 pinfo, tree, tvb, security_tree, pdu_security);
791 /* Give up - we must have tried already... */
797 /**************************************************/
798 /* Create or find an entry for this channel state */
799 channel_key.ueId = p_pdcp_lte_info->ueid;
800 channel_key.plane = p_pdcp_lte_info->plane;
801 channel_key.channelId = p_pdcp_lte_info->channelId;
802 channel_key.direction = p_pdcp_lte_info->direction;
803 channel_key.notUsed = 0;
805 /* Do the table lookup */
806 p_channel_status = (pdcp_channel_status*)g_hash_table_lookup(pdcp_sequence_analysis_channel_hash,
807 get_channel_hash_key(&channel_key));
809 /* Create table entry if necessary */
810 if (p_channel_status == NULL) {
811 createdChannel = TRUE;
813 /* Allocate a new value and duplicate key contents */
814 p_channel_status = wmem_new0(wmem_file_scope(), pdcp_channel_status);
817 g_hash_table_insert(pdcp_sequence_analysis_channel_hash,
818 get_channel_hash_key(&channel_key), p_channel_status);
821 /* Create space for frame state_report */
822 p_report_in_frame = wmem_new(wmem_file_scope(), pdcp_sequence_report_in_frame);
823 p_report_in_frame->nextFrameNum = 0;
825 switch (p_pdcp_lte_info->seqnum_length) {
826 case PDCP_SN_LENGTH_5_BITS:
829 case PDCP_SN_LENGTH_7_BITS:
832 case PDCP_SN_LENGTH_12_BITS:
835 case PDCP_SN_LENGTH_15_BITS:
839 DISSECTOR_ASSERT_NOT_REACHED();
843 /* Work out expected sequence number */
844 if (!createdChannel) {
845 expectedSequenceNumber = (p_channel_status->previousSequenceNumber + 1) % snLimit;
848 expectedSequenceNumber = sequenceNumber;
851 /* Set report for this frame */
852 /* For PDCP, sequence number is always expectedSequence number */
853 p_report_in_frame->sequenceExpectedCorrect = (sequenceNumber == expectedSequenceNumber);
854 p_report_in_frame->hfn = p_channel_status->hfn;
856 /* For wrong sequence number... */
857 if (!p_report_in_frame->sequenceExpectedCorrect) {
859 /* Frames are not missing if we get an earlier sequence number again */
860 if (((snLimit + expectedSequenceNumber - sequenceNumber) % snLimit) > 15) {
861 p_report_in_frame->state = SN_Missing;
862 p_report_in_frame->firstSN = expectedSequenceNumber;
863 p_report_in_frame->lastSN = (snLimit + sequenceNumber - 1) % snLimit;
865 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
866 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
868 /* Update channel status to remember *this* frame */
869 p_channel_status->previousFrameNum = pinfo->fd->num;
870 p_channel_status->previousSequenceNumber = sequenceNumber;
873 /* An SN has been repeated */
874 p_report_in_frame->state = SN_Repeated;
875 p_report_in_frame->firstSN = sequenceNumber;
877 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
878 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
883 p_report_in_frame->state = SN_OK;
884 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
885 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
886 /* SN has rolled around, inc hfn! */
887 if (!createdChannel && (sequenceNumber == 0)) {
888 /* TODO: not worrying about HFN rolling over for now! */
889 p_channel_status->hfn++;
890 p_report_in_frame->hfn = p_channel_status->hfn;
893 /* Update channel status to remember *this* frame */
894 p_channel_status->previousFrameNum = pinfo->fd->num;
895 p_channel_status->previousSequenceNumber = sequenceNumber;
897 if (p_report_in_frame->previousFrameNum != 0) {
898 /* Get report for previous frame */
899 pdcp_sequence_report_in_frame *p_previous_report;
900 p_previous_report = (pdcp_sequence_report_in_frame*)g_hash_table_lookup(pdcp_lte_sequence_analysis_report_hash,
901 get_report_hash_key((sequenceNumber+32767) % 32768,
902 p_report_in_frame->previousFrameNum,
905 /* It really shouldn't be NULL... */
906 if (p_previous_report != NULL) {
907 /* Point it forward to this one */
908 p_previous_report->nextFrameNum = pinfo->fd->num;
913 /* Associate with this frame number */
914 g_hash_table_insert(pdcp_lte_sequence_analysis_report_hash,
915 get_report_hash_key(sequenceNumber, pinfo->fd->num,
916 p_pdcp_lte_info, TRUE),
919 /* Add state report for this frame into tree */
920 addChannelSequenceInfo(p_report_in_frame, p_pdcp_lte_info, sequenceNumber,
921 pinfo, tree, tvb, security_tree, pdu_security);
926 /* Hash table for security state for a UE
927 Maps UEId -> pdcp_security_info_t* */
928 static gint pdcp_lte_ueid_hash_equal(gconstpointer v, gconstpointer v2)
932 static guint pdcp_lte_ueid_hash_func(gconstpointer v)
934 return GPOINTER_TO_UINT(v);
936 static GHashTable *pdcp_security_hash = NULL;
938 /* Result is (ueid, framenum) -> pdcp_security_info_t* */
939 typedef struct ueid_frame_t {
944 /* Convenience function to get a pointer for the hash_func to work with */
945 static gpointer get_ueid_frame_hash_key(guint16 ueid, guint32 frameNumber,
948 static ueid_frame_t key;
951 /* Only allocate a struct when will be adding entry */
953 p_key = wmem_new(wmem_file_scope(), ueid_frame_t);
956 memset(&key, 0, sizeof(ueid_frame_t));
960 /* Fill in details, and return pointer */
961 p_key->framenum = frameNumber;
967 static gint pdcp_lte_ueid_frame_hash_equal(gconstpointer v, gconstpointer v2)
969 const ueid_frame_t *ueid_frame_1 = (const ueid_frame_t *)v;
970 const ueid_frame_t *ueid_frame_2 = (const ueid_frame_t *)v2;
971 return ((ueid_frame_1->framenum == ueid_frame_2->framenum) && (ueid_frame_1->ueid == ueid_frame_2->ueid));
973 static guint pdcp_lte_ueid_frame_hash_func(gconstpointer v)
975 const ueid_frame_t *ueid_frame = (const ueid_frame_t *)v;
976 return ueid_frame->framenum + 100*ueid_frame->ueid;
978 static GHashTable *pdcp_security_result_hash = NULL;
983 /* Write the given formatted text to:
985 - the top-level RLC PDU item */
986 static void write_pdu_label_and_info(proto_item *pdu_ti,
987 packet_info *pinfo, const char *format, ...)
989 #define MAX_INFO_BUFFER 256
990 static char info_buffer[MAX_INFO_BUFFER];
994 va_start(ap, format);
995 g_vsnprintf(info_buffer, MAX_INFO_BUFFER, format, ap);
998 /* Add to indicated places */
999 col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
1000 proto_item_append_text(pdu_ti, "%s", info_buffer);
1005 /***************************************************************/
1009 /* Show in the tree the config info attached to this frame, as generated fields */
1010 static void show_pdcp_config(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree,
1011 pdcp_lte_info *p_pdcp_info)
1014 proto_tree *configuration_tree;
1015 proto_item *configuration_ti = proto_tree_add_item(tree,
1016 hf_pdcp_lte_configuration,
1017 tvb, 0, 0, ENC_ASCII|ENC_NA);
1018 configuration_tree = proto_item_add_subtree(configuration_ti, ett_pdcp_configuration);
1021 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_direction, tvb, 0, 0,
1022 p_pdcp_info->direction);
1023 PROTO_ITEM_SET_GENERATED(ti);
1026 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_plane, tvb, 0, 0,
1027 p_pdcp_info->plane);
1028 PROTO_ITEM_SET_GENERATED(ti);
1031 if (p_pdcp_info->ueid != 0) {
1032 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_ueid, tvb, 0, 0,
1034 PROTO_ITEM_SET_GENERATED(ti);
1038 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_channel_type, tvb, 0, 0,
1039 p_pdcp_info->channelType);
1040 PROTO_ITEM_SET_GENERATED(ti);
1041 if (p_pdcp_info->channelId != 0) {
1043 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_channel_id, tvb, 0, 0,
1044 p_pdcp_info->channelId);
1045 PROTO_ITEM_SET_GENERATED(ti);
1049 /* User-plane-specific fields */
1050 if (p_pdcp_info->plane == USER_PLANE) {
1053 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_no_header_pdu, tvb, 0, 0,
1054 p_pdcp_info->no_header_pdu);
1055 PROTO_ITEM_SET_GENERATED(ti);
1057 if (!p_pdcp_info->no_header_pdu) {
1060 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_seqnum_length, tvb, 0, 0,
1061 p_pdcp_info->seqnum_length);
1062 PROTO_ITEM_SET_GENERATED(ti);
1066 /* ROHC compression */
1067 ti = proto_tree_add_boolean(configuration_tree, hf_pdcp_lte_rohc_compression, tvb, 0, 0,
1068 p_pdcp_info->rohc.rohc_compression);
1069 PROTO_ITEM_SET_GENERATED(ti);
1071 /* ROHC-specific settings */
1072 if (p_pdcp_info->rohc.rohc_compression) {
1074 /* Show ROHC mode */
1075 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_mode, tvb, 0, 0,
1076 p_pdcp_info->rohc.mode);
1077 PROTO_ITEM_SET_GENERATED(ti);
1080 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_rnd, tvb, 0, 0,
1081 p_pdcp_info->rohc.rnd);
1082 PROTO_ITEM_SET_GENERATED(ti);
1085 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_udp_checksum_present, tvb, 0, 0,
1086 p_pdcp_info->rohc.udp_checksum_present);
1087 PROTO_ITEM_SET_GENERATED(ti);
1090 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_profile, tvb, 0, 0,
1091 p_pdcp_info->rohc.profile);
1092 PROTO_ITEM_SET_GENERATED(ti);
1094 /* CID Inclusion Info */
1095 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_cid_inclusion_info, tvb, 0, 0,
1096 p_pdcp_info->rohc.cid_inclusion_info);
1097 PROTO_ITEM_SET_GENERATED(ti);
1100 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_large_cid_present, tvb, 0, 0,
1101 p_pdcp_info->rohc.large_cid_present);
1102 PROTO_ITEM_SET_GENERATED(ti);
1105 /* Append summary to configuration root */
1106 proto_item_append_text(configuration_ti, "(direction=%s, plane=%s",
1107 val_to_str_const(p_pdcp_info->direction, direction_vals, "Unknown"),
1108 val_to_str_const(p_pdcp_info->plane, pdcp_plane_vals, "Unknown"));
1110 if (p_pdcp_info->rohc.rohc_compression) {
1111 const char *mode = val_to_str_const(p_pdcp_info->rohc.mode, rohc_mode_vals, "Error");
1112 proto_item_append_text(configuration_ti, ", mode=%c, profile=%s",
1114 val_to_str_const(p_pdcp_info->rohc.profile, rohc_profile_vals, "Unknown"));
1116 proto_item_append_text(configuration_ti, ")");
1117 PROTO_ITEM_SET_GENERATED(configuration_ti);
1119 /* Show plane in info column */
1120 col_append_fstr(pinfo->cinfo, COL_INFO, " %s: ",
1121 val_to_str_const(p_pdcp_info->plane, pdcp_plane_vals, "Unknown"));
1126 /* Look for an RRC dissector for signalling data (using channel type and direction) */
1127 static dissector_handle_t lookup_rrc_dissector_handle(struct pdcp_lte_info *p_pdcp_info)
1129 dissector_handle_t rrc_handle = 0;
1131 switch (p_pdcp_info->channelType)
1134 if (p_pdcp_info->direction == DIRECTION_UPLINK) {
1135 rrc_handle = find_dissector("lte_rrc.ul_ccch");
1138 rrc_handle = find_dissector("lte_rrc.dl_ccch");
1142 rrc_handle = find_dissector("lte_rrc.pcch");
1145 switch (p_pdcp_info->BCCHTransport) {
1147 rrc_handle = find_dissector("lte_rrc.bcch_bch");
1149 case DLSCH_TRANSPORT:
1150 rrc_handle = find_dissector("lte_rrc.bcch_dl_sch");
1155 if (p_pdcp_info->direction == DIRECTION_UPLINK) {
1156 rrc_handle = find_dissector("lte_rrc.ul_dcch");
1159 rrc_handle = find_dissector("lte_rrc.dl_dcch");
1172 /* Forwad declarations */
1173 static void dissect_pdcp_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
1175 /* Heuristic dissection */
1176 static gboolean global_pdcp_lte_heur = FALSE;
1178 /* Heuristic dissector looks for supported framing protocol (see wiki page) */
1179 static gboolean dissect_pdcp_lte_heur(tvbuff_t *tvb, packet_info *pinfo,
1180 proto_tree *tree, void *data _U_)
1183 struct pdcp_lte_info *p_pdcp_lte_info;
1186 gboolean infoAlreadySet = FALSE;
1187 gboolean seqnumLengthTagPresent = FALSE;
1189 /* This is a heuristic dissector, which means we get all the UDP
1190 * traffic not sent to a known dissector and not claimed by
1191 * a heuristic dissector called before us!
1194 if (!global_pdcp_lte_heur) {
1198 /* Do this again on re-dissection to re-discover offset of actual PDU */
1200 /* Needs to be at least as long as:
1201 - the signature string
1202 - fixed header bytes
1204 - at least one byte of PDCP PDU payload */
1205 if (tvb_length_remaining(tvb, offset) < (gint)(strlen(PDCP_LTE_START_STRING)+3+2)) {
1209 /* OK, compare with signature string */
1210 if (tvb_strneql(tvb, offset, PDCP_LTE_START_STRING, strlen(PDCP_LTE_START_STRING)) != 0) {
1213 offset += (gint)strlen(PDCP_LTE_START_STRING);
1216 /* If redissecting, use previous info struct (if available) */
1217 p_pdcp_lte_info = (pdcp_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0);
1218 if (p_pdcp_lte_info == NULL) {
1219 /* Allocate new info struct for this frame */
1220 p_pdcp_lte_info = wmem_new0(wmem_file_scope(), pdcp_lte_info);
1221 infoAlreadySet = FALSE;
1224 infoAlreadySet = TRUE;
1228 /* Read fixed fields */
1229 p_pdcp_lte_info->no_header_pdu = (gboolean)tvb_get_guint8(tvb, offset++);
1230 p_pdcp_lte_info->plane = (enum pdcp_plane)tvb_get_guint8(tvb, offset++);
1231 if (p_pdcp_lte_info->plane == SIGNALING_PLANE) {
1232 p_pdcp_lte_info->seqnum_length = PDCP_SN_LENGTH_5_BITS;
1234 p_pdcp_lte_info->rohc.rohc_compression = (gboolean)tvb_get_guint8(tvb, offset++);
1236 /* Read optional fields */
1237 while (tag != PDCP_LTE_PAYLOAD_TAG) {
1238 /* Process next tag */
1239 tag = tvb_get_guint8(tvb, offset++);
1241 case PDCP_LTE_SEQNUM_LENGTH_TAG:
1242 p_pdcp_lte_info->seqnum_length = tvb_get_guint8(tvb, offset);
1244 seqnumLengthTagPresent = TRUE;
1246 case PDCP_LTE_DIRECTION_TAG:
1247 p_pdcp_lte_info->direction = tvb_get_guint8(tvb, offset);
1250 case PDCP_LTE_LOG_CHAN_TYPE_TAG:
1251 p_pdcp_lte_info->channelType = (LogicalChannelType)tvb_get_guint8(tvb, offset);
1254 case PDCP_LTE_BCCH_TRANSPORT_TYPE_TAG:
1255 p_pdcp_lte_info->BCCHTransport = (BCCHTransportType)tvb_get_guint8(tvb, offset);
1258 case PDCP_LTE_ROHC_IP_VERSION_TAG:
1259 p_pdcp_lte_info->rohc.rohc_ip_version = tvb_get_ntohs(tvb, offset);
1262 case PDCP_LTE_ROHC_CID_INC_INFO_TAG:
1263 p_pdcp_lte_info->rohc.cid_inclusion_info = tvb_get_guint8(tvb, offset);
1266 case PDCP_LTE_ROHC_LARGE_CID_PRES_TAG:
1267 p_pdcp_lte_info->rohc.large_cid_present = tvb_get_guint8(tvb, offset);
1270 case PDCP_LTE_ROHC_MODE_TAG:
1271 p_pdcp_lte_info->rohc.mode = (enum rohc_mode)tvb_get_guint8(tvb, offset);
1274 case PDCP_LTE_ROHC_RND_TAG:
1275 p_pdcp_lte_info->rohc.rnd = tvb_get_guint8(tvb, offset);
1278 case PDCP_LTE_ROHC_UDP_CHECKSUM_PRES_TAG:
1279 p_pdcp_lte_info->rohc.udp_checksum_present = tvb_get_guint8(tvb, offset);
1282 case PDCP_LTE_ROHC_PROFILE_TAG:
1283 p_pdcp_lte_info->rohc.profile = tvb_get_ntohs(tvb, offset);
1286 case PDCP_LTE_CHANNEL_ID_TAG:
1287 p_pdcp_lte_info->channelId = tvb_get_ntohs(tvb, offset);
1290 case PDCP_LTE_UEID_TAG:
1291 p_pdcp_lte_info->ueid = tvb_get_ntohs(tvb, offset);
1295 case PDCP_LTE_PAYLOAD_TAG:
1296 /* Have reached data, so get out of loop */
1300 /* It must be a recognised tag */
1305 if ((p_pdcp_lte_info->plane == USER_PLANE) && (seqnumLengthTagPresent == FALSE)) {
1306 /* Conditional field is not present */
1310 if (!infoAlreadySet) {
1311 /* Store info in packet */
1312 p_add_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0, p_pdcp_lte_info);
1315 /**************************************/
1316 /* OK, now dissect as PDCP LTE */
1318 /* Create tvb that starts at actual PDCP PDU */
1319 pdcp_tvb = tvb_new_subset_remaining(tvb, offset);
1320 dissect_pdcp_lte(pdcp_tvb, pinfo, tree);
1324 /* Called from control protocol to configure security algorithms for the given UE */
1325 void set_pdcp_lte_security_algorithms(guint16 ueid, pdcp_security_info_t *security_info)
1327 /* Use for this frame so can check integrity on SecurityCommandRequest frame */
1328 /* N.B. won't work for internal, non-RRC signalling methods... */
1329 pdcp_security_info_t *p_frame_security;
1331 /* Copy security struct */
1332 pdcp_security_info_t *p_security = wmem_new(wmem_file_scope(), pdcp_security_info_t);
1333 *p_security = *security_info;
1335 /* And add into security table */
1336 g_hash_table_insert(pdcp_security_hash, GUINT_TO_POINTER((guint)ueid), p_security);
1338 /* Add an entry for this PDU already to use these settings, as otherwise it won't be present
1339 when we query it on the first pass. */
1340 p_frame_security = wmem_new(wmem_file_scope(), pdcp_security_info_t);
1341 *p_frame_security = *p_security;
1342 g_hash_table_insert(pdcp_security_result_hash,
1343 get_ueid_frame_hash_key(ueid, security_info->configuration_frame, TRUE),
1347 /* Decipher payload if algorithm is supported and plausible inputs are available */
1348 static tvbuff_t *decipher_payload(tvbuff_t *tvb, packet_info *pinfo, int *offset,
1349 pdu_security_settings_t *pdu_security_settings,
1350 enum pdcp_plane plane, gboolean will_be_deciphered,
1351 gboolean *deciphered)
1353 guint8* decrypted_data;
1354 gint payload_length;
1355 tvbuff_t *decrypted_tvb;
1357 /* Nothing to do if NULL ciphering */
1358 if (pdu_security_settings->ciphering == eea0) {
1362 /* Nothing to do if don't have valid cipher key */
1363 if (!pdu_security_settings->cipherKeyValid) {
1367 /* Check whether algorithm supported (only drop through and process if we do) */
1368 if (pdu_security_settings->ciphering == eea1) {
1374 if (pdu_security_settings->ciphering == eea2) {
1375 #ifndef HAVE_LIBGCRYPT
1380 /* An algorithm we don't support at all! */
1384 /* Don't decipher if turned off in preferences */
1385 if (((plane == SIGNALING_PLANE) && !global_pdcp_decipher_signalling) ||
1386 ((plane == USER_PLANE) && !global_pdcp_decipher_userplane)) {
1390 /* Don't decipher if not yet past SecurityModeResponse */
1391 if (!will_be_deciphered) {
1395 #ifdef HAVE_LIBGCRYPT
1397 if (pdu_security_settings->ciphering == eea2) {
1398 unsigned char ctr_block[16];
1399 gcry_cipher_hd_t cypher_hd;
1403 memset(ctr_block, 0, 16);
1404 /* Only first 5 bytes set */
1405 ctr_block[0] = (pdu_security_settings->count & 0xff000000) >> 24;
1406 ctr_block[1] = (pdu_security_settings->count & 0x00ff0000) >> 16;
1407 ctr_block[2] = (pdu_security_settings->count & 0x0000ff00) >> 8;
1408 ctr_block[3] = (pdu_security_settings->count & 0x000000ff);
1409 ctr_block[4] = (pdu_security_settings->bearer << 3) + (pdu_security_settings->direction << 2);
1411 /* Open gcrypt handle */
1412 gcrypt_err = gcry_cipher_open(&cypher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0);
1413 if (gcrypt_err != 0) {
1418 gcrypt_err = gcry_cipher_setkey(cypher_hd, pdu_security_settings->cipherKey, 16);
1419 if (gcrypt_err != 0) {
1420 gcry_cipher_close(cypher_hd);
1425 gcrypt_err = gcry_cipher_setctr(cypher_hd, ctr_block, 16);
1426 if (gcrypt_err != 0) {
1427 gcry_cipher_close(cypher_hd);
1431 /* Extract the encrypted data into a buffer */
1432 payload_length = tvb_length_remaining(tvb, *offset);
1433 decrypted_data = (guint8 *)g_malloc0(payload_length);
1434 tvb_memcpy(tvb, decrypted_data, *offset, payload_length);
1436 /* Decrypt the actual data */
1437 gcrypt_err = gcry_cipher_decrypt(cypher_hd,
1438 decrypted_data, payload_length,
1440 if (gcrypt_err != 0) {
1441 gcry_cipher_close(cypher_hd);
1442 g_free(decrypted_data);
1446 /* Close gcrypt handle */
1447 gcry_cipher_close(cypher_hd);
1453 if (pdu_security_settings->ciphering == eea1) {
1454 /* Extract the encrypted data into a buffer */
1455 payload_length = tvb_length_remaining(tvb, *offset);
1456 decrypted_data = (guint8 *)g_malloc0(payload_length+4);
1457 tvb_memcpy(tvb, decrypted_data, *offset, payload_length);
1459 /* Do the algorithm */
1460 snow3g_f8(pdu_security_settings->cipherKey,
1461 pdu_security_settings->count,
1462 pdu_security_settings->bearer,
1463 pdu_security_settings->direction,
1464 decrypted_data, payload_length*8);
1468 /* Create tvb for resulting deciphered sdu */
1469 decrypted_tvb = tvb_new_child_real_data(tvb, decrypted_data, payload_length, payload_length);
1470 tvb_set_free_cb(decrypted_tvb, g_free);
1471 add_new_data_source(pinfo, decrypted_tvb, "Deciphered Payload");
1473 /* Return deciphered data, i.e. beginning of new tvb */
1476 return decrypted_tvb;
1480 /* Try to calculate digest to compare with that found in frame. */
1481 static guint32 calculate_digest(pdu_security_settings_t *pdu_security_settings, guint8 header _U_,
1482 tvbuff_t *tvb _U_, gint offset _U_, gboolean *calculated)
1484 *calculated = FALSE;
1486 if (pdu_security_settings->integrity == eia0) {
1487 /* Should be zero in this case */
1492 /* Can't calculate if don't have valid integrity key */
1493 if (!pdu_security_settings->integrityKeyValid) {
1497 /* Can only do if indicated in preferences */
1498 if (!global_pdcp_check_integrity) {
1502 switch (pdu_security_settings->integrity) {
1508 gint message_length = tvb_length_remaining(tvb, offset) - 4;
1509 guint8 *message_data = (guint8 *)g_malloc0(message_length+5);
1510 message_data[0] = header;
1511 tvb_memcpy(tvb, message_data+1, offset, message_length);
1513 mac = (u8*)snow3g_f9(pdu_security_settings->integrityKey,
1514 pdu_security_settings->count,
1515 pdu_security_settings->bearer << 27,
1516 pdu_security_settings->direction,
1518 (message_length+1)*8);
1521 g_free(message_data);
1522 return ((mac[0] << 24) | (mac[1] << 16) | (mac[2] << 8) | mac[3]);
1526 #if (defined GCRYPT_VERSION_NUMBER) && (GCRYPT_VERSION_NUMBER >= 0x010600)
1529 gcry_mac_hd_t mac_hd;
1531 gint message_length;
1532 guint8 *message_data;
1534 ssize_t read_digest_length = 4;
1536 /* Open gcrypt handle */
1537 /* N.B. Unfortunately GCRY_MAC_CMAC_AES is not available in currently used version of gcrypt! */
1538 gcrypt_err = gcry_mac_open(&mac_hd, GCRY_MAC_CMAC_AES, 0, NULL);
1539 if (gcrypt_err != 0) {
1544 gcrypt_err = gcry_mac_setkey(mac_hd, pdu_security_settings->integrityKey, 16);
1545 if (gcrypt_err != 0) {
1546 gcry_mac_close(mac_hd);
1550 /* Extract the encrypted data into a buffer */
1551 message_length = tvb_length_remaining(tvb, offset) - 4;
1552 message_data = (guint8 *)g_malloc0(message_length+9);
1553 message_data[0] = (pdu_security_settings->count & 0xff000000) >> 24;
1554 message_data[1] = (pdu_security_settings->count & 0x00ff0000) >> 16;
1555 message_data[2] = (pdu_security_settings->count & 0x0000ff00) >> 8;
1556 message_data[3] = (pdu_security_settings->count & 0x000000ff);
1557 message_data[4] = (pdu_security_settings->bearer << 3) + (pdu_security_settings->direction << 2);
1558 /* rest of first 8 bytes are left as zeroes... */
1559 message_data[8] = header;
1560 tvb_memcpy(tvb, message_data+9, offset, message_length);
1562 /* Pass in the message */
1563 gcrypt_err = gcry_mac_write(mac_hd, message_data, message_length+9);
1564 if (gcrypt_err != 0) {
1565 gcry_mac_close(mac_hd);
1566 g_free(message_data);
1570 /* Read out the digest */
1571 gcrypt_err = gcry_mac_read(mac_hd, mac, &read_digest_length);
1572 if (gcrypt_err != 0) {
1573 gcry_mac_close(mac_hd);
1574 g_free(message_data);
1578 /* Now close the mac handle */
1579 gcry_mac_close(mac_hd);
1581 g_free(message_data);
1584 return ((mac[0] << 24) | (mac[1] << 16) | (mac[2] << 8) | mac[3]);
1589 /* Can't calculate */
1590 *calculated = FALSE;
1597 /******************************/
1598 /* Main dissection function. */
1599 static void dissect_pdcp_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1602 proto_tree *pdcp_tree = NULL;
1603 proto_item *root_ti = NULL;
1606 struct pdcp_lte_info *p_pdcp_info;
1607 tvbuff_t *rohc_tvb = NULL;
1609 pdcp_security_info_t *current_security = NULL; /* current security for this UE */
1610 pdcp_security_info_t *pdu_security; /* security in place for this PDU */
1611 proto_tree *security_tree = NULL;
1612 proto_item *security_ti;
1613 tvbuff_t *payload_tvb;
1614 pdu_security_settings_t pdu_security_settings;
1615 gboolean payload_deciphered = FALSE;
1617 /* Initialise security settings */
1618 memset(&pdu_security_settings, 0, sizeof(pdu_security_settings));
1620 /* Set protocol name. */
1621 col_set_str(pinfo->cinfo, COL_PROTOCOL, "PDCP-LTE");
1623 /* Look for attached packet info! */
1624 p_pdcp_info = (struct pdcp_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0);
1625 /* Can't dissect anything without it... */
1626 if (p_pdcp_info == NULL) {
1630 /* Don't want to overwrite the RLC Info column if configured not to */
1631 if ((global_pdcp_lte_layer_to_show == ShowRLCLayer) &&
1632 (p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0) != NULL)) {
1634 col_set_writable(pinfo->cinfo, FALSE);
1637 /* TODO: won't help with multiple PDCP-or-traffic PDUs / frame... */
1638 col_clear(pinfo->cinfo, COL_INFO);
1639 col_set_writable(pinfo->cinfo, TRUE);
1642 /* Create pdcp tree. */
1644 root_ti = proto_tree_add_item(tree, proto_pdcp_lte, tvb, offset, -1, ENC_NA);
1645 pdcp_tree = proto_item_add_subtree(root_ti, ett_pdcp);
1648 /* Set mode string */
1649 mode = val_to_str_const(p_pdcp_info->rohc.mode, rohc_mode_vals, "Error");
1651 /*****************************************************/
1652 /* Show configuration (attached packet) info in tree */
1654 show_pdcp_config(pinfo, tvb, pdcp_tree, p_pdcp_info);
1657 /* Show ROHC mode */
1658 if (p_pdcp_info->rohc.rohc_compression) {
1659 col_append_fstr(pinfo->cinfo, COL_INFO, " (mode=%c)", mode[0]);
1662 /***************************************/
1663 /* UE security algorithms */
1664 if (!pinfo->fd->flags.visited) {
1665 /* Look up current state by UEID */
1666 current_security = (pdcp_security_info_t*)g_hash_table_lookup(pdcp_security_hash,
1667 GUINT_TO_POINTER((guint)p_pdcp_info->ueid));
1668 if (current_security != NULL) {
1669 /* Store any result for this frame in the result table */
1670 pdcp_security_info_t *security_to_store = wmem_new(wmem_file_scope(), pdcp_security_info_t);
1671 /* Take a deep copy of the settings */
1672 *security_to_store = *current_security;
1673 g_hash_table_insert(pdcp_security_result_hash,
1674 get_ueid_frame_hash_key(p_pdcp_info->ueid, pinfo->fd->num, TRUE),
1679 /* Show security settings for this PDU */
1680 pdu_security = (pdcp_security_info_t*)g_hash_table_lookup(pdcp_security_result_hash, get_ueid_frame_hash_key(p_pdcp_info->ueid, pinfo->fd->num, FALSE));
1681 if (pdu_security != NULL) {
1684 /* Create subtree */
1685 security_ti = proto_tree_add_string_format(pdcp_tree,
1686 hf_pdcp_lte_security,
1689 security_tree = proto_item_add_subtree(security_ti, ett_pdcp_security);
1690 PROTO_ITEM_SET_GENERATED(security_ti);
1693 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_setup_frame,
1694 tvb, 0, 0, pdu_security->configuration_frame);
1695 PROTO_ITEM_SET_GENERATED(ti);
1698 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_ciphering_algorithm,
1699 tvb, 0, 0, pdu_security->ciphering);
1700 PROTO_ITEM_SET_GENERATED(ti);
1703 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_integrity_algorithm,
1704 tvb, 0, 0, pdu_security->integrity);
1705 PROTO_ITEM_SET_GENERATED(ti);
1707 proto_item_append_text(security_ti, " (ciphering=%s, integrity=%s)",
1708 val_to_str_const(pdu_security->ciphering, ciphering_algorithm_vals, "Unknown"),
1709 val_to_str_const(pdu_security->integrity, integrity_algorithm_vals, "Unknown"));
1711 pdu_security_settings.ciphering = pdu_security->ciphering;
1712 pdu_security_settings.integrity = pdu_security->integrity;
1716 /***********************************/
1717 /* Handle PDCP header (if present) */
1718 if (!p_pdcp_info->no_header_pdu) {
1720 /* TODO: shouldn't need to initialise this one!! */
1722 gboolean seqnum_set = FALSE;
1724 guint8 first_byte = tvb_get_guint8(tvb, offset);
1726 /*****************************/
1727 /* Signalling plane messages */
1728 if (p_pdcp_info->plane == SIGNALING_PLANE) {
1729 /* Verify 3 reserved bits are 0 */
1730 guint8 reserved = (first_byte & 0xe0) >> 5;
1731 proto_item *ti = proto_tree_add_item(pdcp_tree, hf_pdcp_lte_control_plane_reserved,
1732 tvb, offset, 1, ENC_BIG_ENDIAN);
1733 if (reserved != 0) {
1734 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
1735 "PDCP signalling header reserved bits not zero");
1738 /* 5-bit sequence number */
1739 seqnum = first_byte & 0x1f;
1741 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_seq_num_5, tvb, offset, 1, ENC_BIG_ENDIAN);
1742 write_pdu_label_and_info(root_ti, pinfo, " sn=%-2u ", seqnum);
1745 if (tvb_length_remaining(tvb, offset) == 0) {
1746 /* Only PDCP header was captured, stop dissection here */
1750 else if (p_pdcp_info->plane == USER_PLANE) {
1752 /**********************************/
1753 /* User-plane messages */
1754 gboolean pdu_type = (first_byte & 0x80) >> 7;
1756 /* Data/Control flag */
1757 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_data_control, tvb, offset, 1, ENC_BIG_ENDIAN);
1759 if (pdu_type == 1) {
1760 /*****************************/
1761 /* Use-plane Data */
1763 /* Number of sequence number bits depends upon config */
1764 switch (p_pdcp_info->seqnum_length) {
1765 case PDCP_SN_LENGTH_7_BITS:
1766 seqnum = first_byte & 0x7f;
1768 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_seq_num_7, tvb, offset, 1, ENC_BIG_ENDIAN);
1771 case PDCP_SN_LENGTH_12_BITS:
1774 guint8 reserved_value;
1776 /* 3 reserved bits */
1777 ti = proto_tree_add_item(pdcp_tree, hf_pdcp_lte_reserved3, tvb, offset, 1, ENC_BIG_ENDIAN);
1778 reserved_value = (first_byte & 0x70) >> 4;
1780 /* Complain if not 0 */
1781 if (reserved_value != 0) {
1782 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
1783 "Reserved bits have value 0x%x - should be 0x0",
1787 /* 12-bit sequence number */
1788 seqnum = tvb_get_ntohs(tvb, offset) & 0x0fff;
1790 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_seq_num_12, tvb, offset, 2, ENC_BIG_ENDIAN);
1794 case PDCP_SN_LENGTH_15_BITS:
1795 seqnum = tvb_get_ntohs(tvb, offset) & 0x7fff;
1797 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_seq_num_15, tvb, offset, 2, ENC_BIG_ENDIAN);
1801 /* Not a recognised data format!!!!! */
1805 write_pdu_label_and_info(root_ti, pinfo, " (SN=%u)", seqnum);
1808 /*******************************/
1809 /* User-plane Control messages */
1810 guint8 control_pdu_type = (first_byte & 0x70) >> 4;
1811 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_control_pdu_type, tvb, offset, 1, ENC_BIG_ENDIAN);
1813 switch (control_pdu_type) {
1814 case 0: /* PDCP status report */
1819 guint not_received = 0;
1821 guint32 len, bit_offset;
1822 proto_tree *bitmap_tree;
1823 proto_item *bitmap_ti = NULL;
1825 #define BUFF_SIZE 49
1827 if (p_pdcp_info->seqnum_length == PDCP_SN_LENGTH_12_BITS) {
1828 /* First-Missing-Sequence SN */
1829 fms = tvb_get_ntohs(tvb, offset) & 0x0fff;
1830 sn = (fms + 1) % 4096;
1831 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_fms, tvb,
1832 offset, 2, ENC_BIG_ENDIAN);
1837 guint8 reserved_value;
1839 /* 5 reserved bits */
1840 ti = proto_tree_add_item(pdcp_tree, hf_pdcp_lte_reserved4, tvb, offset, 2, ENC_BIG_ENDIAN);
1841 reserved_value = (tvb_get_ntohs(tvb, offset) & 0x0f80)>>7;
1844 /* Complain if not 0 */
1845 if (reserved_value != 0) {
1846 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
1847 "Reserved bits have value 0x%x - should be 0x0",
1851 /* First-Missing-Sequence SN */
1852 fms = tvb_get_ntohs(tvb, offset) & 0x7fff;
1853 sn = (fms + 1) % 32768;
1854 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_fms2, tvb,
1855 offset, 2, ENC_BIG_ENDIAN);
1861 if (tvb_length_remaining(tvb, offset) > 0) {
1862 bitmap_ti = proto_tree_add_item(pdcp_tree, hf_pdcp_lte_bitmap, tvb,
1863 offset, -1, ENC_NA);
1864 bitmap_tree = proto_item_add_subtree(bitmap_ti, ett_pdcp_report_bitmap);
1866 buff = (gchar *)wmem_alloc(wmem_packet_scope(), BUFF_SIZE);
1867 len = tvb_length_remaining(tvb, offset);
1868 bit_offset = offset<<3;
1869 /* For each byte... */
1870 for (i=0; i<len; i++) {
1871 bits = tvb_get_bits8(tvb, bit_offset, 8);
1872 for (l=0, j=0; l<8; l++) {
1873 if ((bits << l) & 0x80) {
1874 j += g_snprintf(&buff[j], BUFF_SIZE-j, "%5u,", (unsigned)(sn+(8*i)+l)%modulo);
1876 j += g_snprintf(&buff[j], BUFF_SIZE-j, " ,");
1880 proto_tree_add_text(bitmap_tree, tvb, bit_offset/8, 1, "%s", buff);
1885 if (bitmap_ti != NULL) {
1886 proto_item_append_text(bitmap_ti, " (%u SNs not received)", not_received);
1888 write_pdu_label_and_info(root_ti, pinfo, " Status Report (fms=%u) not-received=%u",
1893 case 1: /* ROHC Feedback */
1895 break; /* Drop-through to dissect feedback */
1897 default: /* Reserved */
1903 /* Invalid plane setting...! */
1904 write_pdu_label_and_info(root_ti, pinfo, " - INVALID PLANE (%u)",
1905 p_pdcp_info->plane);
1909 /* Do sequence analysis if configured to. */
1911 gboolean do_analysis = FALSE;
1913 switch (global_pdcp_check_sequence_numbers) {
1916 case SEQUENCE_ANALYSIS_RLC_ONLY:
1917 if ((p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0) != NULL) &&
1918 !p_pdcp_info->is_retx) {
1922 case SEQUENCE_ANALYSIS_PDCP_ONLY:
1923 if (p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0) == NULL) {
1930 checkChannelSequenceInfo(pinfo, tvb, p_pdcp_info,
1931 (guint16)seqnum, pdcp_tree, security_tree,
1932 &pdu_security_settings);
1937 /* Show that it's a no-header PDU */
1938 write_pdu_label_and_info(root_ti, pinfo, " No-Header ");
1941 /*******************************************************/
1942 /* Now deal with the payload */
1943 /*******************************************************/
1945 /* Check pdu_security_settings - may need to do deciphering before calling
1946 further dissectors on payload */
1947 payload_tvb = decipher_payload(tvb, pinfo, &offset, &pdu_security_settings, p_pdcp_info->plane,
1948 pdu_security ? pdu_security->seen_next_ul_pdu: FALSE, &payload_deciphered);
1950 if (p_pdcp_info->plane == SIGNALING_PLANE) {
1951 guint32 data_length;
1954 guint32 calculated_digest = 0;
1955 gboolean digest_was_calculated = FALSE;
1957 /* Try to calculate digest so we can check it */
1958 if (global_pdcp_check_integrity) {
1959 calculated_digest = calculate_digest(&pdu_security_settings, tvb_get_guint8(tvb, 0), payload_tvb,
1960 offset, &digest_was_calculated);
1963 /* RRC data is all but last 4 bytes.
1964 Call lte-rrc dissector (according to direction and channel type) if we have valid data */
1965 if ((global_pdcp_dissect_signalling_plane_as_rrc) &&
1966 ((pdu_security == NULL) || (pdu_security->ciphering == 0) || payload_deciphered || !pdu_security->seen_next_ul_pdu)){
1967 /* Get appropriate dissector handle */
1968 dissector_handle_t rrc_handle = lookup_rrc_dissector_handle(p_pdcp_info);
1970 if (rrc_handle != 0) {
1971 /* Call RRC dissector if have one */
1972 tvbuff_t *rrc_payload_tvb = tvb_new_subset(payload_tvb, offset,
1973 tvb_length_remaining(payload_tvb, offset) - 4,
1974 tvb_length_remaining(payload_tvb, offset) - 4);
1975 gboolean was_writable = col_get_writable(pinfo->cinfo);
1977 /* We always want to see this in the info column */
1978 col_set_writable(pinfo->cinfo, TRUE);
1980 call_dissector_only(rrc_handle, rrc_payload_tvb, pinfo, pdcp_tree, NULL);
1982 /* Restore to whatever it was */
1983 col_set_writable(pinfo->cinfo, was_writable);
1986 /* Just show data */
1987 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_signalling_data, payload_tvb, offset,
1988 tvb_length_remaining(tvb, offset) - 4, ENC_NA);
1991 if (!pinfo->fd->flags.visited &&
1992 (current_security != NULL) && !current_security->seen_next_ul_pdu &&
1993 p_pdcp_info->direction == DIRECTION_UPLINK)
1995 /* i.e. we have already seen SecurityModeResponse! */
1996 current_security->seen_next_ul_pdu = TRUE;
2001 /* Just show as unparsed data */
2002 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_signalling_data, payload_tvb, offset,
2003 tvb_length_remaining(tvb, offset) - 4, ENC_NA);
2006 data_length = tvb_length_remaining(payload_tvb, offset) - 4;
2007 offset += data_length;
2009 /* Last 4 bytes are MAC */
2010 mac = tvb_get_ntohl(payload_tvb, offset);
2011 mac_ti = proto_tree_add_item(pdcp_tree, hf_pdcp_lte_mac, payload_tvb, offset, 4, ENC_BIG_ENDIAN);
2014 if (digest_was_calculated) {
2015 /* Compare what was found with calculated value! */
2016 if (mac != calculated_digest) {
2017 expert_add_info_format(pinfo, mac_ti, &ei_pdcp_lte_digest_wrong,
2018 "MAC-I Digest wrong expected %08x but found %08x",
2019 calculated_digest, mac);
2022 proto_item_append_text(mac_ti, " [Matches calculated result]");
2026 col_append_fstr(pinfo->cinfo, COL_INFO, " MAC=0x%08x (%u bytes data)",
2030 /* User-plane payload here */
2032 /* If not compressed with ROHC, show as user-plane data */
2033 if (!p_pdcp_info->rohc.rohc_compression) {
2034 gint payload_length = tvb_length_remaining(payload_tvb, offset);
2035 if (payload_length > 0) {
2036 if (p_pdcp_info->plane == USER_PLANE) {
2038 /* Not attempting to decode payload if ciphering is enabled
2039 (and NULL ciphering is not being used) */
2040 if (global_pdcp_dissect_user_plane_as_ip &&
2041 ((pdu_security == NULL) || (pdu_security->ciphering == 0) || payload_deciphered))
2043 tvbuff_t *ip_payload_tvb = tvb_new_subset_remaining(payload_tvb, offset);
2045 /* Don't update info column for ROHC unless configured to */
2046 if (global_pdcp_lte_layer_to_show != ShowTrafficLayer) {
2047 col_set_writable(pinfo->cinfo, FALSE);
2050 switch (tvb_get_guint8(ip_payload_tvb, offset) & 0xf0) {
2052 call_dissector_only(ip_handle, ip_payload_tvb, pinfo, pdcp_tree, NULL);
2055 call_dissector_only(ipv6_handle, ip_payload_tvb, pinfo, pdcp_tree, NULL);
2058 call_dissector_only(data_handle, ip_payload_tvb, pinfo, pdcp_tree, NULL);
2062 /* Freeze the columns again because we don't want other layers writing to info */
2063 if (global_pdcp_lte_layer_to_show == ShowTrafficLayer) {
2064 col_set_writable(pinfo->cinfo, FALSE);
2069 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_user_plane_data, payload_tvb, offset, -1, ENC_NA);
2073 write_pdu_label_and_info(root_ti, pinfo, "(%u bytes data)",
2077 /* (there will be no signalling data left at this point) */
2079 /* Let RLC write to columns again */
2080 col_set_writable(pinfo->cinfo, global_pdcp_lte_layer_to_show == ShowRLCLayer);
2082 /* DROPPING OUT HERE IF NOT DOING ROHC! */
2086 /***************************/
2088 /***************************/
2090 /* Only attempt ROHC if configured to */
2091 if (!global_pdcp_dissect_rohc) {
2092 col_append_fstr(pinfo->cinfo, COL_PROTOCOL, "|ROHC(%s)",
2093 val_to_str_const(p_pdcp_info->rohc.profile, rohc_profile_vals, "Unknown"));
2097 rohc_offset = offset;
2098 rohc_tvb = tvb_new_subset_remaining(payload_tvb, rohc_offset);
2100 /* Only enable writing to column if configured to show ROHC */
2101 if (global_pdcp_lte_layer_to_show != ShowTrafficLayer) {
2102 col_set_writable(pinfo->cinfo, FALSE);
2105 col_clear(pinfo->cinfo, COL_INFO);
2108 /* Call the ROHC dissector */
2109 call_dissector_with_data(rohc_handle, rohc_tvb, pinfo, tree, &p_pdcp_info->rohc);
2111 /* Let RLC write to columns again */
2112 col_set_writable(pinfo->cinfo, global_pdcp_lte_layer_to_show == ShowRLCLayer);
2117 /* Initializes the hash tables each time a new
2118 * file is loaded or re-loaded in wireshark */
2119 static void pdcp_lte_init_protocol(void)
2121 /* Destroy any existing hashes. */
2122 if (pdcp_sequence_analysis_channel_hash) {
2123 g_hash_table_destroy(pdcp_sequence_analysis_channel_hash);
2125 if (pdcp_lte_sequence_analysis_report_hash) {
2126 g_hash_table_destroy(pdcp_lte_sequence_analysis_report_hash);
2128 if (pdcp_security_hash) {
2129 g_hash_table_destroy(pdcp_security_hash);
2131 if (pdcp_security_result_hash) {
2132 g_hash_table_destroy(pdcp_security_result_hash);
2135 /* Now create them over */
2136 pdcp_sequence_analysis_channel_hash = g_hash_table_new(pdcp_channel_hash_func, pdcp_channel_equal);
2137 pdcp_lte_sequence_analysis_report_hash = g_hash_table_new(pdcp_result_hash_func, pdcp_result_hash_equal);
2138 pdcp_security_hash = g_hash_table_new(pdcp_lte_ueid_hash_func, pdcp_lte_ueid_hash_equal);
2139 pdcp_security_result_hash = g_hash_table_new(pdcp_lte_ueid_frame_hash_func, pdcp_lte_ueid_frame_hash_equal);
2144 void proto_register_pdcp(void)
2146 static hf_register_info hf[] =
2148 { &hf_pdcp_lte_configuration,
2150 "pdcp-lte.configuration", FT_STRING, BASE_NONE, NULL, 0x0,
2151 "Configuration info passed into dissector", HFILL
2155 { &hf_pdcp_lte_rohc_compression,
2156 { "ROHC Compression",
2157 "pdcp-lte.rohc.compression", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2161 { &hf_pdcp_lte_rohc_mode,
2163 "pdcp-lte.rohc.mode", FT_UINT8, BASE_DEC, VALS(rohc_mode_vals), 0x0,
2167 { &hf_pdcp_lte_rohc_rnd,
2169 "pdcp-lte.rohc.rnd", FT_UINT8, BASE_DEC, NULL, 0x0,
2170 "RND of outer ip header", HFILL
2173 { &hf_pdcp_lte_rohc_udp_checksum_present,
2175 "pdcp-lte.rohc.checksum-present", FT_UINT8, BASE_DEC, NULL, 0x0,
2176 "UDP Checksum present", HFILL
2179 { &hf_pdcp_lte_direction,
2181 "pdcp-lte.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
2182 "Direction of message", HFILL
2185 { &hf_pdcp_lte_ueid,
2187 "pdcp-lte.ueid", FT_UINT16, BASE_DEC, 0, 0x0,
2188 "UE Identifier", HFILL
2191 { &hf_pdcp_lte_channel_type,
2193 "pdcp-lte.channel-type", FT_UINT8, BASE_DEC, VALS(logical_channel_vals), 0x0,
2197 { &hf_pdcp_lte_channel_id,
2199 "pdcp-lte.channel-id", FT_UINT8, BASE_DEC, 0, 0x0,
2203 { &hf_pdcp_lte_rohc_profile,
2205 "pdcp-lte.rohc.profile", FT_UINT8, BASE_DEC, VALS(rohc_profile_vals), 0x0,
2209 { &hf_pdcp_lte_no_header_pdu,
2211 "pdcp-lte.no-header_pdu", FT_UINT8, BASE_DEC, NULL, 0x0,
2215 { &hf_pdcp_lte_plane,
2217 "pdcp-lte.plane", FT_UINT8, BASE_DEC, VALS(pdcp_plane_vals), 0x0,
2221 { &hf_pdcp_lte_seqnum_length,
2223 "pdcp-lte.seqnum_length", FT_UINT8, BASE_DEC, NULL, 0x0,
2224 "Sequence Number Length", HFILL
2229 { &hf_pdcp_lte_cid_inclusion_info,
2230 { "CID Inclusion Info",
2231 "pdcp-lte.cid-inclusion-info", FT_UINT8, BASE_DEC, NULL, 0x0,
2235 { &hf_pdcp_lte_large_cid_present,
2236 { "Large CID Present",
2237 "pdcp-lte.large-cid-present", FT_UINT8, BASE_DEC, NULL, 0x0,
2242 { &hf_pdcp_lte_control_plane_reserved,
2244 "pdcp-lte.reserved", FT_UINT8, BASE_DEC, NULL, 0xe0,
2248 { &hf_pdcp_lte_seq_num_5,
2250 "pdcp-lte.seq-num", FT_UINT8, BASE_DEC, NULL, 0x1f,
2251 "PDCP Seq num", HFILL
2254 { &hf_pdcp_lte_seq_num_7,
2256 "pdcp-lte.seq-num", FT_UINT8, BASE_DEC, NULL, 0x7f,
2257 "PDCP Seq num", HFILL
2260 { &hf_pdcp_lte_reserved3,
2262 "pdcp-lte.reserved3", FT_UINT8, BASE_HEX, NULL, 0x70,
2263 "3 reserved bits", HFILL
2266 { &hf_pdcp_lte_seq_num_12,
2268 "pdcp-lte.seq-num", FT_UINT16, BASE_DEC, NULL, 0x0fff,
2269 "PDCP Seq num", HFILL
2272 { &hf_pdcp_lte_seq_num_15,
2274 "pdcp-lte.seq-num", FT_UINT16, BASE_DEC, NULL, 0x7fff,
2275 "PDCP Seq num", HFILL
2278 { &hf_pdcp_lte_signalling_data,
2279 { "Signalling Data",
2280 "pdcp-lte.signalling-data", FT_BYTES, BASE_NONE, NULL, 0x0,
2286 "pdcp-lte.mac", FT_UINT32, BASE_HEX_DEC, NULL, 0x0,
2290 { &hf_pdcp_lte_data_control,
2292 "pdcp-lte.pdu-type", FT_UINT8, BASE_HEX, VALS(pdu_type_vals), 0x80,
2296 { &hf_pdcp_lte_user_plane_data,
2297 { "User-Plane Data",
2298 "pdcp-lte.user-data", FT_BYTES, BASE_NONE, NULL, 0x0,
2302 { &hf_pdcp_lte_control_pdu_type,
2303 { "Control PDU Type",
2304 "pdcp-lte.control-pdu-type", FT_UINT8, BASE_HEX, VALS(control_pdu_type_vals), 0x70,
2309 { "First Missing Sequence Number",
2310 "pdcp-lte.fms", FT_UINT16, BASE_DEC, NULL, 0x0fff,
2311 "First Missing PDCP Sequence Number", HFILL
2314 { &hf_pdcp_lte_reserved4,
2316 "pdcp-lte.reserved4", FT_UINT16, BASE_HEX, NULL, 0x0f80,
2317 "5 reserved bits", HFILL
2320 { &hf_pdcp_lte_fms2,
2321 { "First Missing Sequence Number",
2322 "pdcp-lte.fms", FT_UINT16, BASE_DEC, NULL, 0x07fff,
2323 "First Missing PDCP Sequence Number", HFILL
2326 { &hf_pdcp_lte_bitmap,
2328 "pdcp-lte.bitmap", FT_NONE, BASE_NONE, NULL, 0x0,
2329 "Status report bitmap (0=error, 1=OK)", HFILL
2334 { &hf_pdcp_lte_sequence_analysis,
2335 { "Sequence Analysis",
2336 "pdcp-lte.sequence-analysis", FT_STRING, BASE_NONE, 0, 0x0,
2340 { &hf_pdcp_lte_sequence_analysis_ok,
2342 "pdcp-lte.sequence-analysis.ok", FT_BOOLEAN, BASE_NONE, 0, 0x0,
2346 { &hf_pdcp_lte_sequence_analysis_previous_frame,
2347 { "Previous frame for channel",
2348 "pdcp-lte.sequence-analysis.previous-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
2352 { &hf_pdcp_lte_sequence_analysis_next_frame,
2353 { "Next frame for channel",
2354 "pdcp-lte.sequence-analysis.next-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
2358 { &hf_pdcp_lte_sequence_analysis_expected_sn,
2360 "pdcp-lte.sequence-analysis.expected-sn", FT_UINT16, BASE_DEC, 0, 0x0,
2364 { &hf_pdcp_lte_sequence_analysis_skipped,
2366 "pdcp-lte.sequence-analysis.skipped-frames", FT_BOOLEAN, BASE_NONE, 0, 0x0,
2370 { &hf_pdcp_lte_sequence_analysis_repeated,
2372 "pdcp-lte.sequence-analysis.repeated-frame", FT_BOOLEAN, BASE_NONE, 0, 0x0,
2377 { &hf_pdcp_lte_security,
2378 { "Security Config",
2379 "pdcp-lte.security-cofig", FT_STRING, BASE_NONE, 0, 0x0,
2383 { &hf_pdcp_lte_security_setup_frame,
2384 { "Configuration frame",
2385 "pdcp-lte.security-config.setup-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
2389 { &hf_pdcp_lte_security_integrity_algorithm,
2390 { "Integrity Algorithm",
2391 "pdcp-lte.security-config.integrity", FT_UINT16, BASE_DEC, VALS(integrity_algorithm_vals), 0x0,
2395 { &hf_pdcp_lte_security_ciphering_algorithm,
2396 { "Ciphering Algorithm",
2397 "pdcp-lte.security-config.ciphering", FT_UINT16, BASE_DEC, VALS(ciphering_algorithm_vals), 0x0,
2401 { &hf_pdcp_lte_security_bearer,
2403 "pdcp-lte.security-config.bearer", FT_UINT8, BASE_DEC, NULL, 0x0,
2407 { &hf_pdcp_lte_security_direction,
2409 "pdcp-lte.security-config.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
2413 { &hf_pdcp_lte_security_count,
2415 "pdcp-lte.security-config.count", FT_UINT32, BASE_DEC, NULL, 0x0,
2419 { &hf_pdcp_lte_security_cipher_key,
2421 "pdcp-lte.security-config.cipher-key", FT_STRING, BASE_NONE, NULL, 0x0,
2425 { &hf_pdcp_lte_security_integrity_key,
2427 "pdcp-lte.security-config.integrity-key", FT_STRING, BASE_NONE, NULL, 0x0,
2433 static gint *ett[] =
2436 &ett_pdcp_configuration,
2438 &ett_pdcp_lte_sequence_analysis,
2439 &ett_pdcp_report_bitmap,
2443 static ei_register_info ei[] = {
2444 { &ei_pdcp_lte_sequence_analysis_sn_missing, { "pdcp-lte.sequence-analysis.sn-missing", PI_SEQUENCE, PI_WARN, "PDCP SN missing", EXPFILL }},
2445 { &ei_pdcp_lte_sequence_analysis_sn_repeated, { "pdcp-lte.sequence-analysis.sn-repeated", PI_SEQUENCE, PI_WARN, "PDCP SN repeated", EXPFILL }},
2446 { &ei_pdcp_lte_sequence_analysis_wrong_sequence_number, { "pdcp-lte.sequence-analysis.wrong-sequence-number", PI_SEQUENCE, PI_WARN, "Wrong Sequence Number", EXPFILL }},
2447 { &ei_pdcp_lte_reserved_bits_not_zero, { "pdcp-lte.reserved-bits-not-zero", PI_MALFORMED, PI_ERROR, "Reserved bits not zero", EXPFILL }},
2448 { &ei_pdcp_lte_digest_wrong, { "pdcp-lte.maci-wrong", PI_SEQUENCE, PI_ERROR, "MAC-I doesn't match expected value", EXPFILL }}
2451 static const enum_val_t sequence_analysis_vals[] = {
2452 {"no-analysis", "No-Analysis", FALSE},
2453 {"rlc-only", "Only-RLC-frames", SEQUENCE_ANALYSIS_RLC_ONLY},
2454 {"pdcp-only", "Only-PDCP-frames", SEQUENCE_ANALYSIS_PDCP_ONLY},
2458 static const enum_val_t show_info_col_vals[] = {
2459 {"show-rlc", "RLC Info", ShowRLCLayer},
2460 {"show-pdcp", "PDCP Info", ShowPDCPLayer},
2461 {"show-traffic", "Traffic Info", ShowTrafficLayer},
2465 static uat_field_t ue_keys_uat_flds[] = {
2466 UAT_FLD_DEC(uat_ue_keys_records, ueid, "UEId", "UE Identifier of UE associated with keys"),
2467 UAT_FLD_CSTRING(uat_ue_keys_records, rrcCipherKeyString, "RRC Cipher Key", "Key for deciphering signalling messages"),
2468 UAT_FLD_CSTRING(uat_ue_keys_records, upCipherKeyString, "User-Plane Cipher Key", "Key for deciphering user-plane messages"),
2469 UAT_FLD_CSTRING(uat_ue_keys_records, rrcIntegrityKeyString, "RRC Integrity Key", "Key for deciphering user-plane messages"),
2473 module_t *pdcp_lte_module;
2474 expert_module_t* expert_pdcp_lte;
2476 /* Register protocol. */
2477 proto_pdcp_lte = proto_register_protocol("PDCP-LTE", "PDCP-LTE", "pdcp-lte");
2478 proto_register_field_array(proto_pdcp_lte, hf, array_length(hf));
2479 proto_register_subtree_array(ett, array_length(ett));
2480 expert_pdcp_lte = expert_register_protocol(proto_pdcp_lte);
2481 expert_register_field_array(expert_pdcp_lte, ei, array_length(ei));
2483 /* Allow other dissectors to find this one by name. */
2484 register_dissector("pdcp-lte", dissect_pdcp_lte, proto_pdcp_lte);
2486 pdcp_lte_module = prefs_register_protocol(proto_pdcp_lte, NULL);
2488 /* Obsolete preferences */
2489 prefs_register_obsolete_preference(pdcp_lte_module, "show_feedback_option_tag_length");
2492 /* Dissect uncompressed user-plane data as IP */
2493 prefs_register_bool_preference(pdcp_lte_module, "show_user_plane_as_ip",
2494 "Show uncompressed User-Plane data as IP",
2495 "Show uncompressed User-Plane data as IP",
2496 &global_pdcp_dissect_user_plane_as_ip);
2498 /* Dissect unciphered signalling data as RRC */
2499 prefs_register_bool_preference(pdcp_lte_module, "show_signalling_plane_as_rrc",
2500 "Show unciphered Signalling-Plane data as RRC",
2501 "Show unciphered Signalling-Plane data as RRC",
2502 &global_pdcp_dissect_signalling_plane_as_rrc);
2504 /* Check for missing sequence numbers */
2505 prefs_register_enum_preference(pdcp_lte_module, "check_sequence_numbers",
2506 "Do sequence number analysis",
2507 "Do sequence number analysis",
2508 &global_pdcp_check_sequence_numbers, sequence_analysis_vals, FALSE);
2510 /* Attempt to dissect ROHC messages */
2511 prefs_register_bool_preference(pdcp_lte_module, "dissect_rohc",
2512 "Attempt to decode ROHC data",
2513 "Attempt to decode ROHC data",
2514 &global_pdcp_dissect_rohc);
2516 prefs_register_bool_preference(pdcp_lte_module, "heuristic_pdcp_lte_over_udp",
2517 "Try Heuristic LTE-PDCP over UDP framing",
2518 "When enabled, use heuristic dissector to find PDCP-LTE frames sent with "
2520 &global_pdcp_lte_heur);
2522 prefs_register_enum_preference(pdcp_lte_module, "layer_to_show",
2523 "Which layer info to show in Info column",
2524 "Can show RLC, PDCP or Traffic layer info in Info column",
2525 &global_pdcp_lte_layer_to_show, show_info_col_vals, FALSE);
2527 ue_keys_uat = uat_new("PDCP UE security keys",
2528 sizeof(uat_ue_keys_record_t), /* record size */
2529 "pdcp_lte_ue_keys", /* filename */
2530 TRUE, /* from_profile */
2531 (void**) &uat_ue_keys_records, /* data_ptr */
2532 &num_ue_keys_uat, /* numitems_ptr */
2533 UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */
2535 uat_ue_keys_record_copy_cb, /* copy callback */
2536 uat_ue_keys_record_update_cb, /* update callback */
2537 uat_ue_keys_record_free_cb, /* free callback */
2538 NULL, /* post update callback */
2539 ue_keys_uat_flds); /* UAT field definitions */
2541 prefs_register_uat_preference(pdcp_lte_module,
2544 "Preconfigured PDCP keys",
2547 /* Attempt to decipher RRC messages */
2548 prefs_register_bool_preference(pdcp_lte_module, "decipher_signalling",
2549 "Attempt to decipher Signalling (RRC) SDUs",
2550 "N.B. only possible if build with algorithm support, and have key available and configured",
2551 &global_pdcp_decipher_signalling);
2553 /* Attempt to decipher user-plane messages */
2554 prefs_register_bool_preference(pdcp_lte_module, "decipher_userplane",
2555 "Attempt to decipher User-plane (IP) SDUs",
2556 "N.B. only possible if build with algorithm support, and have key available and configured",
2557 &global_pdcp_decipher_userplane);
2559 /* Attempt to verify RRC integrity/authentication digest */
2560 prefs_register_bool_preference(pdcp_lte_module, "verify_integrity",
2561 "Attempt to check integrity calculation",
2562 "N.B. only possible if build with algorithm support, and have key available and configured",
2563 &global_pdcp_check_integrity);
2565 register_init_routine(&pdcp_lte_init_protocol);
2568 void proto_reg_handoff_pdcp_lte(void)
2570 /* Add as a heuristic UDP dissector */
2571 heur_dissector_add("udp", dissect_pdcp_lte_heur, proto_pdcp_lte);
2573 ip_handle = find_dissector("ip");
2574 ipv6_handle = find_dissector("ipv6");
2575 rohc_handle = find_dissector("rohc");
2576 data_handle = find_dissector("data");
2585 * indent-tabs-mode: nil
2588 * ex: set shiftwidth=4 tabstop=8 expandtab:
2589 * :indentSize=4:tabSize=8:noTabs=true: