diff options
Diffstat (limited to 'epan/dissectors/packet-ieee80211.c')
-rw-r--r-- | epan/dissectors/packet-ieee80211.c | 99 |
1 files changed, 96 insertions, 3 deletions
diff --git a/epan/dissectors/packet-ieee80211.c b/epan/dissectors/packet-ieee80211.c index cb005a9bc9..5d21443462 100644 --- a/epan/dissectors/packet-ieee80211.c +++ b/epan/dissectors/packet-ieee80211.c @@ -82,6 +82,15 @@ void proto_register_ieee80211(void); void proto_reg_handoff_ieee80211(void); void proto_register_wlan_rsna_eapol(void); +typedef struct { + DOT11DECRYPT_KEY_ITEM used_key; + guint keydata_len; + guint8 keydata[0]; /* dynamic size */ +} proto_eapol_keydata_t; + +#define PROTO_EAPOL_KEYDATA_OFFSET (offsetof(proto_eapol_keydata_t, keydata)) +#define PROTO_EAPOL_MAX_SIZE (DOT11DECRYPT_MAX_CAPLEN + PROTO_EAPOL_KEYDATA_OFFSET) + extern value_string_ext eap_type_vals_ext; /* from packet-eap.c */ #ifndef roundup2 @@ -234,6 +243,7 @@ typedef struct mimo_control #define IS_DMG_KEY 1 #define IS_AP_KEY 2 #define IS_CTRL_GRANT_OR_GRANT_ACK_KEY 2 +#define EAPOL_KEY 3 /* ************************************************************************* */ /* Define some very useful macros that are used to analyze frame types etc. */ /* ************************************************************************* */ @@ -3900,6 +3910,8 @@ static int hf_ieee80211_ccmp_extiv = -1; static int hf_ieee80211_wep_key = -1; static int hf_ieee80211_wep_icv = -1; static int hf_ieee80211_fc_analysis_pmk = -1; +static int hf_ieee80211_fc_analysis_kck = -1; +static int hf_ieee80211_fc_analysis_kek = -1; static int hf_ieee80211_fc_analysis_tk = -1; static int hf_ieee80211_fc_analysis_gtk = -1; @@ -24221,8 +24233,17 @@ dissect_ieee80211_common(tvbuff_t *tvb, packet_info *pinfo, if (enable_decryption && !pinfo->fd->flags.visited) { const guint8 *enc_data = tvb_get_ptr(tvb, 0, hdr_len+reported_len); /* The processing will take care of 4-way handshake sessions for WPA and WPA2 decryption */ - Dot11DecryptPacketProcess(&dot11decrypt_ctx, enc_data, hdr_len, hdr_len+reported_len, NULL, 0, NULL, TRUE); - + proto_eapol_keydata_t *eapol; + eapol = (proto_eapol_keydata_t *)wmem_alloc(wmem_file_scope(), PROTO_EAPOL_MAX_SIZE); + gint ret = Dot11DecryptPacketProcess(&dot11decrypt_ctx, enc_data, hdr_len, hdr_len+reported_len, + eapol->keydata, &eapol->keydata_len, &eapol->used_key, TRUE); + if (ret == DOT11DECRYPT_RET_SUCCESS_HANDSHAKE && eapol->keydata_len > 0) { + /* XXX realloc data for eapol to actual size used? */ + /* Save decrypted eapol keydata for rsna dissector */ + p_add_proto_data(wmem_file_scope(), pinfo, proto_wlan, EAPOL_KEY, eapol); + } else { + wmem_free(wmem_file_scope(), eapol); + } } /* * No-data frames don't have a body. @@ -25037,6 +25058,7 @@ static int hf_wlan_rsna_eapol_wpa_keydes_id = -1; static int hf_wlan_rsna_eapol_wpa_keydes_mic = -1; static int hf_wlan_rsna_eapol_wpa_keydes_data_len = -1; static int hf_wlan_rsna_eapol_wpa_keydes_data = -1; +static int hf_wlan_rsna_eapol_wpa_keydes_padding = -1; static gint ett_keyinfo = -1; static gint ett_wlan_rsna_eapol_keydes_data = -1; @@ -25108,6 +25130,22 @@ static guint16 get_mic_len(guint32 akm_suite) { } static int +keydata_padding_len(tvbuff_t *tvb) +{ + int keydata_len = tvb_reported_length(tvb); + int len_no_padding = keydata_len; + const guint8 *keydata = tvb_get_ptr(tvb, 0, keydata_len); + while (len_no_padding > 0 && (keydata[len_no_padding - 1] == 0x00)) { + len_no_padding--; + } + if (len_no_padding > 0 && keydata[len_no_padding - 1] == 0xdd) { + len_no_padding--; + return keydata_len - len_no_padding; + } + return 0; +} + +static int dissect_wlan_rsna_eapol_wpa_or_rsn_key(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U_) { int offset = 0; @@ -25226,6 +25264,7 @@ dissect_wlan_rsna_eapol_wpa_or_rsn_key(tvbuff_t *tvb, packet_info *pinfo, proto_ PROTO_ITEM_SET_GENERATED(ti); + guint16 keydes_version = tvb_get_ntohs(tvb, offset) & KEY_INFO_KEYDES_VERSION_MASK; proto_tree_add_bitmask_with_flags(tree, tvb, offset, hf_wlan_rsna_eapol_wpa_keydes_keyinfo, ett_keyinfo, wlan_rsna_eapol_wpa_keydes_keyinfo, ENC_BIG_ENDIAN, BMT_NO_APPEND); @@ -25266,9 +25305,48 @@ dissect_wlan_rsna_eapol_wpa_or_rsn_key(tvbuff_t *tvb, packet_info *pinfo, proto_ !(keyinfo & KEY_INFO_KEY_TYPE_MASK)) { /* RSN: EAPOL-Key Key Data is encrypted. * WPA: Group Keys use encrypted Key Data. - * Cannot parse this without knowing the key. + * Decryption engine has already tried to decrypt this. If decrypted it's + * stored in EAPOL_KEY proto data. * IEEE 802.11i-2004 8.5.2. */ + proto_eapol_keydata_t *eapol; + eapol = (proto_eapol_keydata_t*)p_get_proto_data(wmem_file_scope(), pinfo, proto_wlan, EAPOL_KEY); + + if (eapol) { + int keydata_len = eapol->keydata_len; + tvbuff_t *next_tvb = tvb_new_child_real_data(tvb, eapol->keydata, + keydata_len, keydata_len); + + char out_buff[SHORT_STR]; + keydes_tree = proto_item_add_subtree(ti, ett_wlan_rsna_eapol_keydes_data); + + if (keydes_version == KEYDES_VER_TYPE1) { + add_new_data_source(pinfo, next_tvb, "Decrypted RC4 keydata"); + } else if (keydes_version == KEYDES_VER_TYPE2) { + add_new_data_source(pinfo, next_tvb, "Decrypted AES keydata"); + int padding_len = keydata_padding_len(next_tvb); + ieee_80211_add_tagged_parameters(next_tvb, 0, pinfo, keydes_tree, + keydata_len - padding_len, + -1, NULL); + if (padding_len) { + proto_tree_add_item(keydes_tree, hf_wlan_rsna_eapol_wpa_keydes_padding, + next_tvb, keydata_len - padding_len, + padding_len, ENC_NA); + } + } else { + /* TODO? */ + } + /* Also add the PTK used to to decrypt and validate the keydata. */ + bytes_to_hexstr(out_buff, eapol->used_key.KeyData.Wpa.Ptk, 16); /* KCK is stored in PTK at offset 0 */ + out_buff[2*16] = '\0'; + ti = proto_tree_add_string(keydes_tree, hf_ieee80211_fc_analysis_kck, tvb, 0, 0, out_buff); + PROTO_ITEM_SET_GENERATED(ti); + + bytes_to_hexstr(out_buff, eapol->used_key.KeyData.Wpa.Ptk+16, 16); /* KEK is stored in PTK at offset 16 */ + out_buff[2*16] = '\0'; + ti = proto_tree_add_string(keydes_tree, hf_ieee80211_fc_analysis_kek, tvb, 0, 0, out_buff); + PROTO_ITEM_SET_GENERATED(ti); + } } else { keydes_tree = proto_item_add_subtree(ti, ett_wlan_rsna_eapol_keydes_data); ieee_80211_add_tagged_parameters(tvb, offset, pinfo, keydes_tree, @@ -25870,6 +25948,16 @@ proto_register_ieee80211(void) FT_STRING, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + {&hf_ieee80211_fc_analysis_kck, + {"KCK", "wlan.analysis.kck", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + + {&hf_ieee80211_fc_analysis_kek, + {"KEK", "wlan.analysis.kek", + FT_STRING, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, + {&hf_ieee80211_fc_analysis_tk, {"TK", "wlan.analysis.tk", FT_STRING, BASE_NONE, NULL, 0x0, @@ -36957,6 +37045,11 @@ proto_register_wlan_rsna_eapol(void) {"WPA Key Data", "wlan_rsna_eapol.keydes.data", FT_BYTES, BASE_NONE, NULL, 0x0, NULL, HFILL }}, + + {&hf_wlan_rsna_eapol_wpa_keydes_padding, + {"WPA Key Data Padding", "wlan_rsna_eapol.keydes.padding", + FT_BYTES, BASE_NONE, NULL, 0x0, + NULL, HFILL }}, }; static gint *tree_array[] = { |