aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-pdcp-lte.c
diff options
context:
space:
mode:
authorMartin Mathieson <martin.mathieson@keysight.com>2021-01-02 16:09:36 +0000
committerMartin Mathieson <martin.r.mathieson@googlemail.com>2021-01-02 20:59:00 +0000
commit1b81052f9e8ec335b8685e2a95e6dbeb2700e42f (patch)
treef67dc8ddbd3d8af396cbdbeef10e19130618cd4d /epan/dissectors/packet-pdcp-lte.c
parent3506735f0873fa720e9b3a6d800367423beba27b (diff)
PDCP LTE: Check configured key strings
Diffstat (limited to 'epan/dissectors/packet-pdcp-lte.c')
-rw-r--r--epan/dissectors/packet-pdcp-lte.c90
1 files changed, 67 insertions, 23 deletions
diff --git a/epan/dissectors/packet-pdcp-lte.c b/epan/dissectors/packet-pdcp-lte.c
index 188b0a33c8..a518a358b9 100644
--- a/epan/dissectors/packet-pdcp-lte.c
+++ b/epan/dissectors/packet-pdcp-lte.c
@@ -19,6 +19,7 @@
#include <epan/proto_data.h>
#include <wsutil/wsgcrypt.h>
+#include <wsutil/report_message.h>
/* Define this symbol if you have a working implementation of SNOW3G f8() and f9() available.
Note that the use of this algorithm is restricted, and that an administrative charge
@@ -190,8 +191,9 @@ static guchar hex_ascii_to_binary(gchar c)
else if ((c >= 'A') && (c <= 'F')) {
return 10 + c - 'A';
}
- else
+ else {
return 0;
+ }
}
static void* uat_ue_keys_record_copy_cb(void* n, const void* o, size_t siz _U_) {
@@ -206,15 +208,23 @@ static void* uat_ue_keys_record_copy_cb(void* n, const void* o, size_t siz _U_)
return new_rec;
}
-/* If raw_string is a valid key, set check_string & return TRUE */
-static gboolean check_valid_key_string(const char* raw_string, char* checked_string)
+/* If raw_string is a valid key, set check_string & return TRUE. Can be spaced out with ' ' or '-' */
+static gboolean check_valid_key_string(const char* raw_string, char* checked_string, char **error)
{
guint n;
guint written = 0;
guint length = (gint)strlen(raw_string);
+ char error_str[256];
+
/* Can't be valid if not long enough. */
if (length < 32) {
+ if (length > 0) {
+ g_snprintf(error_str, 256, "PDCP LTE: Invalid key string (%s) - should include 32 ASCII hex characters (16 bytes) but only %u chars given",
+ raw_string, length);
+ *error = g_strdup(error_str);
+ }
+
return FALSE;
}
@@ -233,21 +243,36 @@ static gboolean check_valid_key_string(const char* raw_string, char* checked_str
checked_string[written++] = c;
}
else {
+ g_snprintf(error_str, 256, "PDCP-LTE: Invalid char '%c' given in key", c);
+ *error = g_strdup(error_str);
return FALSE;
}
}
/* Must have found exactly 32 hex ascii chars for 16-byte key */
- return (written == 32);
+ if (n<length) {
+ g_snprintf(error_str, 256, "PDCP-LTE: Key (%s) should contain 32 hex characters (16 bytes) but more detected", raw_string);
+ *error = g_strdup(error_str);
+ return FALSE;
+ }
+ if (written != 32) {
+ g_snprintf(error_str, 256, "PDCP-LTE: Key (%s) should contain 32 hex characters (16 bytes) but %u detected", raw_string, written);
+ *error = g_strdup(error_str);
+ return FALSE;
+ }
+ else {
+ return TRUE;
+ }
+
}
/* Write binary key by converting each nibble from the string version */
-static void update_key_from_string(const char *stringKey, guint8 *binaryKey, gboolean *pKeyOK)
+static void update_key_from_string(const char *stringKey, guint8 *binaryKey, gboolean *pKeyOK, char **error)
{
int n;
char cleanString[32];
- if (!check_valid_key_string(stringKey, cleanString)) {
+ if (!check_valid_key_string(stringKey, cleanString, error)) {
*pKeyOK = FALSE;
}
else {
@@ -260,20 +285,20 @@ static void update_key_from_string(const char *stringKey, guint8 *binaryKey, gbo
}
/* Update by checking whether the 3 key strings are valid or not, and storing result */
-static gboolean uat_ue_keys_record_update_cb(void* record, char** error _U_) {
+static gboolean uat_ue_keys_record_update_cb(void* record, char** error) {
uat_ue_keys_record_t* rec = (uat_ue_keys_record_t *)record;
/* Check and convert RRC key */
- update_key_from_string(rec->rrcCipherKeyString, rec->rrcCipherBinaryKey, &rec->rrcCipherKeyOK);
+ update_key_from_string(rec->rrcCipherKeyString, rec->rrcCipherBinaryKey, &rec->rrcCipherKeyOK, error);
/* Check and convert User-plane key */
- update_key_from_string(rec->upCipherKeyString, rec->upCipherBinaryKey, &rec->upCipherKeyOK);
+ update_key_from_string(rec->upCipherKeyString, rec->upCipherBinaryKey, &rec->upCipherKeyOK, error);
/* Check and convert Integrity key */
- update_key_from_string(rec->rrcIntegrityKeyString, rec->rrcIntegrityBinaryKey, &rec->rrcIntegrityKeyOK);
+ update_key_from_string(rec->rrcIntegrityKeyString, rec->rrcIntegrityBinaryKey, &rec->rrcIntegrityKeyOK, error);
- /* Return TRUE regardless, as user might only specify one, or get it wrong and want to edit it later */
- return TRUE;
+ /* Return TRUE only if *error has not been set by checking code. */
+ return *error == NULL;
}
/* Free heap parts of record */
@@ -299,6 +324,8 @@ static wmem_map_t *pdcp_security_key_hash = NULL;
void set_pdcp_lte_rrc_ciphering_key(guint16 ueid, const char *key)
{
+ char **err = NULL;
+
/* Get or create struct for this UE */
uat_ue_keys_record_t *key_record = (uat_ue_keys_record_t*)wmem_map_lookup(pdcp_security_key_hash,
GUINT_TO_POINTER((guint)ueid));
@@ -311,11 +338,17 @@ void set_pdcp_lte_rrc_ciphering_key(guint16 ueid, const char *key)
/* Check and convert RRC key */
key_record->rrcCipherKeyString = g_strdup(key);
- update_key_from_string(key_record->rrcCipherKeyString, key_record->rrcCipherBinaryKey, &key_record->rrcCipherKeyOK);
+ update_key_from_string(key_record->rrcCipherKeyString, key_record->rrcCipherBinaryKey, &key_record->rrcCipherKeyOK, err);
+ if (err) {
+ report_failure("%s: (RRC Ciphering Key)", *err);
+ g_free(*err);
+ }
}
void set_pdcp_lte_rrc_integrity_key(guint16 ueid, const char *key)
{
+ char **err = NULL;
+
/* Get or create struct for this UE */
uat_ue_keys_record_t *key_record = (uat_ue_keys_record_t*)wmem_map_lookup(pdcp_security_key_hash,
GUINT_TO_POINTER((guint)ueid));
@@ -328,11 +361,17 @@ void set_pdcp_lte_rrc_integrity_key(guint16 ueid, const char *key)
/* Check and convert RRC integrity key */
key_record->rrcIntegrityKeyString = g_strdup(key);
- update_key_from_string(key_record->rrcIntegrityKeyString, key_record->rrcIntegrityBinaryKey, &key_record->rrcIntegrityKeyOK);
+ update_key_from_string(key_record->rrcIntegrityKeyString, key_record->rrcIntegrityBinaryKey, &key_record->rrcIntegrityKeyOK, err);
+ if (err) {
+ report_failure("%s: (RRC Integrity Key)", *err);
+ g_free(*err);
+ }
}
void set_pdcp_lte_up_ciphering_key(guint16 ueid, const char *key)
{
+ char **err = NULL;
+
/* Get or create struct for this UE */
uat_ue_keys_record_t *key_record = (uat_ue_keys_record_t*)wmem_map_lookup(pdcp_security_key_hash,
GUINT_TO_POINTER((guint)ueid));
@@ -345,7 +384,11 @@ void set_pdcp_lte_up_ciphering_key(guint16 ueid, const char *key)
/* Check and convert UP key */
key_record->upCipherKeyString = g_strdup(key);
- update_key_from_string(key_record->upCipherKeyString, key_record->upCipherBinaryKey, &key_record->upCipherKeyOK);
+ update_key_from_string(key_record->upCipherKeyString, key_record->upCipherBinaryKey, &key_record->upCipherKeyOK, err);
+ if (err) {
+ report_failure("%s: (UserPlane Ciphering Key)", *err);
+ g_free(*err);
+ }
}
@@ -427,18 +470,18 @@ static const value_string control_pdu_type_vals[] = {
};
static const value_string integrity_algorithm_vals[] = {
- { 0, "EIA0 (NULL)" },
- { 1, "EIA1 (SNOW3G)" },
- { 2, "EIA2 (AES)" },
- { 3, "EIA3 (ZUC)" },
+ { eia0, "EIA0 (NULL)" },
+ { eia1, "EIA1 (SNOW3G)" },
+ { eia2, "EIA2 (AES)" },
+ { eia3, "EIA3 (ZUC)" },
{ 0, NULL }
};
static const value_string ciphering_algorithm_vals[] = {
- { 0, "EEA0 (NULL)" },
- { 1, "EEA1 (SNOW3G)" },
- { 2, "EEA2 (AES)" },
- { 3, "EEA3 (ZUC)" },
+ { eea0, "EEA0 (NULL)" },
+ { eea1, "EEA1 (SNOW3G)" },
+ { eea2, "EEA2 (AES)" },
+ { eea3, "EEA3 (ZUC)" },
{ 0, NULL }
};
@@ -1891,6 +1934,7 @@ static int dissect_pdcp_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
tvb, 0, 0, pdu_security->integrity);
proto_item_set_generated(ti);
+ /* Show algorithms in security root */
proto_item_append_text(security_ti, " (ciphering=%s, integrity=%s)",
val_to_str_const(pdu_security->ciphering, ciphering_algorithm_vals, "Unknown"),
val_to_str_const(pdu_security->integrity, integrity_algorithm_vals, "Unknown"));