forked from osmocom/wireshark
ieee80211: Extended Key ID support
Support Extended Key ID for Individually Addressed Frames from IEEE 802.11 - 2016. Extended Key ID allows unicast (PTK) keys to also use key ID 1 and has an additional RSN attribute "KeyID" in EAPOL #3. Add the additional attribute KeyID to the RSN parser, stop assuming unicast keys are only using key ID 0 and add a test case to verify Extended Key ID parsing and decoding. Change-Id: I43005c74df561be5524fa3738149781f50dafa14 Reviewed-on: https://code.wireshark.org/review/34883 Petri-Dish: Alexis La Goutte <alexis.lagoutte@gmail.com> Tested-by: Petri Dish Buildbot Reviewed-by: Jaap Keuter <jaap.keuter@xs4all.nl>
This commit is contained in:
parent
35615574e5
commit
e7acb32a5a
|
@ -984,13 +984,12 @@ INT Dot11DecryptPacketProcess(
|
|||
} else {
|
||||
DOT11DECRYPT_DEBUG_PRINT_LINE("Dot11DecryptPacketProcess", "TKIP or CCMP encryption", DOT11DECRYPT_DEBUG_LEVEL_3);
|
||||
|
||||
/* If index >= 1, then use the group key. This will not work if the AP is using
|
||||
/* If the destination is a multicast address use the group key. This will not work if the AP is using
|
||||
more than one group key simultaneously. I've not seen this in practice, however.
|
||||
Usually an AP will rotate between the two key index values of 1 and 2 whenever
|
||||
it needs to change the group key to be used. */
|
||||
if (DOT11DECRYPT_KEY_INDEX(data[offset+3])>=1){
|
||||
|
||||
DOT11DECRYPT_DEBUG_PRINT_LINE("Dot11DecryptPacketProcess", "The key index >= 1. This is encrypted with a group key.", DOT11DECRYPT_DEBUG_LEVEL_3);
|
||||
if (((const DOT11DECRYPT_MAC_FRAME_ADDR4 *)(data))->addr1[0] & 0x01) {
|
||||
DOT11DECRYPT_DEBUG_PRINT_LINE("Dot11DecryptPacketProcess", "Broadcast/Multicast address. This is encrypted with a group key.", DOT11DECRYPT_DEBUG_LEVEL_3);
|
||||
|
||||
/* force STA address to broadcast MAC so we load the SA for the groupkey */
|
||||
memcpy(id.sta, broadcast_mac, DOT11DECRYPT_MAC_LEN);
|
||||
|
|
|
@ -4671,6 +4671,7 @@ static int hf_ieee80211_rsn_cap_mfpr = -1;
|
|||
static int hf_ieee80211_rsn_cap_mfpc = -1;
|
||||
static int hf_ieee80211_rsn_cap_jmr = -1;
|
||||
static int hf_ieee80211_rsn_cap_peerkey = -1;
|
||||
static int hf_ieee80211_rsn_cap_extended_key_id_iaf = -1;
|
||||
static int hf_ieee80211_rsn_pmkid_count = -1;
|
||||
static int hf_ieee80211_rsn_pmkid_list = -1;
|
||||
static int hf_ieee80211_rsn_pmkid = -1;
|
||||
|
@ -4798,6 +4799,8 @@ static int hf_ieee80211_vs_aerohive_data = -1;
|
|||
static int hf_ieee80211_vs_mist_ap_name = -1;
|
||||
static int hf_ieee80211_vs_mist_data = -1;
|
||||
|
||||
static int hf_ieee80211_rsn_ie_ptk_keyid = -1;
|
||||
|
||||
static int hf_ieee80211_rsn_ie_gtk_keyid = -1;
|
||||
static int hf_ieee80211_rsn_ie_gtk_tx = -1;
|
||||
static int hf_ieee80211_rsn_ie_gtk_reserved1 = -1;
|
||||
|
@ -13808,6 +13811,15 @@ dissect_vendor_ie_rsn(proto_item * item, proto_tree * tree, tvbuff_t * tvb, int
|
|||
proto_item_append_text(item, ": RSN IGTK");
|
||||
break;
|
||||
}
|
||||
case 10:
|
||||
{
|
||||
/* IEEE 802.11 - 2016 / Key Data Encapsulation / Data Type=10 - KeyID
|
||||
* This is only used within EAPOL-Key frame Key Data when using Extended Key ID */
|
||||
offset += 1;
|
||||
proto_tree_add_item(tree, hf_ieee80211_rsn_ie_ptk_keyid, tvb, offset, 1, ENC_LITTLE_ENDIAN);
|
||||
proto_item_append_text(item, ": RSN PTK");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
proto_tree_add_item(tree, hf_ieee80211_rsn_ie_unknown, tvb, offset, tag_len, ENC_NA);
|
||||
proto_item_append_text(item, ": RSN UNKNOWN");
|
||||
|
@ -14522,6 +14534,7 @@ dissect_rsn_ie(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb,
|
|||
&hf_ieee80211_rsn_cap_mfpc,
|
||||
&hf_ieee80211_rsn_cap_jmr,
|
||||
&hf_ieee80211_rsn_cap_peerkey,
|
||||
&hf_ieee80211_rsn_cap_extended_key_id_iaf,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
@ -24945,7 +24958,7 @@ dissect_ieee80211_common(tvbuff_t *tvb, packet_info *pinfo,
|
|||
bytes_to_hexstr(out_buff, used_key.KeyData.Wpa.Ptk+32, DOT11DECRYPT_TK_LEN); /* TK is stored in PTK at offset 32 bytes and 16 bytes long */
|
||||
out_buff[2*DOT11DECRYPT_TK_LEN] = '\0';
|
||||
|
||||
if (key == 0) { /* encrypted with pairwise key */
|
||||
if (!tvb_get_bits8(tvb, 39, 1)) { /* RA is unicast, encrypted with pairwise key */
|
||||
ti = proto_tree_add_string(wep_tree, hf_ieee80211_fc_analysis_tk, tvb, 0, 0, out_buff);
|
||||
proto_item_set_generated(ti);
|
||||
|
||||
|
@ -30714,6 +30727,11 @@ proto_register_ieee80211(void)
|
|||
FT_BOOLEAN, 16, NULL, 0x0200,
|
||||
NULL, HFILL }},
|
||||
|
||||
{&hf_ieee80211_rsn_cap_extended_key_id_iaf,
|
||||
{"Extended Key ID for Individually Addressed Frames",
|
||||
"wlan.rsn.capabilities.extended_key_id_iaf",
|
||||
FT_BOOLEAN, 16, TFS(&tfs_supported_not_supported), 0x2000, NULL, HFILL }},
|
||||
|
||||
{&hf_ieee80211_rsn_pmkid_count,
|
||||
{"PMKID Count", "wlan.rsn.pmkid.count",
|
||||
FT_UINT16, BASE_DEC, NULL, 0,
|
||||
|
@ -33701,6 +33719,11 @@ proto_register_ieee80211(void)
|
|||
FT_UINT16, BASE_DEC, NULL, 0,
|
||||
NULL, HFILL }},
|
||||
|
||||
{&hf_ieee80211_rsn_ie_ptk_keyid,
|
||||
{"KeyID", "wlan.rsn.ie.ptk.keyid",
|
||||
FT_UINT8, BASE_DEC, NULL, 0x03,
|
||||
NULL, HFILL }},
|
||||
|
||||
{&hf_ieee80211_rsn_ie_gtk_key,
|
||||
{"GTK", "wlan.rsn.ie.gtk.key",
|
||||
FT_BYTES, BASE_NONE, NULL, 0,
|
||||
|
@ -35289,7 +35312,7 @@ proto_register_ieee80211(void)
|
|||
|
||||
{&hf_ieee80211_osen_extended_key_id_iaf,
|
||||
{"Extended Key ID for Individually Addressed Frames",
|
||||
"wlan.osn.rsn.extended_key_id_iaf",
|
||||
"wlan.osn.rsn.extended_key_id_iaf",
|
||||
FT_BOOLEAN, 16, TFS(&tfs_supported_not_supported), 0x2000, NULL, HFILL }},
|
||||
|
||||
{&hf_ieee80211_osen_reserved,
|
||||
|
|
Binary file not shown.
|
@ -112,6 +112,31 @@ class case_decrypt_80211(subprocesstest.SubprocessTestCase):
|
|||
self.assertTrue(self.grepOutput('DHCP Discover'))
|
||||
self.assertEqual(self.countOutput('ICMP.*Echo .ping'), 8)
|
||||
|
||||
def test_80211_wpa_extended_key_id_rekey(self, cmd_tshark, capture_file):
|
||||
'''WPA decode for Extended Key ID'''
|
||||
# Included in git sources test/captures/wpa_ptk_extended_key_id.pcap.gz
|
||||
self.assertRun((cmd_tshark,
|
||||
'-o', 'wlan.enable_decryption: TRUE',
|
||||
'-r', capture_file('wpa_ptk_extended_key_id.pcap.gz'),
|
||||
'-Tfields',
|
||||
'-e' 'wlan.fc.type_subtype',
|
||||
'-e' 'wlan.ra',
|
||||
'-e' 'wlan.analysis.tk',
|
||||
'-e' 'wlan.analysis.gtk',
|
||||
'-e' 'wlan.rsn.ie.ptk.keyid',
|
||||
))
|
||||
# Verify frames are decoded with the correct key
|
||||
self.assertEqual(self.countOutput('^32\t33:33:00:00:00:16\t\t234a9a6ddcca3cb728751cea49d01bb0\t$'), 5)
|
||||
self.assertEqual(self.countOutput('^32\t33:33:ff:00:00:00\t\t234a9a6ddcca3cb728751cea49d01bb0\t$'), 1)
|
||||
self.assertEqual(self.countOutput('^32\t33:33:ff:00:03:00\t\t234a9a6ddcca3cb728751cea49d01bb0\t$'), 1)
|
||||
self.assertEqual(self.countOutput('^32\tff:ff:ff:ff:ff:ff\t\t234a9a6ddcca3cb728751cea49d01bb0\t$'), 4)
|
||||
self.assertEqual(self.countOutput('^40\t02:00:00:00:03:00\t618b4d1829e2a496d7fd8c034a6d024d\t\t$'), 2)
|
||||
self.assertEqual(self.countOutput('^40\t02:00:00:00:00:00\t618b4d1829e2a496d7fd8c034a6d024d\t\t$'), 1)
|
||||
# Verify RSN PTK KeyID parsing
|
||||
self.assertEqual(self.countOutput('^40\t02:00:00:00:00:00\t\t\t1$'), 1)
|
||||
self.assertEqual(self.countOutput('^40\t02:00:00:00:00:00\tf31ecff5452f4c286cf66ef50d10dabe\t\t0$'), 1)
|
||||
self.assertEqual(self.countOutput('^40\t02:00:00:00:00:00\t28dd851decf3f1c2a35df8bcc22fa1d2\t\t1$'), 1)
|
||||
|
||||
@fixtures.mark_usefixtures('test_env')
|
||||
@fixtures.uses_fixtures
|
||||
class case_decrypt_dtls(subprocesstest.SubprocessTestCase):
|
||||
|
|
Loading…
Reference in New Issue