1 /* packet-pdcp-lte.c
2 * Routines for LTE PDCP
3 *
4 * Martin Mathieson
5 *
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
9 *
10 * SPDX-License-Identifier: GPL-2.0-or-later
11 */
12
13 #include "config.h"
14
15 #include <epan/packet.h>
16 #include <epan/prefs.h>
17 #include <epan/expert.h>
18 #include <epan/uat.h>
19 #include <epan/proto_data.h>
20
21 #include <wsutil/wsgcrypt.h>
22 #include <wsutil/report_message.h>
23
24 /* Define these symbols if you have working implementations of SNOW3G/ZUC f8() and f9() available.
25 Note that the use of these algorithms is restricted, so a version of Wireshark with these
26 ciphering algorithms enabled would not be distributable. */
27
28 /* #define HAVE_SNOW3G */
29 /* #define HAVE_ZUC */
30
31 #include "packet-rlc-lte.h"
32 #include "packet-pdcp-lte.h"
33
34 void proto_register_pdcp_lte(void);
35 void proto_reg_handoff_pdcp_lte(void);
36
37 /* Described in:
38 * 3GPP TS 36.323 Evolved Universal Terrestrial Radio Access (E-UTRA)
39 * Packet Data Convergence Protocol (PDCP) specification v14.3.0
40 */
41
42
43 /* TODO:
44 - Decipher even if sequence analysis isn't 'OK'?
45 - know SN, but might be unsure about HFN.
46 - Speed up AES decryption by keeping the crypt handle around for the channel
47 (like ESP decryption in IPSEC dissector). N.B. do lazily when it needs to be used.
48 CTR will need to be applied before each frame.
49 - Add Relay Node user plane data PDU dissection
50 - Add SLRB user data plane data PDU dissection
51 - Break out security and sequence analysis into a separate common file to be
52 shared with pdcp-nr
53 */
54
55
56 /* Initialize the protocol and registered fields. */
57 int proto_pdcp_lte = -1;
58
59 extern int proto_rlc_lte;
60
61 /* Configuration (info known outside of PDU) */
62 static int hf_pdcp_lte_configuration = -1;
63 static int hf_pdcp_lte_direction = -1;
64 static int hf_pdcp_lte_ueid = -1;
65 static int hf_pdcp_lte_channel_type = -1;
66 static int hf_pdcp_lte_channel_id = -1;
67
68 static int hf_pdcp_lte_rohc_compression = -1;
69 static int hf_pdcp_lte_rohc_mode = -1;
70 static int hf_pdcp_lte_rohc_rnd = -1;
71 static int hf_pdcp_lte_rohc_udp_checksum_present = -1;
72 static int hf_pdcp_lte_rohc_profile = -1;
73
74 static int hf_pdcp_lte_no_header_pdu = -1;
75 static int hf_pdcp_lte_plane = -1;
76 static int hf_pdcp_lte_seqnum_length = -1;
77 static int hf_pdcp_lte_cid_inclusion_info = -1;
78 static int hf_pdcp_lte_large_cid_present = -1;
79
80 /* PDCP header fields */
81 static int hf_pdcp_lte_control_plane_reserved = -1;
82 static int hf_pdcp_lte_seq_num_5 = -1;
83 static int hf_pdcp_lte_seq_num_7 = -1;
84 static int hf_pdcp_lte_reserved3 = -1;
85 static int hf_pdcp_lte_seq_num_12 = -1;
86 static int hf_pdcp_lte_seq_num_15 = -1;
87 static int hf_pdcp_lte_polling = -1;
88 static int hf_pdcp_lte_reserved5 = -1;
89 static int hf_pdcp_lte_seq_num_18 = -1;
90 static int hf_pdcp_lte_signalling_data = -1;
91 static int hf_pdcp_lte_mac = -1;
92 static int hf_pdcp_lte_data_control = -1;
93 static int hf_pdcp_lte_user_plane_data = -1;
94 static int hf_pdcp_lte_control_pdu_type = -1;
95 static int hf_pdcp_lte_fms = -1;
96 static int hf_pdcp_lte_reserved4 = -1;
97 static int hf_pdcp_lte_fms2 = -1;
98 static int hf_pdcp_lte_reserved6 = -1;
99 static int hf_pdcp_lte_fms3 = -1;
100 static int hf_pdcp_lte_bitmap = -1;
101 static int hf_pdcp_lte_bitmap_byte = -1;
102 static int hf_pdcp_lte_hrw = -1;
103 static int hf_pdcp_lte_nmp = -1;
104 static int hf_pdcp_lte_reserved7 = -1;
105 static int hf_pdcp_lte_hrw2 = -1;
106 static int hf_pdcp_lte_nmp2 = -1;
107 static int hf_pdcp_lte_hrw3 = -1;
108 static int hf_pdcp_lte_reserved8 = -1;
109 static int hf_pdcp_lte_nmp3 = -1;
110 static int hf_pdcp_lte_lsn = -1;
111 static int hf_pdcp_lte_lsn2 = -1;
112 static int hf_pdcp_lte_lsn3 = -1;
113
114 /* Sequence Analysis */
115 static int hf_pdcp_lte_sequence_analysis = -1;
116 static int hf_pdcp_lte_sequence_analysis_ok = -1;
117 static int hf_pdcp_lte_sequence_analysis_previous_frame = -1;
118 static int hf_pdcp_lte_sequence_analysis_next_frame = -1;
119 static int hf_pdcp_lte_sequence_analysis_expected_sn = -1;
120
121 static int hf_pdcp_lte_sequence_analysis_repeated = -1;
122 static int hf_pdcp_lte_sequence_analysis_skipped = -1;
123
124 /* Security Settings */
125 static int hf_pdcp_lte_security = -1;
126 static int hf_pdcp_lte_security_setup_frame = -1;
127 static int hf_pdcp_lte_security_integrity_algorithm = -1;
128 static int hf_pdcp_lte_security_ciphering_algorithm = -1;
129
130 static int hf_pdcp_lte_security_bearer = -1;
131 static int hf_pdcp_lte_security_direction = -1;
132 static int hf_pdcp_lte_security_count = -1;
133 static int hf_pdcp_lte_security_cipher_key = -1;
134 static int hf_pdcp_lte_security_integrity_key = -1;
135
136
137
138 /* Protocol subtree. */
139 static int ett_pdcp = -1;
140 static int ett_pdcp_configuration = -1;
141 static int ett_pdcp_packet = -1;
142 static int ett_pdcp_lte_sequence_analysis = -1;
143 static int ett_pdcp_report_bitmap = -1;
144 static int ett_pdcp_security = -1;
145
146 static expert_field ei_pdcp_lte_sequence_analysis_wrong_sequence_number = EI_INIT;
147 static expert_field ei_pdcp_lte_reserved_bits_not_zero = EI_INIT;
148 static expert_field ei_pdcp_lte_sequence_analysis_sn_repeated = EI_INIT;
149 static expert_field ei_pdcp_lte_sequence_analysis_sn_missing = EI_INIT;
150 static expert_field ei_pdcp_lte_digest_wrong = EI_INIT;
151 static expert_field ei_pdcp_lte_unknown_udp_framing_tag = EI_INIT;
152 static expert_field ei_pdcp_lte_missing_udp_framing_tag = EI_INIT;
153
154
155 /*-------------------------------------
156 * UAT for UE Keys
157 *-------------------------------------
158 */
159 /* UAT entry structure. */
160 typedef struct {
161 guint32 ueid;
162 gchar *rrcCipherKeyString;
163 gchar *upCipherKeyString;
164 gchar *rrcIntegrityKeyString;
165
166 guint8 rrcCipherBinaryKey[16];
167 gboolean rrcCipherKeyOK;
168 guint8 upCipherBinaryKey[16];
169 gboolean upCipherKeyOK;
170 guint8 rrcIntegrityBinaryKey[16];
171 gboolean rrcIntegrityKeyOK;
172 } uat_ue_keys_record_t;
173
174 /* N.B. this is an array/table of the struct above, where ueid is the key */
175 static uat_ue_keys_record_t *uat_ue_keys_records = NULL;
176
177 /* Entries added by UAT */
178 static uat_t * ue_keys_uat = NULL;
179 static guint num_ue_keys_uat = 0;
180
181 /* Convert an ascii hex character into a digit. Should only be given valid
182 hex ascii characters */
hex_ascii_to_binary(gchar c)183 static guchar hex_ascii_to_binary(gchar c)
184 {
185 if ((c >= '0') && (c <= '9')) {
186 return c - '0';
187 }
188 else if ((c >= 'a') && (c <= 'f')) {
189 return 10 + c - 'a';
190 }
191 else if ((c >= 'A') && (c <= 'F')) {
192 return 10 + c - 'A';
193 }
194 else {
195 return 0;
196 }
197 }
198
uat_ue_keys_record_copy_cb(void * n,const void * o,size_t siz _U_)199 static void* uat_ue_keys_record_copy_cb(void* n, const void* o, size_t siz _U_) {
200 uat_ue_keys_record_t* new_rec = (uat_ue_keys_record_t *)n;
201 const uat_ue_keys_record_t* old_rec = (const uat_ue_keys_record_t *)o;
202
203 new_rec->ueid = old_rec->ueid;
204 new_rec->rrcCipherKeyString = g_strdup(old_rec->rrcCipherKeyString);
205 new_rec->upCipherKeyString = g_strdup(old_rec->upCipherKeyString);
206 new_rec->rrcIntegrityKeyString = g_strdup(old_rec->rrcIntegrityKeyString);
207
208 return new_rec;
209 }
210
211 /* If raw_string is a valid key, set check_string & return TRUE. Can be spaced out with ' ' or '-' */
check_valid_key_string(const char * raw_string,char * checked_string,char ** error)212 static gboolean check_valid_key_string(const char* raw_string, char* checked_string, char **error)
213 {
214 guint n;
215 guint written = 0;
216 guint length = (gint)strlen(raw_string);
217
218 /* Can't be valid if not long enough. */
219 if (length < 32) {
220 if (length > 0) {
221 *error = g_strdup_printf("PDCP LTE: Invalid key string (%s) - should include 32 ASCII hex characters (16 bytes) but only %u chars given",
222 raw_string, length);
223 }
224
225 return FALSE;
226 }
227
228 for (n=0; (n < length) && (written < 32); n++) {
229 char c = raw_string[n];
230
231 /* Skipping past allowed 'padding' characters */
232 if ((c == ' ') || (c == '-')) {
233 continue;
234 }
235
236 /* Other characters must be hex digits, otherwise string is invalid */
237 if (((c >= '0') && (c <= '9')) ||
238 ((c >= 'a') && (c <= 'f')) ||
239 ((c >= 'A') && (c <= 'F'))) {
240 checked_string[written++] = c;
241 }
242 else {
243 *error = g_strdup_printf("PDCP-LTE: Invalid char '%c' given in key", c);
244 return FALSE;
245 }
246 }
247
248 /* Must have found exactly 32 hex ascii chars for 16-byte key */
249 if (n<length) {
250 *error = g_strdup_printf("PDCP-LTE: Key (%s) should contain 32 hex characters (16 bytes) but more detected", raw_string);
251 return FALSE;
252 }
253 if (written != 32) {
254 *error = g_strdup_printf("PDCP-LTE: Key (%s) should contain 32 hex characters (16 bytes) but %u detected", raw_string, written);
255 return FALSE;
256 }
257 else {
258 return TRUE;
259 }
260
261 }
262
263 /* Write binary key by converting each nibble from the string version */
update_key_from_string(const char * stringKey,guint8 * binaryKey,gboolean * pKeyOK,char ** error)264 static void update_key_from_string(const char *stringKey, guint8 *binaryKey, gboolean *pKeyOK, char **error)
265 {
266 int n;
267 char cleanString[32];
268
269 if (!check_valid_key_string(stringKey, cleanString, error)) {
270 *pKeyOK = FALSE;
271 }
272 else {
273 for (n=0; n < 32; n += 2) {
274 binaryKey[n/2] = (hex_ascii_to_binary(cleanString[n]) << 4) +
275 hex_ascii_to_binary(cleanString[n+1]);
276 }
277 *pKeyOK = TRUE;
278 }
279 }
280
281 /* Update by checking whether the 3 key strings are valid or not, and storing result */
uat_ue_keys_record_update_cb(void * record,char ** error)282 static gboolean uat_ue_keys_record_update_cb(void* record, char** error) {
283 uat_ue_keys_record_t* rec = (uat_ue_keys_record_t *)record;
284
285 /* Check and convert RRC key */
286 update_key_from_string(rec->rrcCipherKeyString, rec->rrcCipherBinaryKey, &rec->rrcCipherKeyOK, error);
287
288 /* Check and convert User-plane key */
289 update_key_from_string(rec->upCipherKeyString, rec->upCipherBinaryKey, &rec->upCipherKeyOK, error);
290
291 /* Check and convert Integrity key */
292 update_key_from_string(rec->rrcIntegrityKeyString, rec->rrcIntegrityBinaryKey, &rec->rrcIntegrityKeyOK, error);
293
294 /* Return TRUE only if *error has not been set by checking code. */
295 return *error == NULL;
296 }
297
298 /* Free heap parts of record */
uat_ue_keys_record_free_cb(void * r)299 static void uat_ue_keys_record_free_cb(void*r) {
300 uat_ue_keys_record_t* rec = (uat_ue_keys_record_t*)r;
301
302 g_free(rec->rrcCipherKeyString);
303 g_free(rec->upCipherKeyString);
304 g_free(rec->rrcIntegrityKeyString);
305 }
306
307 UAT_DEC_CB_DEF(uat_ue_keys_records, ueid, uat_ue_keys_record_t)
308 UAT_CSTRING_CB_DEF(uat_ue_keys_records, rrcCipherKeyString, uat_ue_keys_record_t)
309 UAT_CSTRING_CB_DEF(uat_ue_keys_records, upCipherKeyString, uat_ue_keys_record_t)
310 UAT_CSTRING_CB_DEF(uat_ue_keys_records, rrcIntegrityKeyString, uat_ue_keys_record_t)
311
312
313 /* Also supporting a hash table with entries from these functions */
314
315 /* Table from ueid -> uat_ue_keys_record_t* */
316 static wmem_map_t *pdcp_security_key_hash = NULL;
317
318
set_pdcp_lte_rrc_ciphering_key(guint16 ueid,const char * key)319 void set_pdcp_lte_rrc_ciphering_key(guint16 ueid, const char *key)
320 {
321 char *err = NULL;
322
323 /* Get or create struct for this UE */
324 uat_ue_keys_record_t *key_record = (uat_ue_keys_record_t*)wmem_map_lookup(pdcp_security_key_hash,
325 GUINT_TO_POINTER((guint)ueid));
326 if (key_record == NULL) {
327 /* Create and add to table */
328 key_record = wmem_new0(wmem_file_scope(), uat_ue_keys_record_t);
329 key_record->ueid = ueid;
330 wmem_map_insert(pdcp_security_key_hash, GUINT_TO_POINTER((guint)ueid), key_record);
331 }
332
333 /* Check and convert RRC key */
334 key_record->rrcCipherKeyString = g_strdup(key);
335 update_key_from_string(key_record->rrcCipherKeyString, key_record->rrcCipherBinaryKey, &key_record->rrcCipherKeyOK, &err);
336 if (err) {
337 report_failure("%s: (RRC Ciphering Key)", err);
338 g_free(err);
339 }
340 }
341
set_pdcp_lte_rrc_integrity_key(guint16 ueid,const char * key)342 void set_pdcp_lte_rrc_integrity_key(guint16 ueid, const char *key)
343 {
344 char *err = NULL;
345
346 /* Get or create struct for this UE */
347 uat_ue_keys_record_t *key_record = (uat_ue_keys_record_t*)wmem_map_lookup(pdcp_security_key_hash,
348 GUINT_TO_POINTER((guint)ueid));
349 if (key_record == NULL) {
350 /* Create and add to table */
351 key_record = wmem_new0(wmem_file_scope(), uat_ue_keys_record_t);
352 key_record->ueid = ueid;
353 wmem_map_insert(pdcp_security_key_hash, GUINT_TO_POINTER((guint)ueid), key_record);
354 }
355
356 /* Check and convert RRC integrity key */
357 key_record->rrcIntegrityKeyString = g_strdup(key);
358 update_key_from_string(key_record->rrcIntegrityKeyString, key_record->rrcIntegrityBinaryKey, &key_record->rrcIntegrityKeyOK, &err);
359 if (err) {
360 report_failure("%s: (RRC Integrity Key)", err);
361 g_free(err);
362 }
363 }
364
set_pdcp_lte_up_ciphering_key(guint16 ueid,const char * key)365 void set_pdcp_lte_up_ciphering_key(guint16 ueid, const char *key)
366 {
367 char *err = NULL;
368
369 /* Get or create struct for this UE */
370 uat_ue_keys_record_t *key_record = (uat_ue_keys_record_t*)wmem_map_lookup(pdcp_security_key_hash,
371 GUINT_TO_POINTER((guint)ueid));
372 if (key_record == NULL) {
373 /* Create and add to table */
374 key_record = wmem_new0(wmem_file_scope(), uat_ue_keys_record_t);
375 key_record->ueid = ueid;
376 wmem_map_insert(pdcp_security_key_hash, GUINT_TO_POINTER((guint)ueid), key_record);
377 }
378
379 /* Check and convert UP key */
380 key_record->upCipherKeyString = g_strdup(key);
381 update_key_from_string(key_record->upCipherKeyString, key_record->upCipherBinaryKey, &key_record->upCipherKeyOK, &err);
382 if (err) {
383 report_failure("%s: (UserPlane Ciphering Key)", err);
384 g_free(err);
385 }
386 }
387
388
389 /* Preference settings for deciphering and integrity checking. */
390 static gboolean global_pdcp_decipher_signalling = TRUE;
391 static gboolean global_pdcp_decipher_userplane = FALSE; /* Can be slow, so default to FALSE */
392 static gboolean global_pdcp_check_integrity = TRUE;
393 static gboolean global_pdcp_ignore_sec = FALSE; /* Ignore Set Security Algo calls */
394
395 /* Use these values where we know the keys but may have missed the algorithm,
396 e.g. when handing over and RRCReconfigurationRequest goes to target cell only */
397 static enum lte_security_ciphering_algorithm_e global_default_ciphering_algorithm = eea0;
398 static enum lte_security_integrity_algorithm_e global_default_integrity_algorithm = eia0;
399
400
401 static const value_string direction_vals[] =
402 {
403 { DIRECTION_UPLINK, "Uplink"},
404 { DIRECTION_DOWNLINK, "Downlink"},
405 { 0, NULL }
406 };
407
408
409 static const value_string pdcp_plane_vals[] = {
410 { SIGNALING_PLANE, "Signalling" },
411 { USER_PLANE, "User" },
412 { 0, NULL }
413 };
414
415 static const value_string logical_channel_vals[] = {
416 { Channel_DCCH, "DCCH"},
417 { Channel_BCCH, "BCCH"},
418 { Channel_CCCH, "CCCH"},
419 { Channel_PCCH, "PCCH"},
420 { 0, NULL}
421 };
422
423 static const value_string rohc_mode_vals[] = {
424 { UNIDIRECTIONAL, "Unidirectional" },
425 { OPTIMISTIC_BIDIRECTIONAL, "Optimistic Bidirectional" },
426 { RELIABLE_BIDIRECTIONAL, "Reliable Bidirectional" },
427 { 0, NULL }
428 };
429
430
431 /* Values taken from:
432 http://www.iana.org/assignments/rohc-pro-ids/rohc-pro-ids.txt */
433 static const value_string rohc_profile_vals[] = {
434 { 0x0000, "ROHC uncompressed" }, /* [RFC5795] */
435 { 0x0001, "ROHC RTP" }, /* [RFC3095] */
436 { 0x0002, "ROHC UDP" }, /* [RFC3095] */
437 { 0x0003, "ROHC ESP" }, /* [RFC3095] */
438 { 0x0004, "ROHC IP" }, /* [RFC3843] */
439 { 0x0005, "ROHC LLA" }, /* [RFC4362] */
440 { 0x0006, "ROHC TCP" }, /* [RFC4996] */
441 { 0x0007, "ROHC RTP/UDP-Lite" }, /* [RFC4019] */
442 { 0x0008, "ROHC UDP-Lite" }, /* [RFC4019] */
443 { 0x0101, "ROHCv2 RTP" }, /* [RFC5225] */
444 { 0x0102, "ROHCv2 UDP" }, /* [RFC5225] */
445 { 0x0103, "ROHCv2 ESP" }, /* [RFC5225] */
446 { 0x0104, "ROHCv2 IP" }, /* [RFC5225] */
447 { 0x0105, "ROHC LLA with R-mode" }, /* [RFC3408] */
448 { 0x0107, "ROHCv2 RTP/UDP-Lite" }, /* [RFC5225] */
449 { 0x0108, "ROHCv2 UDP-Lite" }, /* [RFC5225] */
450 { 0, NULL }
451 };
452
453 static const true_false_string pdu_type_bit = {
454 "Data PDU",
455 "Control PDU"
456 };
457
458 static const value_string control_pdu_type_vals[] = {
459 { 0, "PDCP status report" },
460 { 1, "Interspersed ROHC feedback packet" },
461 { 2, "LWA status report" },
462 { 3, "LWA end-marker packet"},
463 { 0, NULL }
464 };
465
466 static const value_string integrity_algorithm_vals[] = {
467 { eia0, "EIA0 (NULL)" },
468 { eia1, "EIA1 (SNOW3G)" },
469 { eia2, "EIA2 (AES)" },
470 { eia3, "EIA3 (ZUC)" },
471 { 0, NULL }
472 };
473
474 static const value_string ciphering_algorithm_vals[] = {
475 { eea0, "EEA0 (NULL)" },
476 { eea1, "EEA1 (SNOW3G)" },
477 { eea2, "EEA2 (AES)" },
478 { eea3, "EEA3 (ZUC)" },
479 { 0, NULL }
480 };
481
482
483 static dissector_handle_t ip_handle;
484 static dissector_handle_t ipv6_handle;
485 static dissector_handle_t rohc_handle;
486 static dissector_handle_t lte_rrc_ul_ccch;
487 static dissector_handle_t lte_rrc_dl_ccch;
488 static dissector_handle_t lte_rrc_pcch;
489 static dissector_handle_t lte_rrc_bcch_bch;
490 static dissector_handle_t lte_rrc_bcch_dl_sch;
491 static dissector_handle_t lte_rrc_ul_dcch;
492 static dissector_handle_t lte_rrc_dl_dcch;
493 static dissector_handle_t lte_rrc_ul_ccch_nb;
494 static dissector_handle_t lte_rrc_dl_ccch_nb;
495 static dissector_handle_t lte_rrc_pcch_nb;
496 static dissector_handle_t lte_rrc_bcch_bch_nb;
497 static dissector_handle_t lte_rrc_bcch_dl_sch_nb;
498 static dissector_handle_t lte_rrc_ul_dcch_nb;
499 static dissector_handle_t lte_rrc_dl_dcch_nb;
500
501
502 #define SEQUENCE_ANALYSIS_RLC_ONLY 1
503 #define SEQUENCE_ANALYSIS_PDCP_ONLY 2
504
505 /* Preference variables */
506 static gboolean global_pdcp_dissect_user_plane_as_ip = TRUE;
507 static gboolean global_pdcp_dissect_signalling_plane_as_rrc = TRUE;
508 static gint global_pdcp_check_sequence_numbers = TRUE;
509 static gboolean global_pdcp_dissect_rohc = FALSE;
510
511 /* Which layer info to show in the info column */
512 enum layer_to_show {
513 ShowRLCLayer, ShowPDCPLayer, ShowTrafficLayer
514 };
515 static gint global_pdcp_lte_layer_to_show = (gint)ShowRLCLayer;
516
517
518
519 /**************************************************/
520 /* Sequence number analysis */
521
522 /* Channel key */
523 typedef struct
524 {
525 /* Using bit fields to fit into 32 bits, so avoiding the need to allocate
526 heap memory for these structs */
527 guint ueId : 16;
528 guint plane : 2;
529 guint channelId : 6;
530 guint direction : 1;
531 guint notUsed : 7;
532 } pdcp_channel_hash_key;
533
534 /* Channel state */
535 typedef struct
536 {
537 guint32 previousSequenceNumber;
538 guint32 previousFrameNum;
539 guint32 hfn;
540 } pdcp_channel_status;
541
542 /* The sequence analysis channel hash table.
543 Maps key -> status */
544 static wmem_map_t *pdcp_sequence_analysis_channel_hash = NULL;
545
546
547 /* Hash table types & functions for frame reports */
548
549 typedef struct {
550 guint32 frameNumber;
551 guint32 SN : 18;
552 guint32 plane : 2;
553 guint32 channelId: 5;
554 guint32 direction: 1;
555 guint32 notUsed : 6;
556 } pdcp_result_hash_key;
557
pdcp_result_hash_equal(gconstpointer v,gconstpointer v2)558 static gint pdcp_result_hash_equal(gconstpointer v, gconstpointer v2)
559 {
560 const pdcp_result_hash_key* val1 = (const pdcp_result_hash_key *)v;
561 const pdcp_result_hash_key* val2 = (const pdcp_result_hash_key *)v2;
562
563 /* All fields must match */
564 return (memcmp(val1, val2, sizeof(pdcp_result_hash_key)) == 0);
565 }
566
567 /* Compute a hash value for a given key. */
pdcp_result_hash_func(gconstpointer v)568 static guint pdcp_result_hash_func(gconstpointer v)
569 {
570 const pdcp_result_hash_key* val1 = (const pdcp_result_hash_key *)v;
571
572 /* TODO: This is a bit random. */
573 return val1->frameNumber + (val1->channelId<<7) +
574 (val1->plane<<12) +
575 (val1->SN<<14) +
576 (val1->direction<<6);
577 }
578
579 /* pdcp_channel_hash_key fits into the pointer, so just copy the value into
580 a guint, cast to a pointer and return that as the key */
get_channel_hash_key(pdcp_channel_hash_key * key)581 static gpointer get_channel_hash_key(pdcp_channel_hash_key *key)
582 {
583 guint asInt = 0;
584 /* TODO: assert that sizeof(pdcp_channel_hash_key) <= sizeof(guint) ? */
585 memcpy(&asInt, key, sizeof(pdcp_channel_hash_key));
586 return GUINT_TO_POINTER(asInt);
587 }
588
589 /* Convenience function to get a pointer for the hash_func to work with */
get_report_hash_key(guint32 SN,guint32 frameNumber,pdcp_lte_info * p_pdcp_lte_info,gboolean do_persist)590 static gpointer get_report_hash_key(guint32 SN, guint32 frameNumber,
591 pdcp_lte_info *p_pdcp_lte_info,
592 gboolean do_persist)
593 {
594 static pdcp_result_hash_key key;
595 pdcp_result_hash_key *p_key;
596
597 /* Only allocate a struct when will be adding entry */
598 if (do_persist) {
599 p_key = wmem_new(wmem_file_scope(), pdcp_result_hash_key);
600 }
601 else {
602 memset(&key, 0, sizeof(pdcp_result_hash_key));
603 p_key = &key;
604 }
605
606 /* Fill in details, and return pointer */
607 p_key->frameNumber = frameNumber;
608 p_key->SN = SN;
609 p_key->plane = (guint8)p_pdcp_lte_info->plane;
610 p_key->channelId = p_pdcp_lte_info->channelId;
611 p_key->direction = p_pdcp_lte_info->direction;
612 p_key->notUsed = 0;
613
614 return p_key;
615 }
616
617
618 /* Info to attach to frame when first read, recording what to show about sequence */
619 typedef enum
620 {
621 SN_OK, SN_Repeated, SN_MAC_Retx, SN_Retx, SN_Missing
622 } sequence_state;
623 typedef struct
624 {
625 gboolean sequenceExpectedCorrect;
626 guint32 sequenceExpected;
627 guint32 previousFrameNum;
628 guint32 nextFrameNum;
629
630 guint32 firstSN;
631 guint32 lastSN;
632 guint32 hfn;
633
634 sequence_state state;
635 } pdcp_sequence_report_in_frame;
636
637 /* The sequence analysis frame report hash table.
638 Maps pdcp_result_hash_key* -> pdcp_sequence_report_in_frame* */
639 static wmem_map_t *pdcp_lte_sequence_analysis_report_hash = NULL;
640
641 /* Gather together security settings in order to be able to do deciphering */
642 typedef struct pdu_security_settings_t
643 {
644 enum lte_security_ciphering_algorithm_e ciphering;
645 enum lte_security_integrity_algorithm_e integrity;
646 guint8* cipherKey;
647 guint8* integrityKey;
648 gboolean cipherKeyValid;
649 gboolean integrityKeyValid;
650 guint32 count;
651 guint8 bearer;
652 guint8 direction;
653 } pdu_security_settings_t;
654
655
look_up_keys_record(guint16 ueid)656 static uat_ue_keys_record_t* look_up_keys_record(guint16 ueid)
657 {
658 unsigned int record_id;
659
660 /* Try hash table first (among entries added by set_pdcp_lte_xxx_key() functions) */
661 uat_ue_keys_record_t* key_record = (uat_ue_keys_record_t*)wmem_map_lookup(pdcp_security_key_hash,
662 GUINT_TO_POINTER((guint)ueid));
663 if (key_record != NULL) {
664 return key_record;
665 }
666
667 /* Else look up UAT entries. N.B. linear search... */
668 for (record_id=0; record_id < num_ue_keys_uat; record_id++) {
669 if (uat_ue_keys_records[record_id].ueid == ueid) {
670 return &uat_ue_keys_records[record_id];
671 }
672 }
673
674 /* No match at all - return NULL */
675 return NULL;
676 }
677
678 /* Add to the tree values associated with sequence analysis for this frame */
addChannelSequenceInfo(pdcp_sequence_report_in_frame * p,pdcp_lte_info * p_pdcp_lte_info,guint32 sequenceNumber,packet_info * pinfo,proto_tree * tree,tvbuff_t * tvb,proto_tree * security_tree,pdu_security_settings_t * pdu_security)679 static void addChannelSequenceInfo(pdcp_sequence_report_in_frame *p,
680 pdcp_lte_info *p_pdcp_lte_info,
681 guint32 sequenceNumber,
682 packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb,
683 proto_tree *security_tree,
684 pdu_security_settings_t *pdu_security)
685 {
686 proto_tree *seqnum_tree;
687 proto_item *seqnum_ti;
688 proto_item *ti_expected_sn;
689 proto_item *ti;
690 uat_ue_keys_record_t *keys_record;
691
692 /* Create subtree */
693 seqnum_ti = proto_tree_add_string_format(tree,
694 hf_pdcp_lte_sequence_analysis,
695 tvb, 0, 0,
696 "", "Sequence Analysis");
697 seqnum_tree = proto_item_add_subtree(seqnum_ti,
698 ett_pdcp_lte_sequence_analysis);
699 proto_item_set_generated(seqnum_ti);
700
701
702 /* Previous channel frame */
703 if (p->previousFrameNum != 0) {
704 proto_tree_add_uint(seqnum_tree, hf_pdcp_lte_sequence_analysis_previous_frame,
705 tvb, 0, 0, p->previousFrameNum);
706 }
707
708 /* Expected sequence number */
709 ti_expected_sn = proto_tree_add_uint(seqnum_tree, hf_pdcp_lte_sequence_analysis_expected_sn,
710 tvb, 0, 0, p->sequenceExpected);
711 proto_item_set_generated(ti_expected_sn);
712
713 /* Make sure we have recognised SN length */
714 switch (p_pdcp_lte_info->seqnum_length) {
715 case PDCP_SN_LENGTH_5_BITS:
716 case PDCP_SN_LENGTH_7_BITS:
717 case PDCP_SN_LENGTH_12_BITS:
718 case PDCP_SN_LENGTH_15_BITS:
719 case PDCP_SN_LENGTH_18_BITS:
720 break;
721 default:
722 DISSECTOR_ASSERT_NOT_REACHED();
723 break;
724 }
725
726 switch (p->state) {
727 case SN_OK:
728 proto_item_set_hidden(ti_expected_sn);
729 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_ok,
730 tvb, 0, 0, TRUE);
731 proto_item_set_generated(ti);
732 proto_item_append_text(seqnum_ti, " - OK");
733
734 /* Link to next SN in channel (if known) */
735 if (p->nextFrameNum != 0) {
736 proto_tree_add_uint(seqnum_tree, hf_pdcp_lte_sequence_analysis_next_frame,
737 tvb, 0, 0, p->nextFrameNum);
738 }
739
740 /* May also be able to add key inputs to security tree here */
741 if ((pdu_security->ciphering != eea0) ||
742 (pdu_security->integrity != eia0)) {
743
744 guint32 hfn_multiplier;
745 guint32 count;
746 gchar *cipher_key = NULL;
747 gchar *integrity_key = NULL;
748
749 /* BEARER */
750 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_bearer,
751 tvb, 0, 0, p_pdcp_lte_info->channelId-1);
752 proto_item_set_generated(ti);
753
754 pdu_security->bearer = p_pdcp_lte_info->channelId-1;
755
756 /* DIRECTION */
757 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_direction,
758 tvb, 0, 0, p_pdcp_lte_info->direction);
759 proto_item_set_generated(ti);
760
761 /* COUNT (HFN * snLength^2 + SN) */
762 switch (p_pdcp_lte_info->seqnum_length) {
763 case PDCP_SN_LENGTH_5_BITS:
764 hfn_multiplier = 32;
765 break;
766 case PDCP_SN_LENGTH_7_BITS:
767 hfn_multiplier = 128;
768 break;
769 case PDCP_SN_LENGTH_12_BITS:
770 hfn_multiplier = 4096;
771 break;
772 case PDCP_SN_LENGTH_15_BITS:
773 hfn_multiplier = 32768;
774 break;
775 case PDCP_SN_LENGTH_18_BITS:
776 hfn_multiplier = 262144;
777 break;
778 default:
779 DISSECTOR_ASSERT_NOT_REACHED();
780 break;
781 }
782 count = (p->hfn * hfn_multiplier) + sequenceNumber;
783 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_count,
784 tvb, 0, 0, count);
785 proto_item_set_generated(ti);
786 pdu_security->count = count;
787
788 /* KEY. Look this UE up among UEs that have keys configured */
789 keys_record = look_up_keys_record(p_pdcp_lte_info->ueid);
790 if (keys_record != NULL) {
791 if (p_pdcp_lte_info->plane == SIGNALING_PLANE) {
792 /* Get RRC ciphering key */
793 if (keys_record->rrcCipherKeyOK) {
794 cipher_key = keys_record->rrcCipherKeyString;
795 pdu_security->cipherKey = &(keys_record->rrcCipherBinaryKey[0]);
796 pdu_security->cipherKeyValid = TRUE;
797 }
798 /* Get RRC integrity key */
799 if (keys_record->rrcIntegrityKeyOK) {
800 integrity_key = keys_record->rrcIntegrityKeyString;
801 pdu_security->integrityKey = &(keys_record->rrcIntegrityBinaryKey[0]);
802 pdu_security->integrityKeyValid = TRUE;
803 }
804 }
805 else {
806 /* Get userplane ciphering key */
807 if (keys_record->upCipherKeyOK) {
808 cipher_key = keys_record->upCipherKeyString;
809 pdu_security->cipherKey = &(keys_record->upCipherBinaryKey[0]);
810 pdu_security->cipherKeyValid = TRUE;
811 }
812 }
813
814 /* Show keys where known and valid */
815 if (cipher_key != NULL) {
816 ti = proto_tree_add_string(security_tree, hf_pdcp_lte_security_cipher_key,
817 tvb, 0, 0, cipher_key);
818 proto_item_set_generated(ti);
819 }
820 if (integrity_key != NULL) {
821 ti = proto_tree_add_string(security_tree, hf_pdcp_lte_security_integrity_key,
822 tvb, 0, 0, integrity_key);
823 proto_item_set_generated(ti);
824 }
825
826 pdu_security->direction = p_pdcp_lte_info->direction;
827 }
828 }
829 break;
830
831 case SN_Missing:
832 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_ok,
833 tvb, 0, 0, FALSE);
834 proto_item_set_generated(ti);
835 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_skipped,
836 tvb, 0, 0, TRUE);
837 proto_item_set_generated(ti);
838 if (p->lastSN != p->firstSN) {
839 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_sequence_analysis_sn_missing,
840 "PDCP SNs (%u to %u) missing for %s on UE %u (%s-%u)",
841 p->firstSN, p->lastSN,
842 val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
843 p_pdcp_lte_info->ueid,
844 val_to_str_const(p_pdcp_lte_info->channelType, logical_channel_vals, "Unknown"),
845 p_pdcp_lte_info->channelId);
846 proto_item_append_text(seqnum_ti, " - SNs missing (%u to %u)",
847 p->firstSN, p->lastSN);
848 }
849 else {
850 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_sequence_analysis_sn_missing,
851 "PDCP SN (%u) missing for %s on UE %u (%s-%u)",
852 p->firstSN,
853 val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
854 p_pdcp_lte_info->ueid,
855 val_to_str_const(p_pdcp_lte_info->channelType, logical_channel_vals, "Unknown"),
856 p_pdcp_lte_info->channelId);
857 proto_item_append_text(seqnum_ti, " - SN missing (%u)",
858 p->firstSN);
859 }
860 break;
861
862 case SN_Repeated:
863 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_ok,
864 tvb, 0, 0, FALSE);
865 proto_item_set_generated(ti);
866 ti = proto_tree_add_boolean(seqnum_tree, hf_pdcp_lte_sequence_analysis_repeated,
867 tvb, 0, 0, TRUE);
868 proto_item_set_generated(ti);
869 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_sequence_analysis_sn_repeated,
870 "PDCP SN (%u) repeated for %s for UE %u (%s-%u)",
871 p->firstSN,
872 val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
873 p_pdcp_lte_info->ueid,
874 val_to_str_const(p_pdcp_lte_info->channelType, logical_channel_vals, "Unknown"),
875 p_pdcp_lte_info->channelId);
876 proto_item_append_text(seqnum_ti, "- SN %u Repeated",
877 p->firstSN);
878 break;
879
880 default:
881 /* Incorrect sequence number */
882 expert_add_info_format(pinfo, ti_expected_sn, &ei_pdcp_lte_sequence_analysis_wrong_sequence_number,
883 "Wrong Sequence Number for %s on UE %u (%s-%u) - got %u, expected %u",
884 val_to_str_const(p_pdcp_lte_info->direction, direction_vals, "Unknown"),
885 p_pdcp_lte_info->ueid,
886 val_to_str_const(p_pdcp_lte_info->channelType, logical_channel_vals, "Unknown"),
887 p_pdcp_lte_info->channelId,
888 sequenceNumber, p->sequenceExpected);
889 break;
890 }
891 }
892
893
894 /* Update the channel status and set report for this frame */
checkChannelSequenceInfo(packet_info * pinfo,tvbuff_t * tvb,pdcp_lte_info * p_pdcp_lte_info,guint32 sequenceNumber,proto_tree * tree,proto_tree * security_tree,pdu_security_settings_t * pdu_security)895 static void checkChannelSequenceInfo(packet_info *pinfo, tvbuff_t *tvb,
896 pdcp_lte_info *p_pdcp_lte_info,
897 guint32 sequenceNumber,
898 proto_tree *tree,
899 proto_tree *security_tree,
900 pdu_security_settings_t *pdu_security)
901 {
902 pdcp_channel_hash_key channel_key;
903 pdcp_channel_status *p_channel_status;
904 pdcp_sequence_report_in_frame *p_report_in_frame = NULL;
905 gboolean createdChannel = FALSE;
906 guint32 expectedSequenceNumber = 0;
907 guint32 snLimit = 0;
908
909 /* If find stat_report_in_frame already, use that and get out */
910 if (PINFO_FD_VISITED(pinfo)) {
911 p_report_in_frame =
912 (pdcp_sequence_report_in_frame*)wmem_map_lookup(pdcp_lte_sequence_analysis_report_hash,
913 get_report_hash_key(sequenceNumber,
914 pinfo->num,
915 p_pdcp_lte_info, FALSE));
916 if (p_report_in_frame != NULL) {
917 addChannelSequenceInfo(p_report_in_frame, p_pdcp_lte_info,
918 sequenceNumber,
919 pinfo, tree, tvb, security_tree, pdu_security);
920 return;
921 }
922 else {
923 /* Give up - we must have tried already... */
924 return;
925 }
926 }
927
928
929 /**************************************************/
930 /* Create or find an entry for this channel state */
931 channel_key.ueId = p_pdcp_lte_info->ueid;
932 channel_key.plane = p_pdcp_lte_info->plane;
933 channel_key.channelId = p_pdcp_lte_info->channelId;
934 channel_key.direction = p_pdcp_lte_info->direction;
935 channel_key.notUsed = 0;
936
937 /* Do the table lookup */
938 p_channel_status = (pdcp_channel_status*)wmem_map_lookup(pdcp_sequence_analysis_channel_hash,
939 get_channel_hash_key(&channel_key));
940
941 /* Create table entry if necessary */
942 if (p_channel_status == NULL) {
943 createdChannel = TRUE;
944
945 /* Allocate a new value and duplicate key contents */
946 p_channel_status = wmem_new0(wmem_file_scope(), pdcp_channel_status);
947
948 /* Add entry */
949 wmem_map_insert(pdcp_sequence_analysis_channel_hash,
950 get_channel_hash_key(&channel_key), p_channel_status);
951 }
952
953 /* Create space for frame state_report */
954 p_report_in_frame = wmem_new(wmem_file_scope(), pdcp_sequence_report_in_frame);
955 p_report_in_frame->nextFrameNum = 0;
956
957 switch (p_pdcp_lte_info->seqnum_length) {
958 case PDCP_SN_LENGTH_5_BITS:
959 snLimit = 32;
960 break;
961 case PDCP_SN_LENGTH_7_BITS:
962 snLimit = 128;
963 break;
964 case PDCP_SN_LENGTH_12_BITS:
965 snLimit = 4096;
966 break;
967 case PDCP_SN_LENGTH_15_BITS:
968 snLimit = 32768;
969 break;
970 case PDCP_SN_LENGTH_18_BITS:
971 snLimit = 262144;
972 break;
973 default:
974 DISSECTOR_ASSERT_NOT_REACHED();
975 break;
976 }
977
978 /* Work out expected sequence number */
979 if (!createdChannel) {
980 expectedSequenceNumber = (p_channel_status->previousSequenceNumber + 1) % snLimit;
981 }
982 else {
983 expectedSequenceNumber = sequenceNumber;
984 }
985
986 /* Set report for this frame */
987 /* For PDCP, sequence number is always expectedSequence number */
988 p_report_in_frame->sequenceExpectedCorrect = (sequenceNumber == expectedSequenceNumber);
989 p_report_in_frame->hfn = p_channel_status->hfn;
990
991 /* For wrong sequence number... */
992 if (!p_report_in_frame->sequenceExpectedCorrect) {
993
994 /* Frames are not missing if we get an earlier sequence number again */
995 if (((snLimit + expectedSequenceNumber - sequenceNumber) % snLimit) > 15) {
996 p_report_in_frame->state = SN_Missing;
997 p_report_in_frame->firstSN = expectedSequenceNumber;
998 p_report_in_frame->lastSN = (snLimit + sequenceNumber - 1) % snLimit;
999
1000 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
1001 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
1002
1003 /* Update channel status to remember *this* frame */
1004 p_channel_status->previousFrameNum = pinfo->num;
1005 p_channel_status->previousSequenceNumber = sequenceNumber;
1006 }
1007 else {
1008 /* An SN has been repeated */
1009 p_report_in_frame->state = SN_Repeated;
1010 p_report_in_frame->firstSN = sequenceNumber;
1011
1012 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
1013 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
1014 }
1015 }
1016 else {
1017 /* SN was OK */
1018 p_report_in_frame->state = SN_OK;
1019 p_report_in_frame->sequenceExpected = expectedSequenceNumber;
1020 p_report_in_frame->previousFrameNum = p_channel_status->previousFrameNum;
1021 /* SN has rolled around, inc hfn! */
1022 if (!createdChannel && (sequenceNumber == 0)) {
1023 /* TODO: not worrying about HFN rolling over for now! */
1024 p_channel_status->hfn++;
1025 p_report_in_frame->hfn = p_channel_status->hfn;
1026 }
1027
1028 /* Update channel status to remember *this* frame */
1029 p_channel_status->previousFrameNum = pinfo->num;
1030 p_channel_status->previousSequenceNumber = sequenceNumber;
1031
1032 if (p_report_in_frame->previousFrameNum != 0) {
1033 /* Get report for previous frame */
1034 pdcp_sequence_report_in_frame *p_previous_report;
1035 p_previous_report = (pdcp_sequence_report_in_frame*)wmem_map_lookup(pdcp_lte_sequence_analysis_report_hash,
1036 get_report_hash_key((sequenceNumber+262144) % 262144,
1037 p_report_in_frame->previousFrameNum,
1038 p_pdcp_lte_info,
1039 FALSE));
1040 /* It really shouldn't be NULL... */
1041 if (p_previous_report != NULL) {
1042 /* Point it forward to this one */
1043 p_previous_report->nextFrameNum = pinfo->num;
1044 }
1045 }
1046 }
1047
1048 /* Associate with this frame number */
1049 wmem_map_insert(pdcp_lte_sequence_analysis_report_hash,
1050 get_report_hash_key(sequenceNumber, pinfo->num,
1051 p_pdcp_lte_info, TRUE),
1052 p_report_in_frame);
1053
1054 /* Add state report for this frame into tree */
1055 addChannelSequenceInfo(p_report_in_frame, p_pdcp_lte_info, sequenceNumber,
1056 pinfo, tree, tvb, security_tree, pdu_security);
1057 }
1058
1059
1060
1061 /* Hash table for security state for a UE
1062 Maps UEId -> pdcp_security_info_t* */
1063 static wmem_map_t *pdcp_security_hash = NULL;
1064
1065 /* Result is (ueid, framenum) -> pdcp_security_info_t* */
1066 typedef struct ueid_frame_t {
1067 guint32 framenum;
1068 guint16 ueid;
1069 } ueid_frame_t;
1070
1071 /* Convenience function to get a pointer for the hash_func to work with */
get_ueid_frame_hash_key(guint16 ueid,guint32 frameNumber,gboolean do_persist)1072 static gpointer get_ueid_frame_hash_key(guint16 ueid, guint32 frameNumber,
1073 gboolean do_persist)
1074 {
1075 static ueid_frame_t key;
1076 ueid_frame_t *p_key;
1077
1078 /* Only allocate a struct when will be adding entry */
1079 if (do_persist) {
1080 p_key = wmem_new(wmem_file_scope(), ueid_frame_t);
1081 }
1082 else {
1083 /* Only looking up, so just use static */
1084 memset(&key, 0, sizeof(ueid_frame_t));
1085 p_key = &key;
1086 }
1087
1088 /* Fill in details, and return pointer */
1089 p_key->framenum = frameNumber;
1090 p_key->ueid = ueid;
1091
1092 return p_key;
1093 }
1094
pdcp_lte_ueid_frame_hash_equal(gconstpointer v,gconstpointer v2)1095 static gint pdcp_lte_ueid_frame_hash_equal(gconstpointer v, gconstpointer v2)
1096 {
1097 const ueid_frame_t *ueid_frame_1 = (const ueid_frame_t *)v;
1098 const ueid_frame_t *ueid_frame_2 = (const ueid_frame_t *)v2;
1099 return ((ueid_frame_1->framenum == ueid_frame_2->framenum) &&
1100 (ueid_frame_1->ueid == ueid_frame_2->ueid));
1101 }
pdcp_lte_ueid_frame_hash_func(gconstpointer v)1102 static guint pdcp_lte_ueid_frame_hash_func(gconstpointer v)
1103 {
1104 const ueid_frame_t *ueid_frame = (const ueid_frame_t *)v;
1105 return ueid_frame->framenum + 100*ueid_frame->ueid;
1106 }
1107 static wmem_map_t *pdcp_security_result_hash = NULL;
1108
1109
1110
1111
1112 /* Write the given formatted text to:
1113 - the info column
1114 - the top-level RLC PDU item */
write_pdu_label_and_info(proto_item * pdu_ti,packet_info * pinfo,const char * format,...)1115 static void write_pdu_label_and_info(proto_item *pdu_ti,
1116 packet_info *pinfo, const char *format, ...)
1117 {
1118 #define MAX_INFO_BUFFER 256
1119 static char info_buffer[MAX_INFO_BUFFER];
1120
1121 va_list ap;
1122
1123 va_start(ap, format);
1124 g_vsnprintf(info_buffer, MAX_INFO_BUFFER, format, ap);
1125 va_end(ap);
1126
1127 /* Add to indicated places */
1128 col_append_str(pinfo->cinfo, COL_INFO, info_buffer);
1129 /* TODO: gets called a lot, so a shame there isn't a proto_item_append_string() */
1130 proto_item_append_text(pdu_ti, "%s", info_buffer);
1131 }
1132
1133
1134
1135 /***************************************************************/
1136
1137
1138
1139 /* Show in the tree the config info attached to this frame, as generated fields */
show_pdcp_config(packet_info * pinfo,tvbuff_t * tvb,proto_tree * tree,pdcp_lte_info * p_pdcp_info)1140 static void show_pdcp_config(packet_info *pinfo, tvbuff_t *tvb, proto_tree *tree,
1141 pdcp_lte_info *p_pdcp_info)
1142 {
1143 proto_item *ti;
1144 proto_tree *configuration_tree;
1145 proto_item *configuration_ti = proto_tree_add_item(tree,
1146 hf_pdcp_lte_configuration,
1147 tvb, 0, 0, ENC_ASCII|ENC_NA);
1148 configuration_tree = proto_item_add_subtree(configuration_ti, ett_pdcp_configuration);
1149
1150 /* Direction */
1151 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_direction, tvb, 0, 0,
1152 p_pdcp_info->direction);
1153 proto_item_set_generated(ti);
1154
1155 /* Plane */
1156 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_plane, tvb, 0, 0,
1157 p_pdcp_info->plane);
1158 proto_item_set_generated(ti);
1159
1160 /* UEId */
1161 if (p_pdcp_info->ueid != 0) {
1162 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_ueid, tvb, 0, 0,
1163 p_pdcp_info->ueid);
1164 proto_item_set_generated(ti);
1165 }
1166
1167 /* Channel type */
1168 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_channel_type, tvb, 0, 0,
1169 p_pdcp_info->channelType);
1170 proto_item_set_generated(ti);
1171 if (p_pdcp_info->channelId != 0) {
1172 /* Channel type */
1173 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_channel_id, tvb, 0, 0,
1174 p_pdcp_info->channelId);
1175 proto_item_set_generated(ti);
1176 }
1177
1178
1179 /* User-plane-specific fields */
1180 if (p_pdcp_info->plane == USER_PLANE) {
1181
1182 /* No Header PDU */
1183 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_no_header_pdu, tvb, 0, 0,
1184 p_pdcp_info->no_header_pdu);
1185 proto_item_set_generated(ti);
1186
1187 if (!p_pdcp_info->no_header_pdu) {
1188
1189 /* Seqnum length */
1190 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_seqnum_length, tvb, 0, 0,
1191 p_pdcp_info->seqnum_length);
1192 proto_item_set_generated(ti);
1193 }
1194 }
1195
1196 /* ROHC compression */
1197 ti = proto_tree_add_boolean(configuration_tree, hf_pdcp_lte_rohc_compression, tvb, 0, 0,
1198 p_pdcp_info->rohc.rohc_compression);
1199 proto_item_set_generated(ti);
1200
1201 /* ROHC-specific settings */
1202 if (p_pdcp_info->rohc.rohc_compression) {
1203
1204 /* Show ROHC mode */
1205 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_mode, tvb, 0, 0,
1206 p_pdcp_info->rohc.mode);
1207 proto_item_set_generated(ti);
1208
1209 /* Show RND */
1210 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_rnd, tvb, 0, 0,
1211 p_pdcp_info->rohc.rnd);
1212 proto_item_set_generated(ti);
1213
1214 /* UDP Checksum */
1215 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_udp_checksum_present, tvb, 0, 0,
1216 p_pdcp_info->rohc.udp_checksum_present);
1217 proto_item_set_generated(ti);
1218
1219 /* ROHC profile */
1220 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_rohc_profile, tvb, 0, 0,
1221 p_pdcp_info->rohc.profile);
1222 proto_item_set_generated(ti);
1223
1224 /* CID Inclusion Info */
1225 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_cid_inclusion_info, tvb, 0, 0,
1226 p_pdcp_info->rohc.cid_inclusion_info);
1227 proto_item_set_generated(ti);
1228
1229 /* Large CID */
1230 ti = proto_tree_add_uint(configuration_tree, hf_pdcp_lte_large_cid_present, tvb, 0, 0,
1231 p_pdcp_info->rohc.large_cid_present);
1232 proto_item_set_generated(ti);
1233 }
1234
1235 /* Append summary to configuration root */
1236 proto_item_append_text(configuration_ti, "(direction=%s, plane=%s",
1237 val_to_str_const(p_pdcp_info->direction, direction_vals, "Unknown"),
1238 val_to_str_const(p_pdcp_info->plane, pdcp_plane_vals, "Unknown"));
1239
1240 if (p_pdcp_info->rohc.rohc_compression) {
1241 const char *mode = val_to_str_const(p_pdcp_info->rohc.mode, rohc_mode_vals, "Error");
1242 proto_item_append_text(configuration_ti, ", mode=%c, profile=%s",
1243 mode[0],
1244 val_to_str_const(p_pdcp_info->rohc.profile, rohc_profile_vals, "Unknown"));
1245 }
1246 proto_item_append_text(configuration_ti, ")");
1247 proto_item_set_generated(configuration_ti);
1248
1249 /* Show plane in info column */
1250 col_append_fstr(pinfo->cinfo, COL_INFO, " %s: ",
1251 val_to_str_const(p_pdcp_info->plane, pdcp_plane_vals, "Unknown"));
1252
1253 }
1254
1255
1256 /* Look for an RRC dissector for signalling data (using channel type and direction) */
lookup_rrc_dissector_handle(struct pdcp_lte_info * p_pdcp_info)1257 static dissector_handle_t lookup_rrc_dissector_handle(struct pdcp_lte_info *p_pdcp_info)
1258 {
1259 dissector_handle_t rrc_handle = 0;
1260
1261 switch (p_pdcp_info->channelType)
1262 {
1263 case Channel_CCCH:
1264 if (p_pdcp_info->direction == DIRECTION_UPLINK) {
1265 rrc_handle = lte_rrc_ul_ccch;
1266 }
1267 else {
1268 rrc_handle = lte_rrc_dl_ccch;
1269 }
1270 break;
1271 case Channel_PCCH:
1272 rrc_handle = lte_rrc_pcch;
1273 break;
1274 case Channel_BCCH:
1275 switch (p_pdcp_info->BCCHTransport) {
1276 case BCH_TRANSPORT:
1277 rrc_handle = lte_rrc_bcch_bch;
1278 break;
1279 case DLSCH_TRANSPORT:
1280 rrc_handle = lte_rrc_bcch_dl_sch;
1281 break;
1282 }
1283 break;
1284 case Channel_DCCH:
1285 if (p_pdcp_info->direction == DIRECTION_UPLINK) {
1286 rrc_handle = lte_rrc_ul_dcch;
1287 }
1288 else {
1289 rrc_handle = lte_rrc_dl_dcch;
1290 }
1291 break;
1292 case Channel_CCCH_NB:
1293 if (p_pdcp_info->direction == DIRECTION_UPLINK) {
1294 rrc_handle = lte_rrc_ul_ccch_nb;
1295 }
1296 else {
1297 rrc_handle = lte_rrc_dl_ccch_nb;
1298 }
1299 break;
1300 case Channel_PCCH_NB:
1301 rrc_handle = lte_rrc_pcch_nb;
1302 break;
1303 case Channel_BCCH_NB:
1304 switch (p_pdcp_info->BCCHTransport) {
1305 case BCH_TRANSPORT:
1306 rrc_handle = lte_rrc_bcch_bch_nb;
1307 break;
1308 case DLSCH_TRANSPORT:
1309 rrc_handle = lte_rrc_bcch_dl_sch_nb;
1310 break;
1311 }
1312 break;
1313 case Channel_DCCH_NB:
1314 if (p_pdcp_info->direction == DIRECTION_UPLINK) {
1315 rrc_handle = lte_rrc_ul_dcch_nb;
1316 }
1317 else {
1318 rrc_handle = lte_rrc_dl_dcch_nb;
1319 }
1320 break;
1321
1322
1323 default:
1324 break;
1325 }
1326
1327 return rrc_handle;
1328 }
1329
1330
1331 /* Forwad declarations */
1332 static int dissect_pdcp_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data);
1333
report_heur_error(proto_tree * tree,packet_info * pinfo,expert_field * eiindex,tvbuff_t * tvb,gint start,gint length)1334 static void report_heur_error(proto_tree *tree, packet_info *pinfo, expert_field *eiindex,
1335 tvbuff_t *tvb, gint start, gint length)
1336 {
1337 proto_item *ti;
1338 proto_tree *subtree;
1339
1340 col_set_str(pinfo->cinfo, COL_PROTOCOL, "PDCP-LTE");
1341 col_clear(pinfo->cinfo, COL_INFO);
1342 ti = proto_tree_add_item(tree, proto_pdcp_lte, tvb, 0, -1, ENC_NA);
1343 subtree = proto_item_add_subtree(ti, ett_pdcp);
1344 proto_tree_add_expert(subtree, pinfo, eiindex, tvb, start, length);
1345 }
1346
1347 /* Heuristic dissector looks for supported framing protocol (see wiki page) */
dissect_pdcp_lte_heur(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)1348 static gboolean dissect_pdcp_lte_heur(tvbuff_t *tvb, packet_info *pinfo,
1349 proto_tree *tree, void *data _U_)
1350 {
1351 gint offset = 0;
1352 struct pdcp_lte_info *p_pdcp_lte_info;
1353 tvbuff_t *pdcp_tvb;
1354 guint8 tag = 0;
1355 gboolean seqnumLengthTagPresent = FALSE;
1356
1357 /* Needs to be at least as long as:
1358 - the signature string
1359 - fixed header bytes
1360 - tag for data
1361 - at least one byte of PDCP PDU payload */
1362 if (tvb_captured_length_remaining(tvb, offset) < (gint)(strlen(PDCP_LTE_START_STRING)+3+2)) {
1363 return FALSE;
1364 }
1365
1366 /* OK, compare with signature string */
1367 if (tvb_strneql(tvb, offset, PDCP_LTE_START_STRING, strlen(PDCP_LTE_START_STRING)) != 0) {
1368 return FALSE;
1369 }
1370 offset += (gint)strlen(PDCP_LTE_START_STRING);
1371
1372
1373 /* If redissecting, use previous info struct (if available) */
1374 p_pdcp_lte_info = (pdcp_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0);
1375 if (p_pdcp_lte_info == NULL) {
1376 /* Allocate new info struct for this frame */
1377 p_pdcp_lte_info = wmem_new0(wmem_file_scope(), pdcp_lte_info);
1378
1379 /* Read fixed fields */
1380 p_pdcp_lte_info->no_header_pdu = (gboolean)tvb_get_guint8(tvb, offset++);
1381 p_pdcp_lte_info->plane = (enum pdcp_plane)tvb_get_guint8(tvb, offset++);
1382 if (p_pdcp_lte_info->plane == SIGNALING_PLANE) {
1383 p_pdcp_lte_info->seqnum_length = PDCP_SN_LENGTH_5_BITS;
1384 }
1385 p_pdcp_lte_info->rohc.rohc_compression = (gboolean)tvb_get_guint8(tvb, offset++);
1386
1387 /* Read optional fields */
1388 while (tag != PDCP_LTE_PAYLOAD_TAG) {
1389 /* Process next tag */
1390 tag = tvb_get_guint8(tvb, offset++);
1391 switch (tag) {
1392 case PDCP_LTE_SEQNUM_LENGTH_TAG:
1393 p_pdcp_lte_info->seqnum_length = tvb_get_guint8(tvb, offset);
1394 offset++;
1395 seqnumLengthTagPresent = TRUE;
1396 break;
1397 case PDCP_LTE_DIRECTION_TAG:
1398 p_pdcp_lte_info->direction = tvb_get_guint8(tvb, offset);
1399 offset++;
1400 break;
1401 case PDCP_LTE_LOG_CHAN_TYPE_TAG:
1402 p_pdcp_lte_info->channelType = (LogicalChannelType)tvb_get_guint8(tvb, offset);
1403 offset++;
1404 break;
1405 case PDCP_LTE_BCCH_TRANSPORT_TYPE_TAG:
1406 p_pdcp_lte_info->BCCHTransport = (BCCHTransportType)tvb_get_guint8(tvb, offset);
1407 offset++;
1408 break;
1409 case PDCP_LTE_ROHC_IP_VERSION_TAG:
1410 /* RoHC IP version field is now 1 byte only; let's skip most significant byte
1411 to keep backward compatibility with existing UDP framing protocol */
1412 p_pdcp_lte_info->rohc.rohc_ip_version = tvb_get_guint8(tvb, offset+1);
1413 offset += 2;
1414 break;
1415 case PDCP_LTE_ROHC_CID_INC_INFO_TAG:
1416 p_pdcp_lte_info->rohc.cid_inclusion_info = tvb_get_guint8(tvb, offset);
1417 offset++;
1418 break;
1419 case PDCP_LTE_ROHC_LARGE_CID_PRES_TAG:
1420 p_pdcp_lte_info->rohc.large_cid_present = tvb_get_guint8(tvb, offset);
1421 offset++;
1422 break;
1423 case PDCP_LTE_ROHC_MODE_TAG:
1424 p_pdcp_lte_info->rohc.mode = (enum rohc_mode)tvb_get_guint8(tvb, offset);
1425 offset++;
1426 break;
1427 case PDCP_LTE_ROHC_RND_TAG:
1428 p_pdcp_lte_info->rohc.rnd = tvb_get_guint8(tvb, offset);
1429 offset++;
1430 break;
1431 case PDCP_LTE_ROHC_UDP_CHECKSUM_PRES_TAG:
1432 p_pdcp_lte_info->rohc.udp_checksum_present = tvb_get_guint8(tvb, offset);
1433 offset++;
1434 break;
1435 case PDCP_LTE_ROHC_PROFILE_TAG:
1436 p_pdcp_lte_info->rohc.profile = tvb_get_ntohs(tvb, offset);
1437 offset += 2;
1438 break;
1439 case PDCP_LTE_CHANNEL_ID_TAG:
1440 p_pdcp_lte_info->channelId = tvb_get_ntohs(tvb, offset);
1441 offset += 2;
1442 break;
1443 case PDCP_LTE_UEID_TAG:
1444 p_pdcp_lte_info->ueid = tvb_get_ntohs(tvb, offset);
1445 offset += 2;
1446 break;
1447
1448 case PDCP_LTE_PAYLOAD_TAG:
1449 /* Have reached data, so get out of loop */
1450 p_pdcp_lte_info->pdu_length = tvb_reported_length_remaining(tvb, offset);
1451 continue;
1452
1453 default:
1454 /* It must be a recognised tag */
1455 report_heur_error(tree, pinfo, &ei_pdcp_lte_unknown_udp_framing_tag, tvb, offset-1, 1);
1456 wmem_free(wmem_file_scope(), p_pdcp_lte_info);
1457 return TRUE;
1458 }
1459 }
1460
1461 if ((p_pdcp_lte_info->plane == USER_PLANE) && (seqnumLengthTagPresent == FALSE)) {
1462 /* Conditional field is not present */
1463 report_heur_error(tree, pinfo, &ei_pdcp_lte_missing_udp_framing_tag, tvb, 0, offset);
1464 wmem_free(wmem_file_scope(), p_pdcp_lte_info);
1465 return TRUE;
1466 }
1467
1468 /* Store info in packet */
1469 p_add_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0, p_pdcp_lte_info);
1470 }
1471 else {
1472 offset = tvb_reported_length(tvb) - p_pdcp_lte_info->pdu_length;
1473 }
1474
1475
1476 /**************************************/
1477 /* OK, now dissect as PDCP LTE */
1478
1479 /* Create tvb that starts at actual PDCP PDU */
1480 pdcp_tvb = tvb_new_subset_remaining(tvb, offset);
1481 dissect_pdcp_lte(pdcp_tvb, pinfo, tree, data);
1482 return TRUE;
1483 }
1484
1485 /* Called from control protocol to configure security algorithms for the given UE */
set_pdcp_lte_security_algorithms(guint16 ueid,pdcp_lte_security_info_t * security_info)1486 void set_pdcp_lte_security_algorithms(guint16 ueid, pdcp_lte_security_info_t *security_info)
1487 {
1488 /* Use for this frame so can check integrity on SecurityCommandRequest frame */
1489 /* N.B. won't work for internal, non-RRC signalling methods... */
1490 pdcp_lte_security_info_t *p_frame_security;
1491
1492 /* Disable this entire sub-routine with the Preference */
1493 /* Used when the capture is already deciphered */
1494 if (global_pdcp_ignore_sec) {
1495 return;
1496 }
1497
1498 /* Create or update current settings, by UEID */
1499 pdcp_lte_security_info_t* ue_security =
1500 (pdcp_lte_security_info_t*)wmem_map_lookup(pdcp_security_hash,
1501 GUINT_TO_POINTER((guint)ueid));
1502 if (ue_security == NULL) {
1503 /* Copy whole security struct */
1504 ue_security = wmem_new(wmem_file_scope(), pdcp_lte_security_info_t);
1505 *ue_security = *security_info;
1506
1507 /* And add into security table */
1508 wmem_map_insert(pdcp_security_hash, GUINT_TO_POINTER((guint)ueid), ue_security);
1509 }
1510 else {
1511 /* Just update existing entry already in table */
1512 ue_security->previous_configuration_frame = ue_security->configuration_frame;
1513 ue_security->previous_integrity = ue_security->integrity;
1514 ue_security->previous_ciphering = ue_security->ciphering;
1515
1516 ue_security->configuration_frame = security_info->configuration_frame;
1517 ue_security->integrity = security_info->integrity;
1518 ue_security->ciphering = security_info->ciphering;
1519 ue_security->seen_next_ul_pdu = FALSE;
1520 }
1521
1522 /* Also add an entry for this PDU already to use these settings, as otherwise it won't be present
1523 when we query it on the first pass. */
1524 p_frame_security = wmem_new(wmem_file_scope(), pdcp_lte_security_info_t);
1525 *p_frame_security = *ue_security;
1526 wmem_map_insert(pdcp_security_result_hash,
1527 get_ueid_frame_hash_key(ueid, ue_security->configuration_frame, TRUE),
1528 p_frame_security);
1529 }
1530
1531 /* UE failed to process SecurityModeCommand so go back to previous security settings */
set_pdcp_lte_security_algorithms_failed(guint16 ueid)1532 void set_pdcp_lte_security_algorithms_failed(guint16 ueid)
1533 {
1534 /* Look up current state by UEID */
1535 pdcp_lte_security_info_t* ue_security =
1536 (pdcp_lte_security_info_t*)wmem_map_lookup(pdcp_security_hash,
1537 GUINT_TO_POINTER((guint)ueid));
1538 if (ue_security != NULL) {
1539 /* TODO: could remove from table if previous_configuration_frame is 0 */
1540 /* Go back to previous state */
1541 ue_security->configuration_frame = ue_security->previous_configuration_frame;
1542 ue_security->integrity = ue_security->previous_integrity;
1543 ue_security->ciphering = ue_security->previous_ciphering;
1544 }
1545 }
1546
1547 /* Decipher payload if algorithm is supported and plausible inputs are available */
decipher_payload(tvbuff_t * tvb,packet_info * pinfo,int * offset,pdu_security_settings_t * pdu_security_settings,struct pdcp_lte_info * p_pdcp_info,gboolean will_be_deciphered,gboolean * deciphered)1548 static tvbuff_t *decipher_payload(tvbuff_t *tvb, packet_info *pinfo, int *offset,
1549 pdu_security_settings_t *pdu_security_settings,
1550 struct pdcp_lte_info *p_pdcp_info, gboolean will_be_deciphered,
1551 gboolean *deciphered)
1552 {
1553 guint8* decrypted_data = NULL;
1554 gint payload_length = 0;
1555 tvbuff_t *decrypted_tvb;
1556
1557 /* Nothing to do if NULL ciphering */
1558 if (pdu_security_settings->ciphering == eea0) {
1559 return tvb;
1560 }
1561
1562 /* Nothing to do if don't have valid cipher key */
1563 if (!pdu_security_settings->cipherKeyValid) {
1564 return tvb;
1565 }
1566
1567 /* Check whether algorithm supported (only drop through and process if we do) */
1568 if (pdu_security_settings->ciphering == eea1) {
1569 #ifndef HAVE_SNOW3G
1570 return tvb;
1571 #endif
1572 }
1573 else if (pdu_security_settings->ciphering == eea3) {
1574 #ifndef HAVE_ZUC
1575 return tvb;
1576 #endif
1577 }
1578 else if (pdu_security_settings->ciphering != eea2) {
1579 /* An algorithm we don't support at all! */
1580 return tvb;
1581 }
1582
1583 /* Don't decipher if turned off in preferences */
1584 if (((p_pdcp_info->plane == SIGNALING_PLANE) && !global_pdcp_decipher_signalling) ||
1585 ((p_pdcp_info->plane == USER_PLANE) && !global_pdcp_decipher_userplane)) {
1586 return tvb;
1587 }
1588
1589 /* Don't decipher user-plane control messages */
1590 if ((p_pdcp_info->plane == USER_PLANE) && ((tvb_get_guint8(tvb, 0) & 0x80) == 0x00)) {
1591 return tvb;
1592 }
1593
1594 /* Don't decipher common control messages */
1595 if ((p_pdcp_info->plane == SIGNALING_PLANE) && (p_pdcp_info->channelType != Channel_DCCH)) {
1596 return tvb;
1597 }
1598
1599 /* Don't decipher if not yet past SecurityModeResponse */
1600 if (!will_be_deciphered) {
1601 return tvb;
1602 }
1603
1604 /* AES */
1605 if (pdu_security_settings->ciphering == eea2) {
1606 unsigned char ctr_block[16];
1607 gcry_cipher_hd_t cypher_hd;
1608 int gcrypt_err;
1609
1610 /* TS 33.401 B.1.3 */
1611
1612 /* Set CTR */
1613 memset(ctr_block, 0, 16);
1614 /* Only first 5 bytes set */
1615 ctr_block[0] = (pdu_security_settings->count & 0xff000000) >> 24;
1616 ctr_block[1] = (pdu_security_settings->count & 0x00ff0000) >> 16;
1617 ctr_block[2] = (pdu_security_settings->count & 0x0000ff00) >> 8;
1618 ctr_block[3] = (pdu_security_settings->count & 0x000000ff);
1619 ctr_block[4] = (pdu_security_settings->bearer << 3) + (pdu_security_settings->direction << 2);
1620
1621 /* Open gcrypt handle */
1622 gcrypt_err = gcry_cipher_open(&cypher_hd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR, 0);
1623 if (gcrypt_err != 0) {
1624 return tvb;
1625 }
1626
1627 /* Set the key */
1628 gcrypt_err = gcry_cipher_setkey(cypher_hd, pdu_security_settings->cipherKey, 16);
1629 if (gcrypt_err != 0) {
1630 gcry_cipher_close(cypher_hd);
1631 return tvb;
1632 }
1633
1634 /* Set the CTR */
1635 gcrypt_err = gcry_cipher_setctr(cypher_hd, ctr_block, 16);
1636 if (gcrypt_err != 0) {
1637 gcry_cipher_close(cypher_hd);
1638 return tvb;
1639 }
1640
1641 /* Extract the encrypted data into a buffer */
1642 payload_length = tvb_captured_length_remaining(tvb, *offset);
1643 decrypted_data = (guint8 *)tvb_memdup(pinfo->pool, tvb, *offset, payload_length);
1644
1645 /* Decrypt the actual data */
1646 gcrypt_err = gcry_cipher_decrypt(cypher_hd,
1647 decrypted_data, payload_length,
1648 NULL, 0);
1649 if (gcrypt_err != 0) {
1650 gcry_cipher_close(cypher_hd);
1651 return tvb;
1652 }
1653
1654 /* Close gcrypt handle */
1655 gcry_cipher_close(cypher_hd);
1656 }
1657
1658 #ifdef HAVE_SNOW3G
1659 /* SNOW-3G */
1660 if (pdu_security_settings->ciphering == eea1) {
1661 /* Extract the encrypted data into a buffer */
1662 payload_length = tvb_captured_length_remaining(tvb, *offset);
1663 decrypted_data = (guint8 *)tvb_memdup(pinfo->pool, tvb, *offset, payload_length);
1664
1665 /* Do the algorithm */
1666 snow3g_f8(pdu_security_settings->cipherKey,
1667 pdu_security_settings->count,
1668 pdu_security_settings->bearer,
1669 pdu_security_settings->direction,
1670 decrypted_data, payload_length*8);
1671 }
1672 #endif
1673
1674 #ifdef HAVE_ZUC
1675 /* ZUC */
1676 if (pdu_security_settings->ciphering == eea3) {
1677 /* Extract the encrypted data into a buffer */
1678 payload_length = tvb_captured_length_remaining(tvb, *offset);
1679 decrypted_data = (guint8 *)tvb_memdup(pinfo->pool, tvb, *offset, payload_length);
1680
1681 /* Do the algorithm. Assuming implementation works in-place */
1682 zuc_f8(pdu_security_settings->cipherKey,
1683 pdu_security_settings->count,
1684 pdu_security_settings->bearer,
1685 pdu_security_settings->direction,
1686 payload_length*8, /* Length is in bits */
1687 (guint32*)decrypted_data, (guint32*)decrypted_data);
1688 }
1689 #endif
1690
1691 /* Create tvb for resulting deciphered sdu */
1692 decrypted_tvb = tvb_new_child_real_data(tvb, decrypted_data, payload_length, payload_length);
1693 add_new_data_source(pinfo, decrypted_tvb, "Deciphered Payload");
1694
1695 /* Return deciphered data, i.e. beginning of new tvb */
1696 *offset = 0;
1697 *deciphered = TRUE;
1698 return decrypted_tvb;
1699 }
1700
1701
1702 /* Try to calculate digest to compare with that found in frame. */
1703 #if defined(HAVE_SNOW3G) || GCRYPT_VERSION_NUMBER >= 0x010600 /* 1.6.0 */ || defined(HAVE_ZUC)
1704 /* We can calculate it for at least some integrity types */
calculate_digest(pdu_security_settings_t * pdu_security_settings,guint8 header,tvbuff_t * tvb,packet_info * pinfo,gint offset,gboolean * calculated)1705 static guint32 calculate_digest(pdu_security_settings_t *pdu_security_settings, guint8 header,
1706 tvbuff_t *tvb, packet_info *pinfo, gint offset, gboolean *calculated)
1707 {
1708 *calculated = FALSE;
1709
1710 if (pdu_security_settings->integrity == eia0) {
1711 /* Should be zero in this case */
1712 *calculated = TRUE;
1713 return 0;
1714 }
1715
1716 /* Can't calculate if don't have valid integrity key */
1717 if (!pdu_security_settings->integrityKeyValid) {
1718 return 0;
1719 }
1720
1721 /* Can only do if indicated in preferences */
1722 if (!global_pdcp_check_integrity) {
1723 return 0;
1724 }
1725
1726 switch (pdu_security_settings->integrity) {
1727
1728 #ifdef HAVE_SNOW3G
1729 case eia1:
1730 {
1731 /* SNOW3G */
1732 guint8 *mac;
1733 gint message_length = tvb_captured_length_remaining(tvb, offset) - 4;
1734 guint8 *message_data = (guint8 *)wmem_alloc0(pinfo->pool, message_length+5);
1735
1736 /* TS 33.401 B.2.2 */
1737
1738 /* Data is header byte */
1739 message_data[0] = header;
1740 /* Followed by the decrypted message (but not the digest bytes) */
1741 tvb_memcpy(tvb, message_data+1, offset, message_length);
1742
1743 mac = (u8*)snow3g_f9(pdu_security_settings->integrityKey,
1744 pdu_security_settings->count,
1745 /* 'Fresh' is the bearer bits then zeros */
1746 pdu_security_settings->bearer << 27,
1747 pdu_security_settings->direction,
1748 message_data,
1749 (message_length+1)*8);
1750
1751 *calculated = TRUE;
1752 return ((mac[0] << 24) | (mac[1] << 16) | (mac[2] << 8) | mac[3]);
1753 }
1754 #endif
1755
1756 #if GCRYPT_VERSION_NUMBER >= 0x010600 /* 1.6.0 */
1757 case eia2:
1758 {
1759 /* AES */
1760 gcry_mac_hd_t mac_hd;
1761 int gcrypt_err;
1762 gint message_length;
1763 guint8 *message_data;
1764 guint8 mac[4];
1765 size_t read_digest_length = 4;
1766
1767 /* Open gcrypt handle */
1768 gcrypt_err = gcry_mac_open(&mac_hd, GCRY_MAC_CMAC_AES, 0, NULL);
1769 if (gcrypt_err != 0) {
1770 return 0;
1771 }
1772
1773 /* Set the key */
1774 gcrypt_err = gcry_mac_setkey(mac_hd, pdu_security_settings->integrityKey, 16);
1775 if (gcrypt_err != 0) {
1776 gcry_mac_close(mac_hd);
1777 return 0;
1778 }
1779
1780 /* TS 33.401 B.2.3 */
1781
1782 /* Extract the encrypted data into a buffer */
1783 message_length = tvb_captured_length_remaining(tvb, offset) - 4;
1784 message_data = (guint8 *)wmem_alloc0(pinfo->pool, message_length+9);
1785 message_data[0] = (pdu_security_settings->count & 0xff000000) >> 24;
1786 message_data[1] = (pdu_security_settings->count & 0x00ff0000) >> 16;
1787 message_data[2] = (pdu_security_settings->count & 0x0000ff00) >> 8;
1788 message_data[3] = (pdu_security_settings->count & 0x000000ff);
1789 message_data[4] = (pdu_security_settings->bearer << 3) + (pdu_security_settings->direction << 2);
1790 /* rest of first 8 bytes are left as zeroes... */
1791 /* Now the header byte */
1792 message_data[8] = header;
1793 /* Followed by the decrypted message (but not the digest bytes) */
1794 tvb_memcpy(tvb, message_data+9, offset, message_length);
1795
1796 /* Pass in the message */
1797 gcrypt_err = gcry_mac_write(mac_hd, message_data, message_length+9);
1798 if (gcrypt_err != 0) {
1799 gcry_mac_close(mac_hd);
1800 return 0;
1801 }
1802
1803 /* Read out the digest */
1804 gcrypt_err = gcry_mac_read(mac_hd, mac, &read_digest_length);
1805 if (gcrypt_err != 0) {
1806 gcry_mac_close(mac_hd);
1807 return 0;
1808 }
1809
1810 /* Now close the mac handle */
1811 gcry_mac_close(mac_hd);
1812
1813 *calculated = TRUE;
1814 return ((mac[0] << 24) | (mac[1] << 16) | (mac[2] << 8) | mac[3]);
1815 }
1816 #endif
1817 #ifdef HAVE_ZUC
1818 case eia3:
1819 {
1820 /* ZUC */
1821 guint32 mac;
1822 gint message_length = tvb_captured_length_remaining(tvb, offset) - 4;
1823 guint8 *message_data = (guint8 *)wmem_alloc0(pinfo->pool, message_length+5);
1824
1825 /* Data is header byte */
1826 message_data[0] = header;
1827 /* Followed by the decrypted message (but not the digest bytes) */
1828 tvb_memcpy(tvb, message_data+1, offset, message_length);
1829
1830 zuc_f9(pdu_security_settings->integrityKey,
1831 pdu_security_settings->count,
1832 pdu_security_settings->direction,
1833 pdu_security_settings->bearer,
1834 (message_length+1)*8,
1835 (guint32*)message_data,
1836 &mac);
1837
1838 *calculated = TRUE;
1839 return mac;
1840 }
1841 #endif
1842
1843 default:
1844 /* Can't calculate */
1845 *calculated = FALSE;
1846 return 0;
1847 }
1848 }
1849 #else /* defined(HAVE_SNOW3G) || GCRYPT_VERSION_NUMBER >= 0x010600 || defined(HAVE_ZUC) */
1850 /* We can't calculate it for any integrity types other than eia0 */
calculate_digest(pdu_security_settings_t * pdu_security_settings,guint8 header _U_,tvbuff_t * tvb _U_,packet_info * pinfo _U_,gint offset _U_,gboolean * calculated)1851 static guint32 calculate_digest(pdu_security_settings_t *pdu_security_settings, guint8 header _U_,
1852 tvbuff_t *tvb _U_, packet_info *pinfo _U_, gint offset _U_, gboolean *calculated)
1853 {
1854 *calculated = FALSE;
1855
1856 if (pdu_security_settings->integrity == eia0) {
1857 /* Should be zero in this case */
1858 *calculated = TRUE;
1859 }
1860
1861 /* Otherwise, we can't calculate it */
1862 return 0;
1863 }
1864 #endif /* defined(HAVE_SNOW3G) || GCRYPT_VERSION_NUMBER >= 0x010600 || defined(HAVE_ZUC) */
1865
1866 /******************************/
1867 /* Main dissection function. */
dissect_pdcp_lte(tvbuff_t * tvb,packet_info * pinfo,proto_tree * tree,void * data _U_)1868 static int dissect_pdcp_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_)
1869 {
1870 const char *mode;
1871 proto_tree *pdcp_tree = NULL;
1872 proto_item *root_ti = NULL;
1873 proto_item *ti = NULL;
1874 gint offset = 0;
1875 struct pdcp_lte_info *p_pdcp_info;
1876 tvbuff_t *rohc_tvb = NULL;
1877 guint32 reserved_value;
1878 guint32 seqnum = 0;
1879
1880 pdcp_lte_security_info_t *current_security = NULL; /* current security for this UE */
1881 pdcp_lte_security_info_t *pdu_security; /* security in place for this PDU */
1882 proto_tree *security_tree = NULL;
1883 proto_item *security_ti;
1884 tvbuff_t *payload_tvb;
1885 pdu_security_settings_t pdu_security_settings;
1886 gboolean payload_deciphered = FALSE;
1887
1888 /* Initialise security settings */
1889 memset(&pdu_security_settings, 0, sizeof(pdu_security_settings));
1890
1891 /* Set protocol name. */
1892 col_set_str(pinfo->cinfo, COL_PROTOCOL, "PDCP-LTE");
1893
1894 /* Look for attached packet info! */
1895 p_pdcp_info = (struct pdcp_lte_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_pdcp_lte, 0);
1896 /* Can't dissect anything without it... */
1897 if (p_pdcp_info == NULL) {
1898 return 0;
1899 }
1900
1901 /* Don't want to overwrite the RLC Info column if configured not to */
1902 if ((global_pdcp_lte_layer_to_show == ShowRLCLayer) &&
1903 (p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0) != NULL)) {
1904
1905 col_set_writable(pinfo->cinfo, COL_INFO, FALSE);
1906 }
1907 else {
1908 /* TODO: won't help with multiple PDCP-or-traffic PDUs / frame... */
1909 col_clear(pinfo->cinfo, COL_INFO);
1910 col_set_writable(pinfo->cinfo, COL_INFO, TRUE);
1911 }
1912
1913 /* Create pdcp tree. */
1914 if (tree) {
1915 root_ti = proto_tree_add_item(tree, proto_pdcp_lte, tvb, offset, -1, ENC_NA);
1916 pdcp_tree = proto_item_add_subtree(root_ti, ett_pdcp);
1917 }
1918
1919 /* Set mode string */
1920 mode = val_to_str_const(p_pdcp_info->rohc.mode, rohc_mode_vals, "Error");
1921
1922 /*****************************************************/
1923 /* Show configuration (attached packet) info in tree */
1924 if (pdcp_tree) {
1925 show_pdcp_config(pinfo, tvb, pdcp_tree, p_pdcp_info);
1926 }
1927
1928 /* Show ROHC mode */
1929 if (p_pdcp_info->rohc.rohc_compression) {
1930 col_append_fstr(pinfo->cinfo, COL_INFO, " (mode=%c)", mode[0]);
1931 }
1932
1933 /***************************************/
1934 /* UE security algorithms */
1935 if (!PINFO_FD_VISITED(pinfo)) {
1936 /* Look up current state by UEID */
1937 current_security = (pdcp_lte_security_info_t*)wmem_map_lookup(pdcp_security_hash,
1938 GUINT_TO_POINTER((guint)p_pdcp_info->ueid));
1939 if (current_security != NULL) {
1940 /* Store any result for this frame in the result table */
1941 pdcp_lte_security_info_t *security_to_store = wmem_new(wmem_file_scope(), pdcp_lte_security_info_t);
1942 /* Take a deep copy of the settings */
1943 *security_to_store = *current_security;
1944 wmem_map_insert(pdcp_security_result_hash,
1945 get_ueid_frame_hash_key(p_pdcp_info->ueid, pinfo->num, TRUE),
1946 security_to_store);
1947 }
1948 else {
1949 /* No entry added from RRC, but still use configured defaults */
1950 if ((global_default_ciphering_algorithm != eea0) ||
1951 (global_default_integrity_algorithm != eia0)) {
1952 /* Copy algorithms from preference defaults */
1953 pdcp_lte_security_info_t *security_to_store = wmem_new0(wmem_file_scope(), pdcp_lte_security_info_t);
1954 security_to_store->ciphering = global_default_ciphering_algorithm;
1955 security_to_store->integrity = global_default_integrity_algorithm;
1956 security_to_store->seen_next_ul_pdu = TRUE;
1957 wmem_map_insert(pdcp_security_result_hash,
1958 get_ueid_frame_hash_key(p_pdcp_info->ueid, pinfo->num, TRUE),
1959 security_to_store);
1960 }
1961 }
1962 }
1963
1964 /* Show security settings for this PDU */
1965 pdu_security = (pdcp_lte_security_info_t*)wmem_map_lookup(pdcp_security_result_hash,
1966 get_ueid_frame_hash_key(p_pdcp_info->ueid, pinfo->num, FALSE));
1967 if (pdu_security != NULL) {
1968 /* Create subtree */
1969 security_ti = proto_tree_add_string_format(pdcp_tree,
1970 hf_pdcp_lte_security,
1971 tvb, 0, 0,
1972 "", "UE Security");
1973 security_tree = proto_item_add_subtree(security_ti, ett_pdcp_security);
1974 proto_item_set_generated(security_ti);
1975
1976 /* Setup frame */
1977 if (pinfo->num > pdu_security->configuration_frame) {
1978 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_setup_frame,
1979 tvb, 0, 0, pdu_security->configuration_frame);
1980 proto_item_set_generated(ti);
1981 }
1982
1983 /* Ciphering */
1984 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_ciphering_algorithm,
1985 tvb, 0, 0, pdu_security->ciphering);
1986 proto_item_set_generated(ti);
1987
1988 /* Integrity */
1989 ti = proto_tree_add_uint(security_tree, hf_pdcp_lte_security_integrity_algorithm,
1990 tvb, 0, 0, pdu_security->integrity);
1991 proto_item_set_generated(ti);
1992
1993 /* Show algorithms in security root */
1994 proto_item_append_text(security_ti, " (ciphering=%s, integrity=%s)",
1995 val_to_str_const(pdu_security->ciphering, ciphering_algorithm_vals, "Unknown"),
1996 val_to_str_const(pdu_security->integrity, integrity_algorithm_vals, "Unknown"));
1997
1998 pdu_security_settings.ciphering = pdu_security->ciphering;
1999 pdu_security_settings.integrity = pdu_security->integrity;
2000 }
2001
2002
2003 /***********************************/
2004 /* Handle PDCP header (if present) */
2005 if (!p_pdcp_info->no_header_pdu) {
2006
2007 seqnum = 0;
2008 gboolean seqnum_set = FALSE;
2009
2010 guint8 first_byte = tvb_get_guint8(tvb, offset);
2011
2012 /*****************************/
2013 /* Signalling plane messages */
2014 if (p_pdcp_info->plane == SIGNALING_PLANE) {
2015 /* Verify 3 reserved bits are 0 */
2016 guint8 reserved = (first_byte & 0xe0) >> 5;
2017 ti = proto_tree_add_item(pdcp_tree, hf_pdcp_lte_control_plane_reserved,
2018 tvb, offset, 1, ENC_BIG_ENDIAN);
2019 if (reserved != 0) {
2020 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
2021 "PDCP signalling header reserved bits not zero");
2022 }
2023
2024 /* 5-bit sequence number */
2025 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_seq_num_5, tvb, offset, 1, ENC_BIG_ENDIAN, &seqnum);
2026 seqnum_set = TRUE;
2027 write_pdu_label_and_info(root_ti, pinfo, " sn=%-2u ", seqnum);
2028 offset++;
2029
2030 if (tvb_captured_length_remaining(tvb, offset) == 0) {
2031 /* Only PDCP header was captured, stop dissection here */
2032 return offset;
2033 }
2034 }
2035 else if (p_pdcp_info->plane == USER_PLANE) {
2036
2037 /**********************************/
2038 /* User-plane messages */
2039 guint8 pdu_type = (first_byte & 0x80) >> 7;
2040
2041 /* Data/Control flag */
2042 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_data_control, tvb, offset, 1, ENC_BIG_ENDIAN);
2043
2044 if (pdu_type == 1) {
2045 /*****************************/
2046 /* User-plane Data */
2047
2048 /* Number of sequence number bits depends upon config */
2049 switch (p_pdcp_info->seqnum_length) {
2050 case PDCP_SN_LENGTH_7_BITS:
2051 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_seq_num_7, tvb, offset, 1, ENC_BIG_ENDIAN, &seqnum);
2052 seqnum_set = TRUE;
2053 offset++;
2054 break;
2055 case PDCP_SN_LENGTH_12_BITS:
2056 /* 3 reserved bits */
2057 ti = proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_reserved3, tvb, offset, 1, ENC_BIG_ENDIAN, &reserved_value);
2058
2059 /* Complain if not 0 */
2060 if (reserved_value != 0) {
2061 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
2062 "Reserved bits have value 0x%x - should be 0x0",
2063 reserved_value);
2064 }
2065
2066 /* 12-bit sequence number */
2067 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_seq_num_12, tvb, offset, 2, ENC_BIG_ENDIAN, &seqnum);
2068 seqnum_set = TRUE;
2069 offset += 2;
2070 break;
2071 case PDCP_SN_LENGTH_15_BITS:
2072 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_seq_num_15, tvb, offset, 2, ENC_BIG_ENDIAN, &seqnum);
2073 seqnum_set = TRUE;
2074 offset += 2;
2075 break;
2076 case PDCP_SN_LENGTH_18_BITS:
2077 /* Polling bit */
2078 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_polling, tvb, offset, 1, ENC_BIG_ENDIAN);
2079
2080 /* 4 reserved bits */
2081 ti = proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_reserved5, tvb, offset, 1, ENC_BIG_ENDIAN, &reserved_value);
2082
2083 /* Complain if not 0 */
2084 if (reserved_value != 0) {
2085 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
2086 "Reserved bits have value 0x%x - should be 0x0",
2087 reserved_value);
2088 }
2089
2090 /* 18-bit sequence number */
2091 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_seq_num_18, tvb, offset, 3, ENC_BIG_ENDIAN, &seqnum);
2092 seqnum_set = TRUE;
2093 offset += 3;
2094 break;
2095 default:
2096 /* Not a recognised data format!!!!! */
2097 return 1;
2098 }
2099
2100 write_pdu_label_and_info(root_ti, pinfo, " (SN=%u)", seqnum);
2101 }
2102 else {
2103 /*******************************/
2104 /* User-plane Control messages */
2105 guint32 control_pdu_type;
2106 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_control_pdu_type, tvb,
2107 offset, 1, ENC_BIG_ENDIAN, &control_pdu_type);
2108
2109 switch (control_pdu_type) {
2110 case 0: /* PDCP status report */
2111 {
2112 guint32 fms;
2113 guint32 modulo;
2114 guint not_received = 0;
2115 guint sn, i, j, l;
2116 guint32 len, bit_offset;
2117 proto_tree *bitmap_tree;
2118 proto_item *bitmap_ti = NULL;
2119 gchar *buff = NULL;
2120 #define BUFF_SIZE 57
2121
2122 if (p_pdcp_info->seqnum_length == PDCP_SN_LENGTH_12_BITS) {
2123 /* First-Missing-Sequence SN */
2124 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_fms, tvb,
2125 offset, 2, ENC_BIG_ENDIAN, &fms);
2126 sn = (fms + 1) % 4096;
2127 offset += 2;
2128 modulo = 4096;
2129 } else if (p_pdcp_info->seqnum_length == PDCP_SN_LENGTH_15_BITS) {
2130
2131 /* 5 reserved bits */
2132 ti = proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_reserved4, tvb, offset, 2, ENC_BIG_ENDIAN, &reserved_value);
2133 offset++;
2134
2135 /* Complain if not 0 */
2136 if (reserved_value != 0) {
2137 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
2138 "Reserved bits have value 0x%x - should be 0x0",
2139 reserved_value);
2140 }
2141
2142 /* First-Missing-Sequence SN */
2143 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_fms2, tvb,
2144 offset, 2, ENC_BIG_ENDIAN, &fms);
2145 sn = (fms + 1) % 32768;
2146 offset += 2;
2147 modulo = 32768;
2148 } else {
2149 /* 2 reserved bits */
2150 ti = proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_reserved6, tvb, offset, 1, ENC_BIG_ENDIAN, &reserved_value);
2151
2152 /* Complain if not 0 */
2153 if (reserved_value != 0) {
2154 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
2155 "Reserved bits have value 0x%x - should be 0x0",
2156 reserved_value);
2157 }
2158
2159 /* First-Missing-Sequence SN */
2160 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_fms3, tvb,
2161 offset, 3, ENC_BIG_ENDIAN, &fms);
2162 sn = (fms + 1) % 262144;
2163 offset += 3;
2164 modulo = 262144;
2165 }
2166
2167 /* Bitmap tree */
2168 if (tvb_reported_length_remaining(tvb, offset) > 0) {
2169 bitmap_ti = proto_tree_add_item(pdcp_tree, hf_pdcp_lte_bitmap, tvb,
2170 offset, -1, ENC_NA);
2171 bitmap_tree = proto_item_add_subtree(bitmap_ti, ett_pdcp_report_bitmap);
2172
2173 buff = (gchar *)wmem_alloc(pinfo->pool, BUFF_SIZE);
2174 len = tvb_reported_length_remaining(tvb, offset);
2175 bit_offset = offset<<3;
2176
2177 /* For each byte... */
2178 for (i=0; i<len; i++) {
2179 guint8 bits = tvb_get_bits8(tvb, bit_offset, 8);
2180 for (l=0, j=0; l<8; l++) {
2181 if ((bits << l) & 0x80) {
2182 if (bitmap_tree) {
2183 j += g_snprintf(&buff[j], BUFF_SIZE-j, "%6u,", (unsigned)(sn+(8*i)+l)%modulo);
2184 }
2185 } else {
2186 if (bitmap_tree) {
2187 j += (guint)g_strlcpy(&buff[j], " ,", BUFF_SIZE-j);
2188 }
2189 not_received++;
2190 }
2191 }
2192 if (bitmap_tree) {
2193 proto_tree_add_uint_format(bitmap_tree, hf_pdcp_lte_bitmap_byte, tvb, bit_offset/8, 1, bits, "%s", buff);
2194 }
2195 bit_offset += 8;
2196 }
2197 }
2198
2199 if (bitmap_ti != NULL) {
2200 proto_item_append_text(bitmap_ti, " (%u SNs not received)", not_received);
2201 }
2202 write_pdu_label_and_info(root_ti, pinfo, " Status Report (fms=%u) not-received=%u",
2203 fms, not_received);
2204 }
2205 return 1;
2206
2207 case 1: /* ROHC Feedback */
2208 offset++;
2209 break; /* Drop-through to dissect feedback */
2210
2211
2212 case 2: /* LWA status report */
2213 {
2214 guint32 fms;
2215 guint32 nmp;
2216
2217 if (p_pdcp_info->seqnum_length == PDCP_SN_LENGTH_12_BITS) {
2218 /* First-Missing-Sequence SN */
2219 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_fms, tvb,
2220 offset, 2, ENC_BIG_ENDIAN, &fms);
2221 offset += 2;
2222
2223 /* HRW */
2224 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_hrw, tvb,
2225 offset, 2, ENC_BIG_ENDIAN);
2226 offset += 1;
2227
2228 /* NMP */
2229 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_nmp, tvb,
2230 offset, 2, ENC_BIG_ENDIAN, &nmp);
2231 offset += 2;
2232 } else if (p_pdcp_info->seqnum_length == PDCP_SN_LENGTH_15_BITS) {
2233 /* 5 reserved bits */
2234 ti = proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_reserved4, tvb,
2235 offset, 2, ENC_BIG_ENDIAN, &reserved_value);
2236 offset++;
2237 /* Complain if not 0 */
2238 if (reserved_value != 0) {
2239 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
2240 "Reserved bits have value 0x%x - should be 0x0",
2241 reserved_value);
2242 }
2243
2244 /* First-Missing-Sequence SN */
2245 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_fms2, tvb,
2246 offset, 2, ENC_BIG_ENDIAN, &fms);
2247 offset += 2;
2248
2249 /* 1 reserved bit */
2250 ti = proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_reserved7, tvb,
2251 offset, 1, ENC_BIG_ENDIAN, &reserved_value);
2252 /* Complain if not 0 */
2253 if (reserved_value) {
2254 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
2255 "Reserved bits have value 0x1 - should be 0x0");
2256 }
2257
2258 /* HRW */
2259 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_hrw2, tvb,
2260 offset, 2, ENC_BIG_ENDIAN);
2261 offset += 2;
2262
2263 /* 1 reserved bit */
2264 ti = proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_reserved7, tvb,
2265 offset, 1, ENC_BIG_ENDIAN, &reserved_value);
2266 /* Complain if not 0 */
2267 if (reserved_value) {
2268 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
2269 "Reserved bits have value 0x1 - should be 0x0");
2270 }
2271
2272 /* NMP */
2273 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_nmp2, tvb,
2274 offset, 2, ENC_BIG_ENDIAN, &nmp);
2275 offset += 2;
2276 } else {
2277 /* 2 reserved bits */
2278 ti = proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_reserved6,
2279 tvb, offset, 1, ENC_BIG_ENDIAN, &reserved_value);
2280 /* Complain if not 0 */
2281 if (reserved_value != 0) {
2282 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
2283 "Reserved bits have value 0x%x - should be 0x0",
2284 reserved_value);
2285 }
2286
2287 /* First-Missing-Sequence SN */
2288 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_fms3, tvb,
2289 offset, 3, ENC_BIG_ENDIAN, &fms);
2290 offset += 3;
2291
2292 /* HRW */
2293 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_hrw3, tvb,
2294 offset, 3, ENC_BIG_ENDIAN);
2295 offset += 2;
2296
2297 /* 4 reserved bits */
2298 ti = proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_reserved8,
2299 tvb, offset, 1, ENC_BIG_ENDIAN, &reserved_value);
2300 /* Complain if not 0 */
2301 if (reserved_value != 0) {
2302 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
2303 "Reserved bits have value 0x%x - should be 0x0",
2304 reserved_value);
2305 }
2306
2307 /* NMP */
2308 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_nmp3, tvb,
2309 offset, 3, ENC_BIG_ENDIAN, &nmp);
2310 offset += 3;
2311 }
2312
2313 write_pdu_label_and_info(root_ti, pinfo, " LWA Status Report (fms=%u) not-received=%u",
2314 fms, nmp);
2315 }
2316 return 1;
2317
2318 case 3: /* LWA end-marker packet */
2319 {
2320 guint32 lsn;
2321
2322 if (p_pdcp_info->seqnum_length == PDCP_SN_LENGTH_12_BITS) {
2323 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_lsn, tvb,
2324 offset, 2, ENC_BIG_ENDIAN, &lsn);
2325 offset += 2;
2326 } else if (p_pdcp_info->seqnum_length == PDCP_SN_LENGTH_15_BITS) {
2327 /* 5 reserved bits */
2328 ti = proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_reserved4, tvb,
2329 offset, 2, ENC_BIG_ENDIAN, &reserved_value);
2330 offset++;
2331 /* Complain if not 0 */
2332 if (reserved_value != 0) {
2333 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
2334 "Reserved bits have value 0x%x - should be 0x0",
2335 reserved_value);
2336 }
2337
2338 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_lsn2, tvb,
2339 offset, 2, ENC_BIG_ENDIAN, &lsn);
2340 offset += 2;
2341 } else {
2342 /* 2 reserved bits */
2343 ti = proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_reserved6,
2344 tvb, offset, 1, ENC_BIG_ENDIAN, &reserved_value);
2345 /* Complain if not 0 */
2346 if (reserved_value != 0) {
2347 expert_add_info_format(pinfo, ti, &ei_pdcp_lte_reserved_bits_not_zero,
2348 "Reserved bits have value 0x%x - should be 0x0",
2349 reserved_value);
2350 }
2351
2352 proto_tree_add_item_ret_uint(pdcp_tree, hf_pdcp_lte_lsn3, tvb,
2353 offset, 3, ENC_BIG_ENDIAN, &lsn);
2354 offset += 3;
2355 }
2356
2357 write_pdu_label_and_info(root_ti, pinfo, " LWA End-Marker Packet (lsn=%u)", lsn);
2358 }
2359 return 1;
2360 default: /* Reserved */
2361 return 1;
2362 }
2363 }
2364 }
2365 else {
2366 /* Invalid plane setting...! */
2367 write_pdu_label_and_info(root_ti, pinfo, " - INVALID PLANE (%u)",
2368 p_pdcp_info->plane);
2369 return 1;
2370 }
2371
2372 /* Do sequence analysis if configured to. */
2373 if (seqnum_set) {
2374 gboolean do_analysis = FALSE;
2375
2376 switch (global_pdcp_check_sequence_numbers) {
2377 case FALSE:
2378 break;
2379 case SEQUENCE_ANALYSIS_RLC_ONLY:
2380 if ((p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0) != NULL) &&
2381 !p_pdcp_info->is_retx) {
2382 do_analysis = TRUE;
2383 }
2384 break;
2385 case SEQUENCE_ANALYSIS_PDCP_ONLY:
2386 if (p_get_proto_data(wmem_file_scope(), pinfo, proto_rlc_lte, 0) == NULL) {
2387 do_analysis = TRUE;
2388 }
2389 break;
2390 }
2391
2392 if (do_analysis) {
2393 checkChannelSequenceInfo(pinfo, tvb, p_pdcp_info,
2394 seqnum, pdcp_tree, security_tree,
2395 &pdu_security_settings);
2396 }
2397 }
2398 }
2399 else {
2400 /* Show that it's a no-header PDU */
2401 write_pdu_label_and_info(root_ti, pinfo, " No-Header ");
2402 }
2403
2404 /*******************************************************/
2405 /* Now deal with the payload */
2406 /*******************************************************/
2407
2408 payload_tvb = decipher_payload(tvb, pinfo, &offset, &pdu_security_settings, p_pdcp_info,
2409 pdu_security ? pdu_security->seen_next_ul_pdu: FALSE, &payload_deciphered);
2410
2411 if (p_pdcp_info->plane == SIGNALING_PLANE) {
2412 guint32 data_length;
2413 guint32 mac;
2414 proto_item *mac_ti;
2415 guint32 calculated_digest = 0;
2416 gboolean digest_was_calculated = FALSE;
2417
2418 /* Compute payload length (no MAC on common control channels) */
2419 data_length = tvb_reported_length_remaining(payload_tvb, offset) - ((p_pdcp_info->channelType == Channel_DCCH) ? 4 : 0);
2420
2421 /* Try to calculate digest so we can check it */
2422 if (global_pdcp_check_integrity && (p_pdcp_info->channelType == Channel_DCCH)) {
2423 calculated_digest = calculate_digest(&pdu_security_settings, tvb_get_guint8(tvb, 0), payload_tvb,
2424 pinfo, offset, &digest_was_calculated);
2425 }
2426
2427 /* RRC data is all but last 4 bytes.
2428 Call lte-rrc dissector (according to direction and channel type) if we have valid data */
2429 if ((global_pdcp_dissect_signalling_plane_as_rrc) &&
2430 ((pdu_security == NULL) || (pdu_security->ciphering == eea0) || payload_deciphered || !pdu_security->seen_next_ul_pdu)) {
2431
2432 /* Get appropriate dissector handle */
2433 dissector_handle_t rrc_handle = lookup_rrc_dissector_handle(p_pdcp_info);
2434
2435 if (rrc_handle != 0) {
2436 /* Call RRC dissector if have one */
2437 tvbuff_t *rrc_payload_tvb = tvb_new_subset_length(payload_tvb, offset, data_length);
2438 gboolean was_writable = col_get_writable(pinfo->cinfo, COL_INFO);
2439
2440 /* We always want to see this in the info column */
2441 col_set_writable(pinfo->cinfo, COL_INFO, TRUE);
2442
2443 call_dissector_only(rrc_handle, rrc_payload_tvb, pinfo, pdcp_tree, NULL);
2444
2445 /* Restore to whatever it was */
2446 col_set_writable(pinfo->cinfo, COL_INFO, was_writable);
2447 }
2448 else {
2449 /* Just show data */
2450 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_signalling_data, payload_tvb, offset,
2451 data_length, ENC_NA);
2452 }
2453
2454 if (!PINFO_FD_VISITED(pinfo) &&
2455 (current_security != NULL) && !current_security->seen_next_ul_pdu &&
2456 p_pdcp_info->direction == DIRECTION_UPLINK)
2457 {
2458 /* i.e. we have already seen SecurityModeResponse! */
2459 current_security->seen_next_ul_pdu = TRUE;
2460 }
2461
2462 }
2463 else {
2464 /* Just show as unparsed data */
2465 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_signalling_data, payload_tvb, offset,
2466 data_length, ENC_NA);
2467 }
2468
2469 offset += data_length;
2470
2471 if (p_pdcp_info->channelType == Channel_DCCH) {
2472 /* Last 4 bytes are MAC */
2473 mac = tvb_get_ntohl(payload_tvb, offset);
2474 mac_ti = proto_tree_add_item(pdcp_tree, hf_pdcp_lte_mac, payload_tvb, offset, 4, ENC_BIG_ENDIAN);
2475 offset += 4;
2476
2477 if (digest_was_calculated) {
2478 /* Compare what was found with calculated value! */
2479 if (mac != calculated_digest) {
2480 expert_add_info_format(pinfo, mac_ti, &ei_pdcp_lte_digest_wrong,
2481 "MAC-I Digest wrong - calculated %08x but found %08x",
2482 calculated_digest, mac);
2483 proto_item_append_text(mac_ti, " (but calculated %08x !)", calculated_digest);
2484 }
2485 else {
2486 proto_item_append_text(mac_ti, " [Matches calculated result]");
2487 }
2488 }
2489
2490 col_append_fstr(pinfo->cinfo, COL_INFO, " MAC=0x%08x (%u bytes data)",
2491 mac, data_length);
2492 } else {
2493 col_append_fstr(pinfo->cinfo, COL_INFO, " (%u bytes data)", data_length);
2494 }
2495 }
2496 else if (tvb_captured_length_remaining(payload_tvb, offset)) {
2497 /* User-plane payload here */
2498
2499 /* If not compressed with ROHC, show as user-plane data */
2500 if (!p_pdcp_info->rohc.rohc_compression) {
2501 gint payload_length = tvb_reported_length_remaining(payload_tvb, offset);
2502 if (payload_length > 0) {
2503 if (p_pdcp_info->plane == USER_PLANE) {
2504
2505 /* Not attempting to decode payload if ciphering is enabled
2506 (and NULL ciphering is not being used) */
2507 if (global_pdcp_dissect_user_plane_as_ip &&
2508 ((pdu_security == NULL) || (pdu_security->ciphering == eea0) || payload_deciphered))
2509 {
2510 tvbuff_t *ip_payload_tvb = tvb_new_subset_remaining(payload_tvb, offset);
2511
2512 /* Don't update info column for ROHC unless configured to */
2513 if (global_pdcp_lte_layer_to_show != ShowTrafficLayer) {
2514 col_set_writable(pinfo->cinfo, COL_INFO, FALSE);
2515 }
2516
2517 switch (tvb_get_guint8(ip_payload_tvb, 0) & 0xf0) {
2518 case 0x40:
2519 call_dissector_only(ip_handle, ip_payload_tvb, pinfo, pdcp_tree, NULL);
2520 break;
2521 case 0x60:
2522 call_dissector_only(ipv6_handle, ip_payload_tvb, pinfo, pdcp_tree, NULL);
2523 break;
2524 default:
2525 call_data_dissector(ip_payload_tvb, pinfo, pdcp_tree);
2526 break;
2527 }
2528
2529 /* Freeze the columns again because we don't want other layers writing to info */
2530 if (global_pdcp_lte_layer_to_show == ShowTrafficLayer) {
2531 col_set_writable(pinfo->cinfo, COL_INFO, FALSE);
2532 }
2533
2534 }
2535 else {
2536 proto_tree_add_item(pdcp_tree, hf_pdcp_lte_user_plane_data, payload_tvb, offset, -1, ENC_NA);
2537 }
2538 }
2539
2540 write_pdu_label_and_info(root_ti, pinfo, "(%u bytes data)",
2541 payload_length);
2542 }
2543
2544 /* (there will be no signalling data left at this point) */
2545
2546 /* Let RLC write to columns again */
2547 col_set_writable(pinfo->cinfo, COL_INFO, global_pdcp_lte_layer_to_show == ShowRLCLayer);
2548
2549 /* DROPPING OUT HERE IF NOT DOING ROHC! */
2550 return tvb_captured_length(tvb);
2551 }
2552 else {
2553 /***************************/
2554 /* ROHC packets */
2555 /***************************/
2556
2557 /* Only attempt ROHC if configured to */
2558 if (!global_pdcp_dissect_rohc) {
2559 col_append_fstr(pinfo->cinfo, COL_PROTOCOL, "|ROHC(%s)",
2560 val_to_str_const(p_pdcp_info->rohc.profile, rohc_profile_vals, "Unknown"));
2561 return 1;
2562 }
2563
2564 rohc_tvb = tvb_new_subset_remaining(payload_tvb, offset);
2565
2566 /* Only enable writing to column if configured to show ROHC */
2567 if (global_pdcp_lte_layer_to_show != ShowTrafficLayer) {
2568 col_set_writable(pinfo->cinfo, COL_INFO, FALSE);
2569 }
2570 else {
2571 col_clear(pinfo->cinfo, COL_INFO);
2572 }
2573
2574 /* Call the ROHC dissector */
2575 call_dissector_with_data(rohc_handle, rohc_tvb, pinfo, tree, &p_pdcp_info->rohc);
2576
2577 /* Let RLC write to columns again */
2578 col_set_writable(pinfo->cinfo, COL_INFO, global_pdcp_lte_layer_to_show == ShowRLCLayer);
2579 }
2580 }
2581 return tvb_captured_length(tvb);
2582 }
2583
2584
proto_register_pdcp_lte(void)2585 void proto_register_pdcp_lte(void)
2586 {
2587 static hf_register_info hf[] =
2588 {
2589 { &hf_pdcp_lte_configuration,
2590 { "Configuration",
2591 "pdcp-lte.configuration", FT_STRING, BASE_NONE, NULL, 0x0,
2592 "Configuration info passed into dissector", HFILL
2593 }
2594 },
2595
2596 { &hf_pdcp_lte_rohc_compression,
2597 { "ROHC Compression",
2598 "pdcp-lte.rohc.compression", FT_BOOLEAN, BASE_NONE, NULL, 0x0,
2599 NULL, HFILL
2600 }
2601 },
2602 { &hf_pdcp_lte_rohc_mode,
2603 { "ROHC Mode",
2604 "pdcp-lte.rohc.mode", FT_UINT8, BASE_DEC, VALS(rohc_mode_vals), 0x0,
2605 NULL, HFILL
2606 }
2607 },
2608 { &hf_pdcp_lte_rohc_rnd,
2609 { "RND",
2610 "pdcp-lte.rohc.rnd", FT_UINT8, BASE_DEC, NULL, 0x0,
2611 "RND of outer ip header", HFILL
2612 }
2613 },
2614 { &hf_pdcp_lte_rohc_udp_checksum_present,
2615 { "UDP Checksum",
2616 "pdcp-lte.rohc.checksum-present", FT_UINT8, BASE_DEC, NULL, 0x0,
2617 "UDP Checksum present", HFILL
2618 }
2619 },
2620 { &hf_pdcp_lte_direction,
2621 { "Direction",
2622 "pdcp-lte.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
2623 "Direction of message", HFILL
2624 }
2625 },
2626 { &hf_pdcp_lte_ueid,
2627 { "UE",
2628 "pdcp-lte.ueid", FT_UINT16, BASE_DEC, 0, 0x0,
2629 "UE Identifier", HFILL
2630 }
2631 },
2632 { &hf_pdcp_lte_channel_type,
2633 { "Channel type",
2634 "pdcp-lte.channel-type", FT_UINT8, BASE_DEC, VALS(logical_channel_vals), 0x0,
2635 NULL, HFILL
2636 }
2637 },
2638 { &hf_pdcp_lte_channel_id,
2639 { "Channel Id",
2640 "pdcp-lte.channel-id", FT_UINT8, BASE_DEC, 0, 0x0,
2641 NULL, HFILL
2642 }
2643 },
2644 { &hf_pdcp_lte_rohc_profile,
2645 { "ROHC profile",
2646 "pdcp-lte.rohc.profile", FT_UINT8, BASE_DEC, VALS(rohc_profile_vals), 0x0,
2647 "ROHC Mode", HFILL
2648 }
2649 },
2650 { &hf_pdcp_lte_no_header_pdu,
2651 { "No Header PDU",
2652 "pdcp-lte.no-header_pdu", FT_UINT8, BASE_DEC, NULL, 0x0,
2653 NULL, HFILL
2654 }
2655 },
2656 { &hf_pdcp_lte_plane,
2657 { "Plane",
2658 "pdcp-lte.plane", FT_UINT8, BASE_DEC, VALS(pdcp_plane_vals), 0x0,
2659 NULL, HFILL
2660 }
2661 },
2662 { &hf_pdcp_lte_seqnum_length,
2663 { "Seqnum length",
2664 "pdcp-lte.seqnum_length", FT_UINT8, BASE_DEC, NULL, 0x0,
2665 "Sequence Number Length", HFILL
2666 }
2667 },
2668
2669
2670 { &hf_pdcp_lte_cid_inclusion_info,
2671 { "CID Inclusion Info",
2672 "pdcp-lte.cid-inclusion-info", FT_UINT8, BASE_DEC, NULL, 0x0,
2673 NULL, HFILL
2674 }
2675 },
2676 { &hf_pdcp_lte_large_cid_present,
2677 { "Large CID Present",
2678 "pdcp-lte.large-cid-present", FT_UINT8, BASE_DEC, NULL, 0x0,
2679 NULL, HFILL
2680 }
2681 },
2682
2683 { &hf_pdcp_lte_control_plane_reserved,
2684 { "Reserved",
2685 "pdcp-lte.reserved", FT_UINT8, BASE_DEC, NULL, 0xe0,
2686 NULL, HFILL
2687 }
2688 },
2689 { &hf_pdcp_lte_seq_num_5,
2690 { "Seq Num",
2691 "pdcp-lte.seq-num", FT_UINT8, BASE_DEC, NULL, 0x1f,
2692 "PDCP Seq num", HFILL
2693 }
2694 },
2695 { &hf_pdcp_lte_seq_num_7,
2696 { "Seq Num",
2697 "pdcp-lte.seq-num", FT_UINT8, BASE_DEC, NULL, 0x7f,
2698 "PDCP Seq num", HFILL
2699 }
2700 },
2701 { &hf_pdcp_lte_reserved3,
2702 { "Reserved",
2703 "pdcp-lte.reserved3", FT_UINT8, BASE_HEX, NULL, 0x70,
2704 "3 reserved bits", HFILL
2705 }
2706 },
2707 { &hf_pdcp_lte_seq_num_12,
2708 { "Seq Num",
2709 "pdcp-lte.seq-num", FT_UINT16, BASE_DEC, NULL, 0x0fff,
2710 "PDCP Seq num", HFILL
2711 }
2712 },
2713 { &hf_pdcp_lte_seq_num_15,
2714 { "Seq Num",
2715 "pdcp-lte.seq-num", FT_UINT16, BASE_DEC, NULL, 0x7fff,
2716 "PDCP Seq num", HFILL
2717 }
2718 },
2719 { &hf_pdcp_lte_polling,
2720 { "Polling",
2721 "pdcp-lte.polling", FT_BOOLEAN, 8, NULL, 0x40,
2722 NULL, HFILL
2723 }
2724 },
2725 { &hf_pdcp_lte_reserved5,
2726 { "Reserved",
2727 "pdcp-lte.reserved5", FT_UINT8, BASE_HEX, NULL, 0x3c,
2728 "4 reserved bits", HFILL
2729 }
2730 },
2731 { &hf_pdcp_lte_seq_num_18,
2732 { "Seq Num",
2733 "pdcp-lte.seq-num", FT_UINT24, BASE_DEC, NULL, 0x03ffff,
2734 "PDCP Seq num", HFILL
2735 }
2736 },
2737 { &hf_pdcp_lte_signalling_data,
2738 { "Signalling Data",
2739 "pdcp-lte.signalling-data", FT_BYTES, BASE_NONE, NULL, 0x0,
2740 NULL, HFILL
2741 }
2742 },
2743 { &hf_pdcp_lte_mac,
2744 { "MAC",
2745 "pdcp-lte.mac", FT_UINT32, BASE_HEX, NULL, 0x0,
2746 NULL, HFILL
2747 }
2748 },
2749 { &hf_pdcp_lte_data_control,
2750 { "PDU Type",
2751 "pdcp-lte.pdu-type", FT_BOOLEAN, 8, TFS(& pdu_type_bit), 0x80,
2752 NULL, HFILL
2753 }
2754 },
2755 { &hf_pdcp_lte_user_plane_data,
2756 { "User-Plane Data",
2757 "pdcp-lte.user-data", FT_BYTES, BASE_NONE, NULL, 0x0,
2758 NULL, HFILL
2759 }
2760 },
2761 { &hf_pdcp_lte_control_pdu_type,
2762 { "Control PDU Type",
2763 "pdcp-lte.control-pdu-type", FT_UINT8, BASE_HEX, VALS(control_pdu_type_vals), 0x70,
2764 NULL, HFILL
2765 }
2766 },
2767 { &hf_pdcp_lte_fms,
2768 { "First Missing Sequence Number",
2769 "pdcp-lte.fms", FT_UINT16, BASE_DEC, NULL, 0x0fff,
2770 "First Missing PDCP Sequence Number", HFILL
2771 }
2772 },
2773 { &hf_pdcp_lte_reserved4,
2774 { "Reserved",
2775 "pdcp-lte.reserved4", FT_UINT16, BASE_HEX, NULL, 0x0f80,
2776 "5 reserved bits", HFILL
2777 }
2778 },
2779 { &hf_pdcp_lte_fms2,
2780 { "First Missing Sequence Number",
2781 "pdcp-lte.fms", FT_UINT16, BASE_DEC, NULL, 0x7fff,
2782 "First Missing PDCP Sequence Number", HFILL
2783 }
2784 },
2785 { &hf_pdcp_lte_reserved6,
2786 { "Reserved",
2787 "pdcp-lte.reserved6", FT_UINT8, BASE_HEX, NULL, 0x0c,
2788 "2 reserved bits", HFILL
2789 }
2790 },
2791 { &hf_pdcp_lte_fms3,
2792 { "First Missing Sequence Number",
2793 "pdcp-lte.fms", FT_UINT24, BASE_DEC, NULL, 0x03ffff,
2794 "First Missing PDCP Sequence Number", HFILL
2795 }
2796 },
2797 { &hf_pdcp_lte_bitmap,
2798 { "Bitmap",
2799 "pdcp-lte.bitmap", FT_NONE, BASE_NONE, NULL, 0x0,
2800 "Status report bitmap (0=error, 1=OK)", HFILL
2801 }
2802 },
2803 { &hf_pdcp_lte_bitmap_byte,
2804 { "Bitmap byte",
2805 "pdcp-lte.bitmap.byte", FT_UINT8, BASE_HEX, NULL, 0x0,
2806 NULL, HFILL
2807 }
2808 },
2809 { &hf_pdcp_lte_hrw,
2810 { "Highest Received Sequence Number on WLAN",
2811 "pdcp-lte.hwr", FT_UINT16, BASE_DEC, NULL, 0xfff0,
2812 NULL, HFILL
2813 }
2814 },
2815 { &hf_pdcp_lte_nmp,
2816 { "Number of Missing PDCP SDUs",
2817 "pdcp-lte.nmp", FT_UINT16, BASE_DEC, NULL, 0x0fff,
2818 NULL, HFILL
2819 }
2820 },
2821 { &hf_pdcp_lte_reserved7,
2822 { "Reserved",
2823 "pdcp-lte.reserved7", FT_UINT8, BASE_HEX, NULL, 0x80,
2824 "1 reserved bit", HFILL
2825 }
2826 },
2827 { &hf_pdcp_lte_hrw2,
2828 { "Highest Received Sequence Number on WLAN",
2829 "pdcp-lte.hwr", FT_UINT16, BASE_DEC, NULL, 0x7fff,
2830 NULL, HFILL
2831 }
2832 },
2833 { &hf_pdcp_lte_nmp2,
2834 { "Number of Missing PDCP SDUs",
2835 "pdcp-lte.nmp", FT_UINT16, BASE_DEC, NULL, 0x7fff,
2836 NULL, HFILL
2837 }
2838 },
2839 { &hf_pdcp_lte_hrw3,
2840 { "Highest Received Sequence Number on WLAN",
2841 "pdcp-lte.hwr", FT_UINT24, BASE_DEC, NULL, 0xffffc0,
2842 NULL, HFILL
2843 }
2844 },
2845 { &hf_pdcp_lte_reserved8,
2846 { "Reserved",
2847 "pdcp-lte.reserved8", FT_UINT8, BASE_HEX, NULL, 0x3c,
2848 "4 reserved bits", HFILL
2849 }
2850 },
2851 { &hf_pdcp_lte_nmp3,
2852 { "Number of Missing PDCP SDUs",
2853 "pdcp-lte.nmp", FT_UINT24, BASE_DEC, NULL, 0x03ffff,
2854 NULL, HFILL
2855 }
2856 },
2857 { &hf_pdcp_lte_lsn,
2858 { "Last PDCP PDU SN ciphered with previous key",
2859 "pdcp-lte.lsn", FT_UINT16, BASE_DEC, NULL, 0x0fff,
2860 NULL, HFILL
2861 }
2862 },
2863 { &hf_pdcp_lte_lsn2,
2864 { "Last PDCP PDU SN ciphered with previous key",
2865 "pdcp-lte.lsn", FT_UINT16, BASE_DEC, NULL, 0x7fff,
2866 NULL, HFILL
2867 }
2868 },
2869 { &hf_pdcp_lte_lsn3,
2870 { "Last PDCP PDU SN ciphered with previous key",
2871 "pdcp-lte.lsn", FT_UINT24, BASE_DEC, NULL, 0x03ffff,
2872 NULL, HFILL
2873 }
2874 },
2875
2876 { &hf_pdcp_lte_sequence_analysis,
2877 { "Sequence Analysis",
2878 "pdcp-lte.sequence-analysis", FT_STRING, BASE_NONE, 0, 0x0,
2879 NULL, HFILL
2880 }
2881 },
2882 { &hf_pdcp_lte_sequence_analysis_ok,
2883 { "OK",
2884 "pdcp-lte.sequence-analysis.ok", FT_BOOLEAN, BASE_NONE, 0, 0x0,
2885 NULL, HFILL
2886 }
2887 },
2888 { &hf_pdcp_lte_sequence_analysis_previous_frame,
2889 { "Previous frame for channel",
2890 "pdcp-lte.sequence-analysis.previous-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
2891 NULL, HFILL
2892 }
2893 },
2894 { &hf_pdcp_lte_sequence_analysis_next_frame,
2895 { "Next frame for channel",
2896 "pdcp-lte.sequence-analysis.next-frame", FT_FRAMENUM, BASE_NONE, 0, 0x0,
2897 NULL, HFILL
2898 }
2899 },
2900 { &hf_pdcp_lte_sequence_analysis_expected_sn,
2901 { "Expected SN",
2902 "pdcp-lte.sequence-analysis.expected-sn", FT_UINT32, BASE_DEC, 0, 0x0,
2903 NULL, HFILL
2904 }
2905 },
2906 { &hf_pdcp_lte_sequence_analysis_skipped,
2907 { "Skipped frames",
2908 "pdcp-lte.sequence-analysis.skipped-frames", FT_BOOLEAN, BASE_NONE, 0, 0x0,
2909 NULL, HFILL
2910 }
2911 },
2912 { &hf_pdcp_lte_sequence_analysis_repeated,
2913 { "Repeated frame",
2914 "pdcp-lte.sequence-analysis.repeated-frame", FT_BOOLEAN, BASE_NONE, 0, 0x0,
2915 NULL, HFILL
2916 }
2917 },
2918
2919 /* Security fields */
2920 { &hf_pdcp_lte_security,
2921 { "Security Config",
2922 "pdcp-lte.security-config", FT_STRING, BASE_NONE, 0, 0x0,
2923 NULL, HFILL
2924 }
2925 },
2926 { &hf_pdcp_lte_security_setup_frame,
2927 { "Configuration frame",
2928 "pdcp-lte.security-config.setup-frame", FT_FRAMENUM, BASE_NONE, NULL, 0x0,
2929 NULL, HFILL
2930 }
2931 },
2932 { &hf_pdcp_lte_security_integrity_algorithm,
2933 { "Integrity Algorithm",
2934 "pdcp-lte.security-config.integrity", FT_UINT16, BASE_DEC, VALS(integrity_algorithm_vals), 0x0,
2935 NULL, HFILL
2936 }
2937 },
2938 { &hf_pdcp_lte_security_ciphering_algorithm,
2939 { "Ciphering Algorithm",
2940 "pdcp-lte.security-config.ciphering", FT_UINT16, BASE_DEC, VALS(ciphering_algorithm_vals), 0x0,
2941 NULL, HFILL
2942 }
2943 },
2944 { &hf_pdcp_lte_security_bearer,
2945 { "BEARER",
2946 "pdcp-lte.security-config.bearer", FT_UINT8, BASE_DEC, NULL, 0x0,
2947 NULL, HFILL
2948 }
2949 },
2950 { &hf_pdcp_lte_security_direction,
2951 { "DIRECTION",
2952 "pdcp-lte.security-config.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
2953 NULL, HFILL
2954 }
2955 },
2956 { &hf_pdcp_lte_security_count,
2957 { "COUNT",
2958 "pdcp-lte.security-config.count", FT_UINT32, BASE_DEC, NULL, 0x0,
2959 NULL, HFILL
2960 }
2961 },
2962 { &hf_pdcp_lte_security_cipher_key,
2963 { "CIPHER KEY",
2964 "pdcp-lte.security-config.cipher-key", FT_STRING, BASE_NONE, NULL, 0x0,
2965 NULL, HFILL
2966 }
2967 },
2968 { &hf_pdcp_lte_security_integrity_key,
2969 { "INTEGRITY KEY",
2970 "pdcp-lte.security-config.integrity-key", FT_STRING, BASE_NONE, NULL, 0x0,
2971 NULL, HFILL
2972 }
2973 }
2974 };
2975
2976 static gint *ett[] =
2977 {
2978 &ett_pdcp,
2979 &ett_pdcp_configuration,
2980 &ett_pdcp_packet,
2981 &ett_pdcp_lte_sequence_analysis,
2982 &ett_pdcp_report_bitmap,
2983 &ett_pdcp_security
2984 };
2985
2986 static ei_register_info ei[] = {
2987 { &ei_pdcp_lte_sequence_analysis_sn_missing, { "pdcp-lte.sequence-analysis.sn-missing", PI_SEQUENCE, PI_WARN, "PDCP SN missing", EXPFILL }},
2988 { &ei_pdcp_lte_sequence_analysis_sn_repeated, { "pdcp-lte.sequence-analysis.sn-repeated", PI_SEQUENCE, PI_WARN, "PDCP SN repeated", EXPFILL }},
2989 { &ei_pdcp_lte_sequence_analysis_wrong_sequence_number, { "pdcp-lte.sequence-analysis.wrong-sequence-number", PI_SEQUENCE, PI_WARN, "Wrong Sequence Number", EXPFILL }},
2990 { &ei_pdcp_lte_reserved_bits_not_zero, { "pdcp-lte.reserved-bits-not-zero", PI_MALFORMED, PI_ERROR, "Reserved bits not zero", EXPFILL }},
2991 { &ei_pdcp_lte_digest_wrong, { "pdcp-lte.maci-wrong", PI_SEQUENCE, PI_ERROR, "MAC-I doesn't match expected value", EXPFILL }},
2992 { &ei_pdcp_lte_unknown_udp_framing_tag, { "pdcp-lte.unknown-udp-framing-tag", PI_UNDECODED, PI_WARN, "Unknown UDP framing tag, aborting dissection", EXPFILL }},
2993 { &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 }}
2994 };
2995
2996 static const enum_val_t sequence_analysis_vals[] = {
2997 {"no-analysis", "No-Analysis", FALSE},
2998 {"rlc-only", "Only-RLC-frames", SEQUENCE_ANALYSIS_RLC_ONLY},
2999 {"pdcp-only", "Only-PDCP-frames", SEQUENCE_ANALYSIS_PDCP_ONLY},
3000 {NULL, NULL, -1}
3001 };
3002
3003 static const enum_val_t show_info_col_vals[] = {
3004 {"show-rlc", "RLC Info", ShowRLCLayer},
3005 {"show-pdcp", "PDCP Info", ShowPDCPLayer},
3006 {"show-traffic", "Traffic Info", ShowTrafficLayer},
3007 {NULL, NULL, -1}
3008 };
3009
3010 static const enum_val_t default_ciphering_algorithm_vals[] = {
3011 {"eea0", "EEA0 (NULL)", eea0},
3012 {"eea1", "EEA1 (SNOW3G)", eea1},
3013 {"eea2", "EEA2 (AES)", eea2},
3014 {"eea3", "EEA3 (ZUC)", eea3},
3015 {NULL, NULL, -1}
3016 };
3017
3018 static const enum_val_t default_integrity_algorithm_vals[] = {
3019 {"eia0", "EIA0 (NULL)", eia0},
3020 {"eia1", "EIA1 (SNOW3G)", eia1},
3021 {"eia2", "EIA2 (AES)", eia2},
3022 {"eia3", "EIA3 (ZUC)", eia3},
3023 {NULL, NULL, -1}
3024 };
3025
3026 static uat_field_t ue_keys_uat_flds[] = {
3027 UAT_FLD_DEC(uat_ue_keys_records, ueid, "UEId", "UE Identifier of UE associated with keys"),
3028 UAT_FLD_CSTRING(uat_ue_keys_records, rrcCipherKeyString, "RRC Cipher Key", "Key for deciphering signalling messages"),
3029 UAT_FLD_CSTRING(uat_ue_keys_records, upCipherKeyString, "User-Plane Cipher Key", "Key for deciphering user-plane messages"),
3030 UAT_FLD_CSTRING(uat_ue_keys_records, rrcIntegrityKeyString, "RRC Integrity Key", "Key for calculating integrity MAC"),
3031 UAT_END_FIELDS
3032 };
3033
3034 module_t *pdcp_lte_module;
3035 expert_module_t* expert_pdcp_lte;
3036
3037 /* Register protocol. */
3038 proto_pdcp_lte = proto_register_protocol("PDCP-LTE", "PDCP-LTE", "pdcp-lte");
3039 proto_register_field_array(proto_pdcp_lte, hf, array_length(hf));
3040 proto_register_subtree_array(ett, array_length(ett));
3041 expert_pdcp_lte = expert_register_protocol(proto_pdcp_lte);
3042 expert_register_field_array(expert_pdcp_lte, ei, array_length(ei));
3043
3044 /* Allow other dissectors to find this one by name. */
3045 register_dissector("pdcp-lte", dissect_pdcp_lte, proto_pdcp_lte);
3046
3047 pdcp_lte_module = prefs_register_protocol(proto_pdcp_lte, NULL);
3048
3049 /* Obsolete preferences */
3050 prefs_register_obsolete_preference(pdcp_lte_module, "show_feedback_option_tag_length");
3051
3052 /* Dissect uncompressed user-plane data as IP */
3053 prefs_register_bool_preference(pdcp_lte_module, "show_user_plane_as_ip",
3054 "Show uncompressed User-Plane data as IP",
3055 "Show uncompressed User-Plane data as IP",
3056 &global_pdcp_dissect_user_plane_as_ip);
3057
3058 /* Dissect unciphered signalling data as RRC */
3059 prefs_register_bool_preference(pdcp_lte_module, "show_signalling_plane_as_rrc",
3060 "Show unciphered Signalling-Plane data as RRC",
3061 "Show unciphered Signalling-Plane data as RRC",
3062 &global_pdcp_dissect_signalling_plane_as_rrc);
3063
3064 /* Check for missing sequence numbers */
3065 prefs_register_enum_preference(pdcp_lte_module, "check_sequence_numbers",
3066 "Do sequence number analysis",
3067 "Do sequence number analysis",
3068 &global_pdcp_check_sequence_numbers, sequence_analysis_vals, FALSE);
3069
3070 /* Attempt to dissect ROHC messages */
3071 prefs_register_bool_preference(pdcp_lte_module, "dissect_rohc",
3072 "Attempt to decode ROHC data",
3073 "Attempt to decode ROHC data",
3074 &global_pdcp_dissect_rohc);
3075
3076 prefs_register_obsolete_preference(pdcp_lte_module, "heuristic_pdcp_lte_over_udp");
3077
3078 prefs_register_enum_preference(pdcp_lte_module, "layer_to_show",
3079 "Which layer info to show in Info column",
3080 "Can show RLC, PDCP or Traffic layer info in Info column",
3081 &global_pdcp_lte_layer_to_show, show_info_col_vals, FALSE);
3082
3083 ue_keys_uat = uat_new("PDCP UE security keys",
3084 sizeof(uat_ue_keys_record_t), /* record size */
3085 "pdcp_lte_ue_keys", /* filename */
3086 TRUE, /* from_profile */
3087 &uat_ue_keys_records, /* data_ptr */
3088 &num_ue_keys_uat, /* numitems_ptr */
3089 UAT_AFFECTS_DISSECTION, /* affects dissection of packets, but not set of named fields */
3090 NULL, /* help */
3091 uat_ue_keys_record_copy_cb, /* copy callback */
3092 uat_ue_keys_record_update_cb, /* update callback */
3093 uat_ue_keys_record_free_cb, /* free callback */
3094 NULL, /* post update callback */
3095 NULL, /* reset callback */
3096 ue_keys_uat_flds); /* UAT field definitions */
3097
3098 prefs_register_uat_preference(pdcp_lte_module,
3099 "ue_keys_table",
3100 "PDCP UE Keys",
3101 "Preconfigured PDCP keys",
3102 ue_keys_uat);
3103
3104 prefs_register_enum_preference(pdcp_lte_module, "default_ciphering_algorithm",
3105 "Ciphering algorithm to use if not signalled",
3106 "If RRC Security Info not seen, e.g. in Handover",
3107 (gint*)&global_default_ciphering_algorithm, default_ciphering_algorithm_vals, FALSE);
3108
3109 prefs_register_enum_preference(pdcp_lte_module, "default_integrity_algorithm",
3110 "Integrity algorithm to use if not signalled",
3111 "If RRC Security Info not seen, e.g. in Handover",
3112 (gint*)&global_default_integrity_algorithm, default_integrity_algorithm_vals, FALSE);
3113
3114 /* Attempt to decipher RRC messages */
3115 prefs_register_bool_preference(pdcp_lte_module, "decipher_signalling",
3116 "Attempt to decipher Signalling (RRC) SDUs",
3117 "N.B. only possible if build with algorithm support, and have key available and configured",
3118 &global_pdcp_decipher_signalling);
3119
3120 /* Attempt to decipher user-plane messages */
3121 prefs_register_bool_preference(pdcp_lte_module, "decipher_userplane",
3122 "Attempt to decipher User-plane (IP) SDUs",
3123 "N.B. only possible if build with algorithm support, and have key available and configured",
3124 &global_pdcp_decipher_userplane);
3125
3126 /* Attempt to verify RRC integrity/authentication digest */
3127 prefs_register_bool_preference(pdcp_lte_module, "verify_integrity",
3128 "Attempt to check integrity calculation",
3129 "N.B. only possible if build with algorithm support, and have key available and configured",
3130 &global_pdcp_check_integrity);
3131
3132 prefs_register_bool_preference(pdcp_lte_module, "ignore_rrc_sec_params",
3133 "Ignore RRC security parameters",
3134 "Ignore the LTE RRC security algorithm configuration, to be used when PDCP is already deciphered in the capture",
3135 &global_pdcp_ignore_sec);
3136
3137 pdcp_sequence_analysis_channel_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), g_direct_hash, g_direct_equal);
3138 pdcp_lte_sequence_analysis_report_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), pdcp_result_hash_func, pdcp_result_hash_equal);
3139 pdcp_security_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), g_direct_hash, g_direct_equal);
3140 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);
3141 pdcp_security_key_hash = wmem_map_new_autoreset(wmem_epan_scope(), wmem_file_scope(), g_direct_hash, g_direct_equal);
3142 }
3143
proto_reg_handoff_pdcp_lte(void)3144 void proto_reg_handoff_pdcp_lte(void)
3145 {
3146 /* Add as a heuristic UDP dissector */
3147 heur_dissector_add("udp", dissect_pdcp_lte_heur, "PDCP-LTE over UDP", "pdcp_lte_udp", proto_pdcp_lte, HEURISTIC_DISABLE);
3148
3149 ip_handle = find_dissector_add_dependency("ip", proto_pdcp_lte);
3150 ipv6_handle = find_dissector_add_dependency("ipv6", proto_pdcp_lte);
3151 rohc_handle = find_dissector_add_dependency("rohc", proto_pdcp_lte);
3152 lte_rrc_ul_ccch = find_dissector_add_dependency("lte_rrc.ul_ccch", proto_pdcp_lte);
3153 lte_rrc_dl_ccch = find_dissector_add_dependency("lte_rrc.dl_ccch", proto_pdcp_lte);
3154 lte_rrc_pcch = find_dissector_add_dependency("lte_rrc.pcch", proto_pdcp_lte);
3155 lte_rrc_bcch_bch = find_dissector_add_dependency("lte_rrc.bcch_bch", proto_pdcp_lte);
3156 lte_rrc_bcch_dl_sch = find_dissector_add_dependency("lte_rrc.bcch_dl_sch", proto_pdcp_lte);
3157 lte_rrc_ul_dcch = find_dissector_add_dependency("lte_rrc.ul_dcch", proto_pdcp_lte);
3158 lte_rrc_dl_dcch = find_dissector_add_dependency("lte_rrc.dl_dcch", proto_pdcp_lte);
3159 lte_rrc_ul_ccch_nb = find_dissector_add_dependency("lte_rrc.ul_ccch.nb", proto_pdcp_lte);
3160 lte_rrc_dl_ccch_nb = find_dissector_add_dependency("lte_rrc.dl_ccch.nb", proto_pdcp_lte);
3161 lte_rrc_pcch_nb = find_dissector_add_dependency("lte_rrc.pcch.nb", proto_pdcp_lte);
3162 lte_rrc_bcch_bch_nb = find_dissector_add_dependency("lte_rrc.bcch_bch.nb", proto_pdcp_lte);
3163 lte_rrc_bcch_dl_sch_nb = find_dissector_add_dependency("lte_rrc.bcch_dl_sch.nb", proto_pdcp_lte);
3164 lte_rrc_ul_dcch_nb = find_dissector_add_dependency("lte_rrc.ul_dcch.nb", proto_pdcp_lte);
3165 lte_rrc_dl_dcch_nb = find_dissector_add_dependency("lte_rrc.dl_dcch.nb", proto_pdcp_lte);
3166 }
3167
3168 /*
3169 * Editor modelines
3170 *
3171 * Local Variables:
3172 * c-basic-offset: 4
3173 * tab-width: 8
3174 * indent-tabs-mode: nil
3175 * End:
3176 *
3177 * ex: set shiftwidth=4 tabstop=8 expandtab:
3178 * :indentSize=4:tabSize=8:noTabs=true:
3179 */
3180