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