dot11decrypt: Support decryption using TK user input

Add support for TK user input keys. With this Wireshark can
decrypt packet captures where 4WHS frames are missing and
packet captures with non-supported AKMS, for example
802.11r / Fast BSS Transitioning.

Decryption using user TK works as a backup if the normal
decryption flow does not succeed. Having TK decryption keys
added will affect general IEEE 802.11 dissector performance
as each encrypted packet will be tested with every TK.
Worst case scenario is plenty of TKs where none of them
matches encrypted frames.

On successful user TK decryption an SA is formed based on
parameters used to decrypt the frame. This SA is similar to
what is formed when Wireshark detects and derive keys from
4WHS messages. With the SA entry in place the decryption
performance (success case) should be on par with "normal"
decryption flow.

Bug: 16579
Change-Id: I72c2c1e2c6693131d3ba07f8ddb8ff772c1b54a9
Reviewed-on: https://code.wireshark.org/review/37217
Petri-Dish: Anders Broman <a.broman58@gmail.com>
Tested-by: Petri Dish Buildbot
Reviewed-by: Anders Broman <a.broman58@gmail.com>
This commit is contained in:
Mikael Kanstrup 2020-05-22 21:32:38 +02:00 committed by Anders Broman
parent f1bc8ad34b
commit 42544c8c44
7 changed files with 336 additions and 55 deletions

View File

@ -305,6 +305,7 @@ Dot11DecryptCopyKey(PDOT11DECRYPT_SEC_ASSOCIATION sa, PDOT11DECRYPT_KEY_ITEM key
memcpy(key, sa->key, sizeof(DOT11DECRYPT_KEY_ITEM));
else
memset(key, 0, sizeof(DOT11DECRYPT_KEY_ITEM));
key->KeyData.Wpa.PtkLen = sa->wpa.ptk_len;
memcpy(key->KeyData.Wpa.Ptk, sa->wpa.ptk, sa->wpa.ptk_len);
key->KeyData.Wpa.Akm = sa->wpa.akm;
key->KeyData.Wpa.Cipher = sa->wpa.cipher;
@ -928,6 +929,92 @@ INT Dot11DecryptScanEapolForKeys(
return DOT11DECRYPT_RET_NO_VALID_HANDSHAKE;
}
static int
Dot11DecryptGetNbrOfTkKeys(PDOT11DECRYPT_CONTEXT ctx)
{
int nbr = 0;
for (size_t i = 0; i < ctx->keys_nr; i++) {
if (ctx->keys[i].KeyType == DOT11DECRYPT_KEY_TYPE_TK) {
nbr++;
}
}
return nbr;
}
static int
Dot11DecryptUsingUserTk(
PDOT11DECRYPT_CONTEXT ctx,
UCHAR *decrypt_data,
guint mac_header_len,
guint *decrypt_len,
DOT11DECRYPT_SEC_ASSOCIATION_ID *id,
DOT11DECRYPT_KEY_ITEM *used_key)
{
int ret = DOT11DECRYPT_RET_REQ_DATA;
DOT11DECRYPT_SEC_ASSOCIATION *sa = Dot11DecryptNewSa(id);
DOT11DECRYPT_KEY_ITEM *key;
if (sa == NULL) {
return ret;
}
sa->wpa.akm = 2;
sa->validKey = TRUE;
/* Try decrypt packet with all user TKs applicable ciphers */
for (size_t key_index = 0; key_index < ctx->keys_nr; key_index++) {
key = &ctx->keys[key_index];
if (key->KeyType != DOT11DECRYPT_KEY_TYPE_TK) {
continue;
}
int ciphers_to_try[4] = { 0 };
switch (key->Tk.Len) {
case DOT11DECRYPT_WEP_40_KEY_LEN:
case DOT11DECRYPT_WEP_104_KEY_LEN:
/* TBD implement */
continue;
case 256 / 8:
ciphers_to_try[0] = 9; /* GCMP-256 */
ciphers_to_try[1] = 10; /* CCMP-256 */
break;
case 128 / 8:
ciphers_to_try[0] = 4; /* CCMP-128 */
ciphers_to_try[1] = 8; /* GCMP-128 */
ciphers_to_try[2] = 2; /* TKIP */
break;
default:
continue;
}
sa->key = key;
for (int i = 0; ciphers_to_try[i] != 0; i++) {
sa->wpa.cipher = ciphers_to_try[i];
if (sa->wpa.cipher == 2 /* TKIP */) {
sa->wpa.key_ver = 1;
memcpy(DOT11DECRYPT_GET_TK_TKIP(sa->wpa.ptk),
key->Tk.Tk, key->Tk.Len);
} else {
sa->wpa.key_ver = 2;
sa->wpa.akm = 2;
memcpy(DOT11DECRYPT_GET_TK(sa->wpa.ptk, sa->wpa.akm),
key->Tk.Tk, key->Tk.Len);
}
sa->wpa.ptk_len = Dot11DecryptGetPtkLen(sa->wpa.akm, sa->wpa.cipher) / 8;
ret = Dot11DecryptRsnaMng(decrypt_data, mac_header_len, decrypt_len, used_key, sa);
if (ret == DOT11DECRYPT_RET_SUCCESS) {
/* Successfully decrypted using user TK. Add SA formed from user TK so that
* subsequent frames can be decrypted much faster using normal code path
* without trying each and every user TK entered.
*/
Dot11DecryptAddSa(ctx, id, sa);
return ret;
}
}
}
g_free(sa);
return ret;
}
INT Dot11DecryptDecryptPacket(
PDOT11DECRYPT_CONTEXT ctx,
const guint8 *data,
@ -979,55 +1066,59 @@ INT Dot11DecryptDecryptPacket(
/* check if data is encrypted (use the WEP bit in the Frame Control field) */
if (DOT11DECRYPT_WEP(data[1])==0) {
return DOT11DECRYPT_RET_NO_DATA_ENCRYPTED;
}
PDOT11DECRYPT_SEC_ASSOCIATION sa;
/* create new header and data to modify */
*decrypt_len = tot_len;
memcpy(decrypt_data, data, *decrypt_len);
/* encrypted data */
DEBUG_PRINT_LINE("Encrypted data", DEBUG_LEVEL_3);
/* check the Extension IV to distinguish between WEP encryption and WPA encryption */
/* refer to IEEE 802.11i-2004, 8.2.1.2, pag.35 for WEP, */
/* IEEE 802.11i-2004, 8.3.2.2, pag. 45 for TKIP, */
/* IEEE 802.11i-2004, 8.3.3.2, pag. 57 for CCMP */
if (DOT11DECRYPT_EXTIV(data[mac_header_len + 3]) == 0) {
DEBUG_PRINT_LINE("WEP encryption", DEBUG_LEVEL_3);
/* get the Security Association structure for the STA and AP */
sa = Dot11DecryptGetSa(ctx, &id);
if (sa == NULL) {
return DOT11DECRYPT_RET_REQ_DATA;
}
return Dot11DecryptWepMng(ctx, decrypt_data, mac_header_len, decrypt_len, key, sa);
} else {
PDOT11DECRYPT_SEC_ASSOCIATION sa;
DEBUG_PRINT_LINE("TKIP or CCMP encryption", DEBUG_LEVEL_3);
/* create new header and data to modify */
*decrypt_len = tot_len;
memcpy(decrypt_data, data, *decrypt_len);
/* 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 (((const DOT11DECRYPT_MAC_FRAME_ADDR4 *)(data))->addr1[0] & 0x01) {
DEBUG_PRINT_LINE("Broadcast/Multicast address. This is encrypted with a group key.", DEBUG_LEVEL_3);
/* encrypted data */
DEBUG_PRINT_LINE("Encrypted data", DEBUG_LEVEL_3);
/* check the Extension IV to distinguish between WEP encryption and WPA encryption */
/* refer to IEEE 802.11i-2004, 8.2.1.2, pag.35 for WEP, */
/* IEEE 802.11i-2004, 8.3.2.2, pag. 45 for TKIP, */
/* IEEE 802.11i-2004, 8.3.3.2, pag. 57 for CCMP */
if (DOT11DECRYPT_EXTIV(data[mac_header_len + 3]) == 0) {
DEBUG_PRINT_LINE("WEP encryption", DEBUG_LEVEL_3);
/* get the Security Association structure for the STA and AP */
sa = Dot11DecryptGetSa(ctx, &id);
if (sa == NULL) {
return DOT11DECRYPT_RET_REQ_DATA;
}
return Dot11DecryptWepMng(ctx, decrypt_data, mac_header_len, decrypt_len, key, sa);
} else {
DEBUG_PRINT_LINE("TKIP or CCMP encryption", DEBUG_LEVEL_3);
/* 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 (((const DOT11DECRYPT_MAC_FRAME_ADDR4 *)(data))->addr1[0] & 0x01) {
DEBUG_PRINT_LINE("Broadcast/Multicast address. This is encrypted with a group key.", 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);
/* force STA address to broadcast MAC so we load the SA for the groupkey */
memcpy(id.sta, broadcast_mac, DOT11DECRYPT_MAC_LEN);
#ifdef DOT11DECRYPT_DEBUG
g_snprintf(msgbuf, MSGBUF_LEN, "ST_MAC: %2X.%2X.%2X.%2X.%2X.%2X\t", id.sta[0],id.sta[1],id.sta[2],id.sta[3],id.sta[4],id.sta[5]);
DEBUG_PRINT_LINE(msgbuf, DEBUG_LEVEL_3);
g_snprintf(msgbuf, MSGBUF_LEN, "ST_MAC: %2X.%2X.%2X.%2X.%2X.%2X\t", id.sta[0],id.sta[1],id.sta[2],id.sta[3],id.sta[4],id.sta[5]);
DEBUG_PRINT_LINE(msgbuf, DEBUG_LEVEL_3);
#endif
}
/* search for a cached Security Association for current BSSID and STA/broadcast MAC */
sa = Dot11DecryptGetSa(ctx, &id);
if (sa == NULL) {
return DOT11DECRYPT_RET_REQ_DATA;
}
/* Decrypt the packet using the appropriate SA */
return Dot11DecryptRsnaMng(decrypt_data, mac_header_len, decrypt_len, key, sa);
}
}
/* search for a cached Security Association for current BSSID and STA/broadcast MAC */
int ret = DOT11DECRYPT_RET_REQ_DATA;
sa = Dot11DecryptGetSa(ctx, &id);
if (sa != NULL) {
/* Decrypt the packet using the appropriate SA */
ret = Dot11DecryptRsnaMng(decrypt_data, mac_header_len, decrypt_len, key, sa);
}
if (ret != DOT11DECRYPT_RET_SUCCESS && Dot11DecryptGetNbrOfTkKeys(ctx) > 0) {
/* Decryption with known SAs failed. Try decrypt with TK user entries */
ret = Dot11DecryptUsingUserTk(ctx, decrypt_data, mac_header_len, decrypt_len, &id, key);
}
return ret;
}
return DOT11DECRYPT_RET_UNSUCCESS;
}
@ -1322,6 +1413,12 @@ Dot11DecryptRsnaMng(
/* remove TKIP/CCMP header */
*decrypt_len-=8;
if (*decrypt_len < mac_header_len) {
DEBUG_PRINT_LINE("Invalid decryption length < mac_header_len", DEBUG_LEVEL_3);
g_free(try_data);
return DOT11DECRYPT_RET_UNSUCCESS;
}
/* copy the decrypted data into the decrypt buffer GCS*/
memcpy(decrypt_data + mac_header_len, try_data + mac_header_len + 8,
*decrypt_len - mac_header_len);
@ -1827,7 +1924,7 @@ Dot11DecryptValidateKey(
case DOT11DECRYPT_KEY_TYPE_WPA_PSK:
break;
case DOT11DECRYPT_KEY_TYPE_WPA_PMK:
case DOT11DECRYPT_KEY_TYPE_TK:
break;
default:
@ -2511,6 +2608,40 @@ parse_key_string(gchar* input_string, guint8 key_type)
g_byte_array_free(key_ba, TRUE);
return dk;
case DOT11DECRYPT_KEY_TYPE_TK:
{
/* From IEEE 802.11-2016 Table 12-4 Cipher suite key lengths */
static const guint8 allowed_key_lengths[] = {
// TBD 40 / 8, /* WEP-40 */
// TBD 104 / 8, /* WEP-104 */
256 / 8, /* TKIP, GCMP-256, CCMP-256 */
128 / 8, /* CCMP-128, GCMP-128 */
};
gboolean key_length_ok = FALSE;
key_ba = g_byte_array_new();
res = hex_str_to_bytes(input_string, key_ba, FALSE);
for (size_t i = 0; i < sizeof(allowed_key_lengths); i++) {
if (key_ba->len == allowed_key_lengths[i]) {
key_length_ok = TRUE;
break;
}
}
if (!res || !key_length_ok) {
g_byte_array_free(key_ba, TRUE);
return NULL;
}
dk = (decryption_key_t*)g_malloc(sizeof(decryption_key_t));
dk->type = DOT11DECRYPT_KEY_TYPE_TK;
dk->key = g_string_new(input_string);
dk->bits = (guint) dk->key->len * 4;
dk->ssid = NULL;
g_byte_array_free(key_ba, TRUE);
return dk;
}
}
/* Type not supported */

View File

@ -29,11 +29,12 @@
#define DOT11DECRYPT_KEY_TYPE_WPA_PWD 3
#define DOT11DECRYPT_KEY_TYPE_WPA_PSK 4
#define DOT11DECRYPT_KEY_TYPE_WPA_PMK 5
#define DOT11DECRYPT_KEY_TYPE_TKIP 6
#define DOT11DECRYPT_KEY_TYPE_CCMP 7
#define DOT11DECRYPT_KEY_TYPE_CCMP_256 8
#define DOT11DECRYPT_KEY_TYPE_GCMP 9
#define DOT11DECRYPT_KEY_TYPE_GCMP_256 10
#define DOT11DECRYPT_KEY_TYPE_TK 6
#define DOT11DECRYPT_KEY_TYPE_TKIP 7
#define DOT11DECRYPT_KEY_TYPE_CCMP 8
#define DOT11DECRYPT_KEY_TYPE_CCMP_256 9
#define DOT11DECRYPT_KEY_TYPE_GCMP 10
#define DOT11DECRYPT_KEY_TYPE_GCMP_256 11
#define DOT11DECRYPT_KEY_TYPE_UNKNOWN -1
/* Decryption algorithms fields size definition (bytes) */
@ -48,6 +49,7 @@
#define DOT11DECRYPT_WPA_SSID_MAX_LEN 32
#define DOT11DECRYPT_WPA_PMK_MAX_LEN 48
#define DOT11DECRYPT_WPA_PWD_PSK_LEN 32
#define DOT11DECRYPT_TK_MAX_LEN 32
/* */
/* */
/******************************************************************************/
@ -135,8 +137,14 @@ typedef struct _DOT11DECRYPT_KEY_ITEM {
UINT8 Akm;
UINT8 Cipher;
} Wpa;
} KeyData;
struct DOT11DECRYPT_KEY_ITEMDATA_TK {
guint8 Tk[DOT11DECRYPT_TK_MAX_LEN];
guint8 Len;
} Tk;
struct DOT11DECRYPT_KEY_ITEMDATA_PWD {
/**
* The string (null-terminated) value of

View File

@ -72,6 +72,7 @@ extern "C" {
#define STRING_KEY_TYPE_WEP "wep"
#define STRING_KEY_TYPE_WPA_PWD "wpa-pwd"
#define STRING_KEY_TYPE_WPA_PSK "wpa-psk"
#define STRING_KEY_TYPE_TK "tk"
#ifdef __cplusplus
}

View File

@ -196,6 +196,12 @@ uat_wep_key_record_update_cb(void* r, char** err)
return FALSE;
}
break;
case DOT11DECRYPT_KEY_TYPE_TK:
if (rec->key != DOT11DECRYPT_KEY_TYPE_TK) {
*err = g_strdup("Invalid TK key format");
return FALSE;
}
break;
default:
*err = g_strdup("Invalid key format");
return FALSE;
@ -2791,6 +2797,7 @@ static const value_string wep_type_vals[] = {
{ DOT11DECRYPT_KEY_TYPE_WEP, STRING_KEY_TYPE_WEP },
{ DOT11DECRYPT_KEY_TYPE_WPA_PWD, STRING_KEY_TYPE_WPA_PWD },
{ DOT11DECRYPT_KEY_TYPE_WPA_PSK, STRING_KEY_TYPE_WPA_PSK },
{ DOT11DECRYPT_KEY_TYPE_TK, STRING_KEY_TYPE_TK },
{ 0x00, NULL }
};
@ -25996,7 +26003,7 @@ dissect_ieee80211_common(tvbuff_t *tvb, packet_info *pinfo,
proto_tree *wep_tree = NULL;
guint32 iv;
guint8 wep_key, keybyte;
DOT11DECRYPT_KEY_ITEM used_key;
DOT11DECRYPT_KEY_ITEM used_key = { 0 };
if (len == reported_len) {
next_tvb = try_decrypt(tvb, pinfo, hdr_len, reported_len,
@ -26090,10 +26097,13 @@ dissect_ieee80211_common(tvbuff_t *tvb, packet_info *pinfo,
proto_item_set_generated(ti);
/* Also add the PMK used to to decrypt the packet. (PMK==PSK) */
bytes_to_hexstr(out_buff, used_key.KeyData.Wpa.Psk, used_key.KeyData.Wpa.PskLen);
out_buff[2*used_key.KeyData.Wpa.PskLen] = '\0';
ti = proto_tree_add_string(wep_tree, hf_ieee80211_fc_analysis_pmk, tvb, 0, 0, out_buff);
proto_item_set_generated(ti);
if (used_key.KeyData.Wpa.PskLen > 0) {
bytes_to_hexstr(out_buff, used_key.KeyData.Wpa.Psk, used_key.KeyData.Wpa.PskLen);
out_buff[2*used_key.KeyData.Wpa.PskLen] = '\0';
ti = proto_tree_add_string(wep_tree, hf_ieee80211_fc_analysis_pmk, tvb, 0, 0, out_buff);
proto_item_set_generated(ti);
}
} else { /* Encrypted with Group Key */
key_len = Dot11DecryptGetGTK(&used_key, &key);
@ -27284,7 +27294,7 @@ set_dot11decrypt_keys(void)
if (dk != NULL)
{
DOT11DECRYPT_KEY_ITEM key;
DOT11DECRYPT_KEY_ITEM key = { 0 };
if (dk->type == DOT11DECRYPT_KEY_TYPE_WEP)
{
gboolean res;
@ -27340,6 +27350,18 @@ set_dot11decrypt_keys(void)
keys->nKeys += 1;
}
}
else if (dk->type == DOT11DECRYPT_KEY_TYPE_TK)
{
key.KeyType = DOT11DECRYPT_KEY_TYPE_TK;
bytes = g_byte_array_new();
hex_str_to_bytes(dk->key->str, bytes, FALSE);
memcpy(key.Tk.Tk, bytes->data, bytes->len);
key.Tk.Len = bytes->len;
keys->Keys[keys->nKeys] = key;
keys->nKeys += 1;
}
free_key_string(dk);
if (bytes) {
g_byte_array_free(bytes, TRUE);
@ -38709,7 +38731,8 @@ proto_register_ieee80211(void)
UAT_FLD_CSTRING(uat_wep_key_records, string, "Key",
"wep:<wep hexadecimal key>\n"
"wpa-pwd:<passphrase>[:<ssid>]\n"
"wpa-psk:<wpa hexadecimal key>"),
"wpa-psk:<wpa hexadecimal key>\n"
"tk:<hexadecimal key>\n"),
UAT_END_FIELDS
};

View File

@ -0,0 +1,12 @@
# Keys needed for the 80211 user TK test cases in decryption test suite
"tk","d0e57d224c1bb8806089d8c23154074c"
"tk","6eaf63f4ad7997ced353723de3029f4d"
"tk","fb42811bcb59b7845376246454fbdab7"
"tk","4e30e8c019bea43ea5262b10853b818d"
"tk","70cdbf2e5bc0ca22e53930818a5d80e4"
"tk","4e6abbcf9dc0943936700b6825952218f58a47dfdf51dbb8ce9b02fd7d2d9e40"
"tk","502085ca205e668f7e7c61cdf4f731336bb31e4f5b28ec91860174192e9b2190"
"tk","755a9c1c9e605d5ff62849e4a17a935c"
"tk","7ff30f7a8dd67950eaaf2f20a869a62d"
"tk","b3dc2ff2d88d0d34c1ddc421cea17f304af3c46acbbe7b6d808b6ebf1b98ec38"
"tk","a745ee2313f86515a155c4cb044bc148ae234b9c72707f772b69c2fede3e4016"

View File

@ -301,6 +301,44 @@ def test_env(base_env, conf_path, request, dirs):
return env
@fixtures.fixture
def test_env_80211_user_tk(base_env, conf_path, request, dirs):
'''A process environment with a populated configuration directory.'''
# Populate our UAT files
uat_files = [
'80211_keys',
]
# uat.c replaces backslashes...
key_dir_path = os.path.join(dirs.key_dir, '').replace('\\', '\\x5c')
for uat in uat_files:
template_file = os.path.join(dirs.config_dir, uat + '.user_tk_tmpl')
out_file = os.path.join(conf_path, uat)
with open(template_file, 'r') as f:
template_contents = f.read()
cf_contents = template_contents.replace('TEST_KEYS_DIR', key_dir_path)
with open(out_file, 'w') as f:
f.write(cf_contents)
env = base_env
env['WIRESHARK_RUN_FROM_BUILD_DIRECTORY'] = '1'
env['WIRESHARK_QUIT_AFTER_CAPTURE'] = '1'
# Allow GUI tests to be run without opening windows nor requiring a Xserver.
# Set envvar QT_DEBUG_BACKINGSTORE=1 to save the window contents to a file
# in the current directory, output0000.png, output0001.png, etc. Note that
# this will overwrite existing files.
if sys.platform == 'linux':
# This option was verified working on Arch Linux with Qt 5.12.0-2 and
# Ubuntu 16.04 with libqt5gui5 5.5.1+dfsg-16ubuntu7.5. On macOS and
# Windows it unfortunately crashes (Qt 5.12.0).
env['QT_QPA_PLATFORM'] = 'minimal'
# Remove this if test instances no longer inherit from SubprocessTestCase?
if isinstance(request.instance, subprocesstest.SubprocessTestCase):
# Inject the test environment as default if it was not overridden.
request.instance.injected_test_env = env
return env
@fixtures.fixture
def unicode_env(home_path, make_env):
'''A Wireshark configuration directory with Unicode in its path.'''

View File

@ -214,6 +214,74 @@ class case_decrypt_80211(subprocesstest.SubprocessTestCase):
self.assertTrue(self.grepOutput('DHCP Request')) # Verifies TK is correct
self.assertTrue(self.grepOutput(r'Echo \(ping\) request')) # Verifies TK is correct
@fixtures.mark_usefixtures('test_env_80211_user_tk')
@fixtures.uses_fixtures
class case_decrypt_80211_user_tk(subprocesstest.SubprocessTestCase):
def test_80211_user_tk_tkip(self, cmd_tshark, capture_file):
'''IEEE 802.11 decode TKIP using user TK'''
# Included in git sources test/captures/wpa1-gtk-rekey.pcapng.gz
self.assertRun((cmd_tshark,
'-o', 'wlan.enable_decryption: TRUE',
'-r', capture_file('wpa1-gtk-rekey.pcapng.gz'),
'-Y', 'wlan.analysis.tk == "d0e57d224c1bb8806089d8c23154074c" || wlan.analysis.gtk == "6eaf63f4ad7997ced353723de3029f4d" || wlan.analysis.gtk == "fb42811bcb59b7845376246454fbdab7"',
))
self.assertTrue(self.grepOutput('DHCP Discover'))
self.assertEqual(self.countOutput('ICMP.*Echo .ping'), 8)
def test_80211_user_tk_ccmp(self, cmd_tshark, capture_file, features):
'''IEEE 802.11 decode CCMP-128 using user TK'''
# Included in git sources test/captures/wpa2-psk-mfp.pcapng.gz
self.assertRun((cmd_tshark,
'-o', 'wlan.enable_decryption: TRUE',
'-r', capture_file('wpa2-psk-mfp.pcapng.gz'),
'-Y', 'wlan.analysis.tk == 4e30e8c019bea43ea5262b10853b818d || wlan.analysis.gtk == 70cdbf2e5bc0ca22e53930818a5d80e4',
))
self.assertTrue(self.grepOutput('Who has 192.168.5.5')) # Verifies GTK decryption
self.assertTrue(self.grepOutput('DHCP Request')) # Verifies TK decryption
self.assertTrue(self.grepOutput(r'Echo \(ping\) request')) # Verifies TK decryption
def test_80211_user_tk_ccmp_256(self, cmd_tshark, capture_file, features):
'''IEEE 802.11 decode CCMP-256 using user TK'''
# Included in git sources test/captures/wpa-ccmp-256.pcapng.gz
if not features.have_libgcrypt16:
self.skipTest('Requires GCrypt 1.6 or later.')
self.assertRun((cmd_tshark,
'-o', 'wlan.enable_decryption: TRUE',
'-r', capture_file('wpa-ccmp-256.pcapng.gz'),
'-Y', 'wlan.analysis.tk == 4e6abbcf9dc0943936700b6825952218f58a47dfdf51dbb8ce9b02fd7d2d9e40 || wlan.analysis.gtk == 502085ca205e668f7e7c61cdf4f731336bb31e4f5b28ec91860174192e9b2190',
))
self.assertTrue(self.grepOutput('Who has 192.168.5.5')) # Verifies GTK decryption
self.assertTrue(self.grepOutput('DHCP Request')) # Verifies TK decryption
self.assertTrue(self.grepOutput(r'Echo \(ping\) request')) # Verifies TK decryption
def test_80211_user_tk_gcmp(self, cmd_tshark, capture_file, features):
'''IEEE 802.11 decode GCMP using user TK'''
# Included in git sources test/captures/wpa-gcmp.pcapng.gz
if not features.have_libgcrypt16:
self.skipTest('Requires GCrypt 1.6 or later.')
self.assertRun((cmd_tshark,
'-o', 'wlan.enable_decryption: TRUE',
'-r', capture_file('wpa-gcmp.pcapng.gz'),
'-Y', 'wlan.analysis.tk == 755a9c1c9e605d5ff62849e4a17a935c || wlan.analysis.gtk == 7ff30f7a8dd67950eaaf2f20a869a62d',
))
self.assertTrue(self.grepOutput('Who has 192.168.5.5')) # Verifies GTK decryption
self.assertTrue(self.grepOutput('DHCP Request')) # Verifies TK decryption
self.assertTrue(self.grepOutput(r'Echo \(ping\) request')) # Verifies TK decryption
def test_80211_wpa_gcmp_256(self, cmd_tshark, capture_file, features):
'''IEEE 802.11 decode GCMP-256 using user TK'''
# Included in git sources test/captures/wpa-gcmp-256.pcapng.gz
if not features.have_libgcrypt16:
self.skipTest('Requires GCrypt 1.6 or later.')
self.assertRun((cmd_tshark,
'-o', 'wlan.enable_decryption: TRUE',
'-r', capture_file('wpa-gcmp-256.pcapng.gz'),
'-Y', 'wlan.analysis.tk == b3dc2ff2d88d0d34c1ddc421cea17f304af3c46acbbe7b6d808b6ebf1b98ec38 || wlan.analysis.gtk == a745ee2313f86515a155c4cb044bc148ae234b9c72707f772b69c2fede3e4016',
))
self.assertTrue(self.grepOutput('Who has 192.168.5.5')) # Verifies GTK decryption
self.assertTrue(self.grepOutput('DHCP Request')) # Verifies TK decryption
self.assertTrue(self.grepOutput(r'Echo \(ping\) request')) # Verifies TK decryption
@fixtures.mark_usefixtures('test_env')
@fixtures.uses_fixtures
class case_decrypt_dtls(subprocesstest.SubprocessTestCase):