Coverage Report

Created: 2026-08-14 06:45

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