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
15 #include <epan/packet.h>
16 #include <epan/prefs.h>
17 #include <epan/expert.h>
19 #include <epan/proto_data.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);
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)
48 - look into refactoring/sharing parts of deciphering/integrity with LTE implementation
52 /* Initialize the protocol and registered fields. */
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. */
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 /*-------------------------------------
141 *-------------------------------------
143 /* UAT entry structure. */
146 char *rrcCipherKeyString
;
147 char *upCipherKeyString
;
148 char *rrcIntegrityKeyString
;
149 char *upIntegrityKeyString
;
151 uint8_t rrcCipherBinaryKey
[16];
153 uint8_t upCipherBinaryKey
[16];
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')) {
176 else if ((c
>= 'a') && (c
<= 'f')) {
179 else if ((c
>= 'A') && (c
<= 'F')) {
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
);
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
)
204 unsigned written
= 0;
205 unsigned length
= (int)strlen(raw_string
);
207 /* Can't be valid if not long enough. */
210 *error
= ws_strdup_printf("PDCP NR: Invalid key string (%s) - should include 32 ASCII hex characters (16 bytes) but only %u chars given",
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
== '-')) {
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
;
231 *error
= ws_strdup_printf("PDCP-NR: Invalid char '%c' given in key", c
);
236 /* Must have found exactly 32 hex ascii chars for 16-byte key */
238 *error
= ws_strdup_printf("PDCP-NR: Key (%s) should contain 32 hex characters (16 bytes) but more detected", raw_string
);
242 *error
= ws_strdup_printf("PDCP-NR: Key (%s) should contain 32 hex characters (16 bytes) but %u detected", raw_string
, written
);
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
)
254 char cleanString
[32];
256 if (!check_valid_key_string(stringKey
, cleanString
, error
)) {
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]);
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
;
317 ue_key_type_t key_type
;
319 uint8_t binaryKey
[16];
321 uint32_t setup_frame
;
324 /* List of key entries for an individual UE */
326 #define MAX_KEY_ENTRIES_PER_UE 32
327 unsigned num_entries_set
;
328 key_entry_t entries
[MAX_KEY_ENTRIES_PER_UE
];
332 void set_pdcp_nr_rrc_ciphering_key(uint16_t ueid
, const char *key
, uint32_t frame_num
)
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
) {
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
);
356 report_failure("%s: (RRC Ciphering Key)", err
);
361 void set_pdcp_nr_rrc_integrity_key(uint16_t ueid
, const char *key
, uint32_t frame_num
)
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
) {
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
);
385 report_failure("%s: (RRC Integrity Key)", err
);
390 void set_pdcp_nr_up_ciphering_key(uint16_t ueid
, const char *key
, uint32_t frame_num
)
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
) {
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
);
414 report_failure("%s: (UP Cipher Key)", err
);
419 void set_pdcp_nr_up_integrity_key(uint16_t ueid
, const char *key
, uint32_t frame_num
)
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
) {
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
);
443 report_failure("%s: (UP Integrity Key)", err
);
449 static const value_string direction_vals
[] =
451 { PDCP_NR_DIRECTION_UPLINK
, "Uplink"},
452 { PDCP_NR_DIRECTION_DOWNLINK
, "Downlink"},
457 static const value_string pdcp_plane_vals
[] = {
458 { NR_SIGNALING_PLANE
, "Signalling" },
459 { NR_USER_PLANE
, "User" },
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"},
472 static const value_string rohc_mode_vals
[] = {
473 { UNIDIRECTIONAL
, "Unidirectional" },
474 { OPTIMISTIC_BIDIRECTIONAL
, "Optimistic Bidirectional" },
475 { RELIABLE_BIDIRECTIONAL
, "Reliable Bidirectional" },
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] */
497 static const value_string control_pdu_type_vals
[] = {
498 { 0, "PDCP status report" },
499 { 1, "Interspersed ROHC feedback packet" },
503 static const value_string integrity_algorithm_vals
[] = {
504 { nia0
, "NIA0 (NULL)" },
505 { nia1
, "NIA1 (SNOW3G)" },
506 { nia2
, "NIA2 (AES)" },
507 { nia3
, "NIA3 (ZUC)" },
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" },
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
;
530 static const true_false_string sdap_rdi
= {
531 "To store QoS flow to DRB mapping rule",
535 static const true_false_string sdap_rqi
= {
536 "To inform NAS that RQI bit is set to 1",
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 */
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 */
601 /* Using bit fields to fit into 32 bits, so avoiding the need to allocate
602 heap memory for these structs */
605 unsigned bearerId
: 6;
606 unsigned direction
: 1;
607 unsigned notUsed
: 7;
608 } pdcp_bearer_hash_key
;
613 uint32_t previousSequenceNumber
;
614 uint32_t previousFrameNum
;
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 */
626 uint32_t frameNumber
;
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) +
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
)
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
,
670 static pdcp_result_hash_key key
;
671 pdcp_result_hash_key
*p_key
;
673 /* Only allocate a struct when will be adding entry */
675 p_key
= wmem_new(wmem_file_scope(), pdcp_result_hash_key
);
678 memset(&key
, 0, sizeof(pdcp_result_hash_key
));
682 /* Fill in details, and return pointer */
683 p_key
->frameNumber
= frameNumber
;
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
;
694 /* Info to attach to frame when first read, recording what to show about sequence */
697 SN_OK
, SN_Repeated
, SN_MAC_Retx
, SN_Retx
, SN_Missing
701 bool sequenceExpectedCorrect
;
702 uint32_t sequenceExpected
;
703 uint32_t previousFrameNum
;
704 uint32_t nextFrameNum
;
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
;
723 uint8_t* integrityKey
;
725 bool integrityKeyValid
;
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 */
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
) {
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
;
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
;
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
;
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
;
790 /* Return this struct (even if doesn't have all/any keys set..) */
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 */
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
;
817 uat_ue_keys_record_t
*keys_record
;
820 seqnum_ti
= proto_tree_add_string_format(tree
,
821 hf_pdcp_nr_sequence_analysis
,
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
:
846 DISSECTOR_ASSERT_NOT_REACHED();
852 proto_item_set_hidden(ti_expected_sn
);
853 ti
= proto_tree_add_boolean(seqnum_tree
, hf_pdcp_nr_sequence_analysis_ok
,
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
);
867 ti
= proto_tree_add_boolean(seqnum_tree
, hf_pdcp_nr_sequence_analysis_ok
,
869 proto_item_set_generated(ti
);
870 ti
= proto_tree_add_boolean(seqnum_tree
, hf_pdcp_nr_sequence_analysis_skipped
,
872 proto_item_set_generated(ti
);
873 if (p
->lastSN
!= p
->firstSN
) {
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
);
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)",
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)",
906 ti
= proto_tree_add_boolean(seqnum_tree
, hf_pdcp_nr_sequence_analysis_ok
,
908 proto_item_set_generated(ti
);
909 ti
= proto_tree_add_boolean(seqnum_tree
, hf_pdcp_nr_sequence_analysis_repeated
,
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)",
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",
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
);
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
;
946 char *cipher_key
= NULL
;
947 char *integrity_key
= NULL
;
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;
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;
965 case PDCP_NR_SN_LENGTH_18_BITS
:
966 hfn_multiplier
= 262144;
969 DISSECTOR_ASSERT_NOT_REACHED();
972 count
= (p
->hfn
* hfn_multiplier
) + sequenceNumber
;
973 ti
= proto_tree_add_uint(security_tree
, hf_pdcp_nr_security_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
;
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
,
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
)) {
1069 (pdcp_sequence_report_in_frame
*)wmem_map_lookup(pdcp_nr_sequence_analysis_report_hash
,
1070 get_report_hash_key(sequenceNumber
,
1072 p_pdcp_nr_info
, false));
1073 if (p_report_in_frame
!= NULL
) {
1074 addBearerSequenceInfo(p_report_in_frame
, p_pdcp_nr_info
,
1076 pinfo
, tree
, tvb
, security_tree
, pdu_security
);
1080 /* Give up - we must have tried already... */
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
);
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
:
1118 case PDCP_NR_SN_LENGTH_18_BITS
:
1122 DISSECTOR_ASSERT_NOT_REACHED();
1126 /* Work out expected sequence number */
1127 if (!createdBearer
) {
1128 expectedSequenceNumber
= (p_bearer_status
->previousSequenceNumber
+ 1) % snLimit
;
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
;
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
;
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
,
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),
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
{
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
,
1223 static ueid_frame_t key
;
1224 ueid_frame_t
*p_key
;
1226 /* Only allocate a struct when will be adding entry */
1228 p_key
= wmem_new(wmem_file_scope(), ueid_frame_t
);
1231 /* Only looking up, so just use static */
1232 memset(&key
, 0, sizeof(ueid_frame_t
));
1236 /* Fill in details, and return pointer */
1237 p_key
->framenum
= frameNumber
;
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:
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
];
1275 va_start(ap
, format
);
1276 vsnprintf(info_buffer
, MAX_INFO_BUFFER
, format
, 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
)
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
);
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
);
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
);
1313 if (p_pdcp_info
->ueid
!= 0) {
1314 ti
= proto_tree_add_uint(configuration_tree
, hf_pdcp_nr_ueid
, tvb
, 0, 0,
1316 proto_item_set_generated(ti
);
1317 write_pdu_label_and_info(configuration_ti
, pinfo
, "UEId=%3u", p_pdcp_info
->ueid
);
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) {
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
);
1338 write_pdu_label_and_info(configuration_ti
, pinfo
, " %s",
1339 val_to_str_const(p_pdcp_info
->bearerType
, bearer_type_vals
, "Unknown"));
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
);
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
) {
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
);
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
);
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
);
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
);
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",
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
)
1442 if (p_pdcp_info
->direction
== PDCP_NR_DIRECTION_UPLINK
) {
1443 rrc_handle
= (data_length
== 8) ? nr_rrc_ul_ccch1
: nr_rrc_ul_ccch
;
1445 rrc_handle
= nr_rrc_dl_ccch
;
1449 rrc_handle
= nr_rrc_pcch
;
1451 case Bearer_BCCH_BCH
:
1452 rrc_handle
= nr_rrc_bcch_bch
;
1454 case Bearer_BCCH_DL_SCH
:
1455 rrc_handle
= nr_rrc_bcch_dl_sch
;
1458 if (p_pdcp_info
->direction
== PDCP_NR_DIRECTION_UPLINK
) {
1459 rrc_handle
= nr_rrc_ul_dcch
;
1461 rrc_handle
= nr_rrc_dl_dcch
;
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
) {
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
);
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
);
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),
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 */
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
) {
1569 /* Nothing to do if don't have valid cipher key */
1570 if (!pdu_security_settings
->cipherKeyValid
) {
1574 /* Check whether algorithm supported (only drop through and process if we do) */
1575 if (pdu_security_settings
->ciphering
== nea1
) {
1580 else if (pdu_security_settings
->ciphering
== nea3
) {
1585 else if (pdu_security_settings
->ciphering
!= nea2
) {
1586 /* An algorithm we don't support at all! */
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
)) {
1597 /* Don't decipher user-plane control messages */
1598 if ((p_pdcp_info
->plane
== NR_USER_PLANE
) && ((tvb_get_uint8(tvb
, 0) & 0x80) == 0x00)) {
1602 /* Don't decipher common control messages */
1603 if ((p_pdcp_info
->plane
== NR_SIGNALING_PLANE
) && (p_pdcp_info
->bearerType
!= Bearer_DCCH
)) {
1607 /* Don't decipher if not yet past SecurityModeResponse */
1608 if (!will_be_deciphered
) {
1613 if (pdu_security_settings
->ciphering
== nea2
) {
1614 unsigned char ctr_block
[16];
1615 gcry_cipher_hd_t cypher_hd
;
1617 /* TS 33.501 D.4.4 defers to TS 33.401 B.1.3 */
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) {
1635 gcrypt_err
= gcry_cipher_setkey(cypher_hd
, pdu_security_settings
->cipherKey
, 16);
1636 if (gcrypt_err
!= 0) {
1637 gcry_cipher_close(cypher_hd
);
1642 gcrypt_err
= gcry_cipher_setctr(cypher_hd
, ctr_block
, 16);
1643 if (gcrypt_err
!= 0) {
1644 gcry_cipher_close(cypher_hd
);
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
,
1656 if (gcrypt_err
!= 0) {
1657 gcry_cipher_close(cypher_hd
);
1661 /* Close gcrypt handle */
1662 gcry_cipher_close(cypher_hd
);
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);
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
);
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 */
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 */
1722 /* Can't calculate if don't have valid integrity key */
1723 if (!pdu_security_settings
->integrityKeyValid
) {
1727 /* Can only do if indicated in preferences */
1728 if (!global_pdcp_check_integrity
) {
1732 switch (pdu_security_settings
->integrity
) {
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
,
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
,
1762 (message_length
+1)*8);
1765 return ((mac
[0] << 24) | (mac
[1] << 16) | (mac
[2] << 8) | mac
[3]);
1772 gcry_mac_hd_t mac_hd
;
1774 unsigned header_length
;
1776 uint8_t *message_data
;
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) {
1787 gcrypt_err
= gcry_mac_setkey(mac_hd
, pdu_security_settings
->integrityKey
, 16);
1788 if (gcrypt_err
!= 0) {
1789 gcry_mac_close(mac_hd
);
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
);
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
);
1831 /* Now close the mac handle */
1832 gcry_mac_close(mac_hd
);
1835 return ((mac
[0] << 24) | (mac
[1] << 16) | (mac
[2] << 8) | mac
[3]);
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
,
1871 /* Can't calculate */
1872 *calculated
= false;
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
)
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_
)
1901 struct pdcp_nr_info
*p_pdcp_nr_info
;
1904 bool seqnumLengthTagPresent
= false;
1906 /* Needs to be at least as long as:
1907 - the signature string
1908 - fixed header byte(s)
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
) {
1918 /* OK, compare with signature string */
1919 if (tvb_strneql(tvb
, offset
, PDCP_NR_START_STRING
, strlen(PDCP_NR_START_STRING
)) != 0) {
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
++);
1943 case PDCP_NR_SEQNUM_LENGTH_TAG
:
1944 p_pdcp_nr_info
->seqnum_length
= tvb_get_uint8(tvb
, offset
);
1946 seqnumLengthTagPresent
= true;
1948 case PDCP_NR_DIRECTION_TAG
:
1949 p_pdcp_nr_info
->direction
= tvb_get_uint8(tvb
, offset
);
1952 case PDCP_NR_BEARER_TYPE_TAG
:
1953 p_pdcp_nr_info
->bearerType
= (NRBearerType
)tvb_get_uint8(tvb
, offset
);
1956 case PDCP_NR_BEARER_ID_TAG
:
1957 p_pdcp_nr_info
->bearerId
= tvb_get_uint8(tvb
, offset
);
1960 case PDCP_NR_UEID_TAG
:
1961 p_pdcp_nr_info
->ueid
= tvb_get_ntohs(tvb
, offset
);
1964 case PDCP_NR_ROHC_COMPRESSION_TAG
:
1965 p_pdcp_nr_info
->rohc
.rohc_compression
= true;
1967 case PDCP_NR_ROHC_IP_VERSION_TAG
:
1968 p_pdcp_nr_info
->rohc
.rohc_ip_version
= tvb_get_uint8(tvb
, offset
);
1971 case PDCP_NR_ROHC_CID_INC_INFO_TAG
:
1972 p_pdcp_nr_info
->rohc
.cid_inclusion_info
= true;
1974 case PDCP_NR_ROHC_LARGE_CID_PRES_TAG
:
1975 p_pdcp_nr_info
->rohc
.large_cid_present
= true;
1977 case PDCP_NR_ROHC_MODE_TAG
:
1978 p_pdcp_nr_info
->rohc
.mode
= (enum rohc_mode
)tvb_get_uint8(tvb
, offset
);
1981 case PDCP_NR_ROHC_RND_TAG
:
1982 p_pdcp_nr_info
->rohc
.rnd
= true;
1984 case PDCP_NR_ROHC_UDP_CHECKSUM_PRES_TAG
:
1985 p_pdcp_nr_info
->rohc
.udp_checksum_present
= true;
1987 case PDCP_NR_ROHC_PROFILE_TAG
:
1988 p_pdcp_nr_info
->rohc
.profile
= tvb_get_ntohs(tvb
, offset
);
1991 case PDCP_NR_MACI_PRES_TAG
:
1992 p_pdcp_nr_info
->maci_present
= true;
1994 case PDCP_NR_SDAP_HEADER_TAG
:
1995 p_pdcp_nr_info
->sdap_header
= tvb_get_uint8(tvb
, offset
) & 0x03;
1998 case PDCP_NR_CIPHER_DISABLED_TAG
:
1999 p_pdcp_nr_info
->ciphering_disabled
= true;
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
);
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
);
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
);
2023 /* Store info in packet */
2024 p_add_proto_data(wmem_file_scope(), pinfo
, proto_pdcp_nr
, 0, p_pdcp_nr_info
);
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
);
2040 /******************************/
2041 /* Main dissection function. */
2042 static int dissect_pdcp_nr(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
2045 proto_tree
*pdcp_tree
= NULL
;
2046 proto_item
*root_ti
= NULL
;
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
) {
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
);
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
;
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);
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. */
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 */
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),
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),
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
,
2185 security_tree
= proto_item_add_subtree(security_ti
, ett_pdcp_security
);
2186 proto_item_set_generated(security_ti
);
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
);
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
);
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
);
2243 write_pdu_label_and_info(root_ti
, pinfo
, " (SN=%-4u)", seqnum
);
2246 if (tvb_captured_length_remaining(tvb
, offset
) == 0) {
2247 /* Only PDCP header was captured, stop dissection here */
2252 else if (p_pdcp_info
->plane
== NR_USER_PLANE
) {
2254 /**********************************/
2255 /* User-plane messages */
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",
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
);
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",
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
);
2301 /* Not a recognised data format!!!!! */
2305 write_pdu_label_and_info(root_ti
, pinfo
, " (SN=%-6u)", seqnum
);
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 */
2317 unsigned not_received
= 0;
2319 uint32_t len
, bit_offset
;
2320 proto_tree
*bitmap_tree
;
2321 proto_item
*bitmap_ti
= 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",
2337 /* First-Missing-Count */
2338 proto_tree_add_item_ret_uint(pdcp_tree
, hf_pdcp_nr_fmc
, tvb
, offset
, 4, ENC_BIG_ENDIAN
, &fmc
);
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) {
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));
2363 j
+= (unsigned)g_strlcpy(&buff
[j
], " ,", BUFF_SIZE
-j
);
2369 proto_tree_add_uint_format(bitmap_tree
, hf_pdcp_nr_bitmap_byte
, tvb
, bit_offset
/8, 1, bits
, "%s", buff
);
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",
2383 case 1: /* ROHC Feedback */
2385 break; /* Drop-through to dissect feedback */
2390 /* Invalid plane setting...! */
2391 write_pdu_label_and_info(root_ti
, pinfo
, " - INVALID PLANE (%u)",
2392 p_pdcp_info
->plane
);
2396 /* Have reached the end of the header (for data frames) */
2397 int header_length
= offset
;
2399 /* Do sequence analysis if configured to. */
2401 bool do_analysis
= false;
2403 switch (global_pdcp_check_sequence_numbers
) {
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
) {
2412 case SEQUENCE_ANALYSIS_PDCP_ONLY
:
2413 if (p_get_proto_data(wmem_file_scope(), pinfo
, proto_rlc_nr
, 0) == NULL
) {
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 */
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;
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
,
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
),
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
) {
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
);
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;
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);
2540 /* SDAP (not to be taken from decrypted payload) */
2541 proto_item
*sdap_ti
;
2542 proto_tree
*sdap_tree
;
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
) {
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
));
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) {
2587 call_dissector_only(ip_handle
, ip_payload_tvb
, pinfo
, pdcp_tree
, NULL
);
2590 call_dissector_only(ipv6_handle
, ip_payload_tvb
, pinfo
, pdcp_tree
, NULL
);
2593 call_data_dissector(ip_payload_tvb
, pinfo
, pdcp_tree
);
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);
2604 proto_tree_add_item(pdcp_tree
, hf_pdcp_nr_user_plane_data
, payload_tvb
, offset
, payload_length
, ENC_NA
);
2608 /***************************/
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
);
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);
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
);
2637 if (p_pdcp_info
->maci_present
) {
2638 /* Last 4 bytes are MAC */
2639 int mac_offset
= tvb_reported_length(payload_tvb
)-4;
2641 mac_ti
= proto_tree_add_item_ret_uint(pdcp_tree
, hf_pdcp_nr_mac
, payload_tvb
, mac_offset
, 4, ENC_BIG_ENDIAN
, &mac
);
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
);
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
,
2673 "pdcp-nr.configuration", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2674 "Configuration info passed into dissector", HFILL
2677 { &hf_pdcp_nr_direction
,
2679 "pdcp-nr.direction", FT_UINT8
, BASE_DEC
, VALS(direction_vals
), 0x0,
2680 "Direction of message", HFILL
2685 "pdcp-nr.ueid", FT_UINT16
, BASE_DEC
, 0, 0x0,
2686 "UE Identifier", HFILL
2689 { &hf_pdcp_nr_bearer_type
,
2691 "pdcp-nr.Bearer-type", FT_UINT8
, BASE_DEC
, VALS(bearer_type_vals
), 0x0,
2695 { &hf_pdcp_nr_bearer_id
,
2697 "pdcp-nr.bearer-id", FT_UINT8
, BASE_DEC
, 0, 0x0,
2701 { &hf_pdcp_nr_plane
,
2703 "pdcp-nr.plane", FT_UINT8
, BASE_DEC
, VALS(pdcp_plane_vals
), 0x0,
2707 { &hf_pdcp_nr_seqnum_length
,
2709 "pdcp-nr.seqnum_length", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2710 "Sequence Number Length", HFILL
2713 { &hf_pdcp_nr_maci_present
,
2715 "pdcp-nr.maci_present", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
2716 "Indicates whether MAC-I digest bytes are expected", HFILL
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,
2733 { &hf_pdcp_nr_rohc_compression
,
2734 { "ROHC Compression",
2735 "pdcp-nr.rohc.compression", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
2739 { &hf_pdcp_nr_rohc_mode
,
2741 "pdcp-nr.rohc.mode", FT_UINT8
, BASE_DEC
, VALS(rohc_mode_vals
), 0x0,
2745 { &hf_pdcp_nr_rohc_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
,
2753 "pdcp-nr.rohc.checksum-present", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
2754 "UDP Checksum present", HFILL
2757 { &hf_pdcp_nr_rohc_profile
,
2759 "pdcp-nr.rohc.profile", FT_UINT16
, BASE_DEC
, VALS(rohc_profile_vals
), 0x0,
2763 { &hf_pdcp_nr_cid_inclusion_info
,
2764 { "CID Inclusion Info",
2765 "pdcp-nr.cid-inclusion-info", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
2769 { &hf_pdcp_nr_large_cid_present
,
2770 { "Large CID Present",
2771 "pdcp-nr.large-cid-present", FT_BOOLEAN
, BASE_NONE
, NULL
, 0x0,
2776 { &hf_pdcp_nr_control_plane_reserved
,
2778 "pdcp-nr.reserved", FT_UINT8
, BASE_DEC
, NULL
, 0xf0,
2782 { &hf_pdcp_nr_reserved3
,
2784 "pdcp-nr.reserved3", FT_UINT8
, BASE_HEX
, NULL
, 0x70,
2785 "3 reserved bits", HFILL
2788 { &hf_pdcp_nr_seq_num_12
,
2790 "pdcp-nr.seq-num", FT_UINT16
, BASE_DEC
, NULL
, 0x0fff,
2791 "PDCP Seq num", HFILL
2794 { &hf_pdcp_nr_reserved5
,
2796 "pdcp-nr.reserved5", FT_UINT8
, BASE_HEX
, NULL
, 0x7c,
2797 "5 reserved bits", HFILL
2800 { &hf_pdcp_nr_seq_num_18
,
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,
2814 "pdcp-nr.mac", FT_UINT32
, BASE_HEX
, NULL
, 0x0,
2818 { &hf_pdcp_nr_data_control
,
2820 "pdcp-nr.pdu-type", FT_BOOLEAN
, 8, TFS(&tfs_data_pdu_control_pdu
), 0x80,
2824 { &hf_pdcp_nr_user_plane_data
,
2825 { "User-Plane Data",
2826 "pdcp-nr.user-data", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
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,
2837 { "First Missing Count",
2838 "pdcp-nr.fmc", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2842 { &hf_pdcp_nr_reserved4
,
2844 "pdcp-nr.reserved4", FT_UINT8
, BASE_HEX
, NULL
, 0x0f,
2845 "4 reserved bits", HFILL
2848 { &hf_pdcp_nr_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
,
2856 "pdcp-nr.bitmap.byte", FT_UINT8
, BASE_HEX
, NULL
, 0x0,
2861 { &hf_pdcp_nr_sequence_analysis
,
2862 { "Sequence Analysis",
2863 "pdcp-nr.sequence-analysis", FT_STRING
, BASE_NONE
, 0, 0x0,
2867 { &hf_pdcp_nr_sequence_analysis_ok
,
2869 "pdcp-nr.sequence-analysis.ok", FT_BOOLEAN
, BASE_NONE
, 0, 0x0,
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,
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,
2885 { &hf_pdcp_nr_sequence_analysis_expected_sn
,
2887 "pdcp-nr.sequence-analysis.expected-sn", FT_UINT32
, BASE_DEC
, 0, 0x0,
2891 { &hf_pdcp_nr_sequence_analysis_skipped
,
2893 "pdcp-nr.sequence-analysis.skipped-frames", FT_BOOLEAN
, BASE_NONE
, 0, 0x0,
2897 { &hf_pdcp_nr_sequence_analysis_repeated
,
2899 "pdcp-nr.sequence-analysis.repeated-frame", FT_BOOLEAN
, BASE_NONE
, 0, 0x0,
2904 /* Security fields */
2905 { &hf_pdcp_nr_security
,
2906 { "Security Config",
2907 "pdcp-nr.security-config", FT_STRING
, BASE_NONE
, 0, 0x0,
2911 { &hf_pdcp_nr_security_setup_frame
,
2912 { "Configuration frame",
2913 "pdcp-nr.security-config.setup-frame", FT_FRAMENUM
, BASE_NONE
, NULL
, 0x0,
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,
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,
2929 { &hf_pdcp_nr_security_bearer
,
2931 "pdcp-nr.security-config.bearer", FT_UINT8
, BASE_DEC
, NULL
, 0x0,
2935 { &hf_pdcp_nr_security_direction
,
2937 "pdcp-nr.security-config.direction", FT_UINT8
, BASE_DEC
, VALS(direction_vals
), 0x0,
2941 { &hf_pdcp_nr_security_count
,
2943 "pdcp-nr.security-config.count", FT_UINT32
, BASE_DEC
, NULL
, 0x0,
2947 { &hf_pdcp_nr_security_cipher_key
,
2949 "pdcp-nr.security-config.cipher-key", FT_STRING
, BASE_NONE
, NULL
, 0x0,
2953 { &hf_pdcp_nr_security_integrity_key
,
2955 "pdcp-nr.security-config.integrity-key", FT_STRING
, BASE_NONE
, NULL
, 0x0,
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,
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,
2971 { &hf_pdcp_nr_security_deciphered_data
,
2972 { "Deciphered Data",
2973 "pdcp-nr.deciphered-data", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
2977 { &hf_pdcp_nr_security_integrity_data
,
2979 "pdcp-nr.integrity-data", FT_BYTES
, BASE_NONE
, NULL
, 0x0,
2985 static hf_register_info hf_sdap
[] =
2989 "sdap.rdi", FT_BOOLEAN
, 8, TFS(&sdap_rdi
), 0x80,
2990 "Reflective QoS flow to DRB mapping Indication", HFILL
2995 "sdap.rqi", FT_BOOLEAN
, 8, TFS(&sdap_rqi
), 0x40,
2996 "Reflective QoS Indication", HFILL
3001 "sdap.qfi", FT_UINT8
, BASE_DEC
, NULL
, 0x3f,
3002 "QoS Flow ID", HFILL
3005 { &hf_sdap_data_control
,
3007 "sdap.pdu-type", FT_BOOLEAN
, 8, TFS(&tfs_data_pdu_control_pdu
), 0x80,
3011 { &hf_sdap_reserved
,
3013 "sdap.reserved", FT_UINT8
, BASE_HEX
, NULL
, 0x40,
3022 &ett_pdcp_configuration
,
3024 &ett_pdcp_nr_sequence_analysis
,
3025 &ett_pdcp_report_bitmap
,
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
},
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
},
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
},
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
},
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"),
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 */
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
,
3149 "Preconfigured PDCP keys",
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
);
3218 * indent-tabs-mode: nil
3221 * ex: set shiftwidth=4 tabstop=8 expandtab:
3222 * :indentSize=4:tabSize=8:noTabs=true: