epan/dissectors/pidl/samr/samr.cnf cnf_dissect_lsa_BinaryString => lsarpc_dissect_str...
[wireshark-sm.git] / epan / dissectors / packet-pdcp-lte.c
blob5ad84fcd259a8531a2c7445395024ca690534e4b
1 /* packet-pdcp-lte.c
2 * Routines for LTE PDCP
4 * Martin Mathieson
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
13 #include "config.h"
15 #include <epan/packet.h>
16 #include <epan/prefs.h>
17 #include <epan/expert.h>
18 #include <epan/uat.h>
19 #include <epan/proto_data.h>
20 #include <epan/tfs.h>
22 #include <wsutil/array.h>
23 #include <wsutil/wsgcrypt.h>
24 #include <wsutil/report_message.h>
26 /* Define these symbols if you have working implementations of SNOW3G/ZUC f8() and f9() available.
27 Note that the use of these algorithms is restricted, so a version of Wireshark with these
28 ciphering algorithms enabled would not be distributable. */
30 /* #define HAVE_SNOW3G */
31 /* #define HAVE_ZUC */
33 #include "packet-mac-lte.h"
34 #include "packet-rlc-lte.h"
35 #include "packet-pdcp-lte.h"
37 void proto_register_pdcp_lte(void);
38 void proto_reg_handoff_pdcp_lte(void);
40 /* Described in:
41 * 3GPP TS 36.323 Evolved Universal Terrestrial Radio Access (E-UTRA)
42 * Packet Data Convergence Protocol (PDCP) specification v14.3.0
46 /* TODO:
47 - Decipher even if sequence analysis isn't 'OK'?
48 - know SN, but might be unsure about HFN.
49 - Speed up AES decryption by keeping the crypt handle around for the channel
50 (like ESP decryption in IPSEC dissector). N.B. do lazily when it needs to be used.
51 CTR will need to be applied before each frame.
52 - Add Relay Node user plane data PDU dissection
53 - Add SLRB user data plane data PDU dissection
54 - Break out security and sequence analysis into a separate common file to be
55 shared with pdcp-nr
59 /* Initialize the protocol and registered fields. */
60 int proto_pdcp_lte;
62 extern int proto_rlc_lte;
64 /* Configuration (info known outside of PDU) */
65 static int hf_pdcp_lte_configuration;
66 static int hf_pdcp_lte_direction;
67 static int hf_pdcp_lte_ueid;
68 static int hf_pdcp_lte_channel_type;
69 static int hf_pdcp_lte_channel_id;
71 static int hf_pdcp_lte_rohc_compression;
72 static int hf_pdcp_lte_rohc_mode;
73 static int hf_pdcp_lte_rohc_rnd;
74 static int hf_pdcp_lte_rohc_udp_checksum_present;
75 static int hf_pdcp_lte_rohc_profile;
77 static int hf_pdcp_lte_no_header_pdu;
78 static int hf_pdcp_lte_plane;
79 static int hf_pdcp_lte_seqnum_length;
80 static int hf_pdcp_lte_cid_inclusion_info;
81 static int hf_pdcp_lte_large_cid_present;
83 /* PDCP header fields */
84 static int hf_pdcp_lte_control_plane_reserved;
85 static int hf_pdcp_lte_seq_num_5;
86 static int hf_pdcp_lte_seq_num_7;
87 static int hf_pdcp_lte_reserved3;
88 static int hf_pdcp_lte_seq_num_12;
89 static int hf_pdcp_lte_seq_num_15;
90 static int hf_pdcp_lte_polling;
91 static int hf_pdcp_lte_reserved5;
92 static int hf_pdcp_lte_seq_num_18;
93 static int hf_pdcp_lte_signalling_data;
94 static int hf_pdcp_lte_mac;
95 static int hf_pdcp_lte_data_control;
96 static int hf_pdcp_lte_user_plane_data;
97 static int hf_pdcp_lte_control_pdu_type;
98 static int hf_pdcp_lte_fms;
99 static int hf_pdcp_lte_reserved4;
100 static int hf_pdcp_lte_fms2;
101 static int hf_pdcp_lte_reserved6;
102 static int hf_pdcp_lte_fms3;
103 static int hf_pdcp_lte_bitmap;
104 static int hf_pdcp_lte_bitmap_byte;
105 static int hf_pdcp_lte_hrw;
106 static int hf_pdcp_lte_nmp;
107 static int hf_pdcp_lte_reserved7;
108 static int hf_pdcp_lte_hrw2;
109 static int hf_pdcp_lte_nmp2;
110 static int hf_pdcp_lte_hrw3;
111 static int hf_pdcp_lte_reserved8;
112 static int hf_pdcp_lte_nmp3;
113 static int hf_pdcp_lte_lsn;
114 static int hf_pdcp_lte_lsn2;
115 static int hf_pdcp_lte_lsn3;
117 /* Sequence Analysis */
118 static int hf_pdcp_lte_sequence_analysis;
119 static int hf_pdcp_lte_sequence_analysis_ok;
120 static int hf_pdcp_lte_sequence_analysis_previous_frame;
121 static int hf_pdcp_lte_sequence_analysis_next_frame;
122 static int hf_pdcp_lte_sequence_analysis_expected_sn;
124 static int hf_pdcp_lte_sequence_analysis_repeated;
125 static int hf_pdcp_lte_sequence_analysis_skipped;
127 /* Security Settings */
128 static int hf_pdcp_lte_security;
129 static int hf_pdcp_lte_security_setup_frame;
130 static int hf_pdcp_lte_security_integrity_algorithm;
131 static int hf_pdcp_lte_security_ciphering_algorithm;
133 static int hf_pdcp_lte_security_bearer;
134 static int hf_pdcp_lte_security_direction;
135 static int hf_pdcp_lte_security_count;
136 static int hf_pdcp_lte_security_cipher_key;
137 static int hf_pdcp_lte_security_integrity_key;
139 static int hf_pdcp_lte_security_deciphered_data;
141 /* Protocol subtree. */
142 static int ett_pdcp;
143 static int ett_pdcp_configuration;
144 static int ett_pdcp_packet;
145 static int ett_pdcp_lte_sequence_analysis;
146 static int ett_pdcp_report_bitmap;
147 static int ett_pdcp_security;
149 static expert_field ei_pdcp_lte_sequence_analysis_wrong_sequence_number;
150 static expert_field ei_pdcp_lte_reserved_bits_not_zero;
151 static expert_field ei_pdcp_lte_sequence_analysis_sn_repeated;
152 static expert_field ei_pdcp_lte_sequence_analysis_sn_missing;
153 static expert_field ei_pdcp_lte_digest_wrong;
154 static expert_field ei_pdcp_lte_unknown_udp_framing_tag;
155 static expert_field ei_pdcp_lte_missing_udp_framing_tag;
158 /*-------------------------------------
159 * UAT for UE Keys
160 *-------------------------------------
162 /* UAT entry structure. */
163 typedef struct {
164 uint32_t ueid;
165 char *rrcCipherKeyString;
166 char *upCipherKeyString;
167 char *rrcIntegrityKeyString;
169 uint8_t rrcCipherBinaryKey[16];
170 bool rrcCipherKeyOK;
171 uint8_t upCipherBinaryKey[16];
172 bool upCipherKeyOK;
173 uint8_t rrcIntegrityBinaryKey[16];
174 bool rrcIntegrityKeyOK;
175 } uat_ue_keys_record_t;
177 /* N.B. this is an array/table of the struct above, where ueid is the key */
178 static uat_ue_keys_record_t *uat_ue_keys_records;
180 /* Entries added by UAT */
181 static uat_t * ue_keys_uat;
182 static unsigned num_ue_keys_uat;
184 /* Convert an ascii hex character into a digit. Should only be given valid
185 hex ascii characters */
186 static unsigned char hex_ascii_to_binary(char c)
188 if ((c >= '0') && (c <= '9')) {
189 return c - '0';
191 else if ((c >= 'a') && (c <= 'f')) {
192 return 10 + c - 'a';
194 else if ((c >= 'A') && (c <= 'F')) {
195 return 10 + c - 'A';
197 else {
198 return 0;
202 static void* uat_ue_keys_record_copy_cb(void* n, const void* o, size_t siz _U_) {
203 uat_ue_keys_record_t* new_rec = (uat_ue_keys_record_t *)n;
204 const uat_ue_keys_record_t* old_rec = (const uat_ue_keys_record_t *)o;
206 new_rec->ueid = old_rec->ueid;
207 new_rec->rrcCipherKeyString = g_strdup(old_rec->rrcCipherKeyString);
208 new_rec->upCipherKeyString = g_strdup(old_rec->upCipherKeyString);
209 new_rec->rrcIntegrityKeyString = g_strdup(old_rec->rrcIntegrityKeyString);
211 return new_rec;
214 /* If raw_string is a valid key, set check_string & return true. Can be spaced out with ' ' or '-' */
215 static bool check_valid_key_string(const char* raw_string, char* checked_string, char **error)
217 unsigned n;
218 unsigned written = 0;
219 unsigned length = (int)strlen(raw_string);
221 /* Can't be valid if not long enough. */
222 if (length < 32) {
223 if (length > 0) {
224 *error = ws_strdup_printf("PDCP LTE: Invalid key string (%s) - should include 32 ASCII hex characters (16 bytes) but only %u chars given",
225 raw_string, length);
228 return false;
231 for (n=0; (n < length) && (written < 32); n++) {
232 char c = raw_string[n];
234 /* Skipping past allowed 'padding' characters */
235 if ((c == ' ') || (c == '-')) {
236 continue;
239 /* Other characters must be hex digits, otherwise string is invalid */
240 if (((c >= '0') && (c <= '9')) ||
241 ((c >= 'a') && (c <= 'f')) ||
242 ((c >= 'A') && (c <= 'F'))) {
243 checked_string[written++] = c;
245 else {
246 *error = ws_strdup_printf("PDCP-LTE: Invalid char '%c' given in key", c);
247 return false;
251 /* Must have found exactly 32 hex ascii chars for 16-byte key */
252 if (n<length) {
253 *error = ws_strdup_printf("PDCP-LTE: Key (%s) should contain 32 hex characters (16 bytes) but more detected", raw_string);
254 return false;
256 if (written != 32) {
257 *error = ws_strdup_printf("PDCP-LTE: Key (%s) should contain 32 hex characters (16 bytes) but %u detected", raw_string, written);
258 return false;
260 else {
261 return true;
266 /* Write binary key by converting each nibble from the string version */
267 static void update_key_from_string(const char *stringKey, uint8_t *binaryKey, bool *pKeyOK, char **error)
269 int n;
270 char cleanString[32];
272 if (!check_valid_key_string(stringKey, cleanString, error)) {
273 *pKeyOK = false;
275 else {
276 for (n=0; n < 32; n += 2) {
277 binaryKey[n/2] = (hex_ascii_to_binary(cleanString[n]) << 4) +
278 hex_ascii_to_binary(cleanString[n+1]);
280 *pKeyOK = true;
284 /* Update by checking whether the 3 key strings are valid or not, and storing result */
285 static bool uat_ue_keys_record_update_cb(void* record, char** error) {
286 uat_ue_keys_record_t* rec = (uat_ue_keys_record_t *)record;
288 /* Check and convert RRC key */
289 update_key_from_string(rec->rrcCipherKeyString, rec->rrcCipherBinaryKey, &rec->rrcCipherKeyOK, error);
291 /* Check and convert User-plane key */
292 update_key_from_string(rec->upCipherKeyString, rec->upCipherBinaryKey, &rec->upCipherKeyOK, error);
294 /* Check and convert Integrity key */
295 update_key_from_string(rec->rrcIntegrityKeyString, rec->rrcIntegrityBinaryKey, &rec->rrcIntegrityKeyOK, error);
297 /* Return true only if *error has not been set by checking code. */
298 return *error == NULL;
301 /* Free heap parts of record */
302 static void uat_ue_keys_record_free_cb(void*r) {
303 uat_ue_keys_record_t* rec = (uat_ue_keys_record_t*)r;
305 g_free(rec->rrcCipherKeyString);
306 g_free(rec->upCipherKeyString);
307 g_free(rec->rrcIntegrityKeyString);
310 UAT_DEC_CB_DEF(uat_ue_keys_records, ueid, uat_ue_keys_record_t)
311 UAT_CSTRING_CB_DEF(uat_ue_keys_records, rrcCipherKeyString, uat_ue_keys_record_t)
312 UAT_CSTRING_CB_DEF(uat_ue_keys_records, upCipherKeyString, uat_ue_keys_record_t)
313 UAT_CSTRING_CB_DEF(uat_ue_keys_records, rrcIntegrityKeyString, uat_ue_keys_record_t)
316 /* Also supporting a hash table with entries from these functions */
318 /* Table from ueid -> ue_key_entries_t* */
319 static wmem_map_t *pdcp_security_key_hash;
321 typedef enum {
322 rrc_cipher,
323 rrc_integrity,
324 up_cipher,
325 } ue_key_type_t;
327 typedef struct {
328 ue_key_type_t key_type;
329 char *keyString;
330 uint8_t binaryKey[16];
331 bool keyOK;
332 uint32_t setup_frame;
333 } key_entry_t;
335 /* List of key entries for an individual UE */
336 typedef struct {
337 #define MAX_KEY_ENTRIES_PER_UE 32
338 unsigned num_entries_set;
339 key_entry_t entries[MAX_KEY_ENTRIES_PER_UE];
340 } ue_key_entries_t;
344 void set_pdcp_lte_rrc_ciphering_key(uint16_t ueid, const char *key, uint32_t frame_num)
346 char *err = NULL;
348 /* Get or create struct for this UE */
349 ue_key_entries_t *key_entries = (ue_key_entries_t*)wmem_map_lookup(pdcp_security_key_hash,
350 GUINT_TO_POINTER((unsigned)ueid));
351 if (key_entries == NULL) {
352 /* Create and add to table */
353 key_entries = wmem_new0(wmem_file_scope(), ue_key_entries_t);
354 wmem_map_insert(pdcp_security_key_hash, GUINT_TO_POINTER((unsigned)ueid), key_entries);
357 if (key_entries->num_entries_set == MAX_KEY_ENTRIES_PER_UE) {
358 /* No more room.. */
359 return;
362 key_entry_t *new_key_entry = &key_entries->entries[key_entries->num_entries_set++];
363 new_key_entry->key_type = rrc_cipher;
364 new_key_entry->keyString = g_strdup(key);
365 new_key_entry->setup_frame = frame_num;
366 update_key_from_string(new_key_entry->keyString, new_key_entry->binaryKey, &new_key_entry->keyOK, &err);
367 if (err) {
368 report_failure("%s: (RRC Ciphering Key)", err);
369 g_free(err);
373 void set_pdcp_lte_rrc_integrity_key(uint16_t ueid, const char *key, uint32_t frame_num)
375 char *err = NULL;
377 /* Get or create struct for this UE */
378 ue_key_entries_t *key_entries = (ue_key_entries_t*)wmem_map_lookup(pdcp_security_key_hash,
379 GUINT_TO_POINTER((unsigned)ueid));
380 if (key_entries == NULL) {
381 /* Create and add to table */
382 key_entries = wmem_new0(wmem_file_scope(), ue_key_entries_t);
383 wmem_map_insert(pdcp_security_key_hash, GUINT_TO_POINTER((unsigned)ueid), key_entries);
386 if (key_entries->num_entries_set == MAX_KEY_ENTRIES_PER_UE) {
387 /* No more room.. */
388 return;
391 key_entry_t *new_key_entry = &key_entries->entries[key_entries->num_entries_set++];
392 new_key_entry->key_type = rrc_integrity;
393 new_key_entry->keyString = g_strdup(key);
394 new_key_entry->setup_frame = frame_num;
395 update_key_from_string(new_key_entry->keyString, new_key_entry->binaryKey, &new_key_entry->keyOK, &err);
396 if (err) {
397 report_failure("%s: (RRC Ciphering Key)", err);
398 g_free(err);
402 void set_pdcp_lte_up_ciphering_key(uint16_t ueid, const char *key, uint32_t frame_num)
404 char *err = NULL;
406 /* Get or create struct for this UE */
407 ue_key_entries_t *key_entries = (ue_key_entries_t*)wmem_map_lookup(pdcp_security_key_hash,
408 GUINT_TO_POINTER((unsigned)ueid));
409 if (key_entries == NULL) {
410 /* Create and add to table */
411 key_entries = wmem_new0(wmem_file_scope(), ue_key_entries_t);
412 wmem_map_insert(pdcp_security_key_hash, GUINT_TO_POINTER((unsigned)ueid), key_entries);
415 if (key_entries->num_entries_set == MAX_KEY_ENTRIES_PER_UE) {
416 /* No more room.. */
417 return;
420 key_entry_t *new_key_entry = &key_entries->entries[key_entries->num_entries_set++];
421 new_key_entry->key_type = up_cipher;
422 new_key_entry->keyString = g_strdup(key);
423 new_key_entry->setup_frame = frame_num;
424 update_key_from_string(new_key_entry->keyString, new_key_entry->binaryKey, &new_key_entry->keyOK, &err);
425 if (err) {
426 report_failure("%s: (RRC Ciphering Key)", err);
427 g_free(err);
432 /* Preference settings for deciphering and integrity checking. */
433 static bool global_pdcp_decipher_signalling = true;
434 static bool global_pdcp_decipher_userplane; /* Can be slow, so default to false */
435 static bool global_pdcp_check_integrity = true;
436 static bool global_pdcp_ignore_sec; /* Ignore Set Security Algo calls */
438 /* Use these values where we know the keys but may have missed the algorithm,
439 e.g. when handing over and RRCReconfigurationRequest goes to target cell only */
440 static enum lte_security_ciphering_algorithm_e global_default_ciphering_algorithm = eea0;
441 static enum lte_security_integrity_algorithm_e global_default_integrity_algorithm = eia0;
444 static const value_string direction_vals[] =
446 { DIRECTION_UPLINK, "Uplink"},
447 { DIRECTION_DOWNLINK, "Downlink"},
448 { 0, NULL }
452 static const value_string pdcp_plane_vals[] = {
453 { SIGNALING_PLANE, "Signalling" },
454 { USER_PLANE, "User" },
455 { 0, NULL }
458 static const value_string logical_channel_vals[] = {
459 { Channel_DCCH, "DCCH"},
460 { Channel_BCCH, "BCCH"},
461 { Channel_CCCH, "CCCH"},
462 { Channel_PCCH, "PCCH"},
463 { 0, NULL}
466 static const value_string rohc_mode_vals[] = {
467 { UNIDIRECTIONAL, "Unidirectional" },
468 { OPTIMISTIC_BIDIRECTIONAL, "Optimistic Bidirectional" },
469 { RELIABLE_BIDIRECTIONAL, "Reliable Bidirectional" },
470 { 0, NULL }
474 /* Values taken from:
475 http://www.iana.org/assignments/rohc-pro-ids/rohc-pro-ids.txt */
476 static const value_string rohc_profile_vals[] = {
477 { 0x0000, "ROHC uncompressed" }, /* [RFC5795] */
478 { 0x0001, "ROHC RTP" }, /* [RFC3095] */
479 { 0x0002, "ROHC UDP" }, /* [RFC3095] */
480 { 0x0003, "ROHC ESP" }, /* [RFC3095] */
481 { 0x0004, "ROHC IP" }, /* [RFC3843] */
482 { 0x0005, "ROHC LLA" }, /* [RFC4362] */
483 { 0x0006, "ROHC TCP" }, /* [RFC4996] */
484 { 0x0007, "ROHC RTP/UDP-Lite" }, /* [RFC4019] */
485 { 0x0008, "ROHC UDP-Lite" }, /* [RFC4019] */
486 { 0x0101, "ROHCv2 RTP" }, /* [RFC5225] */
487 { 0x0102, "ROHCv2 UDP" }, /* [RFC5225] */
488 { 0x0103, "ROHCv2 ESP" }, /* [RFC5225] */
489 { 0x0104, "ROHCv2 IP" }, /* [RFC5225] */
490 { 0x0105, "ROHC LLA with R-mode" }, /* [RFC3408] */
491 { 0x0107, "ROHCv2 RTP/UDP-Lite" }, /* [RFC5225] */
492 { 0x0108, "ROHCv2 UDP-Lite" }, /* [RFC5225] */
493 { 0, NULL }
496 static const value_string control_pdu_type_vals[] = {
497 { 0, "PDCP status report" },
498 { 1, "Interspersed ROHC feedback packet" },
499 { 2, "LWA status report" },
500 { 3, "LWA end-marker packet"},
501 { 0, NULL }
504 static const value_string integrity_algorithm_vals[] = {
505 { eia0, "EIA0 (NULL)" },
506 { eia1, "EIA1 (SNOW3G)" },
507 { eia2, "EIA2 (AES)" },
508 { eia3, "EIA3 (ZUC)" },
509 { 0, NULL }
512 static const value_string ciphering_algorithm_vals[] = {
513 { eea0, "EEA0 (NULL)" },
514 { eea1, "EEA1 (SNOW3G)" },
515 { eea2, "EEA2 (AES)" },
516 { eea3, "EEA3 (ZUC)" },
517 { 0, NULL }
521 static dissector_handle_t ip_handle;
522 static dissector_handle_t ipv6_handle;
523 static dissector_handle_t rohc_handle;
524 static dissector_handle_t lte_rrc_ul_ccch;
525 static dissector_handle_t lte_rrc_dl_ccch;
526 static dissector_handle_t lte_rrc_pcch;
527 static dissector_handle_t lte_rrc_bcch_bch;
528 static dissector_handle_t lte_rrc_bcch_dl_sch;
529 static dissector_handle_t lte_rrc_ul_dcch;
530 static dissector_handle_t lte_rrc_dl_dcch;
531 static dissector_handle_t lte_rrc_ul_ccch_nb;
532 static dissector_handle_t lte_rrc_dl_ccch_nb;
533 static dissector_handle_t lte_rrc_pcch_nb;
534 static dissector_handle_t lte_rrc_bcch_bch_nb;
535 static dissector_handle_t lte_rrc_bcch_dl_sch_nb;
536 static dissector_handle_t lte_rrc_ul_dcch_nb;
537 static dissector_handle_t lte_rrc_dl_dcch_nb;
540 #define SEQUENCE_ANALYSIS_RLC_ONLY 1
541 #define SEQUENCE_ANALYSIS_PDCP_ONLY 2
543 /* Preference variables */
544 static bool global_pdcp_dissect_user_plane_as_ip = true;
545 static bool global_pdcp_dissect_signalling_plane_as_rrc = true;
546 static int global_pdcp_check_sequence_numbers = SEQUENCE_ANALYSIS_RLC_ONLY;
547 static bool global_pdcp_dissect_rohc;
549 /* Which layer info to show in the info column */
550 enum layer_to_show {
551 ShowRLCLayer, ShowPDCPLayer, ShowTrafficLayer
553 static int global_pdcp_lte_layer_to_show = (int)ShowRLCLayer;
557 /**************************************************/
558 /* Sequence number analysis */
560 /* Channel key */
561 typedef struct
563 /* Using bit fields to fit into 32 bits, so avoiding the need to allocate
564 heap memory for these structs */
565 unsigned ueId : 16;
566 unsigned plane : 2;
567 unsigned channelId : 6;
568 unsigned direction : 1;
569 unsigned notUsed : 7;
570 } pdcp_channel_hash_key;
572 /* Channel state */
573 typedef struct
575 uint32_t previousSequenceNumber;
576 uint32_t previousFrameNum;
577 uint32_t hfn;
578 } pdcp_channel_status;
580 /* The sequence analysis channel hash table.
581 Maps pdcp_channel_hash_key -> *pdcp_channel_status */
582 static wmem_map_t *pdcp_sequence_analysis_channel_hash;
585 /* Hash table types & functions for frame reports */
587 typedef struct {
588 uint32_t frameNumber;
589 uint32_t SN : 18;
590 uint32_t plane : 2;
591 uint32_t channelId: 5;
592 uint32_t direction: 1;
593 uint32_t notUsed : 6;
594 } pdcp_result_hash_key;
596 static int pdcp_result_hash_equal(const void *v, const void *v2)
598 const pdcp_result_hash_key* val1 = (const pdcp_result_hash_key *)v;
599 const pdcp_result_hash_key* val2 = (const pdcp_result_hash_key *)v2;
601 /* All fields must match */
602 return (memcmp(val1, val2, sizeof(pdcp_result_hash_key)) == 0);
605 /* Compute a hash value for a given key. */
606 static unsigned pdcp_result_hash_func(const void *v)
608 const pdcp_result_hash_key* val1 = (const pdcp_result_hash_key *)v;
610 /* TODO: This is a bit random. */
611 return val1->frameNumber + (val1->channelId<<7) +
612 (val1->plane<<12) +
613 (val1->SN<<14) +
614 (val1->direction<<6);
617 /* pdcp_channel_hash_key fits into the pointer, so just copy the value into
618 a unsigned, cast to a pointer and return that as the key */
619 static void *get_channel_hash_key(pdcp_channel_hash_key *key)
621 unsigned asInt = 0;
622 /* TODO: assert that sizeof(pdcp_channel_hash_key) <= sizeof(unsigned) ? */
623 memcpy(&asInt, key, sizeof(pdcp_channel_hash_key));
624 return GUINT_TO_POINTER(asInt);
627 /* Convenience function to get a pointer for the hash_func to work with */
628 static void *get_report_hash_key(uint32_t SN, uint32_t frameNumber,
629 pdcp_lte_info *p_pdcp_lte_info,
630 bool do_persist)
632 static pdcp_result_hash_key key;
633 pdcp_result_hash_key *p_key;
635 /* Only allocate a struct when will be adding entry */
636 if (do_persist) {
637 p_key = wmem_new(wmem_file_scope(), pdcp_result_hash_key);
639 else {
640 memset(&key, 0, sizeof(pdcp_result_hash_key));
641 p_key = &key;
644 /* Fill in details, and return pointer */
645 p_key->frameNumber = frameNumber;
646 p_key->SN = SN;
647 p_key->plane = (uint8_t)p_pdcp_lte_info->plane;
648 p_key->channelId = p_pdcp_lte_info->channelId;
649 p_key->direction = p_pdcp_lte_info->direction;
650 p_key->notUsed = 0;
652 return p_key;
656 /* Info to attach to frame when first read, recording what to show about sequence */
657 typedef enum
659 SN_OK, SN_Repeated, SN_MAC_Retx, SN_Retx, SN_Missing
660 } sequence_state;
661 typedef struct
663 bool sequenceExpectedCorrect;
664 uint32_t sequenceExpected;
665 uint32_t previousFrameNum;
666 uint32_t nextFrameNum;
668 uint32_t firstSN;
669 uint32_t lastSN;
670 uint32_t hfn;
672 sequence_state state;
673 } pdcp_sequence_report_in_frame;
675 /* The sequence analysis frame report hash table.
676 Maps pdcp_result_hash_key* -> pdcp_sequence_report_in_frame* */
677 static wmem_map_t *pdcp_lte_sequence_analysis_report_hash;
679 /* Gather together security settings in order to be able to do deciphering */
680 typedef struct pdu_security_settings_t
682 enum lte_security_ciphering_algorithm_e ciphering;
683 enum lte_security_integrity_algorithm_e integrity;
684 uint8_t* cipherKey;
685 uint8_t* integrityKey;
686 bool cipherKeyValid;
687 bool integrityKeyValid;
688 uint32_t count;
689 uint8_t bearer;
690 uint8_t direction;
691 } pdu_security_settings_t;
694 static uat_ue_keys_record_t* look_up_keys_record(uint16_t ueid, uint32_t frame_num,
695 uint32_t *config_frame_rrc_cipher,
696 uint32_t *config_frame_rrc_integrity,
697 uint32_t *config_frame_up_cipher)
699 unsigned int record_id;
701 /* Try hash table first (among entries added by set_pdcp_nr_xxx_key() functions) */
702 ue_key_entries_t* key_record = (ue_key_entries_t*)wmem_map_lookup(pdcp_security_key_hash,
703 GUINT_TO_POINTER((unsigned)ueid));
704 if (key_record != NULL) {
705 /* Will build up and return usual type */
706 uat_ue_keys_record_t *keys = wmem_new0(wmem_file_scope(), uat_ue_keys_record_t);
708 /* Fill in details */
709 keys->ueid = ueid;
710 /* Walk entries backwards (want last entry before frame_num) */
711 for (int e=key_record->num_entries_set; e>0; e--) {
712 key_entry_t *entry = &key_record->entries[e-1];
714 if (frame_num > entry->setup_frame) {
715 /* This frame is after corresponding setup, so can adopt if don't have one */
716 switch (entry->key_type) {
717 case rrc_cipher:
718 if (!keys->rrcCipherKeyOK) {
719 keys->rrcCipherKeyString = entry->keyString;
720 memcpy(keys->rrcCipherBinaryKey, entry->binaryKey, 16);
721 keys->rrcCipherKeyOK = entry->keyOK;
722 *config_frame_rrc_cipher = entry->setup_frame;
724 break;
725 case rrc_integrity:
726 if (!keys->rrcIntegrityKeyOK) {
727 keys->rrcIntegrityKeyString = entry->keyString;
728 memcpy(keys->rrcIntegrityBinaryKey, entry->binaryKey, 16);
729 keys->rrcIntegrityKeyOK = entry->keyOK;
730 *config_frame_rrc_integrity = entry->setup_frame;
732 break;
733 case up_cipher:
734 if (!keys->upCipherKeyOK) {
735 keys->upCipherKeyString = entry->keyString;
736 memcpy(keys->upCipherBinaryKey, entry->binaryKey, 16);
737 keys->upCipherKeyOK = entry->keyOK;
738 *config_frame_up_cipher = entry->setup_frame;
740 break;
744 /* Return this struct (even if doesn't have all/any keys set..) */
745 return keys;
749 /* Else look up UAT entries. N.B. linear search... */
750 for (record_id=0; record_id < num_ue_keys_uat; record_id++) {
751 if (uat_ue_keys_records[record_id].ueid == ueid) {
752 return &uat_ue_keys_records[record_id];
756 /* No match at all - return NULL */
757 return NULL;
760 /* Add to the tree values associated with sequence analysis for this frame */
761 static void addChannelSequenceInfo(pdcp_sequence_report_in_frame *p,
762 pdcp_lte_info *p_pdcp_lte_info,
763 uint32_t sequenceNumber,
764 packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb,
765 proto_tree *security_tree,
766 pdu_security_settings_t *pdu_security)
768 proto_tree *seqnum_tree;
769 proto_item *seqnum_ti;
770 proto_item *ti_expected_sn;
771 proto_item *ti;
772 uat_ue_keys_record_t *keys_record;
774 /* Create subtree */
775 seqnum_ti = proto_tree_add_string_format(tree,
776 hf_pdcp_lte_sequence_analysis,
777 tvb, 0, 0,
778 "", "Sequence Analysis");
779 seqnum_tree = proto_item_add_subtree(seqnum_ti,
780 ett_pdcp_lte_sequence_analysis);
781 proto_item_set_generated(seqnum_ti);
784 /* Previous channel frame */
785 if (p->previousFrameNum != 0) {
786 proto_tree_add_uint(seqnum_tree, hf_pdcp_lte_sequence_analysis_previous_frame,
787 tvb, 0, 0, p->previousFrameNum);
790 /* Expected sequence number */
791 ti_expected_sn = proto_tree_add_uint(seqnum_tree, hf_pdcp_lte_sequence_analysis_expected_sn,
792 tvb, 0, 0, p->sequenceExpected);
793 proto_item_set_generated(ti_expected_sn);
795 /* Make sure we have recognised SN length */
796 switch (p_pdcp_lte_info->seqnum_length) {
797 case PDCP_SN_LENGTH_5_BITS:
798 case PDCP_SN_LENGTH_7_BITS:
799 case PDCP_SN_LENGTH_12_BITS:
800 case PDCP_SN_LENGTH_15_BITS:
801 case PDCP_SN_LENGTH_18_BITS:
802 break;
803 default:
804 DISSECTOR_ASSERT_NOT_REACHED();
805 break;
808 switch (p->state) {
809 case SN_OK:
810 proto_item_set_hidden(ti_expected_sn);
811 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_ok,
812 tvb, 0, 0, true);
813 proto_item_set_generated(ti);
814 proto_item_append_text(seqnum_ti, " - OK");
816 /* Link to next SN in channel (if known) */
817 if (p->nextFrameNum != 0) {
818 proto_tree_add_uint(seqnum_tree, hf_pdcp_lte_sequence_analysis_next_frame,
819 tvb, 0, 0, p->nextFrameNum);
822 /* May also be able to add key inputs to security tree here */
823 if ((pdu_security->ciphering != eea0) ||
824 (pdu_security->integrity != eia0)) {
826 uint32_t hfn_multiplier;
827 uint32_t count;
828 char *cipher_key = NULL;
829 char *integrity_key = NULL;
831 /* BEARER */
832 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_bearer,
833 tvb, 0, 0, p_pdcp_lte_info->channelId-1);
834 proto_item_set_generated(ti);
836 pdu_security->bearer = p_pdcp_lte_info->channelId-1;
838 /* DIRECTION */
839 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_direction,
840 tvb, 0, 0, p_pdcp_lte_info->direction);
841 proto_item_set_generated(ti);
843 /* COUNT (HFN * snLength^2 + SN) */
844 switch (p_pdcp_lte_info->seqnum_length) {
845 case PDCP_SN_LENGTH_5_BITS:
846 hfn_multiplier = 32;
847 break;
848 case PDCP_SN_LENGTH_7_BITS:
849 hfn_multiplier = 128;
850 break;
851 case PDCP_SN_LENGTH_12_BITS:
852 hfn_multiplier = 4096;
853 break;
854 case PDCP_SN_LENGTH_15_BITS:
855 hfn_multiplier = 32768;
856 break;
857 case PDCP_SN_LENGTH_18_BITS:
858 hfn_multiplier = 262144;
859 break;
860 default:
861 DISSECTOR_ASSERT_NOT_REACHED();
862 break;
864 count = (p->hfn * hfn_multiplier) + sequenceNumber;
865 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_count,
866 tvb, 0, 0, count);
867 proto_item_set_generated(ti);
868 pdu_security->count = count;
870 /* KEY. Look this UE up among UEs that have keys configured */
871 uint32_t config_frame_rrc_cipher=0, config_frame_rrc_integrity=0,
872 config_frame_up_cipher=0;
873 keys_record = look_up_keys_record(p_pdcp_lte_info->ueid, pinfo->num,
874 &config_frame_rrc_cipher, &config_frame_rrc_integrity,
875 &config_frame_up_cipher);
876 if (keys_record != NULL) {
877 if (p_pdcp_lte_info->plane == SIGNALING_PLANE) {
878 /* Get RRC ciphering key */
879 if (keys_record->rrcCipherKeyOK) {
880 cipher_key = keys_record->rrcCipherKeyString;
881 pdu_security->cipherKey = &(keys_record->rrcCipherBinaryKey[0]);
882 pdu_security->cipherKeyValid = true;
884 /* Get RRC integrity key */
885 if (keys_record->rrcIntegrityKeyOK) {
886 integrity_key = keys_record->rrcIntegrityKeyString;
887 pdu_security->integrityKey = &(keys_record->rrcIntegrityBinaryKey[0]);
888 pdu_security->integrityKeyValid = true;
891 else {
892 /* Get userplane ciphering key */
893 if (keys_record->upCipherKeyOK) {
894 cipher_key = keys_record->upCipherKeyString;
895 pdu_security->cipherKey = &(keys_record->upCipherBinaryKey[0]);
896 pdu_security->cipherKeyValid = true;
900 /* Show keys where known and valid */
901 if (cipher_key != NULL) {
902 ti = proto_tree_add_string(security_tree, hf_pdcp_lte_security_cipher_key,
903 tvb, 0, 0, cipher_key);
904 proto_item_set_generated(ti);
906 if (integrity_key != NULL) {
907 ti = proto_tree_add_string(security_tree, hf_pdcp_lte_security_integrity_key,
908 tvb, 0, 0, integrity_key);
909 proto_item_set_generated(ti);
912 pdu_security->direction = p_pdcp_lte_info->direction;
915 break;
917 case SN_Missing:
918 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_ok,
919 tvb, 0, 0, false);
920 proto_item_set_generated(ti);
921 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_skipped,
922 tvb, 0, 0, true);
923 proto_item_set_generated(ti);
924 if (p->lastSN != p->firstSN) {
925 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_sequence_analysis_sn_missing,
926 "PDCP SNs (%u to %u) missing for %s on UE %u (%s-%u)",
927 p->firstSN, p->lastSN,
928 val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
929 p_pdcp_lte_info->ueid,
930 val_to_str_const(p_pdcp_lte_info->channelType, logical_channel_vals, "Unknown"),
931 p_pdcp_lte_info->channelId);
932 proto_item_append_text(seqnum_ti, " - SNs missing (%u to %u)",
933 p->firstSN, p->lastSN);
935 else {
936 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_sequence_analysis_sn_missing,
937 "PDCP SN (%u) missing for %s on UE %u (%s-%u)",
938 p->firstSN,
939 val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
940 p_pdcp_lte_info->ueid,
941 val_to_str_const(p_pdcp_lte_info->channelType, logical_channel_vals, "Unknown"),
942 p_pdcp_lte_info->channelId);
943 proto_item_append_text(seqnum_ti, " - SN missing (%u)",
944 p->firstSN);
946 break;
948 case SN_Repeated:
949 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_ok,
950 tvb, 0, 0, false);
951 proto_item_set_generated(ti);
952 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_repeated,
953 tvb, 0, 0, true);
954 proto_item_set_generated(ti);
955 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_sequence_analysis_sn_repeated,
956 "PDCP SN (%u) repeated for %s for UE %u (%s-%u)",
957 p->firstSN,
958 val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
959 p_pdcp_lte_info->ueid,
960 val_to_str_const(p_pdcp_lte_info->channelType, logical_channel_vals, "Unknown"),
961 p_pdcp_lte_info->channelId);
962 proto_item_append_text(seqnum_ti, "- SN %u Repeated",
963 p->firstSN);
964 break;
966 default:
967 /* Incorrect sequence number */
968 expert_add_info_format(pinfo, ti_expected_sn, &ei_pdcp_lte_sequence_analysis_wrong_sequence_number,
969 "Wrong Sequence Number for %s on UE %u (%s-%u) - got %u, expected %u",
970 val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
971 p_pdcp_lte_info->ueid,
972 val_to_str_const(p_pdcp_lte_info->channelType, logical_channel_vals, "Unknown"),
973 p_pdcp_lte_info->channelId,
974 sequenceNumber, p->sequenceExpected);
975 break;
980 /* Update the channel status and set report for this frame */
981 static void checkChannelSequenceInfo(packet_info *pinfo, tvbuff_t *tvb,
982 pdcp_lte_info *p_pdcp_lte_info,
983 uint32_t sequenceNumber,
984 proto_tree *tree,
985 proto_tree *security_tree,
986 pdu_security_settings_t *pdu_security)
988 pdcp_channel_hash_key channel_key;
989 pdcp_channel_status *p_channel_status;
990 pdcp_sequence_report_in_frame *p_report_in_frame = NULL;
991 bool createdChannel = false;
992 uint32_t expectedSequenceNumber = 0;
993 uint32_t snLimit = 0;
995 /* If find stat_report_in_frame already, use that and get out */
996 if (PINFO_FD_VISITED(pinfo)) {
997 p_report_in_frame =
998 (pdcp_sequence_report_in_frame*)wmem_map_lookup(pdcp_lte_sequence_analysis_report_hash,
999 get_report_hash_key(sequenceNumber,
1000 pinfo->num,
1001 p_pdcp_lte_info, false));
1002 if (p_report_in_frame != NULL) {
1003 addChannelSequenceInfo(p_report_in_frame, p_pdcp_lte_info,
1004 sequenceNumber,
1005 pinfo, tree, tvb, security_tree, pdu_security);
1006 return;
1008 else {
1009 /* Give up - we must have tried already... */
1010 return;
1015 /**************************************************/
1016 /* Create or find an entry for this channel state */
1017 channel_key.ueId = p_pdcp_lte_info->ueid;
1018 channel_key.plane = p_pdcp_lte_info->plane;
1019 channel_key.channelId = p_pdcp_lte_info->channelId;
1020 channel_key.direction = p_pdcp_lte_info->direction;
1021 channel_key.notUsed = 0;
1023 /* Do the table lookup */
1024 p_channel_status = (pdcp_channel_status*)wmem_map_lookup(pdcp_sequence_analysis_channel_hash,
1025 get_channel_hash_key(&channel_key));
1027 /* Create table entry if necessary */
1028 if (p_channel_status == NULL) {
1029 createdChannel = true;
1031 /* Allocate a new value and duplicate key contents */
1032 p_channel_status = wmem_new0(wmem_file_scope(), pdcp_channel_status);
1034 /* Add entry */
1035 wmem_map_insert(pdcp_sequence_analysis_channel_hash,
1036 get_channel_hash_key(&channel_key), p_channel_status);
1039 /* Create space for frame state_report */
1040 p_report_in_frame = wmem_new(wmem_file_scope(), pdcp_sequence_report_in_frame);
1041 p_report_in_frame->nextFrameNum = 0;
1043 switch (p_pdcp_lte_info->seqnum_length) {
1044 case PDCP_SN_LENGTH_5_BITS:
1045 snLimit = 32;
1046 break;
1047 case PDCP_SN_LENGTH_7_BITS:
1048 snLimit = 128;
1049 break;
1050 case PDCP_SN_LENGTH_12_BITS:
1051 snLimit = 4096;
1052 break;
1053 case PDCP_SN_LENGTH_15_BITS:
1054 snLimit = 32768;
1055 break;
1056 case PDCP_SN_LENGTH_18_BITS:
1057 snLimit = 262144;
1058 break;
1059 default:
1060 DISSECTOR_ASSERT_NOT_REACHED();
1061 break;
1064 /* Work out expected sequence number */
1065 if (!createdChannel) {
1066 expectedSequenceNumber = (p_channel_status->previousSequenceNumber + 1) % snLimit;
1068 else {
1069 expectedSequenceNumber = sequenceNumber;
1072 /* Set report for this frame */
1073 /* For PDCP, sequence number is always expectedSequence number */
1074 p_report_in_frame->sequenceExpectedCorrect = (sequenceNumber == expectedSequenceNumber);
1075 p_report_in_frame->hfn = p_channel_status->hfn;
1077 /* For wrong sequence number... */
1078 if (!p_report_in_frame->sequenceExpectedCorrect) {
1080 /* Frames are not missing if we get an earlier sequence number again */
1081 if (((snLimit + expectedSequenceNumber - sequenceNumber) % snLimit) > 15) {
1082 p_report_in_frame->state = SN_Missing;
1083 p_report_in_frame->firstSN = expectedSequenceNumber;
1084 p_report_in_frame->lastSN = (snLimit + sequenceNumber - 1) % snLimit;
1086 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
1087 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
1089 /* Update channel status to remember *this* frame */
1090 p_channel_status->previousFrameNum = pinfo->num;
1091 p_channel_status->previousSequenceNumber = sequenceNumber;
1093 else {
1094 /* An SN has been repeated */
1095 p_report_in_frame->state = SN_Repeated;
1096 p_report_in_frame->firstSN = sequenceNumber;
1098 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
1099 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
1102 else {
1103 /* SN was OK */
1104 p_report_in_frame->state = SN_OK;
1105 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
1106 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
1107 /* SN has rolled around, inc hfn! */
1108 if (!createdChannel && (sequenceNumber == 0)) {
1109 /* TODO: not worrying about HFN rolling over for now! */
1110 p_channel_status->hfn++;
1111 p_report_in_frame->hfn = p_channel_status->hfn;
1114 /* Update channel status to remember *this* frame */
1115 p_channel_status->previousFrameNum = pinfo->num;
1116 p_channel_status->previousSequenceNumber = sequenceNumber;
1118 if (p_report_in_frame->previousFrameNum != 0) {
1119 /* Get report for previous frame */
1120 pdcp_sequence_report_in_frame *p_previous_report;
1121 p_previous_report = (pdcp_sequence_report_in_frame*)wmem_map_lookup(pdcp_lte_sequence_analysis_report_hash,
1122 get_report_hash_key((sequenceNumber+262144) % 262144,
1123 p_report_in_frame->previousFrameNum,
1124 p_pdcp_lte_info,
1125 false));
1126 /* It really shouldn't be NULL... */
1127 if (p_previous_report != NULL) {
1128 /* Point it forward to this one */
1129 p_previous_report->nextFrameNum = pinfo->num;
1134 /* Associate with this frame number */
1135 wmem_map_insert(pdcp_lte_sequence_analysis_report_hash,
1136 get_report_hash_key(sequenceNumber, pinfo->num,
1137 p_pdcp_lte_info, true),
1138 p_report_in_frame);
1140 /* Add state report for this frame into tree */
1141 addChannelSequenceInfo(p_report_in_frame, p_pdcp_lte_info, sequenceNumber,
1142 pinfo, tree, tvb, security_tree, pdu_security);
1147 /* Hash table for security state for a UE
1148 Maps UEId -> pdcp_security_info_t* */
1149 static wmem_map_t *pdcp_security_hash;
1151 /* Result is (ueid, framenum) -> pdcp_security_info_t* */
1152 typedef struct ueid_frame_t {
1153 uint32_t framenum;
1154 uint16_t ueid;
1155 } ueid_frame_t;
1157 /* Convenience function to get a pointer for the hash_func to work with */
1158 static void *get_ueid_frame_hash_key(uint16_t ueid, uint32_t frameNumber,
1159 bool do_persist)
1161 static ueid_frame_t key;
1162 ueid_frame_t *p_key;
1164 /* Only allocate a struct when will be adding entry */
1165 if (do_persist) {
1166 p_key = wmem_new(wmem_file_scope(), ueid_frame_t);
1168 else {
1169 /* Only looking up, so just use static */
1170 memset(&key, 0, sizeof(ueid_frame_t));
1171 p_key = &key;
1174 /* Fill in details, and return pointer */
1175 p_key->framenum = frameNumber;
1176 p_key->ueid = ueid;
1178 return p_key;
1181 static int pdcp_lte_ueid_frame_hash_equal(const void *v, const void *v2)
1183 const ueid_frame_t *ueid_frame_1 = (const ueid_frame_t *)v;
1184 const ueid_frame_t *ueid_frame_2 = (const ueid_frame_t *)v2;
1185 return ((ueid_frame_1->framenum == ueid_frame_2->framenum) &&
1186 (ueid_frame_1->ueid == ueid_frame_2->ueid));
1188 static unsigned pdcp_lte_ueid_frame_hash_func(const void *v)
1190 const ueid_frame_t *ueid_frame = (const ueid_frame_t *)v;
1191 return ueid_frame->framenum + 100*ueid_frame->ueid;
1193 static wmem_map_t *pdcp_security_result_hash;
1198 /* Write the given formatted text to:
1199 - the info column
1200 - the top-level RLC PDU item */
1201 static void write_pdu_label_and_info(proto_item *pdu_ti,
1202 packet_info *pinfo, const char *format, ...) G_GNUC_PRINTF(3, 4);
1203 static void write_pdu_label_and_info(proto_item *pdu_ti,
1204 packet_info *pinfo, const char *format, ...)
1206 #define MAX_INFO_BUFFER 256
1207 static char info_buffer[MAX_INFO_BUFFER];
1209 va_list ap;
1211 va_start(ap, format);
1212 vsnprintf(info_buffer, MAX_INFO_BUFFER, format, ap);
1213 va_end(ap);
1215 /* Add to indicated places */
1216 col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
1217 /* TODO: gets called a lot, so a shame there isn't a proto_item_append_string() */
1218 proto_item_append_text(pdu_ti, "%s", info_buffer);
1223 /***************************************************************/
1227 /* Show in the tree the config info attached to this frame, as generated fields */
1228 static void show_pdcp_config(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree,
1229 pdcp_lte_info *p_pdcp_info)
1231 proto_item *ti;
1232 proto_tree *configuration_tree;
1233 proto_item *configuration_ti = proto_tree_add_item(tree,
1234 hf_pdcp_lte_configuration,
1235 tvb, 0, 0, ENC_ASCII);
1236 configuration_tree = proto_item_add_subtree(configuration_ti, ett_pdcp_configuration);
1238 /* Direction */
1239 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_direction, tvb, 0, 0,
1240 p_pdcp_info->direction);
1241 proto_item_set_generated(ti);
1243 /* Plane */
1244 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_plane, tvb, 0, 0,
1245 p_pdcp_info->plane);
1246 proto_item_set_generated(ti);
1248 /* UEId */
1249 if (p_pdcp_info->ueid != 0) {
1250 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_ueid, tvb, 0, 0,
1251 p_pdcp_info->ueid);
1252 proto_item_set_generated(ti);
1255 /* Channel type */
1256 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_channel_type, tvb, 0, 0,
1257 p_pdcp_info->channelType);
1258 proto_item_set_generated(ti);
1259 if (p_pdcp_info->channelId != 0) {
1260 /* Channel type */
1261 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_channel_id, tvb, 0, 0,
1262 p_pdcp_info->channelId);
1263 proto_item_set_generated(ti);
1267 /* User-plane-specific fields */
1268 if (p_pdcp_info->plane == USER_PLANE) {
1270 /* No Header PDU */
1271 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_no_header_pdu, tvb, 0, 0,
1272 p_pdcp_info->no_header_pdu);
1273 proto_item_set_generated(ti);
1275 if (!p_pdcp_info->no_header_pdu) {
1277 /* Seqnum length */
1278 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_seqnum_length, tvb, 0, 0,
1279 p_pdcp_info->seqnum_length);
1280 proto_item_set_generated(ti);
1284 /* ROHC compression */
1285 ti = proto_tree_add_boolean(configuration_tree, hf_pdcp_lte_rohc_compression, tvb, 0, 0,
1286 p_pdcp_info->rohc.rohc_compression);
1287 proto_item_set_generated(ti);
1289 /* ROHC-specific settings */
1290 if (p_pdcp_info->rohc.rohc_compression) {
1292 /* Show ROHC mode */
1293 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_mode, tvb, 0, 0,
1294 p_pdcp_info->rohc.mode);
1295 proto_item_set_generated(ti);
1297 /* Show RND */
1298 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_rnd, tvb, 0, 0,
1299 p_pdcp_info->rohc.rnd);
1300 proto_item_set_generated(ti);
1302 /* UDP Checksum */
1303 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_udp_checksum_present, tvb, 0, 0,
1304 p_pdcp_info->rohc.udp_checksum_present);
1305 proto_item_set_generated(ti);
1307 /* ROHC profile */
1308 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_profile, tvb, 0, 0,
1309 p_pdcp_info->rohc.profile);
1310 proto_item_set_generated(ti);
1312 /* CID Inclusion Info */
1313 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_cid_inclusion_info, tvb, 0, 0,
1314 p_pdcp_info->rohc.cid_inclusion_info);
1315 proto_item_set_generated(ti);
1317 /* Large CID */
1318 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_large_cid_present, tvb, 0, 0,
1319 p_pdcp_info->rohc.large_cid_present);
1320 proto_item_set_generated(ti);
1323 /* Append summary to configuration root */
1324 proto_item_append_text(configuration_ti, "(direction=%s, plane=%s",
1325 val_to_str_const(p_pdcp_info->direction, direction_vals, "Unknown"),
1326 val_to_str_const(p_pdcp_info->plane, pdcp_plane_vals, "Unknown"));
1328 if (p_pdcp_info->rohc.rohc_compression) {
1329 const char *mode = val_to_str_const(p_pdcp_info->rohc.mode, rohc_mode_vals, "Error");
1330 proto_item_append_text(configuration_ti, ", mode=%c, profile=%s",
1331 mode[0],
1332 val_to_str_const(p_pdcp_info->rohc.profile, rohc_profile_vals, "Unknown"));
1334 proto_item_append_text(configuration_ti, ")");
1335 proto_item_set_generated(configuration_ti);
1337 /* Show plane in info column */
1338 col_append_fstr(pinfo->cinfo, COL_INFO, " %s: ",
1339 val_to_str_const(p_pdcp_info->plane, pdcp_plane_vals, "Unknown"));
1344 /* Look for an RRC dissector for signalling data (using channel type and direction) */
1345 static dissector_handle_t lookup_rrc_dissector_handle(struct pdcp_lte_info *p_pdcp_info)
1347 dissector_handle_t rrc_handle = 0;
1349 switch (p_pdcp_info->channelType)
1351 case Channel_CCCH:
1352 if (p_pdcp_info->direction == DIRECTION_UPLINK) {
1353 rrc_handle = lte_rrc_ul_ccch;
1355 else {
1356 rrc_handle = lte_rrc_dl_ccch;
1358 break;
1359 case Channel_PCCH:
1360 rrc_handle = lte_rrc_pcch;
1361 break;
1362 case Channel_BCCH:
1363 switch (p_pdcp_info->BCCHTransport) {
1364 case BCH_TRANSPORT:
1365 rrc_handle = lte_rrc_bcch_bch;
1366 break;
1367 case DLSCH_TRANSPORT:
1368 rrc_handle = lte_rrc_bcch_dl_sch;
1369 break;
1371 break;
1372 case Channel_DCCH:
1373 if (p_pdcp_info->direction == DIRECTION_UPLINK) {
1374 rrc_handle = lte_rrc_ul_dcch;
1376 else {
1377 rrc_handle = lte_rrc_dl_dcch;
1379 break;
1380 case Channel_CCCH_NB:
1381 if (p_pdcp_info->direction == DIRECTION_UPLINK) {
1382 rrc_handle = lte_rrc_ul_ccch_nb;
1384 else {
1385 rrc_handle = lte_rrc_dl_ccch_nb;
1387 break;
1388 case Channel_PCCH_NB:
1389 rrc_handle = lte_rrc_pcch_nb;
1390 break;
1391 case Channel_BCCH_NB:
1392 switch (p_pdcp_info->BCCHTransport) {
1393 case BCH_TRANSPORT:
1394 rrc_handle = lte_rrc_bcch_bch_nb;
1395 break;
1396 case DLSCH_TRANSPORT:
1397 rrc_handle = lte_rrc_bcch_dl_sch_nb;
1398 break;
1400 break;
1401 case Channel_DCCH_NB:
1402 if (p_pdcp_info->direction == DIRECTION_UPLINK) {
1403 rrc_handle = lte_rrc_ul_dcch_nb;
1405 else {
1406 rrc_handle = lte_rrc_dl_dcch_nb;
1408 break;
1411 default:
1412 break;
1415 return rrc_handle;
1419 /* Forward declarations */
1420 static int dissect_pdcp_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data);
1422 static void report_heur_error(proto_tree *tree, packet_info *pinfo, expert_field *eiindex,
1423 tvbuff_t *tvb, int start, int length)
1425 proto_item *ti;
1426 proto_tree *subtree;
1428 col_set_str(pinfo->cinfo, COL_PROTOCOL, "PDCP-LTE");
1429 col_clear(pinfo->cinfo, COL_INFO);
1430 ti = proto_tree_add_item(tree, proto_pdcp_lte, tvb, 0, -1, ENC_NA);
1431 subtree = proto_item_add_subtree(ti, ett_pdcp);
1432 proto_tree_add_expert(subtree, pinfo, eiindex, tvb, start, length);
1435 /* Heuristic dissector looks for supported framing protocol (see wiki page) */
1436 static bool dissect_pdcp_lte_heur(tvbuff_t *tvb, packet_info *pinfo,
1437 proto_tree *tree, void *data _U_)
1439 int offset = 0;
1440 struct pdcp_lte_info *p_pdcp_lte_info;
1441 tvbuff_t *pdcp_tvb;
1442 uint8_t tag = 0;
1443 bool seqnumLengthTagPresent = false;
1445 /* Needs to be at least as long as:
1446 - the signature string
1447 - fixed header bytes
1448 - tag for data
1449 - at least one byte of PDCP PDU payload */
1450 if (tvb_captured_length_remaining(tvb, offset) < (int)(strlen(PDCP_LTE_START_STRING)+3+2)) {
1451 return false;
1454 /* OK, compare with signature string */
1455 if (tvb_strneql(tvb, offset, PDCP_LTE_START_STRING, strlen(PDCP_LTE_START_STRING)) != 0) {
1456 return false;
1458 offset += (int)strlen(PDCP_LTE_START_STRING);
1461 /* If redissecting, use previous info struct (if available) */
1462 p_pdcp_lte_info = (pdcp_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0);
1463 if (p_pdcp_lte_info == NULL) {
1464 /* Allocate new info struct for this frame */
1465 p_pdcp_lte_info = wmem_new0(wmem_file_scope(), pdcp_lte_info);
1467 /* Read fixed fields */
1468 p_pdcp_lte_info->no_header_pdu = (bool)tvb_get_uint8(tvb, offset++);
1469 p_pdcp_lte_info->plane = (enum pdcp_plane)tvb_get_uint8(tvb, offset++);
1470 if (p_pdcp_lte_info->plane == SIGNALING_PLANE) {
1471 p_pdcp_lte_info->seqnum_length = PDCP_SN_LENGTH_5_BITS;
1473 p_pdcp_lte_info->rohc.rohc_compression = (bool)tvb_get_uint8(tvb, offset++);
1475 /* Read optional fields */
1476 while (tag != PDCP_LTE_PAYLOAD_TAG) {
1477 /* Process next tag */
1478 tag = tvb_get_uint8(tvb, offset++);
1479 switch (tag) {
1480 case PDCP_LTE_SEQNUM_LENGTH_TAG:
1481 p_pdcp_lte_info->seqnum_length = tvb_get_uint8(tvb, offset);
1482 offset++;
1483 seqnumLengthTagPresent = true;
1484 break;
1485 case PDCP_LTE_DIRECTION_TAG:
1486 p_pdcp_lte_info->direction = tvb_get_uint8(tvb, offset);
1487 offset++;
1488 break;
1489 case PDCP_LTE_LOG_CHAN_TYPE_TAG:
1490 p_pdcp_lte_info->channelType = (LogicalChannelType)tvb_get_uint8(tvb, offset);
1491 offset++;
1492 break;
1493 case PDCP_LTE_BCCH_TRANSPORT_TYPE_TAG:
1494 p_pdcp_lte_info->BCCHTransport = (BCCHTransportType)tvb_get_uint8(tvb, offset);
1495 offset++;
1496 break;
1497 case PDCP_LTE_ROHC_IP_VERSION_TAG:
1498 /* RoHC IP version field is now 1 byte only; let's skip most significant byte
1499 to keep backward compatibility with existing UDP framing protocol */
1500 p_pdcp_lte_info->rohc.rohc_ip_version = tvb_get_uint8(tvb, offset+1);
1501 offset += 2;
1502 break;
1503 case PDCP_LTE_ROHC_CID_INC_INFO_TAG:
1504 p_pdcp_lte_info->rohc.cid_inclusion_info = tvb_get_uint8(tvb, offset);
1505 offset++;
1506 break;
1507 case PDCP_LTE_ROHC_LARGE_CID_PRES_TAG:
1508 p_pdcp_lte_info->rohc.large_cid_present = tvb_get_uint8(tvb, offset);
1509 offset++;
1510 break;
1511 case PDCP_LTE_ROHC_MODE_TAG:
1512 p_pdcp_lte_info->rohc.mode = (enum rohc_mode)tvb_get_uint8(tvb, offset);
1513 offset++;
1514 break;
1515 case PDCP_LTE_ROHC_RND_TAG:
1516 p_pdcp_lte_info->rohc.rnd = tvb_get_uint8(tvb, offset);
1517 offset++;
1518 break;
1519 case PDCP_LTE_ROHC_UDP_CHECKSUM_PRES_TAG:
1520 p_pdcp_lte_info->rohc.udp_checksum_present = tvb_get_uint8(tvb, offset);
1521 offset++;
1522 break;
1523 case PDCP_LTE_ROHC_PROFILE_TAG:
1524 p_pdcp_lte_info->rohc.profile = tvb_get_ntohs(tvb, offset);
1525 offset += 2;
1526 break;
1527 case PDCP_LTE_CHANNEL_ID_TAG:
1528 p_pdcp_lte_info->channelId = tvb_get_ntohs(tvb, offset);
1529 offset += 2;
1530 break;
1531 case PDCP_LTE_UEID_TAG:
1532 p_pdcp_lte_info->ueid = tvb_get_ntohs(tvb, offset);
1533 offset += 2;
1534 break;
1536 case PDCP_LTE_PAYLOAD_TAG:
1537 /* Have reached data, so get out of loop */
1538 p_pdcp_lte_info->pdu_length = tvb_reported_length_remaining(tvb, offset);
1539 continue;
1541 default:
1542 /* It must be a recognised tag */
1543 report_heur_error(tree, pinfo, &ei_pdcp_lte_unknown_udp_framing_tag, tvb, offset-1, 1);
1544 wmem_free(wmem_file_scope(), p_pdcp_lte_info);
1545 return true;
1549 if ((p_pdcp_lte_info->plane == USER_PLANE) && (seqnumLengthTagPresent == false)) {
1550 /* Conditional field is not present */
1551 report_heur_error(tree, pinfo, &ei_pdcp_lte_missing_udp_framing_tag, tvb, 0, offset);
1552 wmem_free(wmem_file_scope(), p_pdcp_lte_info);
1553 return true;
1556 /* Store info in packet */
1557 p_add_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0, p_pdcp_lte_info);
1559 else {
1560 offset = tvb_reported_length(tvb) - p_pdcp_lte_info->pdu_length;
1564 /**************************************/
1565 /* OK, now dissect as PDCP LTE */
1567 /* Create tvb that starts at actual PDCP PDU */
1568 pdcp_tvb = tvb_new_subset_remaining(tvb, offset);
1569 dissect_pdcp_lte(pdcp_tvb, pinfo, tree, data);
1570 return true;
1573 /* Called from control protocol to configure security algorithms for the given UE */
1574 void set_pdcp_lte_security_algorithms(uint16_t ueid, pdcp_lte_security_info_t *security_info)
1576 /* Use for this frame so can check integrity on SecurityCommandRequest frame */
1577 /* N.B. won't work for internal, non-RRC signalling methods... */
1578 pdcp_lte_security_info_t *p_frame_security;
1580 /* Disable this entire sub-routine with the Preference */
1581 /* Used when the capture is already deciphered */
1582 if (global_pdcp_ignore_sec) {
1583 return;
1586 /* Create or update current settings, by UEID */
1587 pdcp_lte_security_info_t* ue_security =
1588 (pdcp_lte_security_info_t*)wmem_map_lookup(pdcp_security_hash,
1589 GUINT_TO_POINTER((unsigned)ueid));
1590 if (ue_security == NULL) {
1591 /* Copy whole security struct */
1592 ue_security = wmem_new(wmem_file_scope(), pdcp_lte_security_info_t);
1593 *ue_security = *security_info;
1595 /* And add into security table */
1596 wmem_map_insert(pdcp_security_hash, GUINT_TO_POINTER((unsigned)ueid), ue_security);
1598 else {
1599 /* Just update existing entry already in table */
1600 ue_security->previous_configuration_frame = ue_security->configuration_frame;
1601 ue_security->previous_integrity = ue_security->integrity;
1602 ue_security->previous_ciphering = ue_security->ciphering;
1604 ue_security->configuration_frame = security_info->configuration_frame;
1605 ue_security->integrity = security_info->integrity;
1606 ue_security->ciphering = security_info->ciphering;
1607 ue_security->seen_next_ul_pdu = false;
1610 /* Also add an entry for this PDU already to use these settings, as otherwise it won't be present
1611 when we query it on the first pass. */
1612 p_frame_security = wmem_new(wmem_file_scope(), pdcp_lte_security_info_t);
1613 *p_frame_security = *ue_security;
1614 wmem_map_insert(pdcp_security_result_hash,
1615 get_ueid_frame_hash_key(ueid, ue_security->configuration_frame, true),
1616 p_frame_security);
1619 /* UE failed to process SecurityModeCommand so go back to previous security settings */
1620 void set_pdcp_lte_security_algorithms_failed(uint16_t ueid)
1622 /* Look up current state by UEID */
1623 pdcp_lte_security_info_t* ue_security =
1624 (pdcp_lte_security_info_t*)wmem_map_lookup(pdcp_security_hash,
1625 GUINT_TO_POINTER((unsigned)ueid));
1626 if (ue_security != NULL) {
1627 /* TODO: could remove from table if previous_configuration_frame is 0 */
1628 /* Go back to previous state */
1629 ue_security->configuration_frame = ue_security->previous_configuration_frame;
1630 ue_security->integrity = ue_security->previous_integrity;
1631 ue_security->ciphering = ue_security->previous_ciphering;
1635 /* Reset UE's bearers */
1636 void pdcp_lte_reset_ue_bearers(packet_info *pinfo, uint16_t ueid, bool including_drb_am)
1638 if (PINFO_FD_VISITED(pinfo)) {
1639 return;
1642 pdcp_channel_hash_key channel_key;
1643 pdcp_channel_status *p_channel_status;
1645 channel_key.notUsed = 0;
1646 channel_key.ueId = ueid;
1647 channel_key.plane = SIGNALING_PLANE;
1649 /* SRBs (1-2, both directions) */
1650 for (uint32_t channelId=1; channelId <= 2; ++channelId) {
1651 for (uint32_t direction=0; direction <=1; ++direction) {
1652 /* Update key */
1653 channel_key.channelId = channelId;
1654 channel_key.direction = direction;
1656 p_channel_status = (pdcp_channel_status*)wmem_map_lookup(pdcp_sequence_analysis_channel_hash,
1657 get_channel_hash_key(&channel_key));
1658 if (p_channel_status) {
1659 p_channel_status->hfn = 0;
1660 p_channel_status->previousFrameNum = 0;
1661 p_channel_status->previousSequenceNumber = -1;
1666 /* DRBs (1-32, both directions) */
1667 channel_key.plane = USER_PLANE;
1668 for (uint32_t channelId=1; channelId <= 32; ++channelId) {
1669 for (uint32_t direction=0; direction <=1; ++direction) {
1670 /* Update key */
1671 channel_key.channelId = channelId;
1672 channel_key.direction = direction;
1674 p_channel_status = (pdcp_channel_status*)wmem_map_lookup(pdcp_sequence_analysis_channel_hash,
1675 get_channel_hash_key(&channel_key));
1676 if (p_channel_status) {
1677 if (including_drb_am || get_mac_lte_channel_mode(ueid, channelId) == RLC_UM_MODE) {
1678 p_channel_status->hfn = 0;
1679 p_channel_status->previousFrameNum = 0;
1680 p_channel_status->previousSequenceNumber = -1;
1688 /* Decipher payload if algorithm is supported and plausible inputs are available */
1689 static tvbuff_t *decipher_payload(tvbuff_t *tvb, packet_info *pinfo, int *offset,
1690 pdu_security_settings_t *pdu_security_settings,
1691 struct pdcp_lte_info *p_pdcp_info, bool will_be_deciphered,
1692 bool *deciphered)
1694 uint8_t* decrypted_data = NULL;
1695 int payload_length = 0;
1696 tvbuff_t *decrypted_tvb;
1698 /* Nothing to do if NULL ciphering */
1699 if (pdu_security_settings->ciphering == eea0) {
1700 return tvb;
1703 /* Nothing to do if don't have valid cipher key */
1704 if (!pdu_security_settings->cipherKeyValid) {
1705 return tvb;
1708 /* Check whether algorithm supported (only drop through and process if we do) */
1709 if (pdu_security_settings->ciphering == eea1) {
1710 #ifndef HAVE_SNOW3G
1711 return tvb;
1712 #endif
1714 else if (pdu_security_settings->ciphering == eea3) {
1715 #ifndef HAVE_ZUC
1716 return tvb;
1717 #endif
1719 else if (pdu_security_settings->ciphering != eea2) {
1720 /* An algorithm we don't support at all! */
1721 return tvb;
1724 /* Don't decipher if turned off in preferences */
1725 if (((p_pdcp_info->plane == SIGNALING_PLANE) && !global_pdcp_decipher_signalling) ||
1726 ((p_pdcp_info->plane == USER_PLANE) && !global_pdcp_decipher_userplane)) {
1727 return tvb;
1730 /* Don't decipher user-plane control messages */
1731 if ((p_pdcp_info->plane == USER_PLANE) && ((tvb_get_uint8(tvb, 0) & 0x80) == 0x00)) {
1732 return tvb;
1735 /* Don't decipher common control messages */
1736 if ((p_pdcp_info->plane == SIGNALING_PLANE) && (p_pdcp_info->channelType != Channel_DCCH)) {
1737 return tvb;
1740 /* Don't decipher if not yet past SecurityModeResponse */
1741 if (!will_be_deciphered) {
1742 return tvb;
1745 /* AES */
1746 if (pdu_security_settings->ciphering == eea2) {
1747 unsigned char ctr_block[16];
1748 gcry_cipher_hd_t cypher_hd;
1749 int gcrypt_err;
1751 /* TS 33.401 B.1.3 */
1753 /* Set CTR */
1754 memset(ctr_block, 0, 16);
1755 /* Only first 5 bytes set */
1756 ctr_block[0] = (pdu_security_settings->count & 0xff000000) >> 24;
1757 ctr_block[1] = (pdu_security_settings->count & 0x00ff0000) >> 16;
1758 ctr_block[2] = (pdu_security_settings->count & 0x0000ff00) >> 8;
1759 ctr_block[3] = (pdu_security_settings->count & 0x000000ff);
1760 ctr_block[4] = (pdu_security_settings->bearer << 3) + (pdu_security_settings->direction << 2);
1762 /* Open gcrypt handle */
1763 gcrypt_err = gcry_cipher_open(&cypher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0);
1764 if (gcrypt_err != 0) {
1765 return tvb;
1768 /* Set the key */
1769 gcrypt_err = gcry_cipher_setkey(cypher_hd, pdu_security_settings->cipherKey, 16);
1770 if (gcrypt_err != 0) {
1771 gcry_cipher_close(cypher_hd);
1772 return tvb;
1775 /* Set the CTR */
1776 gcrypt_err = gcry_cipher_setctr(cypher_hd, ctr_block, 16);
1777 if (gcrypt_err != 0) {
1778 gcry_cipher_close(cypher_hd);
1779 return tvb;
1782 /* Extract the encrypted data into a buffer */
1783 payload_length = tvb_captured_length_remaining(tvb, *offset);
1784 decrypted_data = (uint8_t *)tvb_memdup(pinfo->pool, tvb, *offset, payload_length);
1786 /* Decrypt the actual data */
1787 gcrypt_err = gcry_cipher_decrypt(cypher_hd,
1788 decrypted_data, payload_length,
1789 NULL, 0);
1790 if (gcrypt_err != 0) {
1791 gcry_cipher_close(cypher_hd);
1792 return tvb;
1795 /* Close gcrypt handle */
1796 gcry_cipher_close(cypher_hd);
1799 #ifdef HAVE_SNOW3G
1800 /* SNOW-3G */
1801 if (pdu_security_settings->ciphering == eea1) {
1802 /* Extract the encrypted data into a buffer */
1803 payload_length = tvb_captured_length_remaining(tvb, *offset);
1804 decrypted_data = (uint8_t *)tvb_memdup(pinfo->pool, tvb, *offset, payload_length);
1806 /* Do the algorithm */
1807 snow3g_f8(pdu_security_settings->cipherKey,
1808 pdu_security_settings->count,
1809 pdu_security_settings->bearer,
1810 pdu_security_settings->direction,
1811 decrypted_data, payload_length*8);
1813 #endif
1815 #ifdef HAVE_ZUC
1816 /* ZUC */
1817 if (pdu_security_settings->ciphering == eea3) {
1818 /* Extract the encrypted data into a buffer */
1819 payload_length = tvb_captured_length_remaining(tvb, *offset);
1820 decrypted_data = (uint8_t *)tvb_memdup(pinfo->pool, tvb, *offset, payload_length);
1822 /* Do the algorithm. Assuming implementation works in-place */
1823 zuc_f8(pdu_security_settings->cipherKey,
1824 pdu_security_settings->count,
1825 pdu_security_settings->bearer,
1826 pdu_security_settings->direction,
1827 payload_length*8, /* Length is in bits */
1828 (uint32_t*)decrypted_data, (uint32_t*)decrypted_data);
1830 #endif
1832 /* Create tvb for resulting deciphered sdu */
1833 decrypted_tvb = tvb_new_child_real_data(tvb, decrypted_data, payload_length, payload_length);
1834 add_new_data_source(pinfo, decrypted_tvb, "Deciphered Payload");
1836 /* Return deciphered data, i.e. beginning of new tvb */
1837 *offset = 0;
1838 *deciphered = true;
1839 return decrypted_tvb;
1843 /* Try to calculate digest to compare with that found in frame. */
1844 static uint32_t calculate_digest(pdu_security_settings_t *pdu_security_settings, uint8_t header,
1845 tvbuff_t *tvb, packet_info *pinfo, int offset, bool *calculated)
1847 *calculated = false;
1849 if (pdu_security_settings->integrity == eia0) {
1850 /* Should be zero in this case */
1851 *calculated = true;
1852 return 0;
1855 /* Can't calculate if don't have valid integrity key */
1856 if (!pdu_security_settings->integrityKeyValid) {
1857 return 0;
1860 /* Can only do if indicated in preferences */
1861 if (!global_pdcp_check_integrity) {
1862 return 0;
1865 switch (pdu_security_settings->integrity) {
1867 #ifdef HAVE_SNOW3G
1868 case eia1:
1870 /* SNOW3G */
1871 uint8_t *mac;
1872 int message_length = tvb_captured_length_remaining(tvb, offset) - 4;
1873 uint8_t *message_data = (uint8_t *)wmem_alloc0(pinfo->pool, message_length+5);
1875 /* TS 33.401 B.2.2 */
1877 /* Data is header byte */
1878 message_data[0] = header;
1879 /* Followed by the decrypted message (but not the digest bytes) */
1880 tvb_memcpy(tvb, message_data+1, offset, message_length);
1882 mac = (u8*)snow3g_f9(pdu_security_settings->integrityKey,
1883 pdu_security_settings->count,
1884 /* 'Fresh' is the bearer bits then zeros */
1885 pdu_security_settings->bearer << 27,
1886 pdu_security_settings->direction,
1887 message_data,
1888 (message_length+1)*8);
1890 *calculated = true;
1891 return ((mac[0] << 24) | (mac[1] << 16) | (mac[2] << 8) | mac[3]);
1893 #endif
1895 case eia2:
1897 /* AES */
1898 gcry_mac_hd_t mac_hd;
1899 int gcrypt_err;
1900 int message_length;
1901 uint8_t *message_data;
1902 uint8_t mac[4];
1903 size_t read_digest_length = 4;
1905 /* Open gcrypt handle */
1906 gcrypt_err = gcry_mac_open(&mac_hd, GCRY_MAC_CMAC_AES, 0, NULL);
1907 if (gcrypt_err != 0) {
1908 return 0;
1911 /* Set the key */
1912 gcrypt_err = gcry_mac_setkey(mac_hd, pdu_security_settings->integrityKey, 16);
1913 if (gcrypt_err != 0) {
1914 gcry_mac_close(mac_hd);
1915 return 0;
1918 /* TS 33.401 B.2.3 */
1920 /* Extract the encrypted data into a buffer */
1921 message_length = tvb_captured_length_remaining(tvb, offset) - 4;
1922 message_data = (uint8_t *)wmem_alloc0(pinfo->pool, message_length+9);
1923 message_data[0] = (pdu_security_settings->count & 0xff000000) >> 24;
1924 message_data[1] = (pdu_security_settings->count & 0x00ff0000) >> 16;
1925 message_data[2] = (pdu_security_settings->count & 0x0000ff00) >> 8;
1926 message_data[3] = (pdu_security_settings->count & 0x000000ff);
1927 message_data[4] = (pdu_security_settings->bearer << 3) + (pdu_security_settings->direction << 2);
1928 /* rest of first 8 bytes are left as zeroes... */
1929 /* Now the header byte */
1930 message_data[8] = header;
1931 /* Followed by the decrypted message (but not the digest bytes) */
1932 tvb_memcpy(tvb, message_data+9, offset, message_length);
1934 /* Pass in the message */
1935 gcrypt_err = gcry_mac_write(mac_hd, message_data, message_length+9);
1936 if (gcrypt_err != 0) {
1937 gcry_mac_close(mac_hd);
1938 return 0;
1941 /* Read out the digest */
1942 gcrypt_err = gcry_mac_read(mac_hd, mac, &read_digest_length);
1943 if (gcrypt_err != 0) {
1944 gcry_mac_close(mac_hd);
1945 return 0;
1948 /* Now close the mac handle */
1949 gcry_mac_close(mac_hd);
1951 *calculated = true;
1952 return ((mac[0] << 24) | (mac[1] << 16) | (mac[2] << 8) | mac[3]);
1954 #ifdef HAVE_ZUC
1955 case eia3:
1957 /* ZUC */
1958 uint32_t mac;
1959 int message_length = tvb_captured_length_remaining(tvb, offset) - 4;
1960 uint8_t *message_data = (uint8_t *)wmem_alloc0(pinfo->pool, message_length+5);
1962 /* Data is header byte */
1963 message_data[0] = header;
1964 /* Followed by the decrypted message (but not the digest bytes) */
1965 tvb_memcpy(tvb, message_data+1, offset, message_length);
1967 zuc_f9(pdu_security_settings->integrityKey,
1968 pdu_security_settings->count,
1969 pdu_security_settings->direction,
1970 pdu_security_settings->bearer,
1971 (message_length+1)*8,
1972 (uint32_t*)message_data,
1973 &mac);
1975 *calculated = true;
1976 return mac;
1978 #endif
1980 default:
1981 /* Can't calculate */
1982 *calculated = false;
1983 return 0;
1987 /******************************/
1988 /* Main dissection function. */
1989 static int dissect_pdcp_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1991 const char *mode;
1992 proto_tree *pdcp_tree = NULL;
1993 proto_item *root_ti = NULL;
1994 proto_item *ti = NULL;
1995 int offset = 0;
1996 struct pdcp_lte_info *p_pdcp_info;
1997 tvbuff_t *rohc_tvb = NULL;
1998 uint32_t reserved_value;
1999 uint32_t seqnum = 0;
2001 pdcp_lte_security_info_t *current_security = NULL; /* current security for this UE */
2002 pdcp_lte_security_info_t *pdu_security; /* security in place for this PDU */
2003 proto_tree *security_tree = NULL;
2004 proto_item *security_ti;
2005 tvbuff_t *payload_tvb;
2006 pdu_security_settings_t pdu_security_settings;
2007 bool payload_deciphered = false;
2009 /* Initialise security settings */
2010 memset(&pdu_security_settings, 0, sizeof(pdu_security_settings));
2012 /* Set protocol name. */
2013 col_set_str(pinfo->cinfo, COL_PROTOCOL, "PDCP-LTE");
2015 /* Look for attached packet info! */
2016 p_pdcp_info = (struct pdcp_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0);
2017 /* Can't dissect anything without it... */
2018 if (p_pdcp_info == NULL) {
2019 return 0;
2022 /* Don't want to overwrite the RLC Info column if configured not to */
2023 if ((global_pdcp_lte_layer_to_show == ShowRLCLayer) &&
2024 (p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0) != NULL)) {
2026 col_set_writable(pinfo->cinfo, COL_INFO, false);
2028 else {
2029 /* TODO: won't help with multiple PDCP-or-traffic PDUs / frame... */
2030 col_clear(pinfo->cinfo, COL_INFO);
2031 col_set_writable(pinfo->cinfo, COL_INFO, true);
2034 /* Create pdcp tree. */
2035 if (tree) {
2036 root_ti = proto_tree_add_item(tree, proto_pdcp_lte, tvb, offset, -1, ENC_NA);
2037 pdcp_tree = proto_item_add_subtree(root_ti, ett_pdcp);
2040 /* Set mode string */
2041 mode = val_to_str_const(p_pdcp_info->rohc.mode, rohc_mode_vals, "Error");
2043 /*****************************************************/
2044 /* Show configuration (attached packet) info in tree */
2045 if (pdcp_tree) {
2046 show_pdcp_config(pinfo, tvb, pdcp_tree, p_pdcp_info);
2049 /* Show ROHC mode */
2050 if (p_pdcp_info->rohc.rohc_compression) {
2051 col_append_fstr(pinfo->cinfo, COL_INFO, " (mode=%c)", mode[0]);
2054 /***************************************/
2055 /* UE security algorithms */
2056 if (!PINFO_FD_VISITED(pinfo)) {
2057 /* Look up current state by UEID */
2058 current_security = (pdcp_lte_security_info_t*)wmem_map_lookup(pdcp_security_hash,
2059 GUINT_TO_POINTER((unsigned)p_pdcp_info->ueid));
2060 if (current_security != NULL) {
2061 /* Store any result for this frame in the result table */
2062 pdcp_lte_security_info_t *security_to_store = wmem_new(wmem_file_scope(), pdcp_lte_security_info_t);
2063 /* Take a deep copy of the settings */
2064 *security_to_store = *current_security;
2065 wmem_map_insert(pdcp_security_result_hash,
2066 get_ueid_frame_hash_key(p_pdcp_info->ueid, pinfo->num, true),
2067 security_to_store);
2069 else {
2070 /* No entry added from RRC, but still use configured defaults */
2071 if ((global_default_ciphering_algorithm != eea0) ||
2072 (global_default_integrity_algorithm != eia0)) {
2073 /* Copy algorithms from preference defaults */
2074 pdcp_lte_security_info_t *security_to_store = wmem_new0(wmem_file_scope(), pdcp_lte_security_info_t);
2075 security_to_store->ciphering = global_default_ciphering_algorithm;
2076 security_to_store->integrity = global_default_integrity_algorithm;
2077 security_to_store->seen_next_ul_pdu = true;
2078 wmem_map_insert(pdcp_security_result_hash,
2079 get_ueid_frame_hash_key(p_pdcp_info->ueid, pinfo->num, true),
2080 security_to_store);
2085 /* Show security settings for this PDU */
2086 pdu_security = (pdcp_lte_security_info_t*)wmem_map_lookup(pdcp_security_result_hash,
2087 get_ueid_frame_hash_key(p_pdcp_info->ueid, pinfo->num, false));
2088 if (pdu_security != NULL) {
2089 /* Create subtree */
2090 security_ti = proto_tree_add_string_format(pdcp_tree,
2091 hf_pdcp_lte_security,
2092 tvb, 0, 0,
2093 "", "UE Security");
2094 security_tree = proto_item_add_subtree(security_ti, ett_pdcp_security);
2095 proto_item_set_generated(security_ti);
2097 /* Setup frame */
2098 if (pinfo->num > pdu_security->configuration_frame) {
2099 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_setup_frame,
2100 tvb, 0, 0, pdu_security->configuration_frame);
2101 proto_item_set_generated(ti);
2104 /* Ciphering */
2105 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_ciphering_algorithm,
2106 tvb, 0, 0, pdu_security->ciphering);
2107 proto_item_set_generated(ti);
2109 /* Integrity */
2110 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_integrity_algorithm,
2111 tvb, 0, 0, pdu_security->integrity);
2112 proto_item_set_generated(ti);
2114 /* Show algorithms in security root */
2115 proto_item_append_text(security_ti, " (ciphering=%s, integrity=%s)",
2116 val_to_str_const(pdu_security->ciphering, ciphering_algorithm_vals, "Unknown"),
2117 val_to_str_const(pdu_security->integrity, integrity_algorithm_vals, "Unknown"));
2119 pdu_security_settings.ciphering = pdu_security->ciphering;
2120 pdu_security_settings.integrity = pdu_security->integrity;
2124 /***********************************/
2125 /* Handle PDCP header (if present) */
2126 if (!p_pdcp_info->no_header_pdu) {
2128 seqnum = 0;
2129 bool seqnum_set = false;
2131 uint8_t first_byte = tvb_get_uint8(tvb, offset);
2133 /*****************************/
2134 /* Signalling plane messages */
2135 if (p_pdcp_info->plane == SIGNALING_PLANE) {
2136 /* Verify 3 reserved bits are 0 */
2137 uint8_t reserved = (first_byte & 0xe0) >> 5;
2138 ti = proto_tree_add_item(pdcp_tree, hf_pdcp_lte_control_plane_reserved,
2139 tvb, offset, 1, ENC_BIG_ENDIAN);
2140 if (reserved != 0) {
2141 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
2142 "PDCP signalling header reserved bits not zero");
2145 /* 5-bit sequence number */
2146 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_seq_num_5, tvb, offset, 1, ENC_BIG_ENDIAN, &seqnum);
2147 seqnum_set = true;
2148 write_pdu_label_and_info(root_ti, pinfo, " sn=%-2u ", seqnum);
2149 offset++;
2151 if (tvb_captured_length_remaining(tvb, offset) == 0) {
2152 /* Only PDCP header was captured, stop dissection here */
2153 return offset;
2156 else if (p_pdcp_info->plane == USER_PLANE) {
2158 /**********************************/
2159 /* User-plane messages */
2160 uint8_t pdu_type = (first_byte & 0x80) >> 7;
2162 /* Data/Control flag */
2163 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_data_control, tvb, offset, 1, ENC_BIG_ENDIAN);
2165 if (pdu_type == 1) {
2166 /*****************************/
2167 /* User-plane Data */
2169 /* Number of sequence number bits depends upon config */
2170 switch (p_pdcp_info->seqnum_length) {
2171 case PDCP_SN_LENGTH_7_BITS:
2172 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_seq_num_7, tvb, offset, 1, ENC_BIG_ENDIAN, &seqnum);
2173 seqnum_set = true;
2174 offset++;
2175 break;
2176 case PDCP_SN_LENGTH_12_BITS:
2177 /* 3 reserved bits */
2178 ti = proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_reserved3, tvb, offset, 1, ENC_BIG_ENDIAN, &reserved_value);
2180 /* Complain if not 0 */
2181 if (reserved_value != 0) {
2182 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
2183 "Reserved bits have value 0x%x - should be 0x0",
2184 reserved_value);
2187 /* 12-bit sequence number */
2188 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_seq_num_12, tvb, offset, 2, ENC_BIG_ENDIAN, &seqnum);
2189 seqnum_set = true;
2190 offset += 2;
2191 break;
2192 case PDCP_SN_LENGTH_15_BITS:
2193 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_seq_num_15, tvb, offset, 2, ENC_BIG_ENDIAN, &seqnum);
2194 seqnum_set = true;
2195 offset += 2;
2196 break;
2197 case PDCP_SN_LENGTH_18_BITS:
2198 /* Polling bit */
2199 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_polling, tvb, offset, 1, ENC_BIG_ENDIAN);
2201 /* 4 reserved bits */
2202 ti = proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_reserved5, tvb, offset, 1, ENC_BIG_ENDIAN, &reserved_value);
2204 /* Complain if not 0 */
2205 if (reserved_value != 0) {
2206 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
2207 "Reserved bits have value 0x%x - should be 0x0",
2208 reserved_value);
2211 /* 18-bit sequence number */
2212 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_seq_num_18, tvb, offset, 3, ENC_BIG_ENDIAN, &seqnum);
2213 seqnum_set = true;
2214 offset += 3;
2215 break;
2216 default:
2217 /* Not a recognised data format!!!!! */
2218 return 1;
2221 write_pdu_label_and_info(root_ti, pinfo, " (SN=%u)", seqnum);
2223 else {
2224 /*******************************/
2225 /* User-plane Control messages */
2226 uint32_t control_pdu_type;
2227 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_control_pdu_type, tvb,
2228 offset, 1, ENC_BIG_ENDIAN, &control_pdu_type);
2230 switch (control_pdu_type) {
2231 case 0: /* PDCP status report */
2233 uint32_t fms;
2234 uint32_t modulo;
2235 unsigned not_received = 0;
2236 unsigned sn, i, j, l;
2237 uint32_t len, bit_offset;
2238 proto_tree *bitmap_tree;
2239 proto_item *bitmap_ti = NULL;
2240 char *buff = NULL;
2241 #define BUFF_SIZE 57
2243 if (p_pdcp_info->seqnum_length == PDCP_SN_LENGTH_12_BITS) {
2244 /* First-Missing-Sequence SN */
2245 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_fms, tvb,
2246 offset, 2, ENC_BIG_ENDIAN, &fms);
2247 sn = (fms + 1) % 4096;
2248 offset += 2;
2249 modulo = 4096;
2250 } else if (p_pdcp_info->seqnum_length == PDCP_SN_LENGTH_15_BITS) {
2252 /* 5 reserved bits */
2253 ti = proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_reserved4, tvb, offset, 2, ENC_BIG_ENDIAN, &reserved_value);
2254 offset++;
2256 /* Complain if not 0 */
2257 if (reserved_value != 0) {
2258 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
2259 "Reserved bits have value 0x%x - should be 0x0",
2260 reserved_value);
2263 /* First-Missing-Sequence SN */
2264 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_fms2, tvb,
2265 offset, 2, ENC_BIG_ENDIAN, &fms);
2266 sn = (fms + 1) % 32768;
2267 offset += 2;
2268 modulo = 32768;
2269 } else {
2270 /* 2 reserved bits */
2271 ti = proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_reserved6, tvb, offset, 1, ENC_BIG_ENDIAN, &reserved_value);
2273 /* Complain if not 0 */
2274 if (reserved_value != 0) {
2275 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
2276 "Reserved bits have value 0x%x - should be 0x0",
2277 reserved_value);
2280 /* First-Missing-Sequence SN */
2281 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_fms3, tvb,
2282 offset, 3, ENC_BIG_ENDIAN, &fms);
2283 sn = (fms + 1) % 262144;
2284 offset += 3;
2285 modulo = 262144;
2288 /* Bitmap tree */
2289 if (tvb_reported_length_remaining(tvb, offset) > 0) {
2290 bitmap_ti = proto_tree_add_item(pdcp_tree, hf_pdcp_lte_bitmap, tvb,
2291 offset, -1, ENC_NA);
2292 bitmap_tree = proto_item_add_subtree(bitmap_ti, ett_pdcp_report_bitmap);
2294 buff = (char *)wmem_alloc(pinfo->pool, BUFF_SIZE);
2295 len = tvb_reported_length_remaining(tvb, offset);
2296 bit_offset = offset<<3;
2298 /* For each byte... */
2299 for (i=0; i<len; i++) {
2300 uint8_t bits = tvb_get_bits8(tvb, bit_offset, 8);
2301 for (l=0, j=0; l<8; l++) {
2302 if ((bits << l) & 0x80) {
2303 if (bitmap_tree) {
2304 j += snprintf(&buff[j], BUFF_SIZE-j, "%6u,", (unsigned)(sn+(8*i)+l)%modulo);
2306 } else {
2307 if (bitmap_tree) {
2308 j += (unsigned)g_strlcpy(&buff[j], " ,", BUFF_SIZE-j);
2310 not_received++;
2313 if (bitmap_tree) {
2314 proto_tree_add_uint_format(bitmap_tree, hf_pdcp_lte_bitmap_byte, tvb, bit_offset/8, 1, bits, "%s", buff);
2316 bit_offset += 8;
2320 if (bitmap_ti != NULL) {
2321 proto_item_append_text(bitmap_ti, " (%u SNs not received)", not_received);
2323 write_pdu_label_and_info(root_ti, pinfo, " Status Report (fms=%u) not-received=%u",
2324 fms, not_received);
2326 return 1;
2328 case 1: /* ROHC Feedback */
2329 offset++;
2330 break; /* Drop-through to dissect feedback */
2333 case 2: /* LWA status report */
2335 uint32_t fms;
2336 uint32_t nmp;
2338 if (p_pdcp_info->seqnum_length == PDCP_SN_LENGTH_12_BITS) {
2339 /* First-Missing-Sequence SN */
2340 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_fms, tvb,
2341 offset, 2, ENC_BIG_ENDIAN, &fms);
2342 offset += 2;
2344 /* HRW */
2345 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_hrw, tvb,
2346 offset, 2, ENC_BIG_ENDIAN);
2347 offset += 1;
2349 /* NMP */
2350 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_nmp, tvb,
2351 offset, 2, ENC_BIG_ENDIAN, &nmp);
2352 offset += 2;
2353 } else if (p_pdcp_info->seqnum_length == PDCP_SN_LENGTH_15_BITS) {
2354 /* 5 reserved bits */
2355 ti = proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_reserved4, tvb,
2356 offset, 2, ENC_BIG_ENDIAN, &reserved_value);
2357 offset++;
2358 /* Complain if not 0 */
2359 if (reserved_value != 0) {
2360 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
2361 "Reserved bits have value 0x%x - should be 0x0",
2362 reserved_value);
2365 /* First-Missing-Sequence SN */
2366 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_fms2, tvb,
2367 offset, 2, ENC_BIG_ENDIAN, &fms);
2368 offset += 2;
2370 /* 1 reserved bit */
2371 ti = proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_reserved7, tvb,
2372 offset, 1, ENC_BIG_ENDIAN, &reserved_value);
2373 /* Complain if not 0 */
2374 if (reserved_value) {
2375 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
2376 "Reserved bits have value 0x1 - should be 0x0");
2379 /* HRW */
2380 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_hrw2, tvb,
2381 offset, 2, ENC_BIG_ENDIAN);
2382 offset += 2;
2384 /* 1 reserved bit */
2385 ti = proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_reserved7, tvb,
2386 offset, 1, ENC_BIG_ENDIAN, &reserved_value);
2387 /* Complain if not 0 */
2388 if (reserved_value) {
2389 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
2390 "Reserved bits have value 0x1 - should be 0x0");
2393 /* NMP */
2394 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_nmp2, tvb,
2395 offset, 2, ENC_BIG_ENDIAN, &nmp);
2396 offset += 2;
2397 } else {
2398 /* 2 reserved bits */
2399 ti = proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_reserved6,
2400 tvb, offset, 1, ENC_BIG_ENDIAN, &reserved_value);
2401 /* Complain if not 0 */
2402 if (reserved_value != 0) {
2403 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
2404 "Reserved bits have value 0x%x - should be 0x0",
2405 reserved_value);
2408 /* First-Missing-Sequence SN */
2409 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_fms3, tvb,
2410 offset, 3, ENC_BIG_ENDIAN, &fms);
2411 offset += 3;
2413 /* HRW */
2414 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_hrw3, tvb,
2415 offset, 3, ENC_BIG_ENDIAN);
2416 offset += 2;
2418 /* 4 reserved bits */
2419 ti = proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_reserved8,
2420 tvb, offset, 1, ENC_BIG_ENDIAN, &reserved_value);
2421 /* Complain if not 0 */
2422 if (reserved_value != 0) {
2423 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
2424 "Reserved bits have value 0x%x - should be 0x0",
2425 reserved_value);
2428 /* NMP */
2429 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_nmp3, tvb,
2430 offset, 3, ENC_BIG_ENDIAN, &nmp);
2431 offset += 3;
2434 write_pdu_label_and_info(root_ti, pinfo, " LWA Status Report (fms=%u) not-received=%u",
2435 fms, nmp);
2437 return 1;
2439 case 3: /* LWA end-marker packet */
2441 uint32_t lsn;
2443 if (p_pdcp_info->seqnum_length == PDCP_SN_LENGTH_12_BITS) {
2444 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_lsn, tvb,
2445 offset, 2, ENC_BIG_ENDIAN, &lsn);
2446 offset += 2;
2447 } else if (p_pdcp_info->seqnum_length == PDCP_SN_LENGTH_15_BITS) {
2448 /* 5 reserved bits */
2449 ti = proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_reserved4, tvb,
2450 offset, 2, ENC_BIG_ENDIAN, &reserved_value);
2451 offset++;
2452 /* Complain if not 0 */
2453 if (reserved_value != 0) {
2454 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
2455 "Reserved bits have value 0x%x - should be 0x0",
2456 reserved_value);
2459 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_lsn2, tvb,
2460 offset, 2, ENC_BIG_ENDIAN, &lsn);
2461 offset += 2;
2462 } else {
2463 /* 2 reserved bits */
2464 ti = proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_reserved6,
2465 tvb, offset, 1, ENC_BIG_ENDIAN, &reserved_value);
2466 /* Complain if not 0 */
2467 if (reserved_value != 0) {
2468 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
2469 "Reserved bits have value 0x%x - should be 0x0",
2470 reserved_value);
2473 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_lsn3, tvb,
2474 offset, 3, ENC_BIG_ENDIAN, &lsn);
2475 offset += 3;
2478 write_pdu_label_and_info(root_ti, pinfo, " LWA End-Marker Packet (lsn=%u)", lsn);
2480 return 1;
2481 default: /* Reserved */
2482 return 1;
2486 else {
2487 /* Invalid plane setting...! */
2488 write_pdu_label_and_info(root_ti, pinfo, " - INVALID PLANE (%u)",
2489 p_pdcp_info->plane);
2490 return 1;
2493 /* Do sequence analysis if configured to. */
2494 if (seqnum_set) {
2495 bool do_analysis = false;
2497 switch (global_pdcp_check_sequence_numbers) {
2498 case false:
2499 break;
2500 case SEQUENCE_ANALYSIS_RLC_ONLY:
2501 if ((p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0) != NULL) &&
2502 !p_pdcp_info->is_retx) {
2503 do_analysis = true;
2505 break;
2506 case SEQUENCE_ANALYSIS_PDCP_ONLY:
2507 if (p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0) == NULL) {
2508 do_analysis = true;
2510 break;
2513 if (do_analysis) {
2514 checkChannelSequenceInfo(pinfo, tvb, p_pdcp_info,
2515 seqnum, pdcp_tree, security_tree,
2516 &pdu_security_settings);
2520 else {
2521 /* Show that it's a no-header PDU */
2522 write_pdu_label_and_info(root_ti, pinfo, " No-Header ");
2525 /*******************************************************/
2526 /* Now deal with the payload */
2527 /*******************************************************/
2529 payload_tvb = decipher_payload(tvb, pinfo, &offset, &pdu_security_settings, p_pdcp_info,
2530 pdu_security ? pdu_security->seen_next_ul_pdu: false, &payload_deciphered);
2532 /* Add deciphered data as a filterable field */
2533 if (payload_deciphered) {
2534 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_security_deciphered_data,
2535 payload_tvb, 0, tvb_reported_length(payload_tvb), ENC_NA);
2538 if (p_pdcp_info->plane == SIGNALING_PLANE) {
2539 uint32_t data_length;
2540 uint32_t mac;
2541 proto_item *mac_ti;
2542 uint32_t calculated_digest = 0;
2543 bool digest_was_calculated = false;
2545 /* Compute payload length (no MAC on common control channels) */
2546 data_length = tvb_reported_length_remaining(payload_tvb, offset) - ((p_pdcp_info->channelType == Channel_DCCH) ? 4 : 0);
2548 /* Try to calculate digest so we can check it */
2549 if (global_pdcp_check_integrity && (p_pdcp_info->channelType == Channel_DCCH)) {
2550 calculated_digest = calculate_digest(&pdu_security_settings, tvb_get_uint8(tvb, 0), payload_tvb,
2551 pinfo, offset, &digest_was_calculated);
2554 /* RRC data is all but last 4 bytes.
2555 Call lte-rrc dissector (according to direction and channel type) if we have valid data */
2556 if ((global_pdcp_dissect_signalling_plane_as_rrc) &&
2557 ((pdu_security == NULL) || (pdu_security->ciphering == eea0) || payload_deciphered || !pdu_security->seen_next_ul_pdu)) {
2559 /* Get appropriate dissector handle */
2560 dissector_handle_t rrc_handle = lookup_rrc_dissector_handle(p_pdcp_info);
2562 if (rrc_handle != 0) {
2563 /* Call RRC dissector if have one */
2564 tvbuff_t *rrc_payload_tvb = tvb_new_subset_length(payload_tvb, offset, data_length);
2565 bool was_writable = col_get_writable(pinfo->cinfo, COL_INFO);
2567 /* We always want to see this in the info column */
2568 col_set_writable(pinfo->cinfo, COL_INFO, true);
2570 call_dissector_only(rrc_handle, rrc_payload_tvb, pinfo, pdcp_tree, NULL);
2572 /* Restore to whatever it was */
2573 col_set_writable(pinfo->cinfo, COL_INFO, was_writable);
2575 else {
2576 /* Just show data */
2577 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_signalling_data, payload_tvb, offset,
2578 data_length, ENC_NA);
2581 if (!PINFO_FD_VISITED(pinfo) &&
2582 (current_security != NULL) && !current_security->seen_next_ul_pdu &&
2583 p_pdcp_info->direction == DIRECTION_UPLINK)
2585 /* i.e. we have already seen SecurityModeResponse! */
2586 current_security->seen_next_ul_pdu = true;
2590 else {
2591 /* Just show as unparsed data */
2592 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_signalling_data, payload_tvb, offset,
2593 data_length, ENC_NA);
2596 offset += data_length;
2598 if (p_pdcp_info->channelType == Channel_DCCH) {
2599 /* Last 4 bytes are MAC */
2600 mac_ti = proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_mac, payload_tvb, offset, 4,
2601 ENC_BIG_ENDIAN, &mac);
2602 offset += 4;
2604 if (digest_was_calculated) {
2605 /* Compare what was found with calculated value! */
2606 if (mac != calculated_digest) {
2607 expert_add_info_format(pinfo, mac_ti, &ei_pdcp_lte_digest_wrong,
2608 "MAC-I Digest wrong - calculated %08x but found %08x",
2609 calculated_digest, mac);
2610 proto_item_append_text(mac_ti, " (but calculated %08x !)", calculated_digest);
2612 else {
2613 proto_item_append_text(mac_ti, " [Matches calculated result]");
2617 col_append_fstr(pinfo->cinfo, COL_INFO, " MAC=0x%08x (%u bytes data)",
2618 mac, data_length);
2619 } else {
2620 col_append_fstr(pinfo->cinfo, COL_INFO, " (%u bytes data)", data_length);
2623 else if (tvb_captured_length_remaining(payload_tvb, offset)) {
2624 /* User-plane payload here */
2626 /* If not compressed with ROHC, show as user-plane data */
2627 if (!p_pdcp_info->rohc.rohc_compression) {
2628 int payload_length = tvb_reported_length_remaining(payload_tvb, offset);
2629 if (payload_length > 0) {
2630 if (p_pdcp_info->plane == USER_PLANE) {
2632 /* Not attempting to decode payload if ciphering is enabled
2633 (and NULL ciphering is not being used) */
2634 if (global_pdcp_dissect_user_plane_as_ip &&
2635 ((pdu_security == NULL) || (pdu_security->ciphering == eea0) || payload_deciphered))
2637 tvbuff_t *ip_payload_tvb = tvb_new_subset_remaining(payload_tvb, offset);
2639 /* Don't update info column for ROHC unless configured to */
2640 if (global_pdcp_lte_layer_to_show != ShowTrafficLayer) {
2641 col_set_writable(pinfo->cinfo, COL_INFO, false);
2644 switch (tvb_get_uint8(ip_payload_tvb, 0) & 0xf0) {
2645 case 0x40:
2646 call_dissector_only(ip_handle, ip_payload_tvb, pinfo, pdcp_tree, NULL);
2647 break;
2648 case 0x60:
2649 call_dissector_only(ipv6_handle, ip_payload_tvb, pinfo, pdcp_tree, NULL);
2650 break;
2651 default:
2652 call_data_dissector(ip_payload_tvb, pinfo, pdcp_tree);
2653 break;
2656 /* Freeze the columns again because we don't want other layers writing to info */
2657 if (global_pdcp_lte_layer_to_show == ShowTrafficLayer) {
2658 col_set_writable(pinfo->cinfo, COL_INFO, false);
2662 else {
2663 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_user_plane_data, payload_tvb, offset, -1, ENC_NA);
2667 write_pdu_label_and_info(root_ti, pinfo, "(%u bytes data)",
2668 payload_length);
2671 /* (there will be no signalling data left at this point) */
2673 /* Let RLC write to columns again */
2674 col_set_writable(pinfo->cinfo, COL_INFO, global_pdcp_lte_layer_to_show == ShowRLCLayer);
2676 /* DROPPING OUT HERE IF NOT DOING ROHC! */
2677 return tvb_captured_length(tvb);
2679 else {
2680 /***************************/
2681 /* ROHC packets */
2682 /***************************/
2684 /* Only attempt ROHC if configured to */
2685 if (!global_pdcp_dissect_rohc) {
2686 col_append_fstr(pinfo->cinfo, COL_PROTOCOL, "|ROHC(%s)",
2687 val_to_str_const(p_pdcp_info->rohc.profile, rohc_profile_vals, "Unknown"));
2688 return 1;
2691 rohc_tvb = tvb_new_subset_remaining(payload_tvb, offset);
2693 /* Only enable writing to column if configured to show ROHC */
2694 if (global_pdcp_lte_layer_to_show != ShowTrafficLayer) {
2695 col_set_writable(pinfo->cinfo, COL_INFO, false);
2697 else {
2698 col_clear(pinfo->cinfo, COL_INFO);
2701 /* Call the ROHC dissector */
2702 call_dissector_with_data(rohc_handle, rohc_tvb, pinfo, tree, &p_pdcp_info->rohc);
2704 /* Let RLC write to columns again */
2705 col_set_writable(pinfo->cinfo, COL_INFO, global_pdcp_lte_layer_to_show == ShowRLCLayer);
2708 return tvb_captured_length(tvb);
2712 void proto_register_pdcp_lte(void)
2714 static hf_register_info hf[] =
2716 { &hf_pdcp_lte_configuration,
2717 { "Configuration",
2718 "pdcp-lte.configuration", FT_STRING, BASE_NONE, NULL, 0x0,
2719 "Configuration info passed into dissector", HFILL
2723 { &hf_pdcp_lte_rohc_compression,
2724 { "ROHC Compression",
2725 "pdcp-lte.rohc.compression", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2726 NULL, HFILL
2729 { &hf_pdcp_lte_rohc_mode,
2730 { "ROHC Mode",
2731 "pdcp-lte.rohc.mode", FT_UINT8, BASE_DEC, VALS(rohc_mode_vals), 0x0,
2732 NULL, HFILL
2735 { &hf_pdcp_lte_rohc_rnd,
2736 { "RND",
2737 "pdcp-lte.rohc.rnd", FT_UINT8, BASE_DEC, NULL, 0x0,
2738 "RND of outer ip header", HFILL
2741 { &hf_pdcp_lte_rohc_udp_checksum_present,
2742 { "UDP Checksum",
2743 "pdcp-lte.rohc.checksum-present", FT_UINT8, BASE_DEC, NULL, 0x0,
2744 "UDP Checksum present", HFILL
2747 { &hf_pdcp_lte_direction,
2748 { "Direction",
2749 "pdcp-lte.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
2750 "Direction of message", HFILL
2753 { &hf_pdcp_lte_ueid,
2754 { "UE",
2755 "pdcp-lte.ueid", FT_UINT16, BASE_DEC, 0, 0x0,
2756 "UE Identifier", HFILL
2759 { &hf_pdcp_lte_channel_type,
2760 { "Channel type",
2761 "pdcp-lte.channel-type", FT_UINT8, BASE_DEC, VALS(logical_channel_vals), 0x0,
2762 NULL, HFILL
2765 { &hf_pdcp_lte_channel_id,
2766 { "Channel Id",
2767 "pdcp-lte.channel-id", FT_UINT8, BASE_DEC, 0, 0x0,
2768 NULL, HFILL
2771 { &hf_pdcp_lte_rohc_profile,
2772 { "ROHC profile",
2773 "pdcp-lte.rohc.profile", FT_UINT16, BASE_DEC, VALS(rohc_profile_vals), 0x0,
2774 "ROHC Mode", HFILL
2777 { &hf_pdcp_lte_no_header_pdu,
2778 { "No Header PDU",
2779 "pdcp-lte.no-header_pdu", FT_UINT8, BASE_DEC, NULL, 0x0,
2780 NULL, HFILL
2783 { &hf_pdcp_lte_plane,
2784 { "Plane",
2785 "pdcp-lte.plane", FT_UINT8, BASE_DEC, VALS(pdcp_plane_vals), 0x0,
2786 NULL, HFILL
2789 { &hf_pdcp_lte_seqnum_length,
2790 { "Seqnum length",
2791 "pdcp-lte.seqnum_length", FT_UINT8, BASE_DEC, NULL, 0x0,
2792 "Sequence Number Length", HFILL
2797 { &hf_pdcp_lte_cid_inclusion_info,
2798 { "CID Inclusion Info",
2799 "pdcp-lte.cid-inclusion-info", FT_UINT8, BASE_DEC, NULL, 0x0,
2800 NULL, HFILL
2803 { &hf_pdcp_lte_large_cid_present,
2804 { "Large CID Present",
2805 "pdcp-lte.large-cid-present", FT_UINT8, BASE_DEC, NULL, 0x0,
2806 NULL, HFILL
2810 { &hf_pdcp_lte_control_plane_reserved,
2811 { "Reserved",
2812 "pdcp-lte.reserved", FT_UINT8, BASE_DEC, NULL, 0xe0,
2813 NULL, HFILL
2816 { &hf_pdcp_lte_seq_num_5,
2817 { "Seq Num",
2818 "pdcp-lte.seq-num", FT_UINT8, BASE_DEC, NULL, 0x1f,
2819 "PDCP Seq num", HFILL
2822 { &hf_pdcp_lte_seq_num_7,
2823 { "Seq Num",
2824 "pdcp-lte.seq-num", FT_UINT8, BASE_DEC, NULL, 0x7f,
2825 "PDCP Seq num", HFILL
2828 { &hf_pdcp_lte_reserved3,
2829 { "Reserved",
2830 "pdcp-lte.reserved3", FT_UINT8, BASE_HEX, NULL, 0x70,
2831 "3 reserved bits", HFILL
2834 { &hf_pdcp_lte_seq_num_12,
2835 { "Seq Num",
2836 "pdcp-lte.seq-num", FT_UINT16, BASE_DEC, NULL, 0x0fff,
2837 "PDCP Seq num", HFILL
2840 { &hf_pdcp_lte_seq_num_15,
2841 { "Seq Num",
2842 "pdcp-lte.seq-num", FT_UINT16, BASE_DEC, NULL, 0x7fff,
2843 "PDCP Seq num", HFILL
2846 { &hf_pdcp_lte_polling,
2847 { "Polling",
2848 "pdcp-lte.polling", FT_BOOLEAN, 8, NULL, 0x40,
2849 NULL, HFILL
2852 { &hf_pdcp_lte_reserved5,
2853 { "Reserved",
2854 "pdcp-lte.reserved5", FT_UINT8, BASE_HEX, NULL, 0x3c,
2855 "4 reserved bits", HFILL
2858 { &hf_pdcp_lte_seq_num_18,
2859 { "Seq Num",
2860 "pdcp-lte.seq-num", FT_UINT24, BASE_DEC, NULL, 0x03ffff,
2861 "PDCP Seq num", HFILL
2864 { &hf_pdcp_lte_signalling_data,
2865 { "Signalling Data",
2866 "pdcp-lte.signalling-data", FT_BYTES, BASE_NONE, NULL, 0x0,
2867 NULL, HFILL
2870 { &hf_pdcp_lte_mac,
2871 { "MAC",
2872 "pdcp-lte.mac", FT_UINT32, BASE_HEX, NULL, 0x0,
2873 NULL, HFILL
2876 { &hf_pdcp_lte_data_control,
2877 { "PDU Type",
2878 "pdcp-lte.pdu-type", FT_BOOLEAN, 8, TFS(&tfs_data_pdu_control_pdu), 0x80,
2879 NULL, HFILL
2882 { &hf_pdcp_lte_user_plane_data,
2883 { "User-Plane Data",
2884 "pdcp-lte.user-data", FT_BYTES, BASE_NONE, NULL, 0x0,
2885 NULL, HFILL
2888 { &hf_pdcp_lte_control_pdu_type,
2889 { "Control PDU Type",
2890 "pdcp-lte.control-pdu-type", FT_UINT8, BASE_HEX, VALS(control_pdu_type_vals), 0x70,
2891 NULL, HFILL
2894 { &hf_pdcp_lte_fms,
2895 { "First Missing Sequence Number",
2896 "pdcp-lte.fms", FT_UINT16, BASE_DEC, NULL, 0x0fff,
2897 "First Missing PDCP Sequence Number", HFILL
2900 { &hf_pdcp_lte_reserved4,
2901 { "Reserved",
2902 "pdcp-lte.reserved4", FT_UINT16, BASE_HEX, NULL, 0x0f80,
2903 "5 reserved bits", HFILL
2906 { &hf_pdcp_lte_fms2,
2907 { "First Missing Sequence Number",
2908 "pdcp-lte.fms", FT_UINT16, BASE_DEC, NULL, 0x7fff,
2909 "First Missing PDCP Sequence Number", HFILL
2912 { &hf_pdcp_lte_reserved6,
2913 { "Reserved",
2914 "pdcp-lte.reserved6", FT_UINT8, BASE_HEX, NULL, 0x0c,
2915 "2 reserved bits", HFILL
2918 { &hf_pdcp_lte_fms3,
2919 { "First Missing Sequence Number",
2920 "pdcp-lte.fms", FT_UINT24, BASE_DEC, NULL, 0x03ffff,
2921 "First Missing PDCP Sequence Number", HFILL
2924 { &hf_pdcp_lte_bitmap,
2925 { "Bitmap",
2926 "pdcp-lte.bitmap", FT_NONE, BASE_NONE, NULL, 0x0,
2927 "Status report bitmap (0=error, 1=OK)", HFILL
2930 { &hf_pdcp_lte_bitmap_byte,
2931 { "Bitmap byte",
2932 "pdcp-lte.bitmap.byte", FT_UINT8, BASE_HEX, NULL, 0x0,
2933 NULL, HFILL
2936 { &hf_pdcp_lte_hrw,
2937 { "Highest Received Sequence Number on WLAN",
2938 "pdcp-lte.hwr", FT_UINT16, BASE_DEC, NULL, 0xfff0,
2939 NULL, HFILL
2942 { &hf_pdcp_lte_nmp,
2943 { "Number of Missing PDCP SDUs",
2944 "pdcp-lte.nmp", FT_UINT16, BASE_DEC, NULL, 0x0fff,
2945 NULL, HFILL
2948 { &hf_pdcp_lte_reserved7,
2949 { "Reserved",
2950 "pdcp-lte.reserved7", FT_UINT8, BASE_HEX, NULL, 0x80,
2951 "1 reserved bit", HFILL
2954 { &hf_pdcp_lte_hrw2,
2955 { "Highest Received Sequence Number on WLAN",
2956 "pdcp-lte.hwr", FT_UINT16, BASE_DEC, NULL, 0x7fff,
2957 NULL, HFILL
2960 { &hf_pdcp_lte_nmp2,
2961 { "Number of Missing PDCP SDUs",
2962 "pdcp-lte.nmp", FT_UINT16, BASE_DEC, NULL, 0x7fff,
2963 NULL, HFILL
2966 { &hf_pdcp_lte_hrw3,
2967 { "Highest Received Sequence Number on WLAN",
2968 "pdcp-lte.hwr", FT_UINT24, BASE_DEC, NULL, 0xffffc0,
2969 NULL, HFILL
2972 { &hf_pdcp_lte_reserved8,
2973 { "Reserved",
2974 "pdcp-lte.reserved8", FT_UINT8, BASE_HEX, NULL, 0x3c,
2975 "4 reserved bits", HFILL
2978 { &hf_pdcp_lte_nmp3,
2979 { "Number of Missing PDCP SDUs",
2980 "pdcp-lte.nmp", FT_UINT24, BASE_DEC, NULL, 0x03ffff,
2981 NULL, HFILL
2984 { &hf_pdcp_lte_lsn,
2985 { "Last PDCP PDU SN ciphered with previous key",
2986 "pdcp-lte.lsn", FT_UINT16, BASE_DEC, NULL, 0x0fff,
2987 NULL, HFILL
2990 { &hf_pdcp_lte_lsn2,
2991 { "Last PDCP PDU SN ciphered with previous key",
2992 "pdcp-lte.lsn", FT_UINT16, BASE_DEC, NULL, 0x7fff,
2993 NULL, HFILL
2996 { &hf_pdcp_lte_lsn3,
2997 { "Last PDCP PDU SN ciphered with previous key",
2998 "pdcp-lte.lsn", FT_UINT24, BASE_DEC, NULL, 0x03ffff,
2999 NULL, HFILL
3003 { &hf_pdcp_lte_sequence_analysis,
3004 { "Sequence Analysis",
3005 "pdcp-lte.sequence-analysis", FT_STRING, BASE_NONE, 0, 0x0,
3006 NULL, HFILL
3009 { &hf_pdcp_lte_sequence_analysis_ok,
3010 { "OK",
3011 "pdcp-lte.sequence-analysis.ok", FT_BOOLEAN, BASE_NONE, 0, 0x0,
3012 NULL, HFILL
3015 { &hf_pdcp_lte_sequence_analysis_previous_frame,
3016 { "Previous frame for channel",
3017 "pdcp-lte.sequence-analysis.previous-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
3018 NULL, HFILL
3021 { &hf_pdcp_lte_sequence_analysis_next_frame,
3022 { "Next frame for channel",
3023 "pdcp-lte.sequence-analysis.next-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
3024 NULL, HFILL
3027 { &hf_pdcp_lte_sequence_analysis_expected_sn,
3028 { "Expected SN",
3029 "pdcp-lte.sequence-analysis.expected-sn", FT_UINT32, BASE_DEC, 0, 0x0,
3030 NULL, HFILL
3033 { &hf_pdcp_lte_sequence_analysis_skipped,
3034 { "Skipped frames",
3035 "pdcp-lte.sequence-analysis.skipped-frames", FT_BOOLEAN, BASE_NONE, 0, 0x0,
3036 NULL, HFILL
3039 { &hf_pdcp_lte_sequence_analysis_repeated,
3040 { "Repeated frame",
3041 "pdcp-lte.sequence-analysis.repeated-frame", FT_BOOLEAN, BASE_NONE, 0, 0x0,
3042 NULL, HFILL
3046 /* Security fields */
3047 { &hf_pdcp_lte_security,
3048 { "Security Config",
3049 "pdcp-lte.security-config", FT_STRING, BASE_NONE, 0, 0x0,
3050 NULL, HFILL
3053 { &hf_pdcp_lte_security_setup_frame,
3054 { "Configuration frame",
3055 "pdcp-lte.security-config.setup-frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
3056 NULL, HFILL
3059 { &hf_pdcp_lte_security_integrity_algorithm,
3060 { "Integrity Algorithm",
3061 "pdcp-lte.security-config.integrity", FT_UINT16, BASE_DEC, VALS(integrity_algorithm_vals), 0x0,
3062 NULL, HFILL
3065 { &hf_pdcp_lte_security_ciphering_algorithm,
3066 { "Ciphering Algorithm",
3067 "pdcp-lte.security-config.ciphering", FT_UINT16, BASE_DEC, VALS(ciphering_algorithm_vals), 0x0,
3068 NULL, HFILL
3071 { &hf_pdcp_lte_security_bearer,
3072 { "BEARER",
3073 "pdcp-lte.security-config.bearer", FT_UINT8, BASE_DEC, NULL, 0x0,
3074 NULL, HFILL
3077 { &hf_pdcp_lte_security_direction,
3078 { "DIRECTION",
3079 "pdcp-lte.security-config.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
3080 NULL, HFILL
3083 { &hf_pdcp_lte_security_count,
3084 { "COUNT",
3085 "pdcp-lte.security-config.count", FT_UINT32, BASE_DEC, NULL, 0x0,
3086 NULL, HFILL
3089 { &hf_pdcp_lte_security_cipher_key,
3090 { "CIPHER KEY",
3091 "pdcp-lte.security-config.cipher-key", FT_STRING, BASE_NONE, NULL, 0x0,
3092 NULL, HFILL
3095 { &hf_pdcp_lte_security_integrity_key,
3096 { "INTEGRITY KEY",
3097 "pdcp-lte.security-config.integrity-key", FT_STRING, BASE_NONE, NULL, 0x0,
3098 NULL, HFILL
3101 { &hf_pdcp_lte_security_deciphered_data,
3102 { "Deciphered Data",
3103 "pdcp-lte.deciphered-data", FT_BYTES, BASE_NONE, NULL, 0x0,
3104 NULL, HFILL
3109 static int *ett[] =
3111 &ett_pdcp,
3112 &ett_pdcp_configuration,
3113 &ett_pdcp_packet,
3114 &ett_pdcp_lte_sequence_analysis,
3115 &ett_pdcp_report_bitmap,
3116 &ett_pdcp_security
3119 static ei_register_info ei[] = {
3120 { &ei_pdcp_lte_sequence_analysis_sn_missing, { "pdcp-lte.sequence-analysis.sn-missing", PI_SEQUENCE, PI_WARN, "PDCP SN missing", EXPFILL }},
3121 { &ei_pdcp_lte_sequence_analysis_sn_repeated, { "pdcp-lte.sequence-analysis.sn-repeated", PI_SEQUENCE, PI_WARN, "PDCP SN repeated", EXPFILL }},
3122 { &ei_pdcp_lte_sequence_analysis_wrong_sequence_number, { "pdcp-lte.sequence-analysis.wrong-sequence-number", PI_SEQUENCE, PI_WARN, "Wrong Sequence Number", EXPFILL }},
3123 { &ei_pdcp_lte_reserved_bits_not_zero, { "pdcp-lte.reserved-bits-not-zero", PI_MALFORMED, PI_ERROR, "Reserved bits not zero", EXPFILL }},
3124 { &ei_pdcp_lte_digest_wrong, { "pdcp-lte.maci-wrong", PI_SEQUENCE, PI_ERROR, "MAC-I doesn't match expected value", EXPFILL }},
3125 { &ei_pdcp_lte_unknown_udp_framing_tag, { "pdcp-lte.unknown-udp-framing-tag", PI_UNDECODED, PI_WARN, "Unknown UDP framing tag, aborting dissection", EXPFILL }},
3126 { &ei_pdcp_lte_missing_udp_framing_tag, { "pdcp-lte.missing-udp-framing-tag", PI_UNDECODED, PI_WARN, "Missing UDP framing conditional tag, aborting dissection", EXPFILL }}
3129 static const enum_val_t sequence_analysis_vals[] = {
3130 {"no-analysis", "No-Analysis", false},
3131 {"rlc-only", "Only-RLC-frames", SEQUENCE_ANALYSIS_RLC_ONLY},
3132 {"pdcp-only", "Only-PDCP-frames", SEQUENCE_ANALYSIS_PDCP_ONLY},
3133 {NULL, NULL, -1}
3136 static const enum_val_t show_info_col_vals[] = {
3137 {"show-rlc", "RLC Info", ShowRLCLayer},
3138 {"show-pdcp", "PDCP Info", ShowPDCPLayer},
3139 {"show-traffic", "Traffic Info", ShowTrafficLayer},
3140 {NULL, NULL, -1}
3143 static const enum_val_t default_ciphering_algorithm_vals[] = {
3144 {"eea0", "EEA0 (NULL)", eea0},
3145 {"eea1", "EEA1 (SNOW3G)", eea1},
3146 {"eea2", "EEA2 (AES)", eea2},
3147 {"eea3", "EEA3 (ZUC)", eea3},
3148 {NULL, NULL, -1}
3151 static const enum_val_t default_integrity_algorithm_vals[] = {
3152 {"eia0", "EIA0 (NULL)", eia0},
3153 {"eia1", "EIA1 (SNOW3G)", eia1},
3154 {"eia2", "EIA2 (AES)", eia2},
3155 {"eia3", "EIA3 (ZUC)", eia3},
3156 {NULL, NULL, -1}
3159 static uat_field_t ue_keys_uat_flds[] = {
3160 UAT_FLD_DEC(uat_ue_keys_records, ueid, "UEId", "UE Identifier of UE associated with keys"),
3161 UAT_FLD_CSTRING(uat_ue_keys_records, rrcCipherKeyString, "RRC Cipher Key", "Key for deciphering signalling messages"),
3162 UAT_FLD_CSTRING(uat_ue_keys_records, upCipherKeyString, "User-Plane Cipher Key", "Key for deciphering user-plane messages"),
3163 UAT_FLD_CSTRING(uat_ue_keys_records, rrcIntegrityKeyString, "RRC Integrity Key", "Key for calculating integrity MAC"),
3164 UAT_END_FIELDS
3167 module_t *pdcp_lte_module;
3168 expert_module_t* expert_pdcp_lte;
3170 /* Register protocol. */
3171 proto_pdcp_lte = proto_register_protocol("PDCP-LTE", "PDCP-LTE", "pdcp-lte");
3172 proto_register_field_array(proto_pdcp_lte, hf, array_length(hf));
3173 proto_register_subtree_array(ett, array_length(ett));
3174 expert_pdcp_lte = expert_register_protocol(proto_pdcp_lte);
3175 expert_register_field_array(expert_pdcp_lte, ei, array_length(ei));
3177 /* Allow other dissectors to find this one by name. */
3178 register_dissector("pdcp-lte", dissect_pdcp_lte, proto_pdcp_lte);
3180 pdcp_lte_module = prefs_register_protocol(proto_pdcp_lte, NULL);
3182 /* Obsolete preferences */
3183 prefs_register_obsolete_preference(pdcp_lte_module, "show_feedback_option_tag_length");
3185 /* Dissect uncompressed user-plane data as IP */
3186 prefs_register_bool_preference(pdcp_lte_module, "show_user_plane_as_ip",
3187 "Show uncompressed User-Plane data as IP",
3188 "Show uncompressed User-Plane data as IP",
3189 &global_pdcp_dissect_user_plane_as_ip);
3191 /* Dissect unciphered signalling data as RRC */
3192 prefs_register_bool_preference(pdcp_lte_module, "show_signalling_plane_as_rrc",
3193 "Show unciphered Signalling-Plane data as RRC",
3194 "Show unciphered Signalling-Plane data as RRC",
3195 &global_pdcp_dissect_signalling_plane_as_rrc);
3197 /* Check for missing sequence numbers */
3198 prefs_register_enum_preference(pdcp_lte_module, "check_sequence_numbers",
3199 "Do sequence number analysis",
3200 "Do sequence number analysis",
3201 &global_pdcp_check_sequence_numbers, sequence_analysis_vals, false);
3203 /* Attempt to dissect ROHC messages */
3204 prefs_register_bool_preference(pdcp_lte_module, "dissect_rohc",
3205 "Attempt to decode ROHC data",
3206 "Attempt to decode ROHC data",
3207 &global_pdcp_dissect_rohc);
3209 prefs_register_obsolete_preference(pdcp_lte_module, "heuristic_pdcp_lte_over_udp");
3211 prefs_register_enum_preference(pdcp_lte_module, "layer_to_show",
3212 "Which layer info to show in Info column",
3213 "Can show RLC, PDCP or Traffic layer info in Info column",
3214 &global_pdcp_lte_layer_to_show, show_info_col_vals, false);
3216 ue_keys_uat = uat_new("PDCP UE security keys",
3217 sizeof(uat_ue_keys_record_t), /* record size */
3218 "pdcp_lte_ue_keys", /* filename */
3219 true, /* from_profile */
3220 &uat_ue_keys_records, /* data_ptr */
3221 &num_ue_keys_uat, /* numitems_ptr */
3222 UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */
3223 NULL, /* help */
3224 uat_ue_keys_record_copy_cb, /* copy callback */
3225 uat_ue_keys_record_update_cb, /* update callback */
3226 uat_ue_keys_record_free_cb, /* free callback */
3227 NULL, /* post update callback */
3228 NULL, /* reset callback */
3229 ue_keys_uat_flds); /* UAT field definitions */
3231 prefs_register_uat_preference(pdcp_lte_module,
3232 "ue_keys_table",
3233 "PDCP UE Keys",
3234 "Preconfigured PDCP keys",
3235 ue_keys_uat);
3237 prefs_register_enum_preference(pdcp_lte_module, "default_ciphering_algorithm",
3238 "Ciphering algorithm to use if not signalled",
3239 "If RRC Security Info not seen, e.g. in Handover",
3240 (int*)&global_default_ciphering_algorithm, default_ciphering_algorithm_vals, false);
3242 prefs_register_enum_preference(pdcp_lte_module, "default_integrity_algorithm",
3243 "Integrity algorithm to use if not signalled",
3244 "If RRC Security Info not seen, e.g. in Handover",
3245 (int*)&global_default_integrity_algorithm, default_integrity_algorithm_vals, false);
3247 /* Attempt to decipher RRC messages */
3248 prefs_register_bool_preference(pdcp_lte_module, "decipher_signalling",
3249 "Attempt to decipher Signalling (RRC) SDUs",
3250 "N.B. only possible if build with algorithm support, and have key available and configured",
3251 &global_pdcp_decipher_signalling);
3253 /* Attempt to decipher user-plane messages */
3254 prefs_register_bool_preference(pdcp_lte_module, "decipher_userplane",
3255 "Attempt to decipher User-plane (IP) SDUs",
3256 "N.B. only possible if build with algorithm support, and have key available and configured",
3257 &global_pdcp_decipher_userplane);
3259 /* Attempt to verify RRC integrity/authentication digest */
3260 prefs_register_bool_preference(pdcp_lte_module, "verify_integrity",
3261 "Attempt to check integrity calculation",
3262 "N.B. only possible if build with algorithm support, and have key available and configured",
3263 &global_pdcp_check_integrity);
3265 prefs_register_bool_preference(pdcp_lte_module, "ignore_rrc_sec_params",
3266 "Ignore RRC security parameters",
3267 "Ignore the LTE RRC security algorithm configuration, to be used when PDCP is already deciphered in the capture",
3268 &global_pdcp_ignore_sec);
3270 pdcp_sequence_analysis_channel_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), g_direct_hash, g_direct_equal);
3271 pdcp_lte_sequence_analysis_report_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), pdcp_result_hash_func, pdcp_result_hash_equal);
3272 pdcp_security_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), g_direct_hash, g_direct_equal);
3273 pdcp_security_result_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), pdcp_lte_ueid_frame_hash_func, pdcp_lte_ueid_frame_hash_equal);
3274 pdcp_security_key_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), g_direct_hash, g_direct_equal);
3277 void proto_reg_handoff_pdcp_lte(void)
3279 /* Add as a heuristic UDP dissector */
3280 heur_dissector_add("udp", dissect_pdcp_lte_heur, "PDCP-LTE over UDP", "pdcp_lte_udp", proto_pdcp_lte, HEURISTIC_DISABLE);
3282 ip_handle = find_dissector_add_dependency("ip", proto_pdcp_lte);
3283 ipv6_handle = find_dissector_add_dependency("ipv6", proto_pdcp_lte);
3284 rohc_handle = find_dissector_add_dependency("rohc", proto_pdcp_lte);
3285 lte_rrc_ul_ccch = find_dissector_add_dependency("lte_rrc.ul_ccch", proto_pdcp_lte);
3286 lte_rrc_dl_ccch = find_dissector_add_dependency("lte_rrc.dl_ccch", proto_pdcp_lte);
3287 lte_rrc_pcch = find_dissector_add_dependency("lte_rrc.pcch", proto_pdcp_lte);
3288 lte_rrc_bcch_bch = find_dissector_add_dependency("lte_rrc.bcch_bch", proto_pdcp_lte);
3289 lte_rrc_bcch_dl_sch = find_dissector_add_dependency("lte_rrc.bcch_dl_sch", proto_pdcp_lte);
3290 lte_rrc_ul_dcch = find_dissector_add_dependency("lte_rrc.ul_dcch", proto_pdcp_lte);
3291 lte_rrc_dl_dcch = find_dissector_add_dependency("lte_rrc.dl_dcch", proto_pdcp_lte);
3292 lte_rrc_ul_ccch_nb = find_dissector_add_dependency("lte_rrc.ul_ccch.nb", proto_pdcp_lte);
3293 lte_rrc_dl_ccch_nb = find_dissector_add_dependency("lte_rrc.dl_ccch.nb", proto_pdcp_lte);
3294 lte_rrc_pcch_nb = find_dissector_add_dependency("lte_rrc.pcch.nb", proto_pdcp_lte);
3295 lte_rrc_bcch_bch_nb = find_dissector_add_dependency("lte_rrc.bcch_bch.nb", proto_pdcp_lte);
3296 lte_rrc_bcch_dl_sch_nb = find_dissector_add_dependency("lte_rrc.bcch_dl_sch.nb", proto_pdcp_lte);
3297 lte_rrc_ul_dcch_nb = find_dissector_add_dependency("lte_rrc.ul_dcch.nb", proto_pdcp_lte);
3298 lte_rrc_dl_dcch_nb = find_dissector_add_dependency("lte_rrc.dl_dcch.nb", proto_pdcp_lte);
3302 * Editor modelines
3304 * Local Variables:
3305 * c-basic-offset: 4
3306 * tab-width: 8
3307 * indent-tabs-mode: nil
3308 * End:
3310 * ex: set shiftwidth=4 tabstop=8 expandtab:
3311 * :indentSize=4:tabSize=8:noTabs=true: