tests: Verify that wpa_supplicant clears keys from memory

Check that PMK and PTK and not left in memory (heap or stack)
unnecessarily after they are not needed anymore.

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2014-12-29 13:13:25 +02:00
parent 4e70bbf1c6
commit 5b3c40a65b
6 changed files with 662 additions and 3 deletions

View File

@ -74,6 +74,8 @@ radius_accept_attr=27:d:3
"8"* AKA' [2]
"pap user" TTLS-PAP "password" [2]
"pap-secret" TTLS-PAP "63d2d21ac3c09ed567ee004a34490f1d16e7fa5835edf17ddba70a63f1a90a25" [2]
"pap-secret@example.com" TTLS-PAP "63d2d21ac3c09ed567ee004a34490f1d16e7fa5835edf17ddba70a63f1a90a25" [2]
"chap user" TTLS-CHAP "password" [2]
"mschap user" TTLS-MSCHAP "password" [2]
"DOMAIN\mschapv2 user" TTLS-MSCHAPV2 hash:8846f7eaee8fb117ad06bdd830b7586c [2]

View File

@ -6,6 +6,7 @@
# See README for more details.
import base64
import binascii
import time
import subprocess
import logging
@ -14,7 +15,7 @@ import os
import hwsim_utils
import hostapd
from test_ap_psk import check_mib
from test_ap_psk import check_mib, find_wpas_process, read_process_memory, verify_not_present, get_key_locations
def read_pem(fname):
with open(fname, "r") as f:
@ -2243,3 +2244,98 @@ def test_openssl_cipher_suite_config_hapd(dev, apdev):
anonymous_identity="ttls", password="password",
openssl_ciphers="HIGH:!ADH",
ca_cert="auth_serv/ca.pem", phase2="auth=PAP")
def test_wpa2_eap_ttls_pap_key_lifetime_in_memory(dev, apdev, params):
"""Key lifetime in memory with WPA2-Enterprise using EAP-TTLS/PAP"""
p = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
hapd = hostapd.add_ap(apdev[0]['ifname'], p)
password = "63d2d21ac3c09ed567ee004a34490f1d16e7fa5835edf17ddba70a63f1a90a25"
pid = find_wpas_process(dev[0])
id = eap_connect(dev[0], apdev[0], "TTLS", "pap-secret",
anonymous_identity="ttls", password=password,
ca_cert="auth_serv/ca.pem", phase2="auth=PAP")
time.sleep(0.1)
buf = read_process_memory(pid, password)
dev[0].request("DISCONNECT")
dev[0].wait_disconnected()
dev[0].relog()
pmk = None
ptk = None
gtk = None
with open(os.path.join(params['logdir'], 'log0'), 'r') as f:
for l in f.readlines():
if "WPA: PMK - hexdump" in l:
val = l.strip().split(':')[3].replace(' ', '')
pmk = binascii.unhexlify(val)
if "WPA: PTK - hexdump" in l:
val = l.strip().split(':')[3].replace(' ', '')
ptk = binascii.unhexlify(val)
if "WPA: Group Key - hexdump" in l:
val = l.strip().split(':')[3].replace(' ', '')
gtk = binascii.unhexlify(val)
if not pmk or not ptk or not gtk:
raise Exception("Could not find keys from debug log")
if len(gtk) != 16:
raise Exception("Unexpected GTK length")
kck = ptk[0:16]
kek = ptk[16:32]
tk = ptk[32:48]
fname = os.path.join(params['logdir'],
'wpa2_eap_ttls_pap_key_lifetime_in_memory.memctx-')
logger.info("Checking keys in memory while associated")
get_key_locations(buf, password, "Password")
get_key_locations(buf, pmk, "PMK")
if password not in buf:
print("Password not found while associated")
return "skip"
if pmk not in buf:
print("PMK not found while associated")
return "skip"
if kck not in buf:
raise Exception("KCK not found while associated")
if kek not in buf:
raise Exception("KEK not found while associated")
if tk in buf:
raise Exception("TK found from memory")
if gtk in buf:
raise Exception("GTK found from memory")
logger.info("Checking keys in memory after disassociation")
buf = read_process_memory(pid, password)
# Note: Password is still present in network configuration
# Note: PMK is in PMKSA cache and EAP fast re-auth data
get_key_locations(buf, password, "Password")
get_key_locations(buf, pmk, "PMK")
verify_not_present(buf, kck, fname, "KCK")
verify_not_present(buf, kek, fname, "KEK")
verify_not_present(buf, tk, fname, "TK")
verify_not_present(buf, gtk, fname, "GTK")
dev[0].request("PMKSA_FLUSH")
dev[0].set_network_quoted(id, "identity", "foo")
logger.info("Checking keys in memory after PMKSA cache and EAP fast reauth flush")
buf = read_process_memory(pid, password)
get_key_locations(buf, password, "Password")
get_key_locations(buf, pmk, "PMK")
verify_not_present(buf, pmk, fname, "PMK")
dev[0].request("REMOVE_NETWORK all")
logger.info("Checking keys in memory after network profile removal")
buf = read_process_memory(pid, password)
get_key_locations(buf, password, "Password")
get_key_locations(buf, pmk, "PMK")
verify_not_present(buf, password, fname, "password")
verify_not_present(buf, pmk, fname, "PMK")
verify_not_present(buf, kck, fname, "KCK")
verify_not_present(buf, kek, fname, "KEK")
verify_not_present(buf, tk, fname, "TK")
verify_not_present(buf, gtk, fname, "GTK")

View File

@ -4,6 +4,8 @@
# This software may be distributed under the terms of the BSD license.
# See README for more details.
import binascii
import os
import time
import subprocess
import logging
@ -12,7 +14,7 @@ logger = logging.getLogger()
import hwsim_utils
import hostapd
from wlantest import Wlantest
from test_ap_psk import check_mib
from test_ap_psk import check_mib, find_wpas_process, read_process_memory, verify_not_present, get_key_locations
def ft_base_rsn():
params = { "wpa": "2",
@ -456,3 +458,108 @@ def test_ap_ft_gtk_rekey(dev, apdev):
if ev is None:
raise Exception("GTK rekey timed out after FT protocol")
hwsim_utils.test_connectivity(dev[0], hapd1)
def test_ft_psk_key_lifetime_in_memory(dev, apdev, params):
"""WPA2-PSK-FT and key lifetime in memory"""
ssid = "test-ft"
passphrase="04c2726b4b8d5f1b4db9c07aa4d9e9d8f765cb5d25ec817e6cc4fcdd5255db0"
psk = '93c90846ff67af9037ed83fb72b63dbeddaa81d47f926c20909b5886f1d9358d'
pmk = binascii.unhexlify(psk)
p = ft_params1(ssid=ssid, passphrase=passphrase)
hapd0 = hostapd.add_ap(apdev[0]['ifname'], p)
p = ft_params2(ssid=ssid, passphrase=passphrase)
hapd1 = hostapd.add_ap(apdev[1]['ifname'], p)
pid = find_wpas_process(dev[0])
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
time.sleep(0.1)
buf = read_process_memory(pid, pmk)
dev[0].request("DISCONNECT")
dev[0].wait_disconnected()
dev[0].relog()
pmkr0 = None
pmkr1 = None
ptk = None
gtk = None
with open(os.path.join(params['logdir'], 'log0'), 'r') as f:
for l in f.readlines():
if "FT: PMK-R0 - hexdump" in l:
val = l.strip().split(':')[3].replace(' ', '')
pmkr0 = binascii.unhexlify(val)
if "FT: PMK-R1 - hexdump" in l:
val = l.strip().split(':')[3].replace(' ', '')
pmkr1 = binascii.unhexlify(val)
if "FT: PTK - hexdump" in l:
val = l.strip().split(':')[3].replace(' ', '')
ptk = binascii.unhexlify(val)
if "WPA: Group Key - hexdump" in l:
val = l.strip().split(':')[3].replace(' ', '')
gtk = binascii.unhexlify(val)
if not pmkr0 or not pmkr1 or not ptk or not gtk:
raise Exception("Could not find keys from debug log")
if len(gtk) != 16:
raise Exception("Unexpected GTK length")
kck = ptk[0:16]
kek = ptk[16:32]
tk = ptk[32:48]
logger.info("Checking keys in memory while associated")
get_key_locations(buf, pmk, "PMK")
get_key_locations(buf, pmkr0, "PMK-R0")
get_key_locations(buf, pmkr1, "PMK-R1")
if pmk not in buf:
print("PMK not found while associated")
return "skip"
if pmkr0 not in buf:
print("PMK-R0 not found while associated")
return "skip"
if pmkr1 not in buf:
print("PMK-R1 not found while associated")
return "skip"
if kck not in buf:
raise Exception("KCK not found while associated")
if kek not in buf:
raise Exception("KEK not found while associated")
if tk in buf:
raise Exception("TK found from memory")
if gtk in buf:
raise Exception("GTK found from memory")
logger.info("Checking keys in memory after disassociation")
buf = read_process_memory(pid, pmk)
get_key_locations(buf, pmk, "PMK")
get_key_locations(buf, pmkr0, "PMK-R0")
get_key_locations(buf, pmkr1, "PMK-R1")
# Note: PMK/PSK is still present in network configuration
fname = os.path.join(params['logdir'],
'ft_psk_key_lifetime_in_memory.memctx-')
verify_not_present(buf, pmkr0, fname, "PMK-R0")
verify_not_present(buf, pmkr1, fname, "PMK-R1")
verify_not_present(buf, kck, fname, "KCK")
verify_not_present(buf, kek, fname, "KEK")
verify_not_present(buf, tk, fname, "TK")
verify_not_present(buf, gtk, fname, "GTK")
dev[0].request("REMOVE_NETWORK all")
logger.info("Checking keys in memory after network profile removal")
buf = read_process_memory(pid, pmk)
get_key_locations(buf, pmk, "PMK")
get_key_locations(buf, pmkr0, "PMK-R0")
get_key_locations(buf, pmkr1, "PMK-R1")
verify_not_present(buf, pmk, fname, "PMK")
verify_not_present(buf, pmkr0, fname, "PMK-R0")
verify_not_present(buf, pmkr1, fname, "PMK-R1")
verify_not_present(buf, kck, fname, "KCK")
verify_not_present(buf, kek, fname, "KEK")
verify_not_present(buf, tk, fname, "TK")
verify_not_present(buf, gtk, fname, "GTK")

View File

@ -10,6 +10,7 @@ import hmac
import logging
logger = logging.getLogger()
import os
import re
import struct
import subprocess
import time
@ -818,3 +819,159 @@ def test_ap_wpa2_psk_ext_eapol_key_info(dev, apdev):
reply_eapol("4/4", hapd, addr, msg, 0x030a, None, None, kck)
hapd_connected(hapd)
def find_wpas_process(dev):
ifname = dev.ifname
cmd = subprocess.Popen(['ps', 'ax'], stdout=subprocess.PIPE)
(data,err) = cmd.communicate()
for l in data.splitlines():
if "wpa_supplicant" not in l:
continue
if "-i" + ifname not in l:
continue
return int(l.strip().split(' ')[0])
raise Exception("Could not find wpa_supplicant process")
def read_process_memory(pid, key=None):
buf = bytes()
with open('/proc/%d/maps' % pid, 'r') as maps, \
open('/proc/%d/mem' % pid, 'r') as mem:
for l in maps.readlines():
m = re.match(r'([0-9a-f]+)-([0-9a-f]+) ([-r][-w][-x][-p])', l)
if not m:
continue
start = int(m.group(1), 16)
end = int(m.group(2), 16)
perm = m.group(3)
if start > 0xffffffffffff:
continue
if end < start:
continue
if not perm.startswith('rw'):
continue
mem.seek(start)
data = mem.read(end - start)
buf += data
if key and key in data:
logger.info("Key found in " + l)
return buf
def verify_not_present(buf, key, fname, keyname):
pos = buf.find(key)
if pos < 0:
return
prefix = 2048 if pos > 2048 else pos
with open(fname + keyname, 'w') as f:
f.write(buf[pos - prefix:pos + 2048])
raise Exception(keyname + " found after disassociation")
def get_key_locations(buf, key, keyname):
count = 0
pos = 0
while True:
pos = buf.find(key, pos)
if pos < 0:
break
logger.info("Found %s at %d" % (keyname, pos))
count += 1
pos += len(key)
return count
def test_wpa2_psk_key_lifetime_in_memory(dev, apdev, params):
"""WPA2-PSK and PSK/PTK lifetime in memory"""
ssid = "test-wpa2-psk"
passphrase = 'qwertyuiop'
psk = '602e323e077bc63bd80307ef4745b754b0ae0a925c2638ecd13a794b9527b9e6'
pmk = binascii.unhexlify(psk)
p = hostapd.wpa2_params(ssid=ssid)
p['wpa_psk'] = psk
hapd = hostapd.add_ap(apdev[0]['ifname'], p)
pid = find_wpas_process(dev[0])
id = dev[0].connect(ssid, raw_psk=psk, scan_freq="2412",
only_add_network=True)
logger.info("Checking keys in memory after network profile configuration")
buf = read_process_memory(pid, pmk)
get_key_locations(buf, pmk, "PMK")
dev[0].request("REMOVE_NETWORK all")
logger.info("Checking keys in memory after network profile removal")
buf = read_process_memory(pid, pmk)
get_key_locations(buf, pmk, "PMK")
id = dev[0].connect(ssid, psk=passphrase, scan_freq="2412",
only_add_network=True)
logger.info("Checking keys in memory before connection")
buf = read_process_memory(pid, pmk)
get_key_locations(buf, pmk, "PMK")
dev[0].connect_network(id, timeout=20)
time.sleep(0.1)
buf = read_process_memory(pid, pmk)
dev[0].request("DISCONNECT")
dev[0].wait_disconnected()
dev[0].relog()
ptk = None
gtk = None
with open(os.path.join(params['logdir'], 'log0'), 'r') as f:
for l in f.readlines():
if "WPA: PTK - hexdump" in l:
val = l.strip().split(':')[3].replace(' ', '')
ptk = binascii.unhexlify(val)
if "WPA: Group Key - hexdump" in l:
val = l.strip().split(':')[3].replace(' ', '')
gtk = binascii.unhexlify(val)
if not pmk or not ptk or not gtk:
raise Exception("Could not find keys from debug log")
if len(gtk) != 16:
raise Exception("Unexpected GTK length")
kck = ptk[0:16]
kek = ptk[16:32]
tk = ptk[32:48]
logger.info("Checking keys in memory while associated")
get_key_locations(buf, pmk, "PMK")
if pmk not in buf:
print("PMK not found while associated")
return "skip"
if kck not in buf:
raise Exception("KCK not found while associated")
if kek not in buf:
raise Exception("KEK not found while associated")
if tk in buf:
raise Exception("TK found from memory")
if gtk in buf:
raise Exception("GTK found from memory")
logger.info("Checking keys in memory after disassociation")
buf = read_process_memory(pid, pmk)
get_key_locations(buf, pmk, "PMK")
# Note: PMK/PSK is still present in network configuration
fname = os.path.join(params['logdir'],
'wpa2_psk_key_lifetime_in_memory.memctx-')
verify_not_present(buf, kck, fname, "KCK")
verify_not_present(buf, kek, fname, "KEK")
verify_not_present(buf, tk, fname, "TK")
verify_not_present(buf, gtk, fname, "GTK")
dev[0].request("REMOVE_NETWORK all")
logger.info("Checking keys in memory after network profile removal")
buf = read_process_memory(pid, pmk)
get_key_locations(buf, pmk, "PMK")
verify_not_present(buf, pmk, fname, "PMK")
verify_not_present(buf, kck, fname, "KCK")
verify_not_present(buf, kek, fname, "KEK")
verify_not_present(buf, tk, fname, "TK")
verify_not_present(buf, gtk, fname, "GTK")

View File

@ -4,11 +4,15 @@
# This software may be distributed under the terms of the BSD license.
# See README for more details.
import binascii
import logging
logger = logging.getLogger()
import os
import time
import hostapd
from test_ap_eap import int_eap_server_params
from test_ap_psk import find_wpas_process, read_process_memory, verify_not_present, get_key_locations
def test_erp_initiate_reauth_start(dev, apdev):
"""Authenticator sending EAP-Initiate/Re-auth-Start, but ERP disabled on peer"""
@ -215,3 +219,173 @@ def test_erp_radius_eap_methods(dev, apdev):
private_key="auth_serv/user.key")
erp_test(dev[0], hapd, eap="TTLS", identity="erp-ttls@example.com",
password="password", ca_cert="auth_serv/ca.pem", phase2="auth=PAP")
def test_erp_key_lifetime_in_memory(dev, apdev, params):
"""ERP and key lifetime in memory"""
capab = dev[0].get_capability("erp")
if not capab or 'ERP' not in capab:
return "skip"
p = int_eap_server_params()
p['erp_send_reauth_start'] = '1'
p['erp_domain'] = 'example.com'
p['eap_server_erp'] = '1'
p['disable_pmksa_caching'] = '1'
hapd = hostapd.add_ap(apdev[0]['ifname'], p)
password = "63d2d21ac3c09ed567ee004a34490f1d16e7fa5835edf17ddba70a63f1a90a25"
pid = find_wpas_process(dev[0])
dev[0].request("ERP_FLUSH")
dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
identity="pap-secret@example.com", password=password,
ca_cert="auth_serv/ca.pem", phase2="auth=PAP",
erp="1", scan_freq="2412")
time.sleep(0.1)
buf = read_process_memory(pid, password)
dev[0].request("DISCONNECT")
dev[0].wait_disconnected(timeout=15)
dev[0].relog()
rRK = None
rIK = None
pmk = None
ptk = None
gtk = None
with open(os.path.join(params['logdir'], 'log0'), 'r') as f:
for l in f.readlines():
if "EAP: ERP rRK - hexdump" in l:
val = l.strip().split(':')[3].replace(' ', '')
rRK = binascii.unhexlify(val)
if "EAP: ERP rIK - hexdump" in l:
val = l.strip().split(':')[3].replace(' ', '')
rIK = binascii.unhexlify(val)
if "WPA: PMK - hexdump" in l:
val = l.strip().split(':')[3].replace(' ', '')
pmk = binascii.unhexlify(val)
if "WPA: PTK - hexdump" in l:
val = l.strip().split(':')[3].replace(' ', '')
ptk = binascii.unhexlify(val)
if "WPA: Group Key - hexdump" in l:
val = l.strip().split(':')[3].replace(' ', '')
gtk = binascii.unhexlify(val)
if not rIK or not rRK or not pmk or not ptk or not gtk:
raise Exception("Could not find keys from debug log")
if len(gtk) != 16:
raise Exception("Unexpected GTK length")
kck = ptk[0:16]
kek = ptk[16:32]
tk = ptk[32:48]
fname = os.path.join(params['logdir'],
'erp_key_lifetime_in_memory.memctx-')
logger.info("Checking keys in memory while associated")
get_key_locations(buf, password, "Password")
get_key_locations(buf, pmk, "PMK")
get_key_locations(buf, rRK, "rRK")
get_key_locations(buf, rIK, "rIK")
if password not in buf:
print("Password not found while associated")
return "skip"
if pmk not in buf:
print("PMK not found while associated")
return "skip"
if kck not in buf:
raise Exception("KCK not found while associated")
if kek not in buf:
raise Exception("KEK not found while associated")
if tk in buf:
raise Exception("TK found from memory")
if gtk in buf:
raise Exception("GTK found from memory")
logger.info("Checking keys in memory after disassociation")
buf = read_process_memory(pid, password)
# Note: Password is still present in network configuration
# Note: PMK is in EAP fast re-auth data
get_key_locations(buf, password, "Password")
get_key_locations(buf, pmk, "PMK")
get_key_locations(buf, rRK, "rRK")
get_key_locations(buf, rIK, "rIK")
verify_not_present(buf, kck, fname, "KCK")
verify_not_present(buf, kek, fname, "KEK")
verify_not_present(buf, tk, fname, "TK")
verify_not_present(buf, gtk, fname, "GTK")
dev[0].request("RECONNECT")
ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=15)
if ev is None:
raise Exception("EAP success timed out")
if "EAP re-authentication completed successfully" not in ev:
raise Exception("Did not use ERP")
dev[0].wait_connected(timeout=15, error="Reconnection timed out")
dev[0].request("DISCONNECT")
dev[0].wait_disconnected(timeout=15)
dev[0].relog()
pmk = None
ptk = None
gtk = None
with open(os.path.join(params['logdir'], 'log0'), 'r') as f:
for l in f.readlines():
if "WPA: PMK - hexdump" in l:
val = l.strip().split(':')[3].replace(' ', '')
pmk = binascii.unhexlify(val)
if "WPA: PTK - hexdump" in l:
val = l.strip().split(':')[3].replace(' ', '')
ptk = binascii.unhexlify(val)
if "WPA: GTK in EAPOL-Key - hexdump" in l:
val = l.strip().split(':')[3].replace(' ', '')
gtk = binascii.unhexlify(val)
if not pmk or not ptk or not gtk:
raise Exception("Could not find keys from debug log")
kck = ptk[0:16]
kek = ptk[16:32]
tk = ptk[32:48]
logger.info("Checking keys in memory after ERP and disassociation")
buf = read_process_memory(pid, password)
# Note: Password is still present in network configuration
get_key_locations(buf, password, "Password")
get_key_locations(buf, pmk, "PMK")
get_key_locations(buf, rRK, "rRK")
get_key_locations(buf, rIK, "rIK")
verify_not_present(buf, kck, fname, "KCK")
verify_not_present(buf, kek, fname, "KEK")
verify_not_present(buf, tk, fname, "TK")
verify_not_present(buf, gtk, fname, "GTK")
dev[0].request("REMOVE_NETWORK all")
logger.info("Checking keys in memory after network profile removal")
buf = read_process_memory(pid, password)
# Note: rRK and rIK are still in memory
get_key_locations(buf, password, "Password")
get_key_locations(buf, pmk, "PMK")
get_key_locations(buf, rRK, "rRK")
get_key_locations(buf, rIK, "rIK")
verify_not_present(buf, password, fname, "password")
verify_not_present(buf, pmk, fname, "PMK")
verify_not_present(buf, kck, fname, "KCK")
verify_not_present(buf, kek, fname, "KEK")
verify_not_present(buf, tk, fname, "TK")
verify_not_present(buf, gtk, fname, "GTK")
dev[0].request("ERP_FLUSH")
logger.info("Checking keys in memory after ERP_FLUSH")
buf = read_process_memory(pid, password)
get_key_locations(buf, rRK, "rRK")
get_key_locations(buf, rIK, "rIK")
verify_not_present(buf, rRK, fname, "rRK")
verify_not_present(buf, rIK, fname, "rIK")

View File

@ -1,9 +1,11 @@
# Test cases for SAE
# Copyright (c) 2013, Jouni Malinen <j@w1.fi>
# Copyright (c) 2013-2014, Jouni Malinen <j@w1.fi>
#
# This software may be distributed under the terms of the BSD license.
# See README for more details.
import binascii
import os
import time
import subprocess
import logging
@ -11,6 +13,7 @@ logger = logging.getLogger()
import hwsim_utils
import hostapd
from test_ap_psk import find_wpas_process, read_process_memory, verify_not_present, get_key_locations
def test_sae(dev, apdev):
"""SAE with default group"""
@ -161,3 +164,123 @@ def test_sae_missing_password(dev, apdev):
ev = dev[0].wait_event(['CTRL-EVENT-SSID-TEMP-DISABLED'], timeout=10)
if ev is None:
raise Exception("Invalid network not temporarily disabled")
def test_sae_key_lifetime_in_memory(dev, apdev, params):
"""SAE and key lifetime in memory"""
password = "5ad144a7c1f5a5503baa6fa01dabc15b1843e8c01662d78d16b70b5cd23cf8b"
p = hostapd.wpa2_params(ssid="test-sae", passphrase=password)
p['wpa_key_mgmt'] = 'SAE'
hapd = hostapd.add_ap(apdev[0]['ifname'], p)
pid = find_wpas_process(dev[0])
dev[0].request("SET sae_groups ")
id = dev[0].connect("test-sae", psk=password, key_mgmt="SAE",
scan_freq="2412")
time.sleep(0.1)
buf = read_process_memory(pid, password)
dev[0].request("DISCONNECT")
dev[0].wait_disconnected()
dev[0].relog()
sae_k = None
sae_keyseed = None
sae_kck = None
pmk = None
ptk = None
gtk = None
with open(os.path.join(params['logdir'], 'log0'), 'r') as f:
for l in f.readlines():
if "SAE: k - hexdump" in l:
val = l.strip().split(':')[3].replace(' ', '')
sae_k = binascii.unhexlify(val)
if "SAE: keyseed - hexdump" in l:
val = l.strip().split(':')[3].replace(' ', '')
sae_keyseed = binascii.unhexlify(val)
if "SAE: KCK - hexdump" in l:
val = l.strip().split(':')[3].replace(' ', '')
sae_kck = binascii.unhexlify(val)
if "SAE: PMK - hexdump" in l:
val = l.strip().split(':')[3].replace(' ', '')
pmk = binascii.unhexlify(val)
if "WPA: PTK - hexdump" in l:
val = l.strip().split(':')[3].replace(' ', '')
ptk = binascii.unhexlify(val)
if "WPA: Group Key - hexdump" in l:
val = l.strip().split(':')[3].replace(' ', '')
gtk = binascii.unhexlify(val)
if not sae_k or not sae_keyseed or not sae_kck or not pmk or not ptk or not gtk:
raise Exception("Could not find keys from debug log")
if len(gtk) != 16:
raise Exception("Unexpected GTK length")
kck = ptk[0:16]
kek = ptk[16:32]
tk = ptk[32:48]
fname = os.path.join(params['logdir'],
'sae_key_lifetime_in_memory.memctx-')
logger.info("Checking keys in memory while associated")
get_key_locations(buf, password, "Password")
get_key_locations(buf, pmk, "PMK")
if password not in buf:
print("Password not found while associated")
return "skip"
if pmk not in buf:
print("PMK not found while associated")
return "skip"
if kck not in buf:
raise Exception("KCK not found while associated")
if kek not in buf:
raise Exception("KEK not found while associated")
if tk in buf:
raise Exception("TK found from memory")
if gtk in buf:
raise Exception("GTK found from memory")
verify_not_present(buf, sae_k, fname, "SAE(k)")
verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)")
verify_not_present(buf, sae_kck, fname, "SAE(KCK)")
logger.info("Checking keys in memory after disassociation")
buf = read_process_memory(pid, password)
# Note: Password is still present in network configuration
# Note: PMK is in PMKSA cache
get_key_locations(buf, password, "Password")
get_key_locations(buf, pmk, "PMK")
verify_not_present(buf, kck, fname, "KCK")
verify_not_present(buf, kek, fname, "KEK")
verify_not_present(buf, tk, fname, "TK")
verify_not_present(buf, gtk, fname, "GTK")
verify_not_present(buf, sae_k, fname, "SAE(k)")
verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)")
verify_not_present(buf, sae_kck, fname, "SAE(KCK)")
dev[0].request("PMKSA_FLUSH")
logger.info("Checking keys in memory after PMKSA cache flush")
buf = read_process_memory(pid, password)
get_key_locations(buf, password, "Password")
get_key_locations(buf, pmk, "PMK")
verify_not_present(buf, pmk, fname, "PMK")
dev[0].request("REMOVE_NETWORK all")
logger.info("Checking keys in memory after network profile removal")
buf = read_process_memory(pid, password)
get_key_locations(buf, password, "Password")
get_key_locations(buf, pmk, "PMK")
verify_not_present(buf, password, fname, "password")
verify_not_present(buf, pmk, fname, "PMK")
verify_not_present(buf, kck, fname, "KCK")
verify_not_present(buf, kek, fname, "KEK")
verify_not_present(buf, tk, fname, "TK")
verify_not_present(buf, gtk, fname, "GTK")
verify_not_present(buf, sae_k, fname, "SAE(k)")
verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)")
verify_not_present(buf, sae_kck, fname, "SAE(KCK)")