aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMikael Kanstrup <mikael.kanstrup@sony.com>2019-04-03 14:53:02 +0200
committerAlexis La Goutte <alexis.lagoutte@gmail.com>2019-04-10 02:20:27 +0000
commit47361b27376641bbc6a7339c7540c5248a40f008 (patch)
treef6ab359059b6f7cc3b562791a38ece4fd236f003
parente64976d33af4d2e93db22cfd47a4ac95e345bc65 (diff)
ieee80211: Handle variable MIC length for FT IE
Also the MIC inside FT IE is variable length in coming IEEE 802.11 spec. According to IEEE 802.11 spec the MIC length is based on AKMS negotiated during (re)association phase. This is good as long as the capture file contains needed assoc frames. Though if association frames are missing the MIC length is unknown. As a backup try to use the AKMS found in current frame to determine MIC length. Handle this logic in a new function like this: MIC length is detemined by: 1. User overridden MIC length setting 2. AKMS negotiated during association phase (conversation) 3. AKMS from current frame 4. Default 16 bytes length. Also changes had to be done to the ieee80211_packet_data_t handling. This structure appears to be used as a temporary storage for data related to current frame. However data was stored in file scope making it impossible to know whether data was from current or another frame. This is fixed by changing to the pinfo pool. Bug: 15616 Change-Id: I521d440b47d71cbc94cd6c56714d21274c8dd23e Reviewed-on: https://code.wireshark.org/review/32693 Petri-Dish: Alexis La Goutte <alexis.lagoutte@gmail.com> Tested-by: Petri Dish Buildbot Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
-rw-r--r--epan/dissectors/packet-ieee80211.c221
-rw-r--r--epan/dissectors/packet-ieee80211.h3
2 files changed, 128 insertions, 96 deletions
diff --git a/epan/dissectors/packet-ieee80211.c b/epan/dissectors/packet-ieee80211.c
index 910827fa80..7d43db4487 100644
--- a/epan/dissectors/packet-ieee80211.c
+++ b/epan/dissectors/packet-ieee80211.c
@@ -244,6 +244,7 @@ typedef struct mimo_control
#define IS_AP_KEY 2
#define IS_CTRL_GRANT_OR_GRANT_ACK_KEY 2
#define EAPOL_KEY 3
+#define PACKET_DATA_KEY 4
/* ************************************************************************* */
/* Define some very useful macros that are used to analyze frame types etc. */
/* ************************************************************************* */
@@ -14480,6 +14481,17 @@ dissect_qos_capability(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int
return offset;
}
+static ieee80211_packet_data_t* get_or_create_packet_data(packet_info *pinfo) {
+ ieee80211_packet_data_t *packet_data =
+ (ieee80211_packet_data_t*)p_get_proto_data(pinfo->pool, pinfo, proto_wlan, PACKET_DATA_KEY);
+ if (!packet_data) {
+ packet_data = wmem_new(pinfo->pool, ieee80211_packet_data_t);
+ p_add_proto_data(pinfo->pool, pinfo, proto_wlan, PACKET_DATA_KEY, packet_data);
+ memset(packet_data, 0, sizeof(ieee80211_packet_data_t));
+ }
+ return packet_data;
+}
+
/* See ieee80211_rsn_keymgmt_vals */
static gboolean is_ft_akm_suite(guint32 akm_suite)
{
@@ -14591,6 +14603,9 @@ dissect_rsn_ie(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb,
rsn_akms_item = proto_tree_add_item(tree, hf_ieee80211_rsn_akms_list, tvb, offset, akms_count * 4, ENC_NA);
rsn_akms_tree = proto_item_add_subtree(rsn_akms_item, ett_rsn_akms_tree);
+
+ ieee80211_packet_data_t *packet_data = get_or_create_packet_data(pinfo);
+
for (ii = 0; ii < akms_count; ii++)
{
rsn_sub_akms_item = proto_tree_add_item(rsn_akms_tree, hf_ieee80211_rsn_akms, tvb, offset, 4, ENC_BIG_ENDIAN);
@@ -14603,6 +14618,7 @@ dissect_rsn_ie(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb,
proto_tree_add_item(rsn_sub_akms_tree, hf_ieee80211_rsn_akms_80211_type, tvb, offset+3, 1, ENC_LITTLE_ENDIAN);
proto_item_append_text(rsn_akms_item, " %s", rsn_akms_return(tvb_get_ntohl(tvb, offset)));
+ packet_data->last_akm_suite = tvb_get_ntohl(tvb, offset);
if (association_sanity_check) {
guint32 akm_suite = tvb_get_ntohl(tvb, offset);
association_sanity_check->last_akm_suite = akm_suite;
@@ -15158,11 +15174,113 @@ dissect_mobility_domain(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, voi
return tvb_captured_length(tvb);
}
+static guint16 get_mic_len_owe(guint16 group) {
+ switch(group) {
+ // FFC, len(p) <= 2048
+ case 1:
+ case 2:
+ case 5:
+ case 14:
+ case 22:
+ case 23:
+ case 24:
+ // ECC, len(p) <= 256
+ case 19:
+ case 25:
+ case 26:
+ case 27:
+ case 28:
+ case 31:
+ // HMAC-SHA-256
+ return 16;
+
+ // FFC, 2048 < len(p) <= 3072
+ case 15:
+ // ECC, 256 < len(p) <= 384
+ case 20:
+ case 29:
+ // HMAC-SHA-384
+ return 24;
+
+ // FCC, 3072 < len(p)
+ case 16:
+ case 17:
+ case 18:
+ // ECC, 384 < len(p)
+ case 21:
+ case 30:
+ case 32:
+ // HMAC-SHA-512
+ return 32;
+
+ default:
+ return 16;
+ }
+}
+
+static guint16 get_mic_len(guint32 akm_suite) {
+ switch(akm_suite) {
+ case AKMS_WPA_SHA384_SUITEB:
+ case AKMS_FT_IEEE802_1X_SHA384:
+ // HMAC-SHA-384
+ return 24;
+
+ case AKMS_FILS_SHA256:
+ case AKMS_FILS_SHA384:
+ case AKMS_FT_FILS_SHA256:
+ case AKMS_FT_FILS_SHA384:
+ // AES-SIV-256 and AES-SIV-512
+ return 0;
+
+ default:
+ // HMAC-SHA-1-128, AES-128-CMAC, HMAC-SHA-256
+ return 16;
+ }
+}
+
+static guint16 determine_mic_len(packet_info *pinfo, gboolean assoc_frame) {
+ guint16 eapol_key_mic_len = 16; /* Default MIC length */
+ conversation_t *conversation = find_conversation_pinfo(pinfo, 0);
+ ieee80211_conversation_data_t *conversation_data = NULL;
+ ieee80211_packet_data_t *packet_data =
+ (ieee80211_packet_data_t*)p_get_proto_data(pinfo->pool, pinfo, proto_wlan, PACKET_DATA_KEY);
+ if (conversation) {
+ conversation_data = (ieee80211_conversation_data_t*)conversation_get_proto_data(conversation, proto_wlan);
+ }
+
+ if (wlan_key_mic_len_enable) {
+ /* 1st - Use user overridden MIC length setting */
+ eapol_key_mic_len = wlan_key_mic_len;
+ }
+ else if (conversation_data && !assoc_frame) {
+ /* 2nd - Use AKMS negotiated during association to determine MIC length */
+ if (conversation_data->last_akm_suite == AKMS_OWE) {
+ /* For OWE the the length of MIC depends on the selected group */
+ eapol_key_mic_len = get_mic_len_owe(conversation_data->owe_group);
+ }
+ else {
+ eapol_key_mic_len = get_mic_len(conversation_data->last_akm_suite);
+ }
+ }
+ else if (packet_data) {
+ /* 3rd - Use AKMS from current packet to determine MIC length */
+ if (packet_data->last_akm_suite == AKMS_OWE) {
+ /* For OWE the the length of MIC depends on the selected group */
+ eapol_key_mic_len = get_mic_len_owe(packet_data->owe_group);
+ }
+ else {
+ eapol_key_mic_len = get_mic_len(packet_data->last_akm_suite);
+ }
+ }
+ return eapol_key_mic_len;
+}
+
static int
dissect_fast_bss_transition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
{
int tag_len = tvb_reported_length(tvb);
ieee80211_tagged_field_data_t* field_data = (ieee80211_tagged_field_data_t*)data;
+ gboolean assoc_frame = field_data->sanity_check != NULL;
int offset = 0;
if (tag_len < 82) {
expert_add_info_format(pinfo, field_data->item_tag_length, &ei_ieee80211_tag_length,
@@ -15175,9 +15293,11 @@ dissect_fast_bss_transition(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
proto_tree_add_item(tree, hf_ieee80211_tag_ft_element_count,
tvb, offset, 2, ENC_LITTLE_ENDIAN);
offset += 2;
+
+ int mic_len = determine_mic_len(pinfo, assoc_frame);
proto_tree_add_item(tree, hf_ieee80211_tag_ft_mic,
- tvb, offset, 16, ENC_NA);
- offset += 16;
+ tvb, offset, mic_len, ENC_NA);
+ offset += mic_len;
proto_tree_add_item(tree, hf_ieee80211_tag_ft_anonce,
tvb, offset, 32, ENC_NA);
offset += 32;
@@ -20734,7 +20854,7 @@ static const value_string owe_dh_parameter_group_vals[] = {
};
static int
-dissect_owe_dh_parameter(tvbuff_t *tvb, packet_info *pinfo _U_,
+dissect_owe_dh_parameter(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *tree, int offset, int len _U_, association_sanity_check_t* sanity_check)
{
if (len < 2) {
@@ -20744,6 +20864,8 @@ dissect_owe_dh_parameter(tvbuff_t *tvb, packet_info *pinfo _U_,
return offset + len;
}
+ ieee80211_packet_data_t *packet_data = get_or_create_packet_data(pinfo);
+ packet_data->owe_group = tvb_get_guint16(tvb, offset, ENC_LITTLE_ENDIAN);
if (sanity_check != NULL) {
sanity_check->owe_group = tvb_get_guint16(tvb, offset, ENC_LITTLE_ENDIAN);
}
@@ -25357,70 +25479,6 @@ static gint ett_wlan_rsna_eapol_keydes_data = -1;
static const true_false_string keyinfo_key_type_tfs = { "Pairwise Key", "Group Key" };
-static guint16 get_mic_len_owe(guint16 group) {
- switch(group) {
- // FFC, len(p) <= 2048
- case 1:
- case 2:
- case 5:
- case 14:
- case 22:
- case 23:
- case 24:
- // ECC, len(p) <= 256
- case 19:
- case 25:
- case 26:
- case 27:
- case 28:
- case 31:
- // HMAC-SHA-256
- return 16;
-
- // FFC, 2048 < len(p) <= 3072
- case 15:
- // ECC, 256 < len(p) <= 384
- case 20:
- case 29:
- // HMAC-SHA-384
- return 24;
-
- // FCC, 3072 < len(p)
- case 16:
- case 17:
- case 18:
- // ECC, 384 < len(p)
- case 21:
- case 30:
- case 32:
- // HMAC-SHA-512
- return 32;
-
- default:
- return 16;
- }
-}
-
-static guint16 get_mic_len(guint32 akm_suite) {
- switch(akm_suite) {
- case AKMS_WPA_SHA384_SUITEB:
- case AKMS_FT_IEEE802_1X_SHA384:
- // HMAC-SHA-384
- return 24;
-
- case AKMS_FILS_SHA256:
- case AKMS_FILS_SHA384:
- case AKMS_FT_FILS_SHA256:
- case AKMS_FT_FILS_SHA384:
- // AES-SIV-256 and AES-SIV-512
- return 0;
-
- default:
- // HMAC-SHA-1-128, AES-128-CMAC, HMAC-SHA-256
- return 16;
- }
-}
-
static int
keydata_padding_len(tvbuff_t *tvb)
{
@@ -25460,34 +25518,7 @@ dissect_wlan_rsna_eapol_wpa_or_rsn_key(tvbuff_t *tvb, packet_info *pinfo, proto_
NULL
};
guint16 eapol_data_offset = 76; /* 92 - 16 */
- guint16 eapol_key_mic_len = 16; // Default MIC length
-
- conversation_t *conversation = find_conversation_pinfo(pinfo, 0);
- ieee80211_packet_data_t *packet_data = (ieee80211_packet_data_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_wlan, 0);
-
- if (wlan_key_mic_len_enable) {
- eapol_key_mic_len = wlan_key_mic_len;
- } else if (packet_data) {
- eapol_key_mic_len = packet_data->mic_len;
- } else if (conversation) {
- ieee80211_conversation_data_t *conversation_data = (ieee80211_conversation_data_t*)conversation_get_proto_data(conversation, proto_wlan);
-
- if (conversation_data) {
- if (conversation_data->last_akm_suite == AKMS_OWE) {
- /* For OWE the the length of MIC depends on the selected group */
- eapol_key_mic_len = get_mic_len_owe(conversation_data->owe_group);
- } else {
- eapol_key_mic_len = get_mic_len(conversation_data->last_akm_suite);
- }
- }
- }
-
- if (!packet_data) {
- packet_data = wmem_new(wmem_file_scope(), ieee80211_packet_data_t);
- packet_data->mic_len = eapol_key_mic_len;
- p_add_proto_data(wmem_file_scope(), pinfo, proto_wlan, 0, packet_data);
- }
-
+ guint16 eapol_key_mic_len = determine_mic_len(pinfo, FALSE);
eapol_data_offset += eapol_key_mic_len;
/*
diff --git a/epan/dissectors/packet-ieee80211.h b/epan/dissectors/packet-ieee80211.h
index 3c6be5c4cc..49718f9006 100644
--- a/epan/dissectors/packet-ieee80211.h
+++ b/epan/dissectors/packet-ieee80211.h
@@ -37,7 +37,8 @@ typedef struct {
} ieee80211_conversation_data_t;
typedef struct {
- guint16 mic_len;
+ guint32 last_akm_suite;
+ guint16 owe_group;
} ieee80211_packet_data_t;
typedef struct ieee80211_tagged_field_data