aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Mathieson <martin.r.mathieson@googlemail.com>2014-01-06 18:18:04 +0000
committerMartin Mathieson <martin.r.mathieson@googlemail.com>2014-01-06 18:18:04 +0000
commitf026d8a8076c24f42192c1540b0e348a8292f3fc (patch)
tree1be35f1b077ee745345ec8b4760a94399c7c0e33
parent7bf44dcd97c60ae359b11ca91ef45868869c3831 (diff)
Call deciphering and integrity checking appropriately for
SecurityModeCommand and SecurityModeResponse. Also show when integrity has been checked and found to be correct. svn path=/trunk/; revision=54620
-rw-r--r--epan/dissectors/packet-pdcp-lte.c34
-rw-r--r--epan/dissectors/packet-pdcp-lte.h2
2 files changed, 30 insertions, 6 deletions
diff --git a/epan/dissectors/packet-pdcp-lte.c b/epan/dissectors/packet-pdcp-lte.c
index 6e799d6dcb..80c21fef66 100644
--- a/epan/dissectors/packet-pdcp-lte.c
+++ b/epan/dissectors/packet-pdcp-lte.c
@@ -1322,19 +1322,32 @@ static gboolean dissect_pdcp_lte_heur(tvbuff_t *tvb, packet_info *pinfo,
/* Called from control protocol to configure security algorithms for the given UE */
void set_pdcp_lte_security_algorithms(guint16 ueid, pdcp_security_info_t *security_info)
{
+ /* Use for this frame so can check integrity on SecurityCommandRequest frame */
+ /* N.B. won't work for internal, non-RRC signalling methods... */
+ pdcp_security_info_t *p_frame_security;
+
/* Copy security struct */
pdcp_security_info_t *p_security = wmem_new(wmem_file_scope(), pdcp_security_info_t);
*p_security = *security_info;
/* And add into security table */
g_hash_table_insert(pdcp_security_hash, GUINT_TO_POINTER((guint)ueid), p_security);
+
+ /* Add an entry for this PDU already to use these settings, as otherwise it won't be present
+ when we query it on the first pass. */
+ p_frame_security = wmem_new(wmem_file_scope(), pdcp_security_info_t);
+ *p_frame_security = *p_security;
+ g_hash_table_insert(pdcp_security_result_hash,
+ get_ueid_frame_hash_key(ueid, security_info->configuration_frame, TRUE),
+ p_frame_security);
}
#if HAVE_LIBGCRYPT
/* Decipher payload if algorithm is supported and plausible inputs are available */
static tvbuff_t *decipher_payload(tvbuff_t *tvb, packet_info *pinfo, int *offset,
pdu_security_settings_t *pdu_security_settings,
- enum pdcp_plane plane, gboolean *deciphered)
+ enum pdcp_plane plane, gboolean will_be_deciphered,
+ gboolean *deciphered)
{
unsigned char ctr_block[16];
gcry_cipher_hd_t cypher_hd;
@@ -1359,6 +1372,11 @@ static tvbuff_t *decipher_payload(tvbuff_t *tvb, packet_info *pinfo, int *offset
return tvb;
}
+ /* Don't decipher if not yet past SecurityModeResponse */
+ if (!will_be_deciphered) {
+ return tvb;
+ }
+
/* Set CTR */
memset(ctr_block, 0, 16);
/* Only first 5 bytes set */
@@ -1419,7 +1437,8 @@ static tvbuff_t *decipher_payload(tvbuff_t *tvb, packet_info *pinfo, int *offset
#else
static tvbuff_t *decipher_payload(tvbuff_t *tvb, packet_info *pinfo _U_, int *offset _U_,
pdu_security_settings_t *pdu_security_settings _U_,
- enum pdcp_plane plane _U_, gboolean *deciphered _U_)
+ enum pdcp_plane plane _U_, gboolean will_be_deciphered _U_,
+ gboolean *deciphered _U_)
{
return tvb;
}
@@ -1608,10 +1627,11 @@ static void dissect_pdcp_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree
if (!pinfo->fd->flags.visited) {
/* Look up current state by UEID */
current_security = (pdcp_security_info_t*)g_hash_table_lookup(pdcp_security_hash,
- GUINT_TO_POINTER((guint)p_pdcp_info->ueid));
+ GUINT_TO_POINTER((guint)p_pdcp_info->ueid));
if (current_security != NULL) {
/* Store any result for this frame in the result table */
pdcp_security_info_t *security_to_store = wmem_new(wmem_file_scope(), pdcp_security_info_t);
+ /* Take a deep copy of the settings */
*security_to_store = *current_security;
g_hash_table_insert(pdcp_security_result_hash,
get_ueid_frame_hash_key(p_pdcp_info->ueid, pinfo->fd->num, TRUE),
@@ -1887,7 +1907,8 @@ static void dissect_pdcp_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree
/* Check pdu_security_settings - may need to do deciphering before calling
further dissectors on payload */
- payload_tvb = decipher_payload(tvb, pinfo, &offset, &pdu_security_settings, p_pdcp_info->plane, &payload_deciphered);
+ payload_tvb = decipher_payload(tvb, pinfo, &offset, &pdu_security_settings, p_pdcp_info->plane,
+ pdu_security ? pdu_security->seen_next_ul_pdu: FALSE, &payload_deciphered);
if (p_pdcp_info->plane == SIGNALING_PLANE) {
guint32 data_length;
@@ -1903,7 +1924,7 @@ static void dissect_pdcp_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree
}
/* RRC data is all but last 4 bytes.
- Call lte-rrc dissector (according to direction and channel type) */
+ Call lte-rrc dissector (according to direction and channel type) if we have valid data */
if ((global_pdcp_dissect_signalling_plane_as_rrc) &&
((pdu_security == NULL) || (pdu_security->ciphering == 0) || payload_deciphered || !pdu_security->seen_next_ul_pdu)){
/* Get appropriate dissector handle */
@@ -1960,6 +1981,9 @@ static void dissect_pdcp_lte(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree
"MAC-I Digest wrong expected %08x but found %08x",
calculated_digest, mac);
}
+ else {
+ proto_item_append_text(mac_ti, " [Matches calculated result]");
+ }
}
col_append_fstr(pinfo->cinfo, COL_INFO, " MAC=0x%08x (%u bytes data)",
diff --git a/epan/dissectors/packet-pdcp-lte.h b/epan/dissectors/packet-pdcp-lte.h
index ed4f3b1d1b..b10cdda65b 100644
--- a/epan/dissectors/packet-pdcp-lte.h
+++ b/epan/dissectors/packet-pdcp-lte.h
@@ -60,7 +60,7 @@ enum security_ciphering_algorithm_e { eea0, eea1, eea2 };
typedef struct pdcp_security_info_t
{
guint32 configuration_frame;
- gboolean seen_next_ul_pdu;
+ gboolean seen_next_ul_pdu; /* i.e. have we seen SecurityModeResponse */
enum security_integrity_algorithm_e integrity;
enum security_ciphering_algorithm_e ciphering;
} pdcp_security_info_t;