aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-catapult-dct2000.c
diff options
context:
space:
mode:
authorMartin Mathieson <martin.r.mathieson@googlemail.com>2022-04-19 15:13:51 +0000
committerMartin Mathieson <martin.r.mathieson@googlemail.com>2022-04-19 15:13:51 +0000
commit58821b50b5d260d5aa6b31d08ac1053d2922acda (patch)
treeae45165fe4a84246922850cf9dbdb9d4d2ded865 /epan/dissectors/packet-catapult-dct2000.c
parent371b52120be8b734e58ba717fa49e129eb7919f8 (diff)
PDCP-NR: changes to make security keys work better
Diffstat (limited to 'epan/dissectors/packet-catapult-dct2000.c')
-rw-r--r--epan/dissectors/packet-catapult-dct2000.c290
1 files changed, 284 insertions, 6 deletions
diff --git a/epan/dissectors/packet-catapult-dct2000.c b/epan/dissectors/packet-catapult-dct2000.c
index 4ced9293ef..007536347c 100644
--- a/epan/dissectors/packet-catapult-dct2000.c
+++ b/epan/dissectors/packet-catapult-dct2000.c
@@ -30,6 +30,7 @@
#include "packet-pdcp-lte.h"
#include "packet-mac-nr.h"
+#include "packet-pdcp-nr.h"
void proto_reg_handoff_catapult_dct2000(void);
void proto_register_catapult_dct2000(void);
@@ -89,6 +90,14 @@ static int hf_catapult_dct2000_carrier_type = -1;
static int hf_catapult_dct2000_cell_group = -1;
static int hf_catapult_dct2000_carrier_id = -1;
+static int hf_catapult_dct2000_security_mode_params = -1;
+static int hf_catapult_dct2000_uplink_sec_mode = -1;
+static int hf_catapult_dct2000_downlink_sec_mode = -1;
+static int hf_catapult_dct2000_ciphering_algorithm = -1;
+static int hf_catapult_dct2000_ciphering_key = -1;
+static int hf_catapult_dct2000_integrity_algorithm = -1;
+static int hf_catapult_dct2000_integrity_key = -1;
+
static int hf_catapult_dct2000_lte_ccpri_opcode = -1;
static int hf_catapult_dct2000_lte_ccpri_status = -1;
static int hf_catapult_dct2000_lte_ccpri_channel = -1;
@@ -115,6 +124,11 @@ static int hf_catapult_dct2000_rx_timing_deviation = -1;
static int hf_catapult_dct2000_transport_channel_type = -1;
static int hf_catapult_dct2000_no_padding_bits = -1;
+static int hf_catapult_dct2000_rawtraffic_interface = -1;
+static int hf_catapult_dct2000_rawtraffic_direction = -1;
+static int hf_catapult_dct2000_rawtraffic_pdu = -1;
+
+
/* Variables used for preferences */
static gboolean catapult_dct2000_try_ipprim_heuristic = TRUE;
static gboolean catapult_dct2000_try_sctpprim_heuristic = TRUE;
@@ -128,6 +142,7 @@ static int ett_catapult_dct2000 = -1;
static int ett_catapult_dct2000_ipprim = -1;
static int ett_catapult_dct2000_sctpprim = -1;
static int ett_catapult_dct2000_tty = -1;
+static int ett_catapult_dct2000_security_mode_params = -1;
static expert_field ei_catapult_dct2000_lte_ccpri_status_error = EI_INIT;
static expert_field ei_catapult_dct2000_error_comment_expert = EI_INIT;
@@ -298,6 +313,30 @@ static const value_string carrier_type_vals[] = {
};
+static const value_string security_mode_vals[] = {
+ { 0, "None"},
+ { 1, "Integrity only"},
+ { 2, "Ciphering and Integrity"},
+ { 0, NULL}
+};
+
+static const value_string ciphering_algorithm_vals[] = {
+ { 0, "EEA0"},
+ { 1, "EEA1"},
+ { 2, "EEA2"},
+ { 3, "EEA3"},
+ { 0, NULL}
+};
+
+static const value_string integrity_algorithm_vals[] = {
+ { 0, "EIA0"},
+ { 1, "EIA1"},
+ { 2, "EIA2"},
+ { 3, "EIA3"},
+ { 0, NULL}
+};
+
+
#define MAX_OUTHDR_VALUES 32
extern int proto_fp;
@@ -306,6 +345,7 @@ extern int proto_umts_rlc;
extern int proto_rlc_lte;
extern int proto_pdcp_lte;
+
static dissector_handle_t mac_lte_handle;
static dissector_handle_t rlc_lte_handle;
static dissector_handle_t pdcp_lte_handle;
@@ -314,6 +354,8 @@ static dissector_handle_t nrup_handle;
static dissector_handle_t mac_nr_handle;
+static dissector_handle_t eth_handle;
+
static dissector_handle_t look_for_dissector(const char *protocol_name);
static guint parse_outhdr_string(const guchar *outhdr_string, gint outhdr_length, guint *outhdr_values);
@@ -332,8 +374,6 @@ static void attach_pdcp_lte_info(packet_info *pinfo, guint *outhdr_values,
guint outhdr_values_found);
-
-
/* Return the number of bytes used to encode the length field
(we're not interested in the length value itself) */
static int skipASNLength(guint8 value)
@@ -855,6 +895,14 @@ static void dissect_rlc_umts(tvbuff_t *tvb, gint offset,
}
}
+static char* get_key(tvbuff_t*tvb, gint offset)
+{
+ static gchar key[33];
+ for (int n=0; n < 16; n++) {
+ snprintf(&key[n*2], 33-(n*2), "%02x", tvb_get_guint8(tvb, offset+n));
+ }
+ return key;
+}
/* Dissect an RRC LTE or NR frame by first parsing the header entries then passing
@@ -1027,10 +1075,102 @@ static void dissect_rrc_lte_nr(tvbuff_t *tvb, gint offset,
offset++;
}
else if (opcode == 0x05) {
- /* Data_Req_UE_SM - skip SecurityMode Params */
+ /* Data_Req_UE_SM - SecurityMode Params */
+ /* N.B. DRB keys do not get configured here.. */
offset++; /* tag */
- guint8 len = tvb_get_guint8(tvb, offset); /* length */
- offset += len;
+ guint8 len = tvb_get_guint8(tvb, offset++); /* length */
+
+ /* Uplink Sec Mode */
+ proto_item *sc_ti;
+ proto_tree *sc_tree;
+ sc_ti = proto_tree_add_item(tree, hf_catapult_dct2000_security_mode_params, tvb, offset, len, ENC_NA);
+ sc_tree = proto_item_add_subtree(sc_ti, ett_catapult_dct2000_security_mode_params);
+
+ guint32 uplink_sec_mode;
+ proto_tree_add_item_ret_uint(sc_tree, hf_catapult_dct2000_uplink_sec_mode,
+ tvb, offset++, 1, ENC_BIG_ENDIAN, &uplink_sec_mode);
+
+ /* Downlink Sec Mode */
+ guint32 downlink_sec_mode;
+ proto_tree_add_item_ret_uint(sc_tree, hf_catapult_dct2000_downlink_sec_mode,
+ tvb, offset++, 1, ENC_BIG_ENDIAN, &downlink_sec_mode);
+
+ if (len > 2) {
+ tag = tvb_get_guint8(tvb, offset++); /* Should be 0x21 */
+ len = tvb_get_guint8(tvb, offset++);
+
+ tag = tvb_get_guint8(tvb, offset++);
+ if (tag == 0x25) {
+ /* Cell Group Id */
+ offset++;
+ proto_tree_add_item(sc_tree, hf_catapult_dct2000_cell_group,
+ tvb, offset, 1, ENC_BIG_ENDIAN);
+ }
+
+ /* Optional cryptParams */
+ if (tag == 0x2) {
+ guint32 cipher_algorithm;
+
+ len = tvb_get_guint8(tvb, offset++);
+
+ /* Cipher algorithm (required) */
+ offset += 2; /* Skip tag and length */
+ proto_tree_add_item_ret_uint(sc_tree, hf_catapult_dct2000_ciphering_algorithm,
+ tvb, offset++, 1, ENC_BIG_ENDIAN, &cipher_algorithm);
+
+ /* Ciphering key (optional */
+ if (len > 3) {
+ /* Skip tag and length */
+ offset += 2;
+ proto_tree_add_item(sc_tree, hf_catapult_dct2000_ciphering_key,
+ tvb, offset, 16, ENC_NA);
+ gchar *key = get_key(tvb, offset);
+
+ if (!PINFO_FD_VISITED(pinfo)) {
+ if (lte_or_nr == NR) {
+ set_pdcp_nr_rrc_ciphering_key(ueid, key, pinfo->num);
+ }
+ else {
+ set_pdcp_lte_rrc_ciphering_key(ueid, key);
+ }
+ }
+ offset += 16;
+ }
+ }
+ else {
+ offset--;
+ }
+
+ /* Now should be Auth params (required) */
+ guint32 integrity_algorithm;
+ tag = tvb_get_guint8(tvb, offset++);
+
+ len = tvb_get_guint8(tvb, offset++);
+
+ /* Integrity algorithm (required) */
+ offset += 2; /* Skip tag and length */
+ proto_tree_add_item_ret_uint(sc_tree, hf_catapult_dct2000_integrity_algorithm,
+ tvb, offset++, 1, ENC_BIG_ENDIAN, &integrity_algorithm);
+
+ /* Integrity key (optional */
+ if (len > 3) {
+ /* Skip tag and length */
+ offset += 2;
+ proto_tree_add_item(sc_tree, hf_catapult_dct2000_integrity_key,
+ tvb, offset, 16, ENC_NA);
+ gchar *key = get_key(tvb, offset);
+
+ if (!PINFO_FD_VISITED(pinfo)) {
+ if (lte_or_nr == NR) {
+ set_pdcp_nr_rrc_integrity_key(ueid, key, pinfo->num);
+ }
+ else {
+ set_pdcp_lte_rrc_integrity_key(ueid, key);
+ }
+ }
+ offset += 16;
+ }
+ }
}
/* Optional data tag may follow */
@@ -2258,6 +2398,7 @@ hex_from_char(gchar c)
return 0xff;
}
+
/*****************************************/
/* Main dissection function. */
/*****************************************/
@@ -2838,6 +2979,7 @@ dissect_catapult_dct2000(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, vo
const char *payload = &start[off+1];
+ /* Pad out to nearest 4 bytes if necessary. */
/* Convert data to hex. */
#define MAX_NRUP_DATA_LENGTH 200
static guint8 nrup_data[MAX_NRUP_DATA_LENGTH];
@@ -2863,6 +3005,77 @@ dissect_catapult_dct2000(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, vo
call_dissector_only(nrup_handle, nrup_tvb, pinfo, tree, NULL);
}
+ /* Read key info from formatted lines */
+ /* e.g. NRPDCP: RRCPRIM:ueId= 1;setThreadAuthKey: RRC id=1 alg 2 key: 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 */
+ if (strstr(string, "setThreadAuthKey:")) {
+ guint ue_id, id, alg;
+ if (!PINFO_FD_VISITED(pinfo) && sscanf(string, "NRPDCP: RRCPRIM:ueId= %u; RRC setThreadAuthKey: id=%u alg %u key: ", &ue_id, &id, &alg) == 3) {
+ char *key = g_strdup(strstr(string, "key: ")+5);
+ set_pdcp_nr_rrc_integrity_key(ue_id, key, pinfo->num);
+ g_free(key);
+ }
+ else if (!PINFO_FD_VISITED(pinfo) && sscanf(string, "NRPDCP: RRCPRIM:ueId= %u; UP setThreadAuthKey: id=%u alg %u key: ", &ue_id, &id, &alg) == 3) {
+ char *key = g_strdup(strstr(string, "key: ")+5);
+ set_pdcp_nr_up_integrity_key(ue_id, key, pinfo->num);
+ g_free(key);
+ }
+ }
+ else if (strstr(string, "setThreadCryptKey:")) {
+ guint ue_id, id, alg;
+ if (!PINFO_FD_VISITED(pinfo) && sscanf(string, "NRPDCP: RRCPRIM:ueId= %u; RRC setThreadCryptKey: id=%u alg %u key: ", &ue_id, &id, &alg) == 3) {
+ char *key = g_strdup(strstr(string, "key: ")+5);
+ set_pdcp_nr_rrc_ciphering_key(ue_id, key, pinfo->num);
+ g_free(key);
+ }
+ else if (!PINFO_FD_VISITED(pinfo) && sscanf(string, "NRPDCP: RRCPRIM:ueId= %u; UP setThreadCryptKey: id=%u alg %u key: ", &ue_id, &id, &alg) == 3) {
+ char *key = g_strdup(strstr(string, "key: ")+5);
+ set_pdcp_nr_up_ciphering_key(ue_id, key, pinfo->num);
+ g_free(key);
+ }
+ }
+
+ /* 'raw' (ethernet) frames logged as text comments */
+ int raw_interface;
+ char raw_direction;
+ if (sscanf(string, "RawTraffic: Interface: %d %c $",
+ &raw_interface, &raw_direction) == 2)
+ {
+ /* Interface */
+ proto_tree_add_uint(tree, hf_catapult_dct2000_rawtraffic_interface,
+ tvb, 0, 0, raw_interface);
+
+ /* Direction */
+ proto_tree_add_uint(tree, hf_catapult_dct2000_rawtraffic_direction,
+ tvb, 0, 0, raw_direction == 'r');
+
+ /* Payload is from $ to end of string */
+ int data_offset = 0;
+ for (unsigned int n=0; n < strlen(string); n++) {
+ if (string[n] == '$') {
+ data_offset = n;
+ break;
+ }
+ }
+
+ /* Convert data to hex. */
+ static guint8 eth_data[36000];
+ int idx, m;
+ for (idx=0, m=data_offset+1; idx<36000 && string[m] != '\0'; m+=2, idx++) {
+ eth_data[idx] = (hex_from_char(string[m]) << 4) + hex_from_char(string[m+1]);
+ }
+
+ /* Create tvb */
+ tvbuff_t *raw_traffic_tvb = tvb_new_real_data(eth_data, idx, idx);
+ add_new_data_source(pinfo, raw_traffic_tvb, "Raw-Traffic Payload");
+
+ /* PDU */
+ proto_tree_add_item(tree, hf_catapult_dct2000_rawtraffic_pdu, raw_traffic_tvb,
+ 0, tvb_reported_length(raw_traffic_tvb), ENC_NA);
+
+ /* Call the dissector! */
+ sub_dissector_result = call_dissector_only(eth_handle, raw_traffic_tvb, pinfo, tree, NULL);
+ }
+
return tvb_captured_length(tvb);
}
@@ -3261,6 +3474,8 @@ void proto_reg_handoff_catapult_dct2000(void)
mac_nr_handle = find_dissector("mac-nr");
nrup_handle = find_dissector("nrup");
+ eth_handle = find_dissector("eth_withoutfcs");
+ nrup_handle = find_dissector("nrup");
}
/****************************************/
@@ -3563,6 +3778,49 @@ void proto_register_catapult_dct2000(void)
}
},
+ { &hf_catapult_dct2000_security_mode_params,
+ { "Security Mode Params",
+ "dct2000.security-mode-params", FT_NONE, BASE_NONE, NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_catapult_dct2000_uplink_sec_mode,
+ { "Uplink Security Mode",
+ "dct2000.uplink-security-mode", FT_UINT8, BASE_DEC, VALS(security_mode_vals), 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_catapult_dct2000_downlink_sec_mode,
+ { "Downlink Security Mode",
+ "dct2000.downlink-security-mode", FT_UINT8, BASE_DEC, VALS(security_mode_vals), 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_catapult_dct2000_ciphering_algorithm,
+ { "Ciphering Algorithm",
+ "dct2000.ciphering-algorithm", FT_UINT8, BASE_DEC, VALS(ciphering_algorithm_vals), 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_catapult_dct2000_ciphering_key,
+ { "Ciphering Key",
+ "dct2000.ciphering-key", FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_catapult_dct2000_integrity_algorithm,
+ { "Integrity Algorithm",
+ "dct2000.integrity-algorithm", FT_UINT8, BASE_DEC, VALS(integrity_algorithm_vals), 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_catapult_dct2000_integrity_key,
+ { "Integrity Key",
+ "dct2000.integrity-key", FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+
{ &hf_catapult_dct2000_lte_ccpri_opcode,
{ "CCPRI opcode",
"dct2000.lte.ccpri.opcode", FT_UINT8, BASE_DEC, VALS(ccpri_opcode_vals), 0x0,
@@ -3690,6 +3948,25 @@ void proto_register_catapult_dct2000(void)
"dct2000.number-of-padding-bits", FT_UINT8, BASE_DEC, NULL, 0x0,
NULL, HFILL
}
+ },
+
+ { &hf_catapult_dct2000_rawtraffic_interface,
+ { "Interface",
+ "dct2000.rawtraffic.interface", FT_UINT8, BASE_DEC, NULL, 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_catapult_dct2000_rawtraffic_direction,
+ { "Direction",
+ "dct2000.rawtraffic.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
+ NULL, HFILL
+ }
+ },
+ { &hf_catapult_dct2000_rawtraffic_pdu,
+ { "PDU",
+ "dct2000.rawtraffic.pdu", FT_BYTES, BASE_NONE, NULL, 0x0,
+ NULL, HFILL
+ }
}
};
@@ -3698,7 +3975,8 @@ void proto_register_catapult_dct2000(void)
&ett_catapult_dct2000,
&ett_catapult_dct2000_ipprim,
&ett_catapult_dct2000_sctpprim,
- &ett_catapult_dct2000_tty
+ &ett_catapult_dct2000_tty,
+ &ett_catapult_dct2000_security_mode_params
};
static ei_register_info ei[] = {