Revert "TODO epan/dissectors/asn1/kerberos/packet-kerberos-template.c new GSS flags"
[wireshark-sm.git] / epan / dissectors / packet-pdcp-nr.c
blob356d8b3a55e9b510c0128fa015f13d3e16494a13
1 /* packet-pdcp-nr.c
2 * Routines for nr 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>
21 #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. */
29 /* #define HAVE_SNOW3G */
30 /* #define HAVE_ZUC */
33 #include "packet-rlc-nr.h"
34 #include "packet-pdcp-nr.h"
36 void proto_register_pdcp_nr(void);
37 void proto_reg_handoff_pdcp_nr(void);
39 /* Described in:
40 * 3GPP TS 38.323 Technical Specification Group Radio Access Netowrk; NR;
41 * Packet Data Convergence Protocol (PDCP) specification (Release 15.1.0)
42 * 3GPP TS 37.324 Technical Specification Group Radio Access Network; E-UTRA and NR;
43 * Service Data Adaptation Protocol (SDAP) specification (Release 15)
47 /* TODO:
48 - look into refactoring/sharing parts of deciphering/integrity with LTE implementation
52 /* Initialize the protocol and registered fields. */
53 int proto_pdcp_nr;
55 extern int proto_rlc_nr;
57 /* Configuration (info known outside of PDU) */
58 static int hf_pdcp_nr_configuration;
59 static int hf_pdcp_nr_direction;
60 static int hf_pdcp_nr_ueid;
61 static int hf_pdcp_nr_bearer_type;
62 static int hf_pdcp_nr_bearer_id;
63 static int hf_pdcp_nr_plane;
64 static int hf_pdcp_nr_seqnum_length;
65 static int hf_pdcp_nr_maci_present;
66 static int hf_pdcp_nr_sdap;
67 static int hf_pdcp_nr_ciphering_disabled;
69 static int hf_pdcp_nr_rohc_compression;
70 static int hf_pdcp_nr_rohc_mode;
71 static int hf_pdcp_nr_rohc_rnd;
72 static int hf_pdcp_nr_rohc_udp_checksum_present;
73 static int hf_pdcp_nr_rohc_profile;
74 static int hf_pdcp_nr_cid_inclusion_info;
75 static int hf_pdcp_nr_large_cid_present;
77 /* PDCP header fields */
78 static int hf_pdcp_nr_control_plane_reserved;
79 static int hf_pdcp_nr_reserved3;
80 static int hf_pdcp_nr_seq_num_12;
81 static int hf_pdcp_nr_reserved5;
82 static int hf_pdcp_nr_seq_num_18;
83 static int hf_pdcp_nr_signalling_data;
84 static int hf_pdcp_nr_mac;
85 static int hf_pdcp_nr_data_control;
86 static int hf_pdcp_nr_user_plane_data;
87 static int hf_pdcp_nr_control_pdu_type;
88 static int hf_pdcp_nr_fmc;
89 static int hf_pdcp_nr_reserved4;
90 static int hf_pdcp_nr_bitmap;
91 static int hf_pdcp_nr_bitmap_byte;
93 /* Sequence Analysis */
94 static int hf_pdcp_nr_sequence_analysis;
95 static int hf_pdcp_nr_sequence_analysis_ok;
96 static int hf_pdcp_nr_sequence_analysis_previous_frame;
97 static int hf_pdcp_nr_sequence_analysis_next_frame;
98 static int hf_pdcp_nr_sequence_analysis_expected_sn;
99 static int hf_pdcp_nr_sequence_analysis_repeated;
100 static int hf_pdcp_nr_sequence_analysis_skipped;
102 /* Security Settings */
103 static int hf_pdcp_nr_security;
104 static int hf_pdcp_nr_security_setup_frame;
105 static int hf_pdcp_nr_security_integrity_algorithm;
106 static int hf_pdcp_nr_security_ciphering_algorithm;
108 static int hf_pdcp_nr_security_bearer;
109 static int hf_pdcp_nr_security_direction;
110 static int hf_pdcp_nr_security_count;
111 static int hf_pdcp_nr_security_cipher_key;
112 static int hf_pdcp_nr_security_integrity_key;
113 static int hf_pdcp_nr_security_cipher_key_setup_frame;
114 static int hf_pdcp_nr_security_integrity_key_setup_frame;
115 static int hf_pdcp_nr_security_deciphered_data;
117 static int hf_pdcp_nr_security_integrity_data;
120 /* Protocol subtree. */
121 static int ett_pdcp;
122 static int ett_pdcp_configuration;
123 static int ett_pdcp_packet;
124 static int ett_pdcp_nr_sequence_analysis;
125 static int ett_pdcp_report_bitmap;
126 static int ett_pdcp_security;
128 static expert_field ei_pdcp_nr_sequence_analysis_wrong_sequence_number_ul;
129 static expert_field ei_pdcp_nr_sequence_analysis_wrong_sequence_number_dl;
130 static expert_field ei_pdcp_nr_reserved_bits_not_zero;
131 static expert_field ei_pdcp_nr_sequence_analysis_sn_repeated_ul;
132 static expert_field ei_pdcp_nr_sequence_analysis_sn_repeated_dl;
133 static expert_field ei_pdcp_nr_sequence_analysis_sn_missing_ul;
134 static expert_field ei_pdcp_nr_sequence_analysis_sn_missing_dl;
135 static expert_field ei_pdcp_nr_digest_wrong;
136 static expert_field ei_pdcp_nr_unknown_udp_framing_tag;
137 static expert_field ei_pdcp_nr_missing_udp_framing_tag;
139 /*-------------------------------------
140 * UAT for UE Keys
141 *-------------------------------------
143 /* UAT entry structure. */
144 typedef struct {
145 uint32_t ueid;
146 char *rrcCipherKeyString;
147 char *upCipherKeyString;
148 char *rrcIntegrityKeyString;
149 char *upIntegrityKeyString;
151 uint8_t rrcCipherBinaryKey[16];
152 bool rrcCipherKeyOK;
153 uint8_t upCipherBinaryKey[16];
154 bool upCipherKeyOK;
155 uint8_t rrcIntegrityBinaryKey[16];
156 bool rrcIntegrityKeyOK;
157 uint8_t upIntegrityBinaryKey[16];
158 bool upIntegrityKeyOK;
160 } uat_ue_keys_record_t;
162 /* N.B. this is an array/table of the struct above, where ueid is the key */
163 static uat_ue_keys_record_t *uat_ue_keys_records;
165 /* Entries added by UAT */
166 static uat_t * ue_keys_uat;
167 static unsigned num_ue_keys_uat;
169 /* Convert an ascii hex character into a digit. Should only be given valid
170 hex ascii characters */
171 static unsigned char hex_ascii_to_binary(char c)
173 if ((c >= '0') && (c <= '9')) {
174 return c - '0';
176 else if ((c >= 'a') && (c <= 'f')) {
177 return 10 + c - 'a';
179 else if ((c >= 'A') && (c <= 'F')) {
180 return 10 + c - 'A';
182 else {
183 return 0;
187 static void* uat_ue_keys_record_copy_cb(void* n, const void* o, size_t siz _U_) {
188 uat_ue_keys_record_t* new_rec = (uat_ue_keys_record_t *)n;
189 const uat_ue_keys_record_t* old_rec = (const uat_ue_keys_record_t *)o;
191 new_rec->ueid = old_rec->ueid;
192 new_rec->rrcCipherKeyString = g_strdup(old_rec->rrcCipherKeyString);
193 new_rec->upCipherKeyString = g_strdup(old_rec->upCipherKeyString);
194 new_rec->rrcIntegrityKeyString = g_strdup(old_rec->rrcIntegrityKeyString);
195 new_rec->upIntegrityKeyString = g_strdup(old_rec->upIntegrityKeyString);
197 return new_rec;
200 /* If raw_string is a valid key, set check_string & return true. Can be spaced out with ' ' or '-' */
201 static bool check_valid_key_string(const char* raw_string, char* checked_string, char **error)
203 unsigned n;
204 unsigned written = 0;
205 unsigned length = (int)strlen(raw_string);
207 /* Can't be valid if not long enough. */
208 if (length < 32) {
209 if (length > 0) {
210 *error = ws_strdup_printf("PDCP NR: Invalid key string (%s) - should include 32 ASCII hex characters (16 bytes) but only %u chars given",
211 raw_string, length);
213 return false;
216 for (n=0; (n < length) && (written < 32); n++) {
217 char c = raw_string[n];
219 /* Skipping past allowed 'padding' characters */
220 if ((c == ' ') || (c == '-')) {
221 continue;
224 /* Other characters must be hex digits, otherwise string is invalid */
225 if (((c >= '0') && (c <= '9')) ||
226 ((c >= 'a') && (c <= 'f')) ||
227 ((c >= 'A') && (c <= 'F'))) {
228 checked_string[written++] = c;
230 else {
231 *error = ws_strdup_printf("PDCP-NR: Invalid char '%c' given in key", c);
232 return false;
236 /* Must have found exactly 32 hex ascii chars for 16-byte key */
237 if (n<length) {
238 *error = ws_strdup_printf("PDCP-NR: Key (%s) should contain 32 hex characters (16 bytes) but more detected", raw_string);
239 return false;
241 if (written != 32) {
242 *error = ws_strdup_printf("PDCP-NR: Key (%s) should contain 32 hex characters (16 bytes) but %u detected", raw_string, written);
243 return false;
245 else {
246 return true;
250 /* Write binary key by converting each nibble from the string version */
251 static void update_key_from_string(const char *stringKey, uint8_t *binaryKey, bool *pKeyOK, char **error)
253 int n;
254 char cleanString[32];
256 if (!check_valid_key_string(stringKey, cleanString, error)) {
257 *pKeyOK = false;
259 else {
260 for (n=0; n < 32; n += 2) {
261 binaryKey[n/2] = (hex_ascii_to_binary(cleanString[n]) << 4) +
262 hex_ascii_to_binary(cleanString[n+1]);
264 *pKeyOK = true;
268 /* Update by checking whether the 3 key strings are valid or not, and storing result */
269 static bool uat_ue_keys_record_update_cb(void* record, char** error) {
270 uat_ue_keys_record_t* rec = (uat_ue_keys_record_t *)record;
272 /* Check and convert RRC cipher key */
273 update_key_from_string(rec->rrcCipherKeyString, rec->rrcCipherBinaryKey, &rec->rrcCipherKeyOK, error);
275 /* Check and convert User-plane cipher key */
276 update_key_from_string(rec->upCipherKeyString, rec->upCipherBinaryKey, &rec->upCipherKeyOK, error);
278 /* Check and convert RRC Integrity key */
279 update_key_from_string(rec->rrcIntegrityKeyString, rec->rrcIntegrityBinaryKey, &rec->rrcIntegrityKeyOK, error);
281 /* Check and convert User-plane Integrity key */
282 update_key_from_string(rec->upIntegrityKeyString, rec->upIntegrityBinaryKey, &rec->upIntegrityKeyOK, error);
284 /* Return true only if *error has not been set by checking code. */
285 return *error == NULL;
288 /* Free heap parts of record */
289 static void uat_ue_keys_record_free_cb(void*r) {
290 uat_ue_keys_record_t* rec = (uat_ue_keys_record_t*)r;
292 g_free(rec->rrcCipherKeyString);
293 g_free(rec->upCipherKeyString);
294 g_free(rec->rrcIntegrityKeyString);
295 g_free(rec->upIntegrityKeyString);
298 UAT_DEC_CB_DEF(uat_ue_keys_records, ueid, uat_ue_keys_record_t)
299 UAT_CSTRING_CB_DEF(uat_ue_keys_records, rrcCipherKeyString, uat_ue_keys_record_t)
300 UAT_CSTRING_CB_DEF(uat_ue_keys_records, upCipherKeyString, uat_ue_keys_record_t)
301 UAT_CSTRING_CB_DEF(uat_ue_keys_records, rrcIntegrityKeyString, uat_ue_keys_record_t)
302 UAT_CSTRING_CB_DEF(uat_ue_keys_records, upIntegrityKeyString, uat_ue_keys_record_t)
304 /* Also supporting a hash table with entries from these functions */
306 /* Table from ueid -> ue_key_entries_t* */
307 static wmem_map_t *pdcp_security_key_hash;
309 typedef enum {
310 rrc_cipher,
311 rrc_integrity,
312 up_cipher,
313 up_integrity
314 } ue_key_type_t;
316 typedef struct {
317 ue_key_type_t key_type;
318 char *keyString;
319 uint8_t binaryKey[16];
320 bool keyOK;
321 uint32_t setup_frame;
322 } key_entry_t;
324 /* List of key entries for an individual UE */
325 typedef struct {
326 #define MAX_KEY_ENTRIES_PER_UE 32
327 unsigned num_entries_set;
328 key_entry_t entries[MAX_KEY_ENTRIES_PER_UE];
329 } ue_key_entries_t;
332 void set_pdcp_nr_rrc_ciphering_key(uint16_t ueid, const char *key, uint32_t frame_num)
334 char *err = NULL;
336 /* Get or create struct for this UE */
337 ue_key_entries_t *key_entries = (ue_key_entries_t*)wmem_map_lookup(pdcp_security_key_hash,
338 GUINT_TO_POINTER((unsigned)ueid));
339 if (key_entries == NULL) {
340 /* Create and add to table */
341 key_entries = wmem_new0(wmem_file_scope(), ue_key_entries_t);
342 wmem_map_insert(pdcp_security_key_hash, GUINT_TO_POINTER((unsigned)ueid), key_entries);
345 if (key_entries->num_entries_set == MAX_KEY_ENTRIES_PER_UE) {
346 /* No more room.. */
347 return;
350 key_entry_t *new_key_entry = &key_entries->entries[key_entries->num_entries_set++];
351 new_key_entry->key_type = rrc_cipher;
352 new_key_entry->keyString = g_strdup(key);
353 new_key_entry->setup_frame = frame_num;
354 update_key_from_string(new_key_entry->keyString, new_key_entry->binaryKey, &new_key_entry->keyOK, &err);
355 if (err) {
356 report_failure("%s: (RRC Ciphering Key)", err);
357 g_free(err);
361 void set_pdcp_nr_rrc_integrity_key(uint16_t ueid, const char *key, uint32_t frame_num)
363 char *err = NULL;
365 /* Get or create struct for this UE */
366 ue_key_entries_t *key_entries = (ue_key_entries_t*)wmem_map_lookup(pdcp_security_key_hash,
367 GUINT_TO_POINTER((unsigned)ueid));
368 if (key_entries == NULL) {
369 /* Create and add to table */
370 key_entries = wmem_new0(wmem_file_scope(), ue_key_entries_t);
371 wmem_map_insert(pdcp_security_key_hash, GUINT_TO_POINTER((unsigned)ueid), key_entries);
374 if (key_entries->num_entries_set == MAX_KEY_ENTRIES_PER_UE) {
375 /* No more room.. */
376 return;
379 key_entry_t *new_key_entry = &key_entries->entries[key_entries->num_entries_set++];
380 new_key_entry->key_type = rrc_integrity;
381 new_key_entry->keyString = g_strdup(key);
382 new_key_entry->setup_frame = frame_num;
383 update_key_from_string(new_key_entry->keyString, new_key_entry->binaryKey, &new_key_entry->keyOK, &err);
384 if (err) {
385 report_failure("%s: (RRC Integrity Key)", err);
386 g_free(err);
390 void set_pdcp_nr_up_ciphering_key(uint16_t ueid, const char *key, uint32_t frame_num)
392 char *err = NULL;
394 /* Get or create struct for this UE */
395 ue_key_entries_t *key_entries = (ue_key_entries_t*)wmem_map_lookup(pdcp_security_key_hash,
396 GUINT_TO_POINTER((unsigned)ueid));
397 if (key_entries == NULL) {
398 /* Create and add to table */
399 key_entries = wmem_new0(wmem_file_scope(), ue_key_entries_t);
400 wmem_map_insert(pdcp_security_key_hash, GUINT_TO_POINTER((unsigned)ueid), key_entries);
403 if (key_entries->num_entries_set == MAX_KEY_ENTRIES_PER_UE) {
404 /* No more room.. */
405 return;
408 key_entry_t *new_key_entry = &key_entries->entries[key_entries->num_entries_set++];
409 new_key_entry->key_type = up_cipher;
410 new_key_entry->keyString = g_strdup(key);
411 new_key_entry->setup_frame = frame_num;
412 update_key_from_string(new_key_entry->keyString, new_key_entry->binaryKey, &new_key_entry->keyOK, &err);
413 if (err) {
414 report_failure("%s: (UP Cipher Key)", err);
415 g_free(err);
419 void set_pdcp_nr_up_integrity_key(uint16_t ueid, const char *key, uint32_t frame_num)
421 char *err = NULL;
423 /* Get or create struct for this UE */
424 ue_key_entries_t *key_entries = (ue_key_entries_t*)wmem_map_lookup(pdcp_security_key_hash,
425 GUINT_TO_POINTER((unsigned)ueid));
426 if (key_entries == NULL) {
427 /* Create and add to table */
428 key_entries = wmem_new0(wmem_file_scope(), ue_key_entries_t);
429 wmem_map_insert(pdcp_security_key_hash, GUINT_TO_POINTER((unsigned)ueid), key_entries);
432 if (key_entries->num_entries_set == MAX_KEY_ENTRIES_PER_UE) {
433 /* No more room.. */
434 return;
437 key_entry_t *new_key_entry = &key_entries->entries[key_entries->num_entries_set++];
438 new_key_entry->key_type = up_integrity;
439 new_key_entry->keyString = g_strdup(key);
440 new_key_entry->setup_frame = frame_num;
441 update_key_from_string(new_key_entry->keyString, new_key_entry->binaryKey, &new_key_entry->keyOK, &err);
442 if (err) {
443 report_failure("%s: (UP Integrity Key)", err);
444 g_free(err);
449 static const value_string direction_vals[] =
451 { PDCP_NR_DIRECTION_UPLINK, "Uplink"},
452 { PDCP_NR_DIRECTION_DOWNLINK, "Downlink"},
453 { 0, NULL }
457 static const value_string pdcp_plane_vals[] = {
458 { NR_SIGNALING_PLANE, "Signalling" },
459 { NR_USER_PLANE, "User" },
460 { 0, NULL }
463 static const value_string bearer_type_vals[] = {
464 { Bearer_DCCH, "DCCH"},
465 { Bearer_BCCH_BCH, "BCCH_BCH"},
466 { Bearer_BCCH_DL_SCH, "BCCH_DL_SCH"},
467 { Bearer_CCCH, "CCCH"},
468 { Bearer_PCCH, "PCCH"},
469 { 0, NULL}
472 static const value_string rohc_mode_vals[] = {
473 { UNIDIRECTIONAL, "Unidirectional" },
474 { OPTIMISTIC_BIDIRECTIONAL, "Optimistic Bidirectional" },
475 { RELIABLE_BIDIRECTIONAL, "Reliable Bidirectional" },
476 { 0, NULL }
480 /* Entries taken from Table 5.7.1-1.
481 Descriptions from http://www.iana.org/assignments/rohc-pro-ids/rohc-pro-ids.txt */
482 static const value_string rohc_profile_vals[] = {
483 { 0x0000, "ROHC uncompressed" }, /* [RFC5795] */
484 { 0x0001, "ROHC RTP" }, /* [RFC3095] */
485 { 0x0002, "ROHC UDP" }, /* [RFC3095] */
486 { 0x0003, "ROHC ESP" }, /* [RFC3095] */
487 { 0x0004, "ROHC IP" }, /* [RFC3843] */
488 { 0x0006, "ROHC TCP" }, /* [RFC4996] */
490 { 0x0101, "ROHCv2 RTP" }, /* [RFC5225] */
491 { 0x0102, "ROHCv2 UDP" }, /* [RFC5225] */
492 { 0x0103, "ROHCv2 ESP" }, /* [RFC5225] */
493 { 0x0104, "ROHCv2 IP" }, /* [RFC5225] */
494 { 0, NULL }
497 static const value_string control_pdu_type_vals[] = {
498 { 0, "PDCP status report" },
499 { 1, "Interspersed ROHC feedback packet" },
500 { 0, NULL }
503 static const value_string integrity_algorithm_vals[] = {
504 { nia0, "NIA0 (NULL)" },
505 { nia1, "NIA1 (SNOW3G)" },
506 { nia2, "NIA2 (AES)" },
507 { nia3, "NIA3 (ZUC)" },
508 { 0, NULL }
511 static const value_string ciphering_algorithm_vals[] = {
512 { nea0, "NEA0 (NULL)" },
513 { nea1, "NEA1 (SNOW3G)" },
514 { nea2, "NEA2 (AES)" },
515 { nea3, "NEA3 (ZUC)" },
516 { nea_disabled, "Ciphering disabled" },
517 { 0, NULL }
521 /* SDAP header fields and tree */
522 static int proto_sdap;
523 static int hf_sdap_rdi;
524 static int hf_sdap_rqi;
525 static int hf_sdap_qfi;
526 static int hf_sdap_data_control;
527 static int hf_sdap_reserved;
528 static int ett_sdap;
530 static const true_false_string sdap_rdi = {
531 "To store QoS flow to DRB mapping rule",
532 "No action"
535 static const true_false_string sdap_rqi = {
536 "To inform NAS that RQI bit is set to 1",
537 "No action"
541 static dissector_handle_t ip_handle;
542 static dissector_handle_t ipv6_handle;
543 static dissector_handle_t rohc_handle;
544 static dissector_handle_t nr_rrc_ul_ccch;
545 static dissector_handle_t nr_rrc_ul_ccch1;
546 static dissector_handle_t nr_rrc_dl_ccch;
547 static dissector_handle_t nr_rrc_pcch;
548 static dissector_handle_t nr_rrc_bcch_bch;
549 static dissector_handle_t nr_rrc_bcch_dl_sch;
550 static dissector_handle_t nr_rrc_ul_dcch;
551 static dissector_handle_t nr_rrc_dl_dcch;
554 #define SEQUENCE_ANALYSIS_RLC_ONLY 1
555 #define SEQUENCE_ANALYSIS_PDCP_ONLY 2
557 /* Preference variables */
558 static bool global_pdcp_dissect_user_plane_as_ip = true;
559 static bool global_pdcp_dissect_signalling_plane_as_rrc = true;
560 static int global_pdcp_check_sequence_numbers = SEQUENCE_ANALYSIS_RLC_ONLY;
561 static bool global_pdcp_dissect_rohc;
563 /* Preference settings for deciphering and integrity checking. */
564 static bool global_pdcp_decipher_signalling = true;
565 static bool global_pdcp_decipher_userplane; /* Can be slow, so default to false */
566 static bool global_pdcp_check_integrity = true;
567 static bool global_pdcp_ignore_sec; /* Ignore Set Security Algo calls */
569 /* Use these values where we know the keys but may have missed the algorithm,
570 e.g. when handing over and RRCReconfigurationRequest goes to target cell only */
571 static enum nr_security_ciphering_algorithm_e global_default_ciphering_algorithm = nea0;
572 static enum nr_security_integrity_algorithm_e global_default_integrity_algorithm = nia0;
574 /* Which layer info to show in the info column */
575 enum layer_to_show {
576 ShowRLCLayer, ShowPDCPLayer, ShowTrafficLayer
578 static int global_pdcp_nr_layer_to_show = (int)ShowRLCLayer;
581 /* Function to be called from outside this module (e.g. in a plugin) to get per-packet data */
582 pdcp_nr_info *get_pdcp_nr_proto_data(packet_info *pinfo)
584 return (pdcp_nr_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_pdcp_nr, 0);
587 /* Function to be called from outside this module (e.g. in a plugin) to set per-packet data */
588 void set_pdcp_nr_proto_data(packet_info *pinfo, pdcp_nr_info *p_pdcp_nr_info)
590 p_add_proto_data(wmem_file_scope(), pinfo, proto_pdcp_nr, 0, p_pdcp_nr_info);
595 /**************************************************/
596 /* Sequence number analysis */
598 /* Bearer key */
599 typedef struct
601 /* Using bit fields to fit into 32 bits, so avoiding the need to allocate
602 heap memory for these structs */
603 unsigned ueId : 16;
604 unsigned plane : 2;
605 unsigned bearerId : 6;
606 unsigned direction : 1;
607 unsigned notUsed : 7;
608 } pdcp_bearer_hash_key;
610 /* Bearer state */
611 typedef struct
613 uint32_t previousSequenceNumber;
614 uint32_t previousFrameNum;
615 uint32_t hfn;
616 } pdcp_bearer_status;
618 /* The sequence analysis bearer hash table.
619 Maps key -> status */
620 static wmem_map_t *pdcp_sequence_analysis_bearer_hash;
623 /* Hash table types & functions for frame reports */
625 typedef struct {
626 uint32_t frameNumber;
627 uint32_t SN : 18;
628 uint32_t plane : 2;
629 uint32_t bearerId: 5;
630 uint32_t direction: 1;
631 uint32_t notUsed : 6;
632 } pdcp_result_hash_key;
634 static int pdcp_result_hash_equal(const void *v, const void *v2)
636 const pdcp_result_hash_key* val1 = (const pdcp_result_hash_key *)v;
637 const pdcp_result_hash_key* val2 = (const pdcp_result_hash_key *)v2;
639 /* All fields must match */
640 return (memcmp(val1, val2, sizeof(pdcp_result_hash_key)) == 0);
643 /* Compute a hash value for a given key. */
644 static unsigned pdcp_result_hash_func(const void *v)
646 const pdcp_result_hash_key* val1 = (const pdcp_result_hash_key *)v;
648 /* TODO: This is a bit random. */
649 return val1->frameNumber + (val1->bearerId<<7) +
650 (val1->plane<<12) +
651 (val1->SN<<14) +
652 (val1->direction<<6);
655 /* pdcp_bearer_hash_key fits into the pointer, so just copy the value into
656 a unsigned, cast to a pointer and return that as the key */
657 static void *get_bearer_hash_key(pdcp_bearer_hash_key *key)
659 unsigned asInt = 0;
660 /* TODO: assert that sizeof(pdcp_bearer_hash_key) <= sizeof(unsigned) ? */
661 memcpy(&asInt, key, sizeof(pdcp_bearer_hash_key));
662 return GUINT_TO_POINTER(asInt);
665 /* Convenience function to get a pointer for the hash_func to work with */
666 static void *get_report_hash_key(uint32_t SN, uint32_t frameNumber,
667 pdcp_nr_info *p_pdcp_nr_info,
668 bool do_persist)
670 static pdcp_result_hash_key key;
671 pdcp_result_hash_key *p_key;
673 /* Only allocate a struct when will be adding entry */
674 if (do_persist) {
675 p_key = wmem_new(wmem_file_scope(), pdcp_result_hash_key);
677 else {
678 memset(&key, 0, sizeof(pdcp_result_hash_key));
679 p_key = &key;
682 /* Fill in details, and return pointer */
683 p_key->frameNumber = frameNumber;
684 p_key->SN = SN;
685 p_key->plane = (uint8_t)p_pdcp_nr_info->plane;
686 p_key->bearerId = p_pdcp_nr_info->bearerId;
687 p_key->direction = p_pdcp_nr_info->direction;
688 p_key->notUsed = 0;
690 return p_key;
694 /* Info to attach to frame when first read, recording what to show about sequence */
695 typedef enum
697 SN_OK, SN_Repeated, SN_MAC_Retx, SN_Retx, SN_Missing
698 } sequence_state;
699 typedef struct
701 bool sequenceExpectedCorrect;
702 uint32_t sequenceExpected;
703 uint32_t previousFrameNum;
704 uint32_t nextFrameNum;
706 uint32_t firstSN;
707 uint32_t lastSN;
708 uint32_t hfn;
710 sequence_state state;
711 } pdcp_sequence_report_in_frame;
713 /* The sequence analysis frame report hash table.
714 Maps pdcp_result_hash_key* -> pdcp_sequence_report_in_frame* */
715 static wmem_map_t *pdcp_nr_sequence_analysis_report_hash;
717 /* Gather together security settings in order to be able to do deciphering */
718 typedef struct pdu_security_settings_t
720 enum nr_security_ciphering_algorithm_e ciphering;
721 enum nr_security_integrity_algorithm_e integrity;
722 uint8_t* cipherKey;
723 uint8_t* integrityKey;
724 bool cipherKeyValid;
725 bool integrityKeyValid;
726 uint32_t count;
727 uint8_t bearer;
728 uint8_t direction;
729 } pdu_security_settings_t;
731 static uat_ue_keys_record_t* look_up_keys_record(uint16_t ueid, uint32_t frame_num,
732 uint32_t *config_frame_rrc_cipher,
733 uint32_t *config_frame_rrc_integrity,
734 uint32_t *config_frame_up_cipher,
735 uint32_t *config_frame_up_integrity)
737 unsigned int record_id;
739 /* Try hash table first (among entries added by set_pdcp_nr_xxx_key() functions) */
740 ue_key_entries_t* key_record = (ue_key_entries_t*)wmem_map_lookup(pdcp_security_key_hash,
741 GUINT_TO_POINTER((unsigned)ueid));
742 if (key_record != NULL) {
743 /* Will build up and return usual type */
744 uat_ue_keys_record_t *keys = wmem_new0(wmem_file_scope(), uat_ue_keys_record_t);
746 /* Fill in details */
747 keys->ueid = ueid;
748 /* Walk entries backwards (want last entry before frame_num) */
749 for (int e=key_record->num_entries_set; e>0; e--) {
750 key_entry_t *entry = &key_record->entries[e-1];
752 if (frame_num > entry->setup_frame) {
753 /* This frame is after corresponding setup, so can adopt if don't have one */
754 switch (entry->key_type) {
755 case rrc_cipher:
756 if (!keys->rrcCipherKeyOK) {
757 keys->rrcCipherKeyString = entry->keyString;
758 memcpy(keys->rrcCipherBinaryKey, entry->binaryKey, 16);
759 keys->rrcCipherKeyOK = entry->keyOK;
760 *config_frame_rrc_cipher = entry->setup_frame;
762 break;
763 case rrc_integrity:
764 if (!keys->rrcIntegrityKeyOK) {
765 keys->rrcIntegrityKeyString = entry->keyString;
766 memcpy(keys->rrcIntegrityBinaryKey, entry->binaryKey, 16);
767 keys->rrcIntegrityKeyOK = entry->keyOK;
768 *config_frame_rrc_integrity = entry->setup_frame;
770 break;
771 case up_cipher:
772 if (!keys->upCipherKeyOK) {
773 keys->upCipherKeyString = entry->keyString;
774 memcpy(keys->upCipherBinaryKey, entry->binaryKey, 16);
775 keys->upCipherKeyOK = entry->keyOK;
776 *config_frame_up_cipher = entry->setup_frame;
778 break;
779 case up_integrity:
780 if (!keys->upIntegrityKeyOK) {
781 keys->upIntegrityKeyString = entry->keyString;
782 memcpy(keys->upIntegrityBinaryKey, entry->binaryKey, 16);
783 keys->upIntegrityKeyOK = entry->keyOK;
784 *config_frame_up_integrity = entry->setup_frame;
786 break;
790 /* Return this struct (even if doesn't have all/any keys set..) */
791 return keys;
794 /* Else look up UAT entries. N.B. linear search... */
795 for (record_id=0; record_id < num_ue_keys_uat; record_id++) {
796 if (uat_ue_keys_records[record_id].ueid == ueid) {
797 return &uat_ue_keys_records[record_id];
801 /* No match at all - return NULL */
802 return NULL;
805 /* Add to the tree values associated with sequence analysis for this frame */
806 static void addBearerSequenceInfo(pdcp_sequence_report_in_frame *p,
807 pdcp_nr_info *p_pdcp_nr_info,
808 uint32_t sequenceNumber,
809 packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb,
810 proto_tree *security_tree,
811 pdu_security_settings_t *pdu_security)
813 proto_tree *seqnum_tree;
814 proto_item *seqnum_ti;
815 proto_item *ti_expected_sn;
816 proto_item *ti;
817 uat_ue_keys_record_t *keys_record;
819 /* Create subtree */
820 seqnum_ti = proto_tree_add_string_format(tree,
821 hf_pdcp_nr_sequence_analysis,
822 tvb, 0, 0,
823 "", "Sequence Analysis");
824 seqnum_tree = proto_item_add_subtree(seqnum_ti,
825 ett_pdcp_nr_sequence_analysis);
826 proto_item_set_generated(seqnum_ti);
829 /* Previous bearer frame */
830 if (p->previousFrameNum != 0) {
831 proto_tree_add_uint(seqnum_tree, hf_pdcp_nr_sequence_analysis_previous_frame,
832 tvb, 0, 0, p->previousFrameNum);
835 /* Expected sequence number */
836 ti_expected_sn = proto_tree_add_uint(seqnum_tree, hf_pdcp_nr_sequence_analysis_expected_sn,
837 tvb, 0, 0, p->sequenceExpected);
838 proto_item_set_generated(ti_expected_sn);
840 /* Make sure we have recognised SN length */
841 switch (p_pdcp_nr_info->seqnum_length) {
842 case PDCP_NR_SN_LENGTH_12_BITS:
843 case PDCP_NR_SN_LENGTH_18_BITS:
844 break;
845 default:
846 DISSECTOR_ASSERT_NOT_REACHED();
847 break;
850 switch (p->state) {
851 case SN_OK:
852 proto_item_set_hidden(ti_expected_sn);
853 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_nr_sequence_analysis_ok,
854 tvb, 0, 0, true);
855 proto_item_set_generated(ti);
856 proto_item_append_text(seqnum_ti, " - OK");
858 /* Link to next SN in bearer (if known) */
859 if (p->nextFrameNum != 0) {
860 proto_tree_add_uint(seqnum_tree, hf_pdcp_nr_sequence_analysis_next_frame,
861 tvb, 0, 0, p->nextFrameNum);
864 break;
866 case SN_Missing:
867 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_nr_sequence_analysis_ok,
868 tvb, 0, 0, false);
869 proto_item_set_generated(ti);
870 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_nr_sequence_analysis_skipped,
871 tvb, 0, 0, true);
872 proto_item_set_generated(ti);
873 if (p->lastSN != p->firstSN) {
874 /* Range missing */
875 expert_add_info_format(pinfo, ti,
876 (p_pdcp_nr_info->direction == PDCP_NR_DIRECTION_UPLINK) ?
877 &ei_pdcp_nr_sequence_analysis_sn_missing_ul :
878 &ei_pdcp_nr_sequence_analysis_sn_missing_dl,
879 "PDCP SNs (%u to %u) missing for %s on UE %u (%s-%u)",
880 p->firstSN, p->lastSN,
881 val_to_str_const(p_pdcp_nr_info->direction, direction_vals, "Unknown"),
882 p_pdcp_nr_info->ueid,
883 val_to_str_const(p_pdcp_nr_info->bearerType, bearer_type_vals, "Unknown"),
884 p_pdcp_nr_info->bearerId);
885 proto_item_append_text(seqnum_ti, " - SNs missing (%u to %u)",
886 p->firstSN, p->lastSN);
888 else {
889 /* Single SN missing */
890 expert_add_info_format(pinfo, ti,
891 (p_pdcp_nr_info->direction == PDCP_NR_DIRECTION_UPLINK) ?
892 &ei_pdcp_nr_sequence_analysis_sn_missing_ul :
893 &ei_pdcp_nr_sequence_analysis_sn_missing_dl,
894 "PDCP SN (%u) missing for %s on UE %u (%s-%u)",
895 p->firstSN,
896 val_to_str_const(p_pdcp_nr_info->direction, direction_vals, "Unknown"),
897 p_pdcp_nr_info->ueid,
898 val_to_str_const(p_pdcp_nr_info->bearerType, bearer_type_vals, "Unknown"),
899 p_pdcp_nr_info->bearerId);
900 proto_item_append_text(seqnum_ti, " - SN missing (%u)",
901 p->firstSN);
903 break;
905 case SN_Repeated:
906 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_nr_sequence_analysis_ok,
907 tvb, 0, 0, false);
908 proto_item_set_generated(ti);
909 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_nr_sequence_analysis_repeated,
910 tvb, 0, 0, true);
911 proto_item_set_generated(ti);
912 expert_add_info_format(pinfo, ti,
913 (p_pdcp_nr_info->direction == PDCP_NR_DIRECTION_UPLINK) ?
914 &ei_pdcp_nr_sequence_analysis_sn_repeated_ul :
915 &ei_pdcp_nr_sequence_analysis_sn_repeated_dl,
916 "PDCP SN (%u) repeated for %s for UE %u (%s-%u)",
917 p->firstSN,
918 val_to_str_const(p_pdcp_nr_info->direction, direction_vals, "Unknown"),
919 p_pdcp_nr_info->ueid,
920 val_to_str_const(p_pdcp_nr_info->bearerType, bearer_type_vals, "Unknown"),
921 p_pdcp_nr_info->bearerId);
922 proto_item_append_text(seqnum_ti, "- SN %u Repeated",
923 p->firstSN);
924 break;
926 default:
927 /* Incorrect sequence number */
928 expert_add_info_format(pinfo, ti_expected_sn,
929 (p_pdcp_nr_info->direction == PDCP_NR_DIRECTION_UPLINK) ?
930 &ei_pdcp_nr_sequence_analysis_wrong_sequence_number_ul :
931 &ei_pdcp_nr_sequence_analysis_wrong_sequence_number_dl,
932 "Wrong Sequence Number for %s on UE %u (%s-%u) - got %u, expected %u",
933 val_to_str_const(p_pdcp_nr_info->direction, direction_vals, "Unknown"),
934 p_pdcp_nr_info->ueid,
935 val_to_str_const(p_pdcp_nr_info->bearerType, bearer_type_vals, "Unknown"),
936 p_pdcp_nr_info->bearerId,
937 sequenceNumber, p->sequenceExpected);
938 break;
941 /* May also be able to add key inputs to security tree here */
942 if ((pdu_security->ciphering != nea0) ||
943 (pdu_security->integrity != nia0)) {
944 uint32_t hfn_multiplier;
945 uint32_t count;
946 char *cipher_key = NULL;
947 char *integrity_key = NULL;
949 /* BEARER */
950 ti = proto_tree_add_uint(security_tree, hf_pdcp_nr_security_bearer,
951 tvb, 0, 0, p_pdcp_nr_info->bearerId-1);
952 proto_item_set_generated(ti);
953 pdu_security->bearer = p_pdcp_nr_info->bearerId-1;
955 /* DIRECTION */
956 ti = proto_tree_add_uint(security_tree, hf_pdcp_nr_security_direction,
957 tvb, 0, 0, p_pdcp_nr_info->direction);
958 proto_item_set_generated(ti);
960 /* COUNT (HFN * snLength^2 + SN) */
961 switch (p_pdcp_nr_info->seqnum_length) {
962 case PDCP_NR_SN_LENGTH_12_BITS:
963 hfn_multiplier = 4096;
964 break;
965 case PDCP_NR_SN_LENGTH_18_BITS:
966 hfn_multiplier = 262144;
967 break;
968 default:
969 DISSECTOR_ASSERT_NOT_REACHED();
970 break;
972 count = (p->hfn * hfn_multiplier) + sequenceNumber;
973 ti = proto_tree_add_uint(security_tree, hf_pdcp_nr_security_count,
974 tvb, 0, 0, count);
975 proto_item_set_generated(ti);
976 pdu_security->count = count;
978 /* KEY. Look this UE up among UEs that have keys configured */
979 uint32_t config_frame_rrc_cipher=0, config_frame_rrc_integrity=0,
980 config_frame_up_cipher=0, config_frame_up_integrity=0;
981 keys_record = look_up_keys_record(p_pdcp_nr_info->ueid, pinfo->num,
982 &config_frame_rrc_cipher, &config_frame_rrc_integrity,
983 &config_frame_up_cipher, &config_frame_up_integrity);
985 uint32_t config_frame_cipher=0, config_frame_integrity=0;
987 if (keys_record != NULL) {
988 if (p_pdcp_nr_info->plane == NR_SIGNALING_PLANE) {
989 /* Get RRC ciphering key */
990 if (keys_record->rrcCipherKeyOK) {
991 cipher_key = keys_record->rrcCipherKeyString;
992 pdu_security->cipherKey = &(keys_record->rrcCipherBinaryKey[0]);
993 pdu_security->cipherKeyValid = true;
994 config_frame_cipher = config_frame_rrc_cipher;
996 /* Get RRC integrity key */
997 if (keys_record->rrcIntegrityKeyOK) {
998 integrity_key = keys_record->rrcIntegrityKeyString;
999 pdu_security->integrityKey = &(keys_record->rrcIntegrityBinaryKey[0]);
1000 pdu_security->integrityKeyValid = true;
1001 config_frame_integrity = config_frame_rrc_integrity;
1004 else {
1005 /* Get userplane ciphering key */
1006 if (keys_record->upCipherKeyOK) {
1007 cipher_key = keys_record->upCipherKeyString;
1008 pdu_security->cipherKey = &(keys_record->upCipherBinaryKey[0]);
1009 pdu_security->cipherKeyValid = true;
1010 config_frame_cipher = config_frame_up_cipher;
1012 /* Get userplane integrity key */
1013 if (keys_record->upIntegrityKeyOK) {
1014 integrity_key = keys_record->upIntegrityKeyString;
1015 pdu_security->integrityKey = &(keys_record->upIntegrityBinaryKey[0]);
1016 pdu_security->integrityKeyValid = true;
1017 config_frame_integrity = config_frame_up_integrity;
1021 /* Show keys where known and valid */
1022 if (cipher_key != NULL) {
1023 ti = proto_tree_add_string(security_tree, hf_pdcp_nr_security_cipher_key,
1024 tvb, 0, 0, cipher_key);
1025 proto_item_set_generated(ti);
1026 /* If came from frame, link to it */
1027 if (config_frame_cipher != 0) {
1028 ti = proto_tree_add_uint(security_tree, hf_pdcp_nr_security_cipher_key_setup_frame,
1029 tvb, 0, 0, config_frame_cipher);
1030 proto_item_set_generated(ti);
1033 if (integrity_key != NULL) {
1034 ti = proto_tree_add_string(security_tree, hf_pdcp_nr_security_integrity_key,
1035 tvb, 0, 0, integrity_key);
1036 proto_item_set_generated(ti);
1037 /* If came from frame, link to it */
1038 if (config_frame_integrity != 0) {
1039 ti = proto_tree_add_uint(security_tree, hf_pdcp_nr_security_integrity_key_setup_frame,
1040 tvb, 0, 0, config_frame_integrity);
1041 proto_item_set_generated(ti);
1045 pdu_security->direction = p_pdcp_nr_info->direction;
1051 /* Update the bearer status and set report for this frame */
1052 static void checkBearerSequenceInfo(packet_info *pinfo, tvbuff_t *tvb,
1053 pdcp_nr_info *p_pdcp_nr_info,
1054 uint32_t sequenceNumber,
1055 proto_tree *tree,
1056 proto_tree *security_tree,
1057 pdu_security_settings_t *pdu_security)
1059 pdcp_bearer_hash_key bearer_key;
1060 pdcp_bearer_status *p_bearer_status;
1061 pdcp_sequence_report_in_frame *p_report_in_frame = NULL;
1062 bool createdBearer = false;
1063 uint32_t expectedSequenceNumber = 0;
1064 uint32_t snLimit = 0;
1066 /* If find stat_report_in_frame already, use that and get out */
1067 if (PINFO_FD_VISITED(pinfo)) {
1068 p_report_in_frame =
1069 (pdcp_sequence_report_in_frame*)wmem_map_lookup(pdcp_nr_sequence_analysis_report_hash,
1070 get_report_hash_key(sequenceNumber,
1071 pinfo->num,
1072 p_pdcp_nr_info, false));
1073 if (p_report_in_frame != NULL) {
1074 addBearerSequenceInfo(p_report_in_frame, p_pdcp_nr_info,
1075 sequenceNumber,
1076 pinfo, tree, tvb, security_tree, pdu_security);
1077 return;
1079 else {
1080 /* Give up - we must have tried already... */
1081 return;
1086 /**************************************************/
1087 /* Create or find an entry for this bearer state */
1088 bearer_key.ueId = p_pdcp_nr_info->ueid;
1089 bearer_key.plane = p_pdcp_nr_info->plane;
1090 bearer_key.bearerId = p_pdcp_nr_info->bearerId;
1091 bearer_key.direction = p_pdcp_nr_info->direction;
1092 bearer_key.notUsed = 0;
1094 /* Do the table lookup */
1095 p_bearer_status = (pdcp_bearer_status*)wmem_map_lookup(pdcp_sequence_analysis_bearer_hash,
1096 get_bearer_hash_key(&bearer_key));
1098 /* Create table entry if necessary */
1099 if (p_bearer_status == NULL) {
1100 createdBearer = true;
1102 /* Allocate a new value and duplicate key contents */
1103 p_bearer_status = wmem_new0(wmem_file_scope(), pdcp_bearer_status);
1105 /* Add entry */
1106 wmem_map_insert(pdcp_sequence_analysis_bearer_hash,
1107 get_bearer_hash_key(&bearer_key), p_bearer_status);
1110 /* Create space for frame state_report */
1111 p_report_in_frame = wmem_new(wmem_file_scope(), pdcp_sequence_report_in_frame);
1112 p_report_in_frame->nextFrameNum = 0;
1114 switch (p_pdcp_nr_info->seqnum_length) {
1115 case PDCP_NR_SN_LENGTH_12_BITS:
1116 snLimit = 4096;
1117 break;
1118 case PDCP_NR_SN_LENGTH_18_BITS:
1119 snLimit = 262144;
1120 break;
1121 default:
1122 DISSECTOR_ASSERT_NOT_REACHED();
1123 break;
1126 /* Work out expected sequence number */
1127 if (!createdBearer) {
1128 expectedSequenceNumber = (p_bearer_status->previousSequenceNumber + 1) % snLimit;
1130 else {
1131 expectedSequenceNumber = sequenceNumber;
1134 /* Set report for this frame */
1135 /* For PDCP, sequence number is always expectedSequence number */
1136 p_report_in_frame->sequenceExpectedCorrect = (sequenceNumber == expectedSequenceNumber);
1137 p_report_in_frame->hfn = p_bearer_status->hfn;
1140 /* For wrong sequence number... */
1141 if (!p_report_in_frame->sequenceExpectedCorrect) {
1143 /* Frames are not missing if we get an earlier sequence number again */
1144 if (((snLimit + expectedSequenceNumber - sequenceNumber) % snLimit) > 15) {
1145 p_report_in_frame->state = SN_Missing;
1146 p_report_in_frame->firstSN = expectedSequenceNumber;
1147 p_report_in_frame->lastSN = (snLimit + sequenceNumber - 1) % snLimit;
1149 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
1150 p_report_in_frame->previousFrameNum = p_bearer_status->previousFrameNum;
1152 /* Update Bearer status to remember *this* frame */
1153 p_bearer_status->previousFrameNum = pinfo->num;
1154 p_bearer_status->previousSequenceNumber = sequenceNumber;
1156 else {
1157 /* An SN has been repeated */
1158 p_report_in_frame->state = SN_Repeated;
1159 p_report_in_frame->firstSN = sequenceNumber;
1161 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
1162 p_report_in_frame->previousFrameNum = p_bearer_status->previousFrameNum;
1165 else {
1166 /* SN was OK */
1167 p_report_in_frame->state = SN_OK;
1168 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
1169 p_report_in_frame->previousFrameNum = p_bearer_status->previousFrameNum;
1170 /* SN has rolled around, inc hfn! */
1171 if (!createdBearer && (sequenceNumber == 0)) {
1172 /* Should handover before HFN needs to wrap, so don't worry about it */
1173 p_bearer_status->hfn++;
1174 p_report_in_frame->hfn = p_bearer_status->hfn;
1177 /* Update Bearer status to remember *this* frame */
1178 p_bearer_status->previousFrameNum = pinfo->num;
1179 p_bearer_status->previousSequenceNumber = sequenceNumber;
1181 if (p_report_in_frame->previousFrameNum != 0) {
1182 /* Get report for previous frame */
1183 pdcp_sequence_report_in_frame *p_previous_report;
1184 p_previous_report = (pdcp_sequence_report_in_frame*)wmem_map_lookup(pdcp_nr_sequence_analysis_report_hash,
1185 get_report_hash_key((sequenceNumber+262144) % 262144,
1186 p_report_in_frame->previousFrameNum,
1187 p_pdcp_nr_info,
1188 false));
1189 /* It really shouldn't be NULL... */
1190 if (p_previous_report != NULL) {
1191 /* Point it forward to this one */
1192 p_previous_report->nextFrameNum = pinfo->num;
1197 /* Associate with this frame number */
1198 wmem_map_insert(pdcp_nr_sequence_analysis_report_hash,
1199 get_report_hash_key(sequenceNumber, pinfo->num,
1200 p_pdcp_nr_info, true),
1201 p_report_in_frame);
1203 /* Add state report for this frame into tree */
1204 addBearerSequenceInfo(p_report_in_frame, p_pdcp_nr_info, sequenceNumber,
1205 pinfo, tree, tvb, security_tree, pdu_security);
1209 /* Hash table for security state for a UE during first pass.
1210 Maps UEId -> pdcp_security_info_t* */
1211 static wmem_map_t *pdcp_security_hash;
1214 typedef struct ueid_frame_t {
1215 uint32_t framenum;
1216 uint16_t ueid;
1217 } ueid_frame_t;
1219 /* Convenience function to get a pointer for the hash_func to work with */
1220 static void *get_ueid_frame_hash_key(uint16_t ueid, uint32_t frameNumber,
1221 bool do_persist)
1223 static ueid_frame_t key;
1224 ueid_frame_t *p_key;
1226 /* Only allocate a struct when will be adding entry */
1227 if (do_persist) {
1228 p_key = wmem_new(wmem_file_scope(), ueid_frame_t);
1230 else {
1231 /* Only looking up, so just use static */
1232 memset(&key, 0, sizeof(ueid_frame_t));
1233 p_key = &key;
1236 /* Fill in details, and return pointer */
1237 p_key->framenum = frameNumber;
1238 p_key->ueid = ueid;
1240 return p_key;
1243 static int pdcp_nr_ueid_frame_hash_equal(const void *v, const void *v2)
1245 const ueid_frame_t *ueid_frame_1 = (const ueid_frame_t *)v;
1246 const ueid_frame_t *ueid_frame_2 = (const ueid_frame_t *)v2;
1247 return ((ueid_frame_1->framenum == ueid_frame_2->framenum) &&
1248 (ueid_frame_1->ueid == ueid_frame_2->ueid));
1250 static unsigned pdcp_nr_ueid_frame_hash_func(const void *v)
1252 const ueid_frame_t *ueid_frame = (const ueid_frame_t *)v;
1253 return ueid_frame->framenum + 100*ueid_frame->ueid;
1256 /* Result is ueid_frame_t -> pdcp_security_info_t* */
1257 static wmem_map_t *pdcp_security_result_hash;
1262 /* Write the given formatted text to:
1263 - the info column
1264 - the top-level PDCP PDU item */
1265 static void write_pdu_label_and_info(proto_item *pdu_ti,
1266 packet_info *pinfo, const char *format, ...) G_GNUC_PRINTF(3, 4);
1267 static void write_pdu_label_and_info(proto_item *pdu_ti,
1268 packet_info *pinfo, const char *format, ...)
1270 #define MAX_INFO_BUFFER 256
1271 static char info_buffer[MAX_INFO_BUFFER];
1273 va_list ap;
1275 va_start(ap, format);
1276 vsnprintf(info_buffer, MAX_INFO_BUFFER, format, ap);
1277 va_end(ap);
1279 /* Add to indicated places */
1280 col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
1281 /* TODO: gets called a lot, so a shame there isn't a proto_item_append_string() */
1282 proto_item_append_text(pdu_ti, "%s", info_buffer);
1287 /***************************************************************/
1291 /* Show in the tree the config info attached to this frame, as generated fields */
1292 static void show_pdcp_config(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree,
1293 pdcp_nr_info *p_pdcp_info)
1295 proto_item *ti;
1296 proto_tree *configuration_tree;
1297 proto_item *configuration_ti = proto_tree_add_item(tree,
1298 hf_pdcp_nr_configuration,
1299 tvb, 0, 0, ENC_ASCII);
1300 configuration_tree = proto_item_add_subtree(configuration_ti, ett_pdcp_configuration);
1302 /* Direction */
1303 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_nr_direction, tvb, 0, 0,
1304 p_pdcp_info->direction);
1305 proto_item_set_generated(ti);
1307 /* Plane */
1308 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_nr_plane, tvb, 0, 0,
1309 p_pdcp_info->plane);
1310 proto_item_set_generated(ti);
1312 /* UEId */
1313 if (p_pdcp_info->ueid != 0) {
1314 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_nr_ueid, tvb, 0, 0,
1315 p_pdcp_info->ueid);
1316 proto_item_set_generated(ti);
1317 write_pdu_label_and_info(configuration_ti, pinfo, "UEId=%3u", p_pdcp_info->ueid);
1320 /* Bearer type */
1321 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_nr_bearer_type, tvb, 0, 0,
1322 p_pdcp_info->bearerType);
1323 proto_item_set_generated(ti);
1324 if (p_pdcp_info->bearerId != 0) {
1325 /* Bearer id */
1326 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_nr_bearer_id, tvb, 0, 0,
1327 p_pdcp_info->bearerId);
1328 proto_item_set_generated(ti);
1331 /* Show bearer type in root/Info */
1332 if (p_pdcp_info->bearerType == Bearer_DCCH) {
1333 write_pdu_label_and_info(configuration_ti, pinfo, " %s-%u ",
1334 (p_pdcp_info->plane == NR_SIGNALING_PLANE) ? "SRB" : "DRB",
1335 p_pdcp_info->bearerId);
1337 else {
1338 write_pdu_label_and_info(configuration_ti, pinfo, " %s",
1339 val_to_str_const(p_pdcp_info->bearerType, bearer_type_vals, "Unknown"));
1342 /* Seqnum length */
1343 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_nr_seqnum_length, tvb, 0, 0,
1344 p_pdcp_info->seqnum_length);
1345 proto_item_set_generated(ti);
1347 /* MAC-I Present */
1348 ti = proto_tree_add_boolean(configuration_tree, hf_pdcp_nr_maci_present, tvb, 0, 0,
1349 p_pdcp_info->maci_present);
1350 proto_item_set_generated(ti);
1352 /* Ciphering disabled */
1353 ti = proto_tree_add_boolean(configuration_tree, hf_pdcp_nr_ciphering_disabled, tvb, 0, 0,
1354 p_pdcp_info->ciphering_disabled);
1355 proto_item_set_generated(ti);
1356 /* Hide unless set */
1357 if (!p_pdcp_info->ciphering_disabled) {
1358 proto_item_set_hidden(ti);
1362 if (p_pdcp_info->plane == NR_USER_PLANE) {
1364 /* SDAP */
1365 ti = proto_tree_add_boolean(configuration_tree, hf_pdcp_nr_sdap, tvb, 0, 0,
1366 (p_pdcp_info->direction == PDCP_NR_DIRECTION_UPLINK) ?
1367 p_pdcp_info->sdap_header & PDCP_NR_UL_SDAP_HEADER_PRESENT :
1368 p_pdcp_info->sdap_header & PDCP_NR_DL_SDAP_HEADER_PRESENT);
1369 proto_item_set_generated(ti);
1372 /* ROHC compression */
1373 ti = proto_tree_add_boolean(configuration_tree, hf_pdcp_nr_rohc_compression, tvb, 0, 0,
1374 p_pdcp_info->rohc.rohc_compression);
1375 proto_item_set_generated(ti);
1377 /* ROHC-specific settings */
1378 if (p_pdcp_info->rohc.rohc_compression) {
1380 /* Show ROHC mode */
1381 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_nr_rohc_mode, tvb, 0, 0,
1382 p_pdcp_info->rohc.mode);
1383 proto_item_set_generated(ti);
1385 /* Show RND */
1386 ti = proto_tree_add_boolean(configuration_tree, hf_pdcp_nr_rohc_rnd, tvb, 0, 0,
1387 p_pdcp_info->rohc.rnd);
1388 proto_item_set_generated(ti);
1390 /* UDP Checksum */
1391 ti = proto_tree_add_boolean(configuration_tree, hf_pdcp_nr_rohc_udp_checksum_present, tvb, 0, 0,
1392 p_pdcp_info->rohc.udp_checksum_present);
1393 proto_item_set_generated(ti);
1395 /* ROHC profile */
1396 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_nr_rohc_profile, tvb, 0, 0,
1397 p_pdcp_info->rohc.profile);
1398 proto_item_set_generated(ti);
1400 /* CID Inclusion Info */
1401 ti = proto_tree_add_boolean(configuration_tree, hf_pdcp_nr_cid_inclusion_info, tvb, 0, 0,
1402 p_pdcp_info->rohc.cid_inclusion_info);
1403 proto_item_set_generated(ti);
1405 /* Large CID */
1406 ti = proto_tree_add_boolean(configuration_tree, hf_pdcp_nr_large_cid_present, tvb, 0, 0,
1407 p_pdcp_info->rohc.large_cid_present);
1408 proto_item_set_generated(ti);
1413 /* Append summary to configuration root */
1414 proto_item_append_text(configuration_ti, "(direction=%s, plane=%s",
1415 val_to_str_const(p_pdcp_info->direction, direction_vals, "Unknown"),
1416 val_to_str_const(p_pdcp_info->plane, pdcp_plane_vals, "Unknown"));
1418 if (p_pdcp_info->rohc.rohc_compression) {
1419 const char *mode = val_to_str_const(p_pdcp_info->rohc.mode, rohc_mode_vals, "Error");
1420 proto_item_append_text(configuration_ti, ", mode=%c, profile=%s",
1421 mode[0],
1422 val_to_str_const(p_pdcp_info->rohc.profile, rohc_profile_vals, "Unknown"));
1424 proto_item_append_text(configuration_ti, ")");
1425 proto_item_set_generated(configuration_ti);
1427 /* Show plane in info column */
1428 col_append_fstr(pinfo->cinfo, COL_INFO, " %s: ",
1429 val_to_str_const(p_pdcp_info->plane, pdcp_plane_vals, "Unknown"));
1434 /* Look for an RRC dissector for signalling data (using Bearer type and direction) */
1435 static dissector_handle_t lookup_rrc_dissector_handle(struct pdcp_nr_info *p_pdcp_info, uint32_t data_length)
1437 dissector_handle_t rrc_handle = NULL;
1439 switch (p_pdcp_info->bearerType)
1441 case Bearer_CCCH:
1442 if (p_pdcp_info->direction == PDCP_NR_DIRECTION_UPLINK) {
1443 rrc_handle = (data_length == 8) ? nr_rrc_ul_ccch1 : nr_rrc_ul_ccch;
1444 } else {
1445 rrc_handle = nr_rrc_dl_ccch;
1447 break;
1448 case Bearer_PCCH:
1449 rrc_handle = nr_rrc_pcch;
1450 break;
1451 case Bearer_BCCH_BCH:
1452 rrc_handle = nr_rrc_bcch_bch;
1453 break;
1454 case Bearer_BCCH_DL_SCH:
1455 rrc_handle = nr_rrc_bcch_dl_sch;
1456 break;
1457 case Bearer_DCCH:
1458 if (p_pdcp_info->direction == PDCP_NR_DIRECTION_UPLINK) {
1459 rrc_handle = nr_rrc_ul_dcch;
1460 } else {
1461 rrc_handle = nr_rrc_dl_dcch;
1463 break;
1465 default:
1466 break;
1469 return rrc_handle;
1473 /* Called from control protocol to configure security algorithms for the given UE */
1474 void set_pdcp_nr_security_algorithms(uint16_t ueid, pdcp_nr_security_info_t *security_info)
1476 /* Use for this frame so can check integrity on SecurityCommandRequest frame */
1477 /* N.B. won't work for internal, non-RRC signalling methods... */
1478 pdcp_nr_security_info_t *p_frame_security;
1480 /* Disable this entire sub-routine with the Preference */
1481 /* Used when the capture is already deciphered */
1482 if (global_pdcp_ignore_sec) {
1483 return;
1486 /* Create or update current settings, by UEID */
1487 pdcp_nr_security_info_t* ue_security =
1488 (pdcp_nr_security_info_t*)wmem_map_lookup(pdcp_security_hash,
1489 GUINT_TO_POINTER((unsigned)ueid));
1490 if (ue_security == NULL) {
1491 /* Copy whole security struct */
1492 ue_security = wmem_new(wmem_file_scope(), pdcp_nr_security_info_t);
1493 *ue_security = *security_info;
1495 /* And add into security table */
1496 wmem_map_insert(pdcp_security_hash, GUINT_TO_POINTER((unsigned)ueid), ue_security);
1498 else {
1499 /* Just update existing entry already in table */
1500 ue_security->previous_algorithm_configuration_frame = ue_security->algorithm_configuration_frame;
1501 ue_security->previous_integrity = ue_security->integrity;
1502 ue_security->previous_ciphering = ue_security->ciphering;
1504 ue_security->algorithm_configuration_frame = security_info->algorithm_configuration_frame;
1505 ue_security->integrity = security_info->integrity;
1506 ue_security->ciphering = security_info->ciphering;
1507 ue_security->seen_next_ul_pdu = false;
1508 ue_security->dl_after_reest_request = false;
1511 /* Also add an entry for this PDU already to use these settings, as otherwise it won't be present
1512 when we query it on the first pass. */
1513 p_frame_security = wmem_new(wmem_file_scope(), pdcp_nr_security_info_t);
1514 /* Deep copy*/
1515 *p_frame_security = *ue_security;
1516 wmem_map_insert(pdcp_security_result_hash,
1517 get_ueid_frame_hash_key(ueid, ue_security->algorithm_configuration_frame, true),
1518 p_frame_security);
1522 /* UE failed to process SecurityModeCommand so go back to previous security settings */
1523 void set_pdcp_nr_security_algorithms_failed(uint16_t ueid)
1525 /* Look up current state by UEID */
1526 pdcp_nr_security_info_t* ue_security =
1527 (pdcp_nr_security_info_t*)wmem_map_lookup(pdcp_security_hash,
1528 GUINT_TO_POINTER((unsigned)ueid));
1529 if (ue_security != NULL) {
1530 /* TODO: could remove from table if previous_configuration_frame is 0 */
1531 /* Go back to previous state */
1532 ue_security->algorithm_configuration_frame = ue_security->previous_algorithm_configuration_frame;
1533 ue_security->integrity = ue_security->previous_integrity;
1534 ue_security->ciphering = ue_security->previous_ciphering;
1538 /* Function to indicate rrcReestablishmentRequest.
1539 * This results in the next DL SRB1 PDU not being decrypted */
1540 void set_pdcp_nr_rrc_reestablishment_request(uint16_t ueid)
1542 pdcp_nr_security_info_t *pdu_security = (pdcp_nr_security_info_t*)wmem_map_lookup(pdcp_security_hash,
1543 GUINT_TO_POINTER(ueid));
1545 /* Set flag if entry found */
1546 if (pdu_security) {
1547 pdu_security->dl_after_reest_request = true;
1548 /* Also, will need to repeat securityCommand, so unset this flag */
1549 pdu_security->seen_next_ul_pdu = false;
1554 /* Decipher payload if algorithm is supported and plausible inputs are available */
1555 static tvbuff_t *decipher_payload(tvbuff_t *tvb, packet_info *pinfo, int *offset,
1556 pdu_security_settings_t *pdu_security_settings,
1557 struct pdcp_nr_info *p_pdcp_info, unsigned sdap_length,
1558 bool will_be_deciphered, bool *deciphered)
1560 uint8_t* decrypted_data = NULL;
1561 int payload_length = 0;
1562 tvbuff_t *decrypted_tvb;
1564 /* Nothing to do if NULL ciphering */
1565 if (pdu_security_settings->ciphering == nea0 || pdu_security_settings->ciphering == nea_disabled) {
1566 return tvb;
1569 /* Nothing to do if don't have valid cipher key */
1570 if (!pdu_security_settings->cipherKeyValid) {
1571 return tvb;
1574 /* Check whether algorithm supported (only drop through and process if we do) */
1575 if (pdu_security_settings->ciphering == nea1) {
1576 #ifndef HAVE_SNOW3G
1577 return tvb;
1578 #endif
1580 else if (pdu_security_settings->ciphering == nea3) {
1581 #ifndef HAVE_ZUC
1582 return tvb;
1583 #endif
1585 else if (pdu_security_settings->ciphering != nea2) {
1586 /* An algorithm we don't support at all! */
1587 return tvb;
1591 /* Don't decipher if turned off in preferences */
1592 if (((p_pdcp_info->plane == NR_SIGNALING_PLANE) && !global_pdcp_decipher_signalling) ||
1593 ((p_pdcp_info->plane == NR_USER_PLANE) && !global_pdcp_decipher_userplane)) {
1594 return tvb;
1597 /* Don't decipher user-plane control messages */
1598 if ((p_pdcp_info->plane == NR_USER_PLANE) && ((tvb_get_uint8(tvb, 0) & 0x80) == 0x00)) {
1599 return tvb;
1602 /* Don't decipher common control messages */
1603 if ((p_pdcp_info->plane == NR_SIGNALING_PLANE) && (p_pdcp_info->bearerType != Bearer_DCCH)) {
1604 return tvb;
1607 /* Don't decipher if not yet past SecurityModeResponse */
1608 if (!will_be_deciphered) {
1609 return tvb;
1612 /* AES */
1613 if (pdu_security_settings->ciphering == nea2) {
1614 unsigned char ctr_block[16];
1615 gcry_cipher_hd_t cypher_hd;
1616 int gcrypt_err;
1617 /* TS 33.501 D.4.4 defers to TS 33.401 B.1.3 */
1619 /* Set CTR */
1620 memset(ctr_block, 0, 16);
1621 /* Only first 5 bytes set */
1622 ctr_block[0] = (pdu_security_settings->count & 0xff000000) >> 24;
1623 ctr_block[1] = (pdu_security_settings->count & 0x00ff0000) >> 16;
1624 ctr_block[2] = (pdu_security_settings->count & 0x0000ff00) >> 8;
1625 ctr_block[3] = (pdu_security_settings->count & 0x000000ff);
1626 ctr_block[4] = (pdu_security_settings->bearer << 3) + (pdu_security_settings->direction << 2);
1628 /* Open gcrypt handle */
1629 gcrypt_err = gcry_cipher_open(&cypher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0);
1630 if (gcrypt_err != 0) {
1631 return tvb;
1634 /* Set the key */
1635 gcrypt_err = gcry_cipher_setkey(cypher_hd, pdu_security_settings->cipherKey, 16);
1636 if (gcrypt_err != 0) {
1637 gcry_cipher_close(cypher_hd);
1638 return tvb;
1641 /* Set the CTR */
1642 gcrypt_err = gcry_cipher_setctr(cypher_hd, ctr_block, 16);
1643 if (gcrypt_err != 0) {
1644 gcry_cipher_close(cypher_hd);
1645 return tvb;
1648 /* Extract the encrypted data into a buffer */
1649 payload_length = tvb_captured_length_remaining(tvb, *offset+sdap_length);
1650 decrypted_data = (uint8_t *)tvb_memdup(pinfo->pool, tvb, *offset+sdap_length, payload_length);
1652 /* Decrypt the actual data */
1653 gcrypt_err = gcry_cipher_decrypt(cypher_hd,
1654 decrypted_data, payload_length,
1655 NULL, 0);
1656 if (gcrypt_err != 0) {
1657 gcry_cipher_close(cypher_hd);
1658 return tvb;
1661 /* Close gcrypt handle */
1662 gcry_cipher_close(cypher_hd);
1665 #ifdef HAVE_SNOW3G
1666 /* SNOW-3G */
1667 if (pdu_security_settings->ciphering == nea1) {
1668 /* TS 33.501 D.4.3 defers to RS 33.401 */
1670 /* Extract the encrypted data into a buffer */
1671 payload_length = tvb_captured_length_remaining(tvb, *offset+sdap_length);
1672 decrypted_data = (uint8_t *)tvb_memdup(pinfo->pool, tvb, *offset+sdap_length, payload_length);
1674 /* Do the algorithm */
1675 snow3g_f8(pdu_security_settings->cipherKey,
1676 pdu_security_settings->count,
1677 pdu_security_settings->bearer,
1678 pdu_security_settings->direction,
1679 decrypted_data, payload_length*8);
1681 #endif
1683 #ifdef HAVE_ZUC
1684 /* ZUC */
1685 if (pdu_security_settings->ciphering == nea3) {
1686 /* Extract the encrypted data into a buffer */
1687 payload_length = tvb_captured_length_remaining(tvb, *offset+sdap_length);
1688 decrypted_data = (uint8_t *)tvb_memdup(pinfo->pool, tvb, *offset+sdap_length, payload_length);
1690 /* Do the algorithm. Assuming implementation works in-place */
1691 zuc_f8(pdu_security_settings->cipherKey,
1692 pdu_security_settings->count,
1693 pdu_security_settings->bearer,
1694 pdu_security_settings->direction,
1695 payload_length*8, /* Length is in bits */
1696 (uint32_t*)decrypted_data, (uint32_t*)decrypted_data);
1698 #endif
1700 /* Create tvb for resulting deciphered sdu */
1701 decrypted_tvb = tvb_new_child_real_data(tvb, decrypted_data, payload_length, payload_length);
1702 add_new_data_source(pinfo, decrypted_tvb, "Deciphered Payload");
1704 /* Return deciphered data, i.e. beginning of new tvb */
1705 *offset = 0;
1706 *deciphered = true;
1707 return decrypted_tvb;
1710 /* Try to calculate digest to compare with that found in frame. */
1711 static uint32_t calculate_digest(pdu_security_settings_t *pdu_security_settings, packet_info *pinfo, proto_tree *security_tree, tvbuff_t *header_tvb _U_,
1712 tvbuff_t *tvb _U_, int offset _U_, unsigned sdap_length _U_, bool *calculated)
1714 *calculated = false;
1716 if (pdu_security_settings->integrity == nia0) {
1717 /* Should be zero in this case */
1718 *calculated = true;
1719 return 0;
1722 /* Can't calculate if don't have valid integrity key */
1723 if (!pdu_security_settings->integrityKeyValid) {
1724 return 0;
1727 /* Can only do if indicated in preferences */
1728 if (!global_pdcp_check_integrity) {
1729 return 0;
1732 switch (pdu_security_settings->integrity) {
1734 #ifdef HAVE_SNOW3G
1735 case nia1:
1737 /* SNOW3G */
1738 uint8_t *mac;
1739 unsigned header_length = tvb_reported_length(header_tvb);
1740 int message_length = tvb_captured_length_remaining(tvb, offset) - 4;
1741 uint8_t *message_data = (uint8_t *)wmem_alloc0(pinfo->pool, header_length+message_length-sdap_length+4);
1743 /* TS 33.401 B.2.2 */
1745 /* Data is header bytes */
1746 tvb_memcpy(header_tvb, message_data, 0, header_length);
1747 /* Followed by the decrypted message (but not the digest bytes) */
1748 tvb_memcpy(tvb, message_data+header_length, offset+sdap_length, message_length-sdap_length);
1750 /* Show message data in security tree */
1751 proto_item *integ_data_ti = proto_tree_add_bytes_with_length(security_tree, hf_pdcp_nr_security_integrity_data,
1752 tvb, 0, 0, message_data,
1753 message_length+1);
1754 proto_item_set_generated(integ_data_ti);
1756 mac = (u8*)snow3g_f9(pdu_security_settings->integrityKey,
1757 pdu_security_settings->count,
1758 /* 'Fresh' is the bearer bits then zeros */
1759 pdu_security_settings->bearer << 27,
1760 pdu_security_settings->direction,
1761 message_data,
1762 (message_length+1)*8);
1764 *calculated = true;
1765 return ((mac[0] << 24) | (mac[1] << 16) | (mac[2] << 8) | mac[3]);
1767 #endif
1769 case nia2:
1771 /* AES */
1772 gcry_mac_hd_t mac_hd;
1773 int gcrypt_err;
1774 unsigned header_length;
1775 int message_length;
1776 uint8_t *message_data;
1777 uint8_t mac[4];
1778 size_t read_digest_length = 4;
1780 /* Open gcrypt handle */
1781 gcrypt_err = gcry_mac_open(&mac_hd, GCRY_MAC_CMAC_AES, 0, NULL);
1782 if (gcrypt_err != 0) {
1783 return 0;
1786 /* Set the key */
1787 gcrypt_err = gcry_mac_setkey(mac_hd, pdu_security_settings->integrityKey, 16);
1788 if (gcrypt_err != 0) {
1789 gcry_mac_close(mac_hd);
1790 return 0;
1793 /* TS 33.501 D.4.3 defers to TS 33.401 B.2.3 */
1795 /* Extract the encrypted data into a buffer */
1796 header_length = tvb_reported_length(header_tvb);
1797 message_length = tvb_captured_length_remaining(tvb, offset) - 4;
1798 message_data = (uint8_t *)wmem_alloc0(pinfo->pool, 8+header_length+message_length-sdap_length);
1799 message_data[0] = (pdu_security_settings->count & 0xff000000) >> 24;
1800 message_data[1] = (pdu_security_settings->count & 0x00ff0000) >> 16;
1801 message_data[2] = (pdu_security_settings->count & 0x0000ff00) >> 8;
1802 message_data[3] = (pdu_security_settings->count & 0x000000ff);
1803 message_data[4] = (pdu_security_settings->bearer << 3) + (pdu_security_settings->direction << 2);
1804 /* rest of first 8 bytes are left as zeroes... */
1806 /* Now the header bytes */
1807 tvb_memcpy(header_tvb, message_data+8, 0, header_length);
1808 /* Followed by the decrypted message (but not the digest bytes or any SDAP bytes) */
1809 tvb_memcpy(tvb, message_data+8+header_length, offset+sdap_length, message_length-sdap_length);
1811 /* Show message data in security tree */
1812 proto_item *integ_data_ti = proto_tree_add_bytes_with_length(security_tree, hf_pdcp_nr_security_integrity_data,
1813 tvb, 0, 0, message_data,
1814 8+header_length+message_length-sdap_length);
1815 proto_item_set_generated(integ_data_ti);
1817 /* Pass in the message */
1818 gcrypt_err = gcry_mac_write(mac_hd, message_data, 8+header_length+message_length-sdap_length);
1819 if (gcrypt_err != 0) {
1820 gcry_mac_close(mac_hd);
1821 return 0;
1824 /* Read out the digest */
1825 gcrypt_err = gcry_mac_read(mac_hd, mac, &read_digest_length);
1826 if (gcrypt_err != 0) {
1827 gcry_mac_close(mac_hd);
1828 return 0;
1831 /* Now close the mac handle */
1832 gcry_mac_close(mac_hd);
1834 *calculated = true;
1835 return ((mac[0] << 24) | (mac[1] << 16) | (mac[2] << 8) | mac[3]);
1837 #ifdef HAVE_ZUC
1838 case nia3:
1840 /* ZUC */
1841 uint32_t mac;
1842 unsigned header_length = tvb_reported_length(header_tvb);
1843 int message_length = tvb_captured_length_remaining(tvb, offset) - 4;
1844 uint8_t *message_data = (uint8_t *)wmem_alloc0(pinfo->pool, header_length+message_length-sdap_length+4);
1846 /* Data is header bytes */
1847 tvb_memcpy(header_tvb, message_data, 0, header_length);
1848 /* Followed by the decrypted message (but not the digest bytes) */
1849 tvb_memcpy(tvb, message_data+header_length, offset+sdap_length, message_length-sdap_length);
1851 /* Show message data in security tree */
1852 proto_item *integ_data_ti = proto_tree_add_bytes_with_length(security_tree, hf_pdcp_nr_security_integrity_data,
1853 tvb, 0, 0, message_data,
1854 message_length+header_length);
1855 proto_item_set_generated(integ_data_ti);
1857 zuc_f9(pdu_security_settings->integrityKey,
1858 pdu_security_settings->count,
1859 pdu_security_settings->direction,
1860 pdu_security_settings->bearer,
1861 (message_length+header_length)*8,
1862 (uint32_t*)message_data,
1863 &mac);
1865 *calculated = true;
1866 return mac;
1868 #endif
1870 default:
1871 /* Can't calculate */
1872 *calculated = false;
1873 return 0;
1880 /* Forward declarations */
1881 static int dissect_pdcp_nr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data);
1883 static void report_heur_error(proto_tree *tree, packet_info *pinfo, expert_field *eiindex,
1884 tvbuff_t *tvb, int start, int length)
1886 proto_item *ti;
1887 proto_tree *subtree;
1889 col_set_str(pinfo->cinfo, COL_PROTOCOL, "PDCP-NR");
1890 col_clear(pinfo->cinfo, COL_INFO);
1891 ti = proto_tree_add_item(tree, proto_pdcp_nr, tvb, 0, -1, ENC_NA);
1892 subtree = proto_item_add_subtree(ti, ett_pdcp);
1893 proto_tree_add_expert(subtree, pinfo, eiindex, tvb, start, length);
1896 /* Heuristic dissector looks for supported framing protocol (see wiki page) */
1897 static bool dissect_pdcp_nr_heur(tvbuff_t *tvb, packet_info *pinfo,
1898 proto_tree *tree, void *data _U_)
1900 int offset = 0;
1901 struct pdcp_nr_info *p_pdcp_nr_info;
1902 tvbuff_t *pdcp_tvb;
1903 uint8_t tag = 0;
1904 bool seqnumLengthTagPresent = false;
1906 /* Needs to be at least as long as:
1907 - the signature string
1908 - fixed header byte(s)
1909 - tag for data
1910 - at least one byte of PDCP PDU payload.
1911 However, let attempted dissection show if there are any tags at all. */
1912 int min_length = (int)(strlen(PDCP_NR_START_STRING) + 3); /* signature */
1914 if (tvb_captured_length_remaining(tvb, offset) < min_length) {
1915 return false;
1918 /* OK, compare with signature string */
1919 if (tvb_strneql(tvb, offset, PDCP_NR_START_STRING, strlen(PDCP_NR_START_STRING)) != 0) {
1920 return false;
1922 offset += (int)strlen(PDCP_NR_START_STRING);
1925 /* If redissecting, use previous info struct (if available) */
1926 p_pdcp_nr_info = (pdcp_nr_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_pdcp_nr, 0);
1927 if (p_pdcp_nr_info == NULL) {
1928 /* Allocate new info struct for this frame */
1929 p_pdcp_nr_info = wmem_new0(wmem_file_scope(), pdcp_nr_info);
1931 /* Read fixed fields */
1932 p_pdcp_nr_info->plane = (enum pdcp_nr_plane)tvb_get_uint8(tvb, offset++);
1933 if (p_pdcp_nr_info->plane == NR_SIGNALING_PLANE) {
1934 /* Signalling plane always has 12 SN bits */
1935 p_pdcp_nr_info->seqnum_length = PDCP_NR_SN_LENGTH_12_BITS;
1938 /* Read tagged fields */
1939 while (tag != PDCP_NR_PAYLOAD_TAG) {
1940 /* Process next tag */
1941 tag = tvb_get_uint8(tvb, offset++);
1942 switch (tag) {
1943 case PDCP_NR_SEQNUM_LENGTH_TAG:
1944 p_pdcp_nr_info->seqnum_length = tvb_get_uint8(tvb, offset);
1945 offset++;
1946 seqnumLengthTagPresent = true;
1947 break;
1948 case PDCP_NR_DIRECTION_TAG:
1949 p_pdcp_nr_info->direction = tvb_get_uint8(tvb, offset);
1950 offset++;
1951 break;
1952 case PDCP_NR_BEARER_TYPE_TAG:
1953 p_pdcp_nr_info->bearerType = (NRBearerType)tvb_get_uint8(tvb, offset);
1954 offset++;
1955 break;
1956 case PDCP_NR_BEARER_ID_TAG:
1957 p_pdcp_nr_info->bearerId = tvb_get_uint8(tvb, offset);
1958 offset++;
1959 break;
1960 case PDCP_NR_UEID_TAG:
1961 p_pdcp_nr_info->ueid = tvb_get_ntohs(tvb, offset);
1962 offset += 2;
1963 break;
1964 case PDCP_NR_ROHC_COMPRESSION_TAG:
1965 p_pdcp_nr_info->rohc.rohc_compression = true;
1966 break;
1967 case PDCP_NR_ROHC_IP_VERSION_TAG:
1968 p_pdcp_nr_info->rohc.rohc_ip_version = tvb_get_uint8(tvb, offset);
1969 offset++;
1970 break;
1971 case PDCP_NR_ROHC_CID_INC_INFO_TAG:
1972 p_pdcp_nr_info->rohc.cid_inclusion_info = true;
1973 break;
1974 case PDCP_NR_ROHC_LARGE_CID_PRES_TAG:
1975 p_pdcp_nr_info->rohc.large_cid_present = true;
1976 break;
1977 case PDCP_NR_ROHC_MODE_TAG:
1978 p_pdcp_nr_info->rohc.mode = (enum rohc_mode)tvb_get_uint8(tvb, offset);
1979 offset++;
1980 break;
1981 case PDCP_NR_ROHC_RND_TAG:
1982 p_pdcp_nr_info->rohc.rnd = true;
1983 break;
1984 case PDCP_NR_ROHC_UDP_CHECKSUM_PRES_TAG:
1985 p_pdcp_nr_info->rohc.udp_checksum_present = true;
1986 break;
1987 case PDCP_NR_ROHC_PROFILE_TAG:
1988 p_pdcp_nr_info->rohc.profile = tvb_get_ntohs(tvb, offset);
1989 offset += 2;
1990 break;
1991 case PDCP_NR_MACI_PRES_TAG:
1992 p_pdcp_nr_info->maci_present = true;
1993 break;
1994 case PDCP_NR_SDAP_HEADER_TAG:
1995 p_pdcp_nr_info->sdap_header = tvb_get_uint8(tvb, offset) & 0x03;
1996 offset++;
1997 break;
1998 case PDCP_NR_CIPHER_DISABLED_TAG:
1999 p_pdcp_nr_info->ciphering_disabled = true;
2000 break;
2003 case PDCP_NR_PAYLOAD_TAG:
2004 /* Have reached data, so get out of loop */
2005 p_pdcp_nr_info->pdu_length = tvb_reported_length_remaining(tvb, offset);
2006 continue;
2008 default:
2009 /* It must be a recognised tag */
2010 report_heur_error(tree, pinfo, &ei_pdcp_nr_unknown_udp_framing_tag, tvb, offset-1, 1);
2011 wmem_free(wmem_file_scope(), p_pdcp_nr_info);
2012 return true;
2016 if ((p_pdcp_nr_info->plane == NR_USER_PLANE) && (seqnumLengthTagPresent == false)) {
2017 /* Conditional field is not present */
2018 report_heur_error(tree, pinfo, &ei_pdcp_nr_missing_udp_framing_tag, tvb, 0, offset);
2019 wmem_free(wmem_file_scope(), p_pdcp_nr_info);
2020 return true;
2023 /* Store info in packet */
2024 p_add_proto_data(wmem_file_scope(), pinfo, proto_pdcp_nr, 0, p_pdcp_nr_info);
2026 else {
2027 offset = tvb_reported_length(tvb) - p_pdcp_nr_info->pdu_length;
2030 /**************************************/
2031 /* OK, now dissect as PDCP nr */
2033 /* Create tvb that starts at actual PDCP PDU */
2034 pdcp_tvb = tvb_new_subset_remaining(tvb, offset);
2035 dissect_pdcp_nr(pdcp_tvb, pinfo, tree, data);
2036 return true;
2040 /******************************/
2041 /* Main dissection function. */
2042 static int dissect_pdcp_nr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
2044 const char *mode;
2045 proto_tree *pdcp_tree = NULL;
2046 proto_item *root_ti = NULL;
2047 proto_item *ti;
2048 int offset = 0;
2049 struct pdcp_nr_info *p_pdcp_info;
2050 tvbuff_t *rohc_tvb = NULL;
2052 pdcp_nr_security_info_t *current_security = NULL; /* current security for this UE */
2053 pdcp_nr_security_info_t *pdu_security; /* security in place for this PDU */
2054 proto_tree *security_tree = NULL;
2055 proto_item *security_ti;
2056 tvbuff_t *payload_tvb;
2057 pdu_security_settings_t pdu_security_settings;
2058 bool payload_deciphered = false;
2060 /* Initialise security settings */
2061 memset(&pdu_security_settings, 0, sizeof(pdu_security_settings));
2063 /* Set protocol name. */
2064 col_set_str(pinfo->cinfo, COL_PROTOCOL, "PDCP-NR");
2066 /* Look for attached packet info! */
2067 p_pdcp_info = (struct pdcp_nr_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_pdcp_nr, 0);
2068 /* Can't dissect anything without it... */
2069 if (p_pdcp_info == NULL) {
2070 if (!data) {
2071 return 0;
2073 p_pdcp_info = (struct pdcp_nr_info *)data;
2076 /* Even if no RLC layer in this frame, query RLC table for configured drb settings */
2077 /* Signalling plane is always 12 bits SN */
2078 if (p_pdcp_info->plane == NR_SIGNALING_PLANE && p_pdcp_info->bearerType == Bearer_DCCH) {
2079 p_pdcp_info->seqnum_length = PDCP_NR_SN_LENGTH_12_BITS;
2081 /* If DRB channel, query rlc mappings (hopefully set from RRC) */
2082 else if (p_pdcp_info->plane == NR_USER_PLANE) {
2083 pdcp_bearer_parameters *params = get_rlc_nr_drb_pdcp_mapping(p_pdcp_info->ueid, p_pdcp_info->bearerId);
2084 if (params) {
2085 if (p_pdcp_info->direction == DIRECTION_UPLINK) {
2086 p_pdcp_info->seqnum_length = params->pdcp_sn_bits_ul;
2087 if (params->pdcp_sdap_ul) {
2088 p_pdcp_info->sdap_header |= PDCP_NR_UL_SDAP_HEADER_PRESENT;
2091 else {
2092 p_pdcp_info->seqnum_length = params->pdcp_sn_bits_dl;
2093 if (params->pdcp_sdap_dl) {
2094 p_pdcp_info->sdap_header |= PDCP_NR_DL_SDAP_HEADER_PRESENT;
2097 p_pdcp_info->maci_present = params->pdcp_integrity;
2098 p_pdcp_info->ciphering_disabled = params->pdcp_ciphering_disabled;
2102 /* Don't want to overwrite the RLC Info column if configured not to */
2103 if ((global_pdcp_nr_layer_to_show == ShowRLCLayer) &&
2104 (p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_nr, 0) != NULL)) {
2106 col_set_writable(pinfo->cinfo, COL_INFO, false);
2108 else {
2109 /* TODO: won't help with multiple PDCP-or-traffic PDUs / frame... */
2110 col_clear(pinfo->cinfo, COL_INFO);
2111 col_set_writable(pinfo->cinfo, COL_INFO, true);
2114 /* MACI always present for SRBs */
2115 if ((p_pdcp_info->plane == NR_SIGNALING_PLANE) && (p_pdcp_info->bearerType == Bearer_DCCH)) {
2116 p_pdcp_info->maci_present = true;
2119 /* Create pdcp tree. */
2120 if (tree) {
2121 root_ti = proto_tree_add_item(tree, proto_pdcp_nr, tvb, offset, -1, ENC_NA);
2122 pdcp_tree = proto_item_add_subtree(root_ti, ett_pdcp);
2125 /* Set mode string */
2126 mode = val_to_str_const(p_pdcp_info->rohc.mode, rohc_mode_vals, "Error");
2128 /*****************************************************/
2129 /* Show configuration (attached packet) info in tree */
2130 if (pdcp_tree) {
2131 show_pdcp_config(pinfo, tvb, pdcp_tree, p_pdcp_info);
2134 /* Show ROHC mode */
2135 if (p_pdcp_info->rohc.rohc_compression) {
2136 col_append_fstr(pinfo->cinfo, COL_INFO, " (mode=%c)", mode[0]);
2139 /***************************************/
2140 /* UE security algorithms */
2141 if (!PINFO_FD_VISITED(pinfo)) {
2142 /* Look up current state by UEID */
2143 current_security = (pdcp_nr_security_info_t*)wmem_map_lookup(pdcp_security_hash,
2144 GUINT_TO_POINTER((unsigned)p_pdcp_info->ueid));
2145 if (current_security != NULL) {
2146 /* Store any result for this frame in the result table */
2147 pdcp_nr_security_info_t *security_to_store = wmem_new(wmem_file_scope(), pdcp_nr_security_info_t);
2148 /* Take a deep copy of the settings */
2149 *security_to_store = *current_security;
2151 /* But ciphering may be turned off for this channel */
2152 if (p_pdcp_info->ciphering_disabled) {
2153 security_to_store->ciphering = nea_disabled;
2155 wmem_map_insert(pdcp_security_result_hash,
2156 get_ueid_frame_hash_key(p_pdcp_info->ueid, pinfo->num, true),
2157 security_to_store);
2159 else {
2160 /* No entry added from RRC, but still use configured defaults */
2161 if ((global_default_ciphering_algorithm != nea0) ||
2162 (global_default_integrity_algorithm != nia0)) {
2164 /* Copy algorithms from preference defaults into new entry. */
2165 pdcp_nr_security_info_t *security_to_store = wmem_new0(wmem_file_scope(), pdcp_nr_security_info_t);
2166 security_to_store->ciphering = global_default_ciphering_algorithm;
2167 security_to_store->integrity = global_default_integrity_algorithm;
2168 security_to_store->seen_next_ul_pdu = false;
2169 wmem_map_insert(pdcp_security_result_hash,
2170 get_ueid_frame_hash_key(p_pdcp_info->ueid, pinfo->num, true),
2171 security_to_store);
2176 /* Show security settings for this PDU */
2177 pdu_security = (pdcp_nr_security_info_t*)wmem_map_lookup(pdcp_security_result_hash,
2178 get_ueid_frame_hash_key(p_pdcp_info->ueid, pinfo->num, false));
2179 if (pdu_security != NULL) {
2180 /* Create subtree */
2181 security_ti = proto_tree_add_string_format(pdcp_tree,
2182 hf_pdcp_nr_security,
2183 tvb, 0, 0,
2184 "", "UE Security");
2185 security_tree = proto_item_add_subtree(security_ti, ett_pdcp_security);
2186 proto_item_set_generated(security_ti);
2188 /* Setup frame */
2189 if (pdu_security->algorithm_configuration_frame &&
2190 pinfo->num > pdu_security->algorithm_configuration_frame) {
2191 /* Must be set, and be seen before this frame */
2192 ti = proto_tree_add_uint(security_tree, hf_pdcp_nr_security_setup_frame,
2193 tvb, 0, 0, pdu_security->algorithm_configuration_frame);
2194 proto_item_set_generated(ti);
2197 /* Ciphering */
2198 ti = proto_tree_add_uint(security_tree, hf_pdcp_nr_security_ciphering_algorithm,
2199 tvb, 0, 0, pdu_security->ciphering);
2200 proto_item_set_generated(ti);
2202 /* Integrity */
2203 ti = proto_tree_add_uint(security_tree, hf_pdcp_nr_security_integrity_algorithm,
2204 tvb, 0, 0, pdu_security->integrity);
2205 proto_item_set_generated(ti);
2207 /* Show algorithms in security root */
2208 proto_item_append_text(security_ti, " (ciphering=%s, integrity=%s)",
2209 val_to_str_const(pdu_security->ciphering, ciphering_algorithm_vals, "Unknown"),
2210 val_to_str_const(pdu_security->integrity, integrity_algorithm_vals, "Unknown"));
2212 pdu_security_settings.ciphering = pdu_security->ciphering;
2213 pdu_security_settings.integrity = pdu_security->integrity;
2218 /***********************************/
2219 /* Handle PDCP header */
2221 uint32_t seqnum = 0;
2222 bool seqnum_set = false;
2224 uint8_t first_byte = tvb_get_uint8(tvb, offset);
2226 /*****************************/
2227 /* Signalling plane messages */
2228 if (p_pdcp_info->plane == NR_SIGNALING_PLANE) {
2229 if (p_pdcp_info->seqnum_length != 0) {
2230 /* Always 12 bits SN */
2231 /* Verify 4 reserved bits are 0 */
2232 uint8_t reserved = (first_byte & 0xf0) >> 4;
2233 ti = proto_tree_add_item(pdcp_tree, hf_pdcp_nr_control_plane_reserved,
2234 tvb, offset, 1, ENC_BIG_ENDIAN);
2235 if (reserved != 0) {
2236 expert_add_info_format(pinfo, ti, &ei_pdcp_nr_reserved_bits_not_zero,
2237 "PDCP signalling header reserved bits not zero");
2240 /* 12-bit sequence number */
2241 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_nr_seq_num_12, tvb, offset, 2, ENC_BIG_ENDIAN, &seqnum);
2242 seqnum_set = true;
2243 write_pdu_label_and_info(root_ti, pinfo, " (SN=%-4u)", seqnum);
2244 offset += 2;
2246 if (tvb_captured_length_remaining(tvb, offset) == 0) {
2247 /* Only PDCP header was captured, stop dissection here */
2248 return offset;
2252 else if (p_pdcp_info->plane == NR_USER_PLANE) {
2254 /**********************************/
2255 /* User-plane messages */
2256 bool is_user_plane;
2258 /* Data/Control flag */
2259 proto_tree_add_item_ret_boolean(pdcp_tree, hf_pdcp_nr_data_control, tvb, offset, 1, ENC_BIG_ENDIAN, &is_user_plane);
2261 if (is_user_plane) {
2262 /*****************************/
2263 /* User-plane Data */
2264 uint32_t reserved_value;
2266 /* Number of sequence number bits depends upon config */
2267 switch (p_pdcp_info->seqnum_length) {
2268 case PDCP_NR_SN_LENGTH_12_BITS:
2269 /* 3 reserved bits */
2270 ti = proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_nr_reserved3, tvb, offset, 1, ENC_BIG_ENDIAN, &reserved_value);
2272 /* Complain if not 0 */
2273 if (reserved_value != 0) {
2274 expert_add_info_format(pinfo, ti, &ei_pdcp_nr_reserved_bits_not_zero,
2275 "Reserved bits have value 0x%x - should be 0x0",
2276 reserved_value);
2279 /* 12-bit sequence number */
2280 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_nr_seq_num_12, tvb, offset, 2, ENC_BIG_ENDIAN, &seqnum);
2281 seqnum_set = true;
2282 offset += 2;
2283 break;
2284 case PDCP_NR_SN_LENGTH_18_BITS:
2285 /* 5 reserved bits */
2286 ti = proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_nr_reserved5, tvb, offset, 1, ENC_BIG_ENDIAN, &reserved_value);
2288 /* Complain if not 0 */
2289 if (reserved_value != 0) {
2290 expert_add_info_format(pinfo, ti, &ei_pdcp_nr_reserved_bits_not_zero,
2291 "Reserved bits have value 0x%x - should be 0x0",
2292 reserved_value);
2295 /* 18-bit sequence number */
2296 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_nr_seq_num_18, tvb, offset, 3, ENC_BIG_ENDIAN, &seqnum);
2297 seqnum_set = true;
2298 offset += 3;
2299 break;
2300 default:
2301 /* Not a recognised data format!!!!! */
2302 return 1;
2305 write_pdu_label_and_info(root_ti, pinfo, " (SN=%-6u)", seqnum);
2307 else {
2308 /*******************************/
2309 /* User-plane Control messages */
2310 uint32_t control_pdu_type;
2311 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_nr_control_pdu_type, tvb, offset, 1, ENC_BIG_ENDIAN, &control_pdu_type);
2313 switch (control_pdu_type) {
2314 case 0: /* PDCP status report */
2316 uint32_t fmc;
2317 unsigned not_received = 0;
2318 unsigned i, j, l;
2319 uint32_t len, bit_offset;
2320 proto_tree *bitmap_tree;
2321 proto_item *bitmap_ti = NULL;
2322 char *buff = NULL;
2323 #define BUFF_SIZE 89
2324 uint32_t reserved_value;
2326 /* 4 bits reserved */
2327 ti = proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_nr_reserved4, tvb, offset, 1, ENC_BIG_ENDIAN, &reserved_value);
2329 /* Complain if not 0 */
2330 if (reserved_value != 0) {
2331 expert_add_info_format(pinfo, ti, &ei_pdcp_nr_reserved_bits_not_zero,
2332 "Reserved bits have value 0x%x - should be 0x0",
2333 reserved_value);
2335 offset++;
2337 /* First-Missing-Count */
2338 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_nr_fmc, tvb, offset, 4, ENC_BIG_ENDIAN, &fmc);
2339 offset += 4;
2342 /* Bitmap tree */
2343 if (tvb_reported_length_remaining(tvb, offset) > 0) {
2344 bitmap_ti = proto_tree_add_item(pdcp_tree, hf_pdcp_nr_bitmap, tvb,
2345 offset, -1, ENC_NA);
2346 bitmap_tree = proto_item_add_subtree(bitmap_ti, ett_pdcp_report_bitmap);
2348 buff = (char *)wmem_alloc(pinfo->pool, BUFF_SIZE);
2349 len = tvb_reported_length_remaining(tvb, offset);
2350 bit_offset = offset<<3;
2352 /* For each byte... */
2353 for (i=0; i<len; i++) {
2354 uint8_t bits = tvb_get_bits8(tvb, bit_offset, 8);
2355 for (l=0, j=0; l<8; l++) {
2356 if ((bits << l) & 0x80) {
2357 if (bitmap_tree) {
2358 /* TODO: better to do mod and show as SN instead? */
2359 j += snprintf(&buff[j], BUFF_SIZE-j, "%10u,", (unsigned)(fmc+(8*i)+l+1));
2361 } else {
2362 if (bitmap_tree) {
2363 j += (unsigned)g_strlcpy(&buff[j], " ,", BUFF_SIZE-j);
2365 not_received++;
2368 if (bitmap_tree) {
2369 proto_tree_add_uint_format(bitmap_tree, hf_pdcp_nr_bitmap_byte, tvb, bit_offset/8, 1, bits, "%s", buff);
2371 bit_offset += 8;
2375 if (bitmap_ti != NULL) {
2376 proto_item_append_text(bitmap_ti, " (%u SNs not received)", not_received);
2378 write_pdu_label_and_info(root_ti, pinfo, " Status Report (fmc=%u) not-received=%u",
2379 fmc, not_received);
2381 return 1;
2383 case 1: /* ROHC Feedback */
2384 offset++;
2385 break; /* Drop-through to dissect feedback */
2389 else {
2390 /* Invalid plane setting...! */
2391 write_pdu_label_and_info(root_ti, pinfo, " - INVALID PLANE (%u)",
2392 p_pdcp_info->plane);
2393 return 1;
2396 /* Have reached the end of the header (for data frames) */
2397 int header_length = offset;
2399 /* Do sequence analysis if configured to. */
2400 if (seqnum_set) {
2401 bool do_analysis = false;
2403 switch (global_pdcp_check_sequence_numbers) {
2404 case false:
2405 break;
2406 case SEQUENCE_ANALYSIS_RLC_ONLY:
2407 if ((p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_nr, 0) != NULL) &&
2408 !p_pdcp_info->is_retx) {
2409 do_analysis = true;
2411 break;
2412 case SEQUENCE_ANALYSIS_PDCP_ONLY:
2413 if (p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_nr, 0) == NULL) {
2414 do_analysis = true;
2416 break;
2419 if (do_analysis) {
2420 checkBearerSequenceInfo(pinfo, tvb, p_pdcp_info,
2421 seqnum, pdcp_tree, security_tree,
2422 &pdu_security_settings);
2427 /*******************************************************/
2428 /* Now deal with the payload */
2429 /*******************************************************/
2431 /* Any SDAP bytes (between header and payload) are ignored for integrity/encryption */
2432 unsigned sdap_length = 0;
2433 if (p_pdcp_info->plane == NR_USER_PLANE) {
2434 if ((p_pdcp_info->direction == PDCP_NR_DIRECTION_UPLINK && (p_pdcp_info->sdap_header & PDCP_NR_UL_SDAP_HEADER_PRESENT)) ||
2435 (p_pdcp_info->direction == PDCP_NR_DIRECTION_DOWNLINK && (p_pdcp_info->sdap_header & PDCP_NR_DL_SDAP_HEADER_PRESENT))) {
2436 /* Currently, all SDAP message bytes are 1 byte long */
2437 sdap_length = 1;
2441 /* Decipher payload if necessary */
2442 bool should_decipher = false;
2443 if (pdu_security && !p_pdcp_info->ciphering_disabled) {
2444 if (p_pdcp_info->plane == NR_USER_PLANE) {
2445 /* Should decipher DRBs if have key */
2446 should_decipher = true;
2448 else {
2449 /* Control plane */
2450 /* Decipher if past securityModeComplete, snf not on DL after reestRequest */
2451 should_decipher = pdu_security->seen_next_ul_pdu && !pdu_security->dl_after_reest_request;
2455 int pdcp_offset = offset;
2456 payload_tvb = decipher_payload(tvb, pinfo, &offset, &pdu_security_settings, p_pdcp_info, sdap_length,
2457 should_decipher,
2458 &payload_deciphered);
2460 /* Add deciphered data as a filterable field */
2461 if (payload_deciphered) {
2462 proto_tree_add_item(pdcp_tree, hf_pdcp_nr_security_deciphered_data,
2463 payload_tvb, 0, tvb_reported_length(payload_tvb), ENC_NA);
2466 if ((p_pdcp_info->direction == PDCP_NR_DIRECTION_DOWNLINK) && current_security && (current_security->dl_after_reest_request)) {
2467 /* Have passed DL frame following reestRequest, so set back again */
2468 current_security->dl_after_reest_request = false;
2471 proto_item *mac_ti = NULL;
2472 uint32_t calculated_digest = 0;
2473 bool digest_was_calculated = false;
2475 /* Try to calculate digest so we can check it */
2476 if (global_pdcp_check_integrity && p_pdcp_info->maci_present) {
2477 calculated_digest = calculate_digest(&pdu_security_settings, pinfo, security_tree,
2478 tvb_new_subset_length(tvb, 0, header_length),
2479 payload_tvb,
2480 offset, sdap_length, &digest_was_calculated);
2483 if (p_pdcp_info->plane == NR_SIGNALING_PLANE) {
2484 /* Compute payload length (no MAC on common control Bearers) */
2485 uint32_t data_length = tvb_reported_length_remaining(payload_tvb, offset);
2486 if (p_pdcp_info->maci_present) {
2487 data_length -= 4;
2490 /* Call nr-rrc dissector (according to direction and Bearer type) if we have valid data */
2491 if ((global_pdcp_dissect_signalling_plane_as_rrc) &&
2492 ((pdu_security == NULL) || (pdu_security->ciphering == nea0) || payload_deciphered ||
2493 p_pdcp_info->ciphering_disabled || !pdu_security->seen_next_ul_pdu || pdu_security->dl_after_reest_request)) {
2495 /* Get appropriate dissector handle */
2496 dissector_handle_t rrc_handle = lookup_rrc_dissector_handle(p_pdcp_info, data_length);
2498 if (rrc_handle != NULL) {
2499 /* Call RRC dissector if have one */
2500 tvbuff_t *rrc_payload_tvb = tvb_new_subset_length(payload_tvb, offset, data_length);
2501 bool was_writable = col_get_writable(pinfo->cinfo, COL_INFO);
2503 /* We always want to see this in the info column */
2504 col_set_writable(pinfo->cinfo, COL_INFO, true);
2506 /* N.B. Have seen some cases where RRC dissector throws an exception and doesn't return here, or show as malformed... */
2507 /* Have attempted to TRY CATCH etc, but with no joy */
2508 call_dissector_only(rrc_handle, rrc_payload_tvb, pinfo, pdcp_tree, NULL);
2510 /* Restore to whatever it was */
2511 col_set_writable(pinfo->cinfo, COL_INFO, was_writable);
2513 else {
2514 /* Just show data */
2515 proto_tree_add_item(pdcp_tree, hf_pdcp_nr_signalling_data, payload_tvb, offset,
2516 data_length, ENC_NA);
2519 /* After payload - have we seen SecurityModResponse? */
2520 if (!PINFO_FD_VISITED(pinfo) &&
2521 (current_security != NULL) && !current_security->seen_next_ul_pdu &&
2522 p_pdcp_info->direction == PDCP_NR_DIRECTION_UPLINK)
2524 /* i.e. we have now seen SecurityModeComplete ! */
2525 /* Set current security for UE, but not value stored for this PDU */
2526 current_security->seen_next_ul_pdu = true;
2529 else {
2530 /* Just show as unparsed data */
2531 proto_tree_add_item(pdcp_tree, hf_pdcp_nr_signalling_data, payload_tvb, offset,
2532 data_length, ENC_NA);
2535 else if (tvb_captured_length_remaining(payload_tvb, offset)) {
2536 /* User-plane payload here. */
2537 int payload_length = tvb_reported_length_remaining(payload_tvb, offset) - ((p_pdcp_info->maci_present) ? 4 : 0);
2539 if (sdap_length) {
2540 /* SDAP (not to be taken from decrypted payload) */
2541 proto_item *sdap_ti;
2542 proto_tree *sdap_tree;
2543 uint32_t qfi;
2545 /* Protocol subtree */
2546 sdap_ti = proto_tree_add_item(pdcp_tree, proto_sdap, tvb, pdcp_offset, 1, ENC_NA);
2547 sdap_tree = proto_item_add_subtree(sdap_ti, ett_sdap);
2548 if (p_pdcp_info->direction == PDCP_NR_DIRECTION_UPLINK) {
2549 bool data_control;
2550 proto_tree_add_item_ret_boolean(sdap_tree, hf_sdap_data_control, tvb, pdcp_offset, 1, ENC_NA, &data_control);
2551 proto_tree_add_item(sdap_tree, hf_sdap_reserved, tvb, pdcp_offset, 1, ENC_NA);
2552 proto_item_append_text(sdap_ti, " (%s", tfs_get_string(data_control, &tfs_data_pdu_control_pdu));
2553 } else {
2554 bool rdi, rqi;
2555 proto_tree_add_item_ret_boolean(sdap_tree, hf_sdap_rdi, tvb, pdcp_offset, 1, ENC_NA, &rdi);
2556 proto_tree_add_item_ret_boolean(sdap_tree, hf_sdap_rqi, tvb, pdcp_offset, 1, ENC_NA, &rqi);
2557 proto_item_append_text(sdap_ti, " (RDI=%s, RQI=%s",
2558 tfs_get_string(rdi, &sdap_rdi), tfs_get_string(rqi, &sdap_rqi));
2560 /* QFI is common to both directions */
2561 proto_tree_add_item_ret_uint(sdap_tree, hf_sdap_qfi, tvb, pdcp_offset, 1, ENC_NA, &qfi);
2563 /* Did SDAP come out of main tvb? If ciphered, was already taken off the front.. */
2564 if (!payload_deciphered) {
2565 offset += sdap_length;
2566 payload_length -= sdap_length;
2568 proto_item_append_text(sdap_ti, " QFI=%u)", qfi);
2571 if (payload_length > 0) {
2572 /* If not compressed with ROHC, show as user-plane data */
2573 if (!p_pdcp_info->rohc.rohc_compression) {
2574 /* Not attempting to decode payload if payload ciphered and we did decipher */
2575 if (global_pdcp_dissect_user_plane_as_ip &&
2576 ((pdu_security == NULL) || (pdu_security->ciphering == nea0) || payload_deciphered)) {
2578 tvbuff_t *ip_payload_tvb = tvb_new_subset_length(payload_tvb, offset, payload_length);
2580 /* Don't update info column for ROHC unless configured to */
2581 if (global_pdcp_nr_layer_to_show != ShowTrafficLayer) {
2582 col_set_writable(pinfo->cinfo, COL_INFO, false);
2585 switch (tvb_get_uint8(ip_payload_tvb, 0) & 0xf0) {
2586 case 0x40:
2587 call_dissector_only(ip_handle, ip_payload_tvb, pinfo, pdcp_tree, NULL);
2588 break;
2589 case 0x60:
2590 call_dissector_only(ipv6_handle, ip_payload_tvb, pinfo, pdcp_tree, NULL);
2591 break;
2592 default:
2593 call_data_dissector(ip_payload_tvb, pinfo, pdcp_tree);
2594 break;
2597 /* Freeze the columns again because we don't want other layers writing to info */
2598 if (global_pdcp_nr_layer_to_show == ShowTrafficLayer) {
2599 col_set_writable(pinfo->cinfo, COL_INFO, false);
2603 else {
2604 proto_tree_add_item(pdcp_tree, hf_pdcp_nr_user_plane_data, payload_tvb, offset, payload_length, ENC_NA);
2607 else {
2608 /***************************/
2609 /* ROHC packets */
2610 /***************************/
2612 /* Only attempt ROHC if configured to */
2613 if (!global_pdcp_dissect_rohc) {
2614 col_append_fstr(pinfo->cinfo, COL_PROTOCOL, "|ROHC(%s)",
2615 val_to_str_const(p_pdcp_info->rohc.profile, rohc_profile_vals, "Unknown"));
2616 proto_tree_add_item(pdcp_tree, hf_pdcp_nr_user_plane_data, payload_tvb, offset, payload_length, ENC_NA);
2618 else {
2619 rohc_tvb = tvb_new_subset_length(payload_tvb, offset, payload_length);
2621 /* Only enable writing to column if configured to show ROHC */
2622 if (global_pdcp_nr_layer_to_show != ShowTrafficLayer) {
2623 col_set_writable(pinfo->cinfo, COL_INFO, false);
2625 else {
2626 col_clear(pinfo->cinfo, COL_INFO);
2629 /* Call the ROHC dissector */
2630 call_dissector_with_data(rohc_handle, rohc_tvb, pinfo, tree, &p_pdcp_info->rohc);
2636 /* MAC */
2637 if (p_pdcp_info->maci_present) {
2638 /* Last 4 bytes are MAC */
2639 int mac_offset = tvb_reported_length(payload_tvb)-4;
2640 uint32_t mac;
2641 mac_ti = proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_nr_mac, payload_tvb, mac_offset, 4, ENC_BIG_ENDIAN, &mac);
2642 offset += 4;
2644 if (digest_was_calculated) {
2645 /* Compare what was found with calculated value! */
2646 if (mac != calculated_digest) {
2647 expert_add_info_format(pinfo, mac_ti, &ei_pdcp_nr_digest_wrong,
2648 "MAC-I Digest wrong - calculated %08x but found %08x",
2649 calculated_digest, mac);
2650 proto_item_append_text(mac_ti, " (but calculated 0x%08x !)", calculated_digest);
2652 else {
2653 proto_item_append_text(mac_ti, " [Matches calculated result]");
2657 col_append_fstr(pinfo->cinfo, COL_INFO, " MAC=0x%08x", mac);
2660 /* Let RLC write to columns again */
2661 col_set_writable(pinfo->cinfo, COL_INFO, global_pdcp_nr_layer_to_show == ShowRLCLayer);
2663 return tvb_captured_length(tvb);
2667 void proto_register_pdcp_nr(void)
2669 static hf_register_info hf_pdcp[] =
2671 { &hf_pdcp_nr_configuration,
2672 { "Configuration",
2673 "pdcp-nr.configuration", FT_STRING, BASE_NONE, NULL, 0x0,
2674 "Configuration info passed into dissector", HFILL
2677 { &hf_pdcp_nr_direction,
2678 { "Direction",
2679 "pdcp-nr.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
2680 "Direction of message", HFILL
2683 { &hf_pdcp_nr_ueid,
2684 { "UE",
2685 "pdcp-nr.ueid", FT_UINT16, BASE_DEC, 0, 0x0,
2686 "UE Identifier", HFILL
2689 { &hf_pdcp_nr_bearer_type,
2690 { "Bearer type",
2691 "pdcp-nr.Bearer-type", FT_UINT8, BASE_DEC, VALS(bearer_type_vals), 0x0,
2692 NULL, HFILL
2695 { &hf_pdcp_nr_bearer_id,
2696 { "Bearer Id",
2697 "pdcp-nr.bearer-id", FT_UINT8, BASE_DEC, 0, 0x0,
2698 NULL, HFILL
2701 { &hf_pdcp_nr_plane,
2702 { "Plane",
2703 "pdcp-nr.plane", FT_UINT8, BASE_DEC, VALS(pdcp_plane_vals), 0x0,
2704 NULL, HFILL
2707 { &hf_pdcp_nr_seqnum_length,
2708 { "Seqnum length",
2709 "pdcp-nr.seqnum_length", FT_UINT8, BASE_DEC, NULL, 0x0,
2710 "Sequence Number Length", HFILL
2713 { &hf_pdcp_nr_maci_present,
2714 { "MAC-I Present",
2715 "pdcp-nr.maci_present", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2716 "Indicates whether MAC-I digest bytes are expected", HFILL
2719 { &hf_pdcp_nr_sdap,
2720 { "SDAP header",
2721 "pdcp-nr.sdap", FT_BOOLEAN, BASE_NONE, TFS(&tfs_present_not_present), 0x0,
2722 "Indicates whether SDAP appears after PDCP headers", HFILL
2725 { &hf_pdcp_nr_ciphering_disabled,
2726 { "Ciphering disabled",
2727 "pdcp-nr.ciphering-disabled", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2728 NULL, HFILL
2733 { &hf_pdcp_nr_rohc_compression,
2734 { "ROHC Compression",
2735 "pdcp-nr.rohc.compression", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2736 NULL, HFILL
2739 { &hf_pdcp_nr_rohc_mode,
2740 { "ROHC Mode",
2741 "pdcp-nr.rohc.mode", FT_UINT8, BASE_DEC, VALS(rohc_mode_vals), 0x0,
2742 NULL, HFILL
2745 { &hf_pdcp_nr_rohc_rnd,
2746 { "RND",
2747 "pdcp-nr.rohc.rnd", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2748 "RND of outer ip header", HFILL
2751 { &hf_pdcp_nr_rohc_udp_checksum_present,
2752 { "UDP Checksum",
2753 "pdcp-nr.rohc.checksum-present", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2754 "UDP Checksum present", HFILL
2757 { &hf_pdcp_nr_rohc_profile,
2758 { "ROHC profile",
2759 "pdcp-nr.rohc.profile", FT_UINT16, BASE_DEC, VALS(rohc_profile_vals), 0x0,
2760 "ROHC Mode", HFILL
2763 { &hf_pdcp_nr_cid_inclusion_info,
2764 { "CID Inclusion Info",
2765 "pdcp-nr.cid-inclusion-info", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2766 NULL, HFILL
2769 { &hf_pdcp_nr_large_cid_present,
2770 { "Large CID Present",
2771 "pdcp-nr.large-cid-present", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2772 NULL, HFILL
2776 { &hf_pdcp_nr_control_plane_reserved,
2777 { "Reserved",
2778 "pdcp-nr.reserved", FT_UINT8, BASE_DEC, NULL, 0xf0,
2779 NULL, HFILL
2782 { &hf_pdcp_nr_reserved3,
2783 { "Reserved",
2784 "pdcp-nr.reserved3", FT_UINT8, BASE_HEX, NULL, 0x70,
2785 "3 reserved bits", HFILL
2788 { &hf_pdcp_nr_seq_num_12,
2789 { "Seq Num",
2790 "pdcp-nr.seq-num", FT_UINT16, BASE_DEC, NULL, 0x0fff,
2791 "PDCP Seq num", HFILL
2794 { &hf_pdcp_nr_reserved5,
2795 { "Reserved",
2796 "pdcp-nr.reserved5", FT_UINT8, BASE_HEX, NULL, 0x7c,
2797 "5 reserved bits", HFILL
2800 { &hf_pdcp_nr_seq_num_18,
2801 { "Seq Num",
2802 "pdcp-nr.seq-num", FT_UINT24, BASE_DEC, NULL, 0x03ffff,
2803 "PDCP Seq num", HFILL
2806 { &hf_pdcp_nr_signalling_data,
2807 { "Signalling Data",
2808 "pdcp-nr.signalling-data", FT_BYTES, BASE_NONE, NULL, 0x0,
2809 NULL, HFILL
2812 { &hf_pdcp_nr_mac,
2813 { "MAC",
2814 "pdcp-nr.mac", FT_UINT32, BASE_HEX, NULL, 0x0,
2815 NULL, HFILL
2818 { &hf_pdcp_nr_data_control,
2819 { "PDU Type",
2820 "pdcp-nr.pdu-type", FT_BOOLEAN, 8, TFS(&tfs_data_pdu_control_pdu), 0x80,
2821 NULL, HFILL
2824 { &hf_pdcp_nr_user_plane_data,
2825 { "User-Plane Data",
2826 "pdcp-nr.user-data", FT_BYTES, BASE_NONE, NULL, 0x0,
2827 NULL, HFILL
2830 { &hf_pdcp_nr_control_pdu_type,
2831 { "Control PDU Type",
2832 "pdcp-nr.control-pdu-type", FT_UINT8, BASE_HEX, VALS(control_pdu_type_vals), 0x70,
2833 NULL, HFILL
2836 { &hf_pdcp_nr_fmc,
2837 { "First Missing Count",
2838 "pdcp-nr.fmc", FT_UINT32, BASE_DEC, NULL, 0x0,
2839 NULL, HFILL
2842 { &hf_pdcp_nr_reserved4,
2843 { "Reserved",
2844 "pdcp-nr.reserved4", FT_UINT8, BASE_HEX, NULL, 0x0f,
2845 "4 reserved bits", HFILL
2848 { &hf_pdcp_nr_bitmap,
2849 { "Bitmap",
2850 "pdcp-nr.bitmap", FT_NONE, BASE_NONE, NULL, 0x0,
2851 "Status report bitmap (0=error, 1=OK)", HFILL
2854 { &hf_pdcp_nr_bitmap_byte,
2855 { "Bitmap byte",
2856 "pdcp-nr.bitmap.byte", FT_UINT8, BASE_HEX, NULL, 0x0,
2857 NULL, HFILL
2861 { &hf_pdcp_nr_sequence_analysis,
2862 { "Sequence Analysis",
2863 "pdcp-nr.sequence-analysis", FT_STRING, BASE_NONE, 0, 0x0,
2864 NULL, HFILL
2867 { &hf_pdcp_nr_sequence_analysis_ok,
2868 { "OK",
2869 "pdcp-nr.sequence-analysis.ok", FT_BOOLEAN, BASE_NONE, 0, 0x0,
2870 NULL, HFILL
2873 { &hf_pdcp_nr_sequence_analysis_previous_frame,
2874 { "Previous frame for Bearer",
2875 "pdcp-nr.sequence-analysis.previous-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
2876 NULL, HFILL
2879 { &hf_pdcp_nr_sequence_analysis_next_frame,
2880 { "Next frame for Bearer",
2881 "pdcp-nr.sequence-analysis.next-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
2882 NULL, HFILL
2885 { &hf_pdcp_nr_sequence_analysis_expected_sn,
2886 { "Expected SN",
2887 "pdcp-nr.sequence-analysis.expected-sn", FT_UINT32, BASE_DEC, 0, 0x0,
2888 NULL, HFILL
2891 { &hf_pdcp_nr_sequence_analysis_skipped,
2892 { "Skipped frames",
2893 "pdcp-nr.sequence-analysis.skipped-frames", FT_BOOLEAN, BASE_NONE, 0, 0x0,
2894 NULL, HFILL
2897 { &hf_pdcp_nr_sequence_analysis_repeated,
2898 { "Repeated frame",
2899 "pdcp-nr.sequence-analysis.repeated-frame", FT_BOOLEAN, BASE_NONE, 0, 0x0,
2900 NULL, HFILL
2904 /* Security fields */
2905 { &hf_pdcp_nr_security,
2906 { "Security Config",
2907 "pdcp-nr.security-config", FT_STRING, BASE_NONE, 0, 0x0,
2908 NULL, HFILL
2911 { &hf_pdcp_nr_security_setup_frame,
2912 { "Configuration frame",
2913 "pdcp-nr.security-config.setup-frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2914 NULL, HFILL
2917 { &hf_pdcp_nr_security_integrity_algorithm,
2918 { "Integrity Algorithm",
2919 "pdcp-nr.security-config.integrity", FT_UINT16, BASE_DEC, VALS(integrity_algorithm_vals), 0x0,
2920 NULL, HFILL
2923 { &hf_pdcp_nr_security_ciphering_algorithm,
2924 { "Ciphering Algorithm",
2925 "pdcp-nr.security-config.ciphering", FT_UINT16, BASE_DEC, VALS(ciphering_algorithm_vals), 0x0,
2926 NULL, HFILL
2929 { &hf_pdcp_nr_security_bearer,
2930 { "BEARER",
2931 "pdcp-nr.security-config.bearer", FT_UINT8, BASE_DEC, NULL, 0x0,
2932 NULL, HFILL
2935 { &hf_pdcp_nr_security_direction,
2936 { "DIRECTION",
2937 "pdcp-nr.security-config.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
2938 NULL, HFILL
2941 { &hf_pdcp_nr_security_count,
2942 { "COUNT",
2943 "pdcp-nr.security-config.count", FT_UINT32, BASE_DEC, NULL, 0x0,
2944 NULL, HFILL
2947 { &hf_pdcp_nr_security_cipher_key,
2948 { "CIPHER KEY",
2949 "pdcp-nr.security-config.cipher-key", FT_STRING, BASE_NONE, NULL, 0x0,
2950 NULL, HFILL
2953 { &hf_pdcp_nr_security_integrity_key,
2954 { "INTEGRITY KEY",
2955 "pdcp-nr.security-config.integrity-key", FT_STRING, BASE_NONE, NULL, 0x0,
2956 NULL, HFILL
2959 { &hf_pdcp_nr_security_cipher_key_setup_frame,
2960 { "CIPHER KEY setup",
2961 "pdcp-nr.security-config.cipher-key.setup-frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2962 NULL, HFILL
2965 { &hf_pdcp_nr_security_integrity_key_setup_frame,
2966 { "INTEGRITY KEY setup",
2967 "pdcp-nr.security-config.integrity-key.setup-frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2968 NULL, HFILL
2971 { &hf_pdcp_nr_security_deciphered_data,
2972 { "Deciphered Data",
2973 "pdcp-nr.deciphered-data", FT_BYTES, BASE_NONE, NULL, 0x0,
2974 NULL, HFILL
2977 { &hf_pdcp_nr_security_integrity_data,
2978 { "Integrity Data",
2979 "pdcp-nr.integrity-data", FT_BYTES, BASE_NONE, NULL, 0x0,
2980 NULL, HFILL
2985 static hf_register_info hf_sdap[] =
2987 { &hf_sdap_rdi,
2988 { "RDI",
2989 "sdap.rdi", FT_BOOLEAN, 8, TFS(&sdap_rdi), 0x80,
2990 "Reflective QoS flow to DRB mapping Indication", HFILL
2993 { &hf_sdap_rqi,
2994 { "RQI",
2995 "sdap.rqi", FT_BOOLEAN, 8, TFS(&sdap_rqi), 0x40,
2996 "Reflective QoS Indication", HFILL
2999 { &hf_sdap_qfi,
3000 { "QFI",
3001 "sdap.qfi", FT_UINT8, BASE_DEC, NULL, 0x3f,
3002 "QoS Flow ID", HFILL
3005 { &hf_sdap_data_control,
3006 { "PDU Type",
3007 "sdap.pdu-type", FT_BOOLEAN, 8, TFS(&tfs_data_pdu_control_pdu), 0x80,
3008 NULL, HFILL
3011 { &hf_sdap_reserved,
3012 { "Reserved",
3013 "sdap.reserved", FT_UINT8, BASE_HEX, NULL, 0x40,
3014 NULL, HFILL
3019 static int *ett[] =
3021 &ett_pdcp,
3022 &ett_pdcp_configuration,
3023 &ett_pdcp_packet,
3024 &ett_pdcp_nr_sequence_analysis,
3025 &ett_pdcp_report_bitmap,
3026 &ett_sdap,
3027 &ett_pdcp_security
3030 static ei_register_info ei[] = {
3031 { &ei_pdcp_nr_sequence_analysis_sn_missing_ul, { "pdcp-nr.sequence-analysis.sn-missing-ul", PI_SEQUENCE, PI_WARN, "UL PDCP SNs missing", EXPFILL }},
3032 { &ei_pdcp_nr_sequence_analysis_sn_missing_dl, { "pdcp-nr.sequence-analysis.sn-missing-dl", PI_SEQUENCE, PI_WARN, "DL PDCP SNs missing", EXPFILL }},
3033 { &ei_pdcp_nr_sequence_analysis_sn_repeated_ul, { "pdcp-nr.sequence-analysis.sn-repeated-ul", PI_SEQUENCE, PI_WARN, "UL PDCP SNs repeated", EXPFILL }},
3034 { &ei_pdcp_nr_sequence_analysis_sn_repeated_dl, { "pdcp-nr.sequence-analysis.sn-repeated-dl", PI_SEQUENCE, PI_WARN, "DL PDCP SNs repeated", EXPFILL }},
3035 { &ei_pdcp_nr_sequence_analysis_wrong_sequence_number_ul, { "pdcp-nr.sequence-analysis.wrong-sequence-number-ul", PI_SEQUENCE, PI_WARN, "UL Wrong Sequence Number", EXPFILL }},
3036 { &ei_pdcp_nr_sequence_analysis_wrong_sequence_number_dl, { "pdcp-nr.sequence-analysis.wrong-sequence-number-dl", PI_SEQUENCE, PI_WARN, "DL Wrong Sequence Number", EXPFILL }},
3037 { &ei_pdcp_nr_reserved_bits_not_zero, { "pdcp-nr.reserved-bits-not-zero", PI_MALFORMED, PI_ERROR, "Reserved bits not zero", EXPFILL }},
3038 { &ei_pdcp_nr_digest_wrong, { "pdcp-nr.maci-wrong", PI_SEQUENCE, PI_ERROR, "MAC-I doesn't match expected value", EXPFILL }},
3039 { &ei_pdcp_nr_unknown_udp_framing_tag, { "pdcp-nr.unknown-udp-framing-tag", PI_UNDECODED, PI_WARN, "Unknown UDP framing tag, aborting dissection", EXPFILL }},
3040 { &ei_pdcp_nr_missing_udp_framing_tag, { "pdcp-nr.missing-udp-framing-tag", PI_UNDECODED, PI_WARN, "Missing UDP framing conditional tag, aborting dissection", EXPFILL }}
3043 static const enum_val_t sequence_analysis_vals[] = {
3044 {"no-analysis", "No-Analysis", false},
3045 {"rlc-only", "Only-RLC-frames", SEQUENCE_ANALYSIS_RLC_ONLY},
3046 {"pdcp-only", "Only-PDCP-frames", SEQUENCE_ANALYSIS_PDCP_ONLY},
3047 {NULL, NULL, -1}
3050 static const enum_val_t show_info_col_vals[] = {
3051 {"show-rlc", "RLC Info", ShowRLCLayer},
3052 {"show-pdcp", "PDCP Info", ShowPDCPLayer},
3053 {"show-traffic", "Traffic Info", ShowTrafficLayer},
3054 {NULL, NULL, -1}
3057 static const enum_val_t default_ciphering_algorithm_vals[] = {
3058 {"nea0", "NEA0 (NULL)", nea0},
3059 {"nea1", "NEA1 (SNOW3G)", nea1},
3060 {"nea2", "NEA2 (AES)", nea2},
3061 {"nea3", "NEA3 (ZUC)", nea3},
3062 {NULL, NULL, -1}
3065 static const enum_val_t default_integrity_algorithm_vals[] = {
3066 {"nia0", "NIA0 (NULL)", nia0},
3067 {"nia1", "NIA1 (SNOW3G)", nia1},
3068 {"nia2", "NIA2 (AES)", nia2},
3069 {"nia3", "NIA3 (ZUC)", nia3},
3070 {NULL, NULL, -1}
3073 static uat_field_t ue_keys_uat_flds[] = {
3074 UAT_FLD_DEC(uat_ue_keys_records, ueid, "UEId", "UE Identifier of UE associated with keys"),
3075 UAT_FLD_CSTRING(uat_ue_keys_records, rrcCipherKeyString, "RRC Cipher Key", "Key for deciphering signalling messages"),
3076 UAT_FLD_CSTRING(uat_ue_keys_records, upCipherKeyString, "User-Plane Cipher Key", "Key for deciphering user-plane messages"),
3077 UAT_FLD_CSTRING(uat_ue_keys_records, rrcIntegrityKeyString, "RRC Integrity Key", "Key for calculating signalling integrity MAC"),
3078 UAT_FLD_CSTRING(uat_ue_keys_records, upIntegrityKeyString, "User-Plane Integrity Key", "Key for calculating user-plane integrity MAC"),
3079 UAT_END_FIELDS
3083 module_t *pdcp_nr_module;
3084 expert_module_t* expert_pdcp_nr;
3086 /* Register protocol. */
3087 proto_pdcp_nr = proto_register_protocol("PDCP-NR", "PDCP-NR", "pdcp-nr");
3088 proto_register_field_array(proto_pdcp_nr, hf_pdcp, array_length(hf_pdcp));
3089 proto_register_subtree_array(ett, array_length(ett));
3090 expert_pdcp_nr = expert_register_protocol(proto_pdcp_nr);
3091 expert_register_field_array(expert_pdcp_nr, ei, array_length(ei));
3092 proto_sdap = proto_register_protocol("SDAP", "SDAP", "sdap");
3093 proto_register_field_array(proto_sdap, hf_sdap, array_length(hf_sdap));
3095 /* Allow other dissectors to find this one by name. */
3096 register_dissector("pdcp-nr", dissect_pdcp_nr, proto_pdcp_nr);
3098 pdcp_nr_module = prefs_register_protocol(proto_pdcp_nr, NULL);
3100 /* Dissect uncompressed user-plane data as IP */
3101 prefs_register_bool_preference(pdcp_nr_module, "show_user_plane_as_ip",
3102 "Show uncompressed User-Plane data as IP",
3103 "Show uncompressed User-Plane data as IP",
3104 &global_pdcp_dissect_user_plane_as_ip);
3106 /* Dissect unciphered signalling data as RRC */
3107 prefs_register_bool_preference(pdcp_nr_module, "show_signalling_plane_as_rrc",
3108 "Show unciphered Signalling-Plane data as RRC",
3109 "Show unciphered Signalling-Plane data as RRC",
3110 &global_pdcp_dissect_signalling_plane_as_rrc);
3112 /* Check for missing sequence numbers */
3113 prefs_register_enum_preference(pdcp_nr_module, "check_sequence_numbers",
3114 "Do sequence number analysis",
3115 "Do sequence number analysis",
3116 &global_pdcp_check_sequence_numbers, sequence_analysis_vals, false);
3118 /* Attempt to dissect ROHC messages */
3119 prefs_register_bool_preference(pdcp_nr_module, "dissect_rohc",
3120 "Attempt to decode ROHC data",
3121 "Attempt to decode ROHC data",
3122 &global_pdcp_dissect_rohc);
3124 prefs_register_obsolete_preference(pdcp_nr_module, "heuristic_pdcp_nr_over_udp");
3126 prefs_register_enum_preference(pdcp_nr_module, "layer_to_show",
3127 "Which layer info to show in Info column",
3128 "Can show RLC, PDCP or Traffic layer info in Info column",
3129 &global_pdcp_nr_layer_to_show, show_info_col_vals, false);
3131 ue_keys_uat = uat_new("PDCP UE security keys",
3132 sizeof(uat_ue_keys_record_t), /* record size */
3133 "pdcp_nr_ue_keys", /* filename */
3134 true, /* from_profile */
3135 &uat_ue_keys_records, /* data_ptr */
3136 &num_ue_keys_uat, /* numitems_ptr */
3137 UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */
3138 NULL, /* help */
3139 uat_ue_keys_record_copy_cb, /* copy callback */
3140 uat_ue_keys_record_update_cb, /* update callback */
3141 uat_ue_keys_record_free_cb, /* free callback */
3142 NULL, /* post update callback */
3143 NULL, /* reset callback */
3144 ue_keys_uat_flds); /* UAT field definitions */
3146 prefs_register_uat_preference(pdcp_nr_module,
3147 "ue_keys_table",
3148 "PDCP UE Keys",
3149 "Preconfigured PDCP keys",
3150 ue_keys_uat);
3152 prefs_register_enum_preference(pdcp_nr_module, "default_ciphering_algorithm",
3153 "Ciphering algorithm to use if not signalled",
3154 "If RRC Security Info not seen, e.g. in Handover",
3155 (int*)&global_default_ciphering_algorithm, default_ciphering_algorithm_vals, false);
3157 prefs_register_enum_preference(pdcp_nr_module, "default_integrity_algorithm",
3158 "Integrity algorithm to use if not signalled",
3159 "If RRC Security Info not seen, e.g. in Handover",
3160 (int*)&global_default_integrity_algorithm, default_integrity_algorithm_vals, false);
3162 /* Attempt to decipher RRC messages */
3163 prefs_register_bool_preference(pdcp_nr_module, "decipher_signalling",
3164 "Attempt to decipher Signalling (RRC) SDUs",
3165 "N.B. only possible if build with algorithm support, and have key available and configured",
3166 &global_pdcp_decipher_signalling);
3168 /* Attempt to decipher user-plane messages */
3169 prefs_register_bool_preference(pdcp_nr_module, "decipher_userplane",
3170 "Attempt to decipher User-plane (IP) SDUs",
3171 "N.B. only possible if build with algorithm support, and have key available and configured",
3172 &global_pdcp_decipher_userplane);
3174 /* Attempt to verify RRC integrity/authentication digest */
3175 prefs_register_bool_preference(pdcp_nr_module, "verify_integrity",
3176 "Attempt to check integrity calculation",
3177 "N.B. only possible if build with algorithm support, and have key available and configured",
3178 &global_pdcp_check_integrity);
3181 prefs_register_bool_preference(pdcp_nr_module, "ignore_rrc_sec_params",
3182 "Ignore RRC security parameters",
3183 "Ignore the NR RRC security algorithm configuration, to be used when PDCP is already deciphered in the capture",
3184 &global_pdcp_ignore_sec);
3187 pdcp_sequence_analysis_bearer_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), g_direct_hash, g_direct_equal);
3188 pdcp_nr_sequence_analysis_report_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), pdcp_result_hash_func, pdcp_result_hash_equal);
3189 pdcp_security_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), g_direct_hash, g_direct_equal);
3190 pdcp_security_result_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), pdcp_nr_ueid_frame_hash_func, pdcp_nr_ueid_frame_hash_equal);
3191 pdcp_security_key_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), g_direct_hash, g_direct_equal);
3194 void proto_reg_handoff_pdcp_nr(void)
3196 /* Add as a heuristic UDP dissector */
3197 heur_dissector_add("udp", dissect_pdcp_nr_heur, "PDCP-NR over UDP", "pdcp_nr_udp", proto_pdcp_nr, HEURISTIC_DISABLE);
3199 ip_handle = find_dissector_add_dependency("ip", proto_pdcp_nr);
3200 ipv6_handle = find_dissector_add_dependency("ipv6", proto_pdcp_nr);
3201 rohc_handle = find_dissector_add_dependency("rohc", proto_pdcp_nr);
3202 nr_rrc_ul_ccch = find_dissector_add_dependency("nr-rrc.ul.ccch", proto_pdcp_nr);
3203 nr_rrc_ul_ccch1 = find_dissector_add_dependency("nr-rrc.ul.ccch1", proto_pdcp_nr);
3204 nr_rrc_dl_ccch = find_dissector_add_dependency("nr-rrc.dl.ccch", proto_pdcp_nr);
3205 nr_rrc_pcch = find_dissector_add_dependency("nr-rrc.pcch", proto_pdcp_nr);
3206 nr_rrc_bcch_bch = find_dissector_add_dependency("nr-rrc.bcch.bch", proto_pdcp_nr);
3207 nr_rrc_bcch_dl_sch = find_dissector_add_dependency("nr-rrc.bcch.dl.sch", proto_pdcp_nr);
3208 nr_rrc_ul_dcch = find_dissector_add_dependency("nr-rrc.ul.dcch", proto_pdcp_nr);
3209 nr_rrc_dl_dcch = find_dissector_add_dependency("nr-rrc.dl.dcch", proto_pdcp_nr);
3213 * Editor modelines
3215 * Local Variables:
3216 * c-basic-offset: 4
3217 * tab-width: 8
3218 * indent-tabs-mode: nil
3219 * End:
3221 * ex: set shiftwidth=4 tabstop=8 expandtab:
3222 * :indentSize=4:tabSize=8:noTabs=true: