hostapd/tests/hwsim/test_ap_ft.py
Jouni Malinen 6219d5a5c2 tests: Make FT roaming and data connectivity checks more robust
Dump pending monitor interface messages between each roaming step to
make the test log easier to understand and hostapd wait for the new
connection more robust by ensuring that the processed event if for the
very last reassociation. It looks like at least ap_ft_vlan_over_ds_many
could fail due to the connectivity check being started before the final
roam had been completed on the AP side even though there was an explicit
hapd2ap.wait_sta() wait before the test.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
2021-03-19 20:54:16 +02:00

3451 lines
136 KiB
Python

# Fast BSS Transition tests
# Copyright (c) 2013-2019, Jouni Malinen <j@w1.fi>
#
# This software may be distributed under the terms of the BSD license.
# See README for more details.
from remotehost import remote_compatible
import binascii
import os
import time
import logging
logger = logging.getLogger()
import signal
import struct
import subprocess
import hwsim_utils
from hwsim import HWSimRadio
import hostapd
from tshark import run_tshark
from utils import *
from wlantest import Wlantest
from test_ap_psk import check_mib, find_wpas_process, read_process_memory, verify_not_present, get_key_locations
from test_rrm import check_beacon_req
from test_suite_b import check_suite_b_192_capa
def ft_base_rsn():
params = {"wpa": "2",
"wpa_key_mgmt": "FT-PSK",
"rsn_pairwise": "CCMP"}
return params
def ft_base_mixed():
params = {"wpa": "3",
"wpa_key_mgmt": "WPA-PSK FT-PSK",
"wpa_pairwise": "TKIP",
"rsn_pairwise": "CCMP"}
return params
def ft_params(rsn=True, ssid=None, passphrase=None):
if rsn:
params = ft_base_rsn()
else:
params = ft_base_mixed()
if ssid:
params["ssid"] = ssid
if passphrase:
params["wpa_passphrase"] = passphrase
params["mobility_domain"] = "a1b2"
params["r0_key_lifetime"] = "10000"
params["pmk_r1_push"] = "1"
params["reassociation_deadline"] = "1000"
return params
def ft_params1a(rsn=True, ssid=None, passphrase=None):
params = ft_params(rsn, ssid, passphrase)
params['nas_identifier'] = "nas1.w1.fi"
params['r1_key_holder'] = "000102030405"
return params
def ft_params1(rsn=True, ssid=None, passphrase=None, discovery=False):
params = ft_params1a(rsn, ssid, passphrase)
if discovery:
params['r0kh'] = "ff:ff:ff:ff:ff:ff * 100102030405060708090a0b0c0d0e0f100102030405060708090a0b0c0d0e0f"
params['r1kh'] = "00:00:00:00:00:00 00:00:00:00:00:00 100102030405060708090a0b0c0d0e0f100102030405060708090a0b0c0d0e0f"
else:
params['r0kh'] = ["02:00:00:00:03:00 nas1.w1.fi 100102030405060708090a0b0c0d0e0f100102030405060708090a0b0c0d0e0f",
"02:00:00:00:04:00 nas2.w1.fi 300102030405060708090a0b0c0d0e0f300102030405060708090a0b0c0d0e0f"]
params['r1kh'] = "02:00:00:00:04:00 00:01:02:03:04:06 200102030405060708090a0b0c0d0e0f200102030405060708090a0b0c0d0e0f"
return params
def ft_params1_old_key(rsn=True, ssid=None, passphrase=None):
params = ft_params1a(rsn, ssid, passphrase)
params['r0kh'] = ["02:00:00:00:03:00 nas1.w1.fi 100102030405060708090a0b0c0d0e0f",
"02:00:00:00:04:00 nas2.w1.fi 300102030405060708090a0b0c0d0e0f"]
params['r1kh'] = "02:00:00:00:04:00 00:01:02:03:04:06 200102030405060708090a0b0c0d0e0f"
return params
def ft_params2a(rsn=True, ssid=None, passphrase=None):
params = ft_params(rsn, ssid, passphrase)
params['nas_identifier'] = "nas2.w1.fi"
params['r1_key_holder'] = "000102030406"
return params
def ft_params2(rsn=True, ssid=None, passphrase=None, discovery=False):
params = ft_params2a(rsn, ssid, passphrase)
if discovery:
params['r0kh'] = "ff:ff:ff:ff:ff:ff * 100102030405060708090a0b0c0d0e0f100102030405060708090a0b0c0d0e0f"
params['r1kh'] = "00:00:00:00:00:00 00:00:00:00:00:00 100102030405060708090a0b0c0d0e0f100102030405060708090a0b0c0d0e0f"
else:
params['r0kh'] = ["02:00:00:00:03:00 nas1.w1.fi 200102030405060708090a0b0c0d0e0f200102030405060708090a0b0c0d0e0f",
"02:00:00:00:04:00 nas2.w1.fi 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"]
params['r1kh'] = "02:00:00:00:03:00 00:01:02:03:04:05 300102030405060708090a0b0c0d0e0f300102030405060708090a0b0c0d0e0f"
return params
def ft_params2_old_key(rsn=True, ssid=None, passphrase=None):
params = ft_params2a(rsn, ssid, passphrase)
params['r0kh'] = ["02:00:00:00:03:00 nas1.w1.fi 200102030405060708090a0b0c0d0e0f",
"02:00:00:00:04:00 nas2.w1.fi 000102030405060708090a0b0c0d0e0f"]
params['r1kh'] = "02:00:00:00:03:00 00:01:02:03:04:05 300102030405060708090a0b0c0d0e0f"
return params
def ft_params1_r0kh_mismatch(rsn=True, ssid=None, passphrase=None):
params = ft_params(rsn, ssid, passphrase)
params['nas_identifier'] = "nas1.w1.fi"
params['r1_key_holder'] = "000102030405"
params['r0kh'] = ["02:00:00:00:03:00 nas1.w1.fi 100102030405060708090a0b0c0d0e0f100102030405060708090a0b0c0d0e0f",
"12:00:00:00:04:00 nas2.w1.fi 300102030405060708090a0b0c0d0e0f300102030405060708090a0b0c0d0e0f"]
params['r1kh'] = "12:00:00:00:04:00 10:01:02:03:04:06 200102030405060708090a0b0c0d0e0f200102030405060708090a0b0c0d0e0f"
return params
def ft_params2_incorrect_rrb_key(rsn=True, ssid=None, passphrase=None):
params = ft_params(rsn, ssid, passphrase)
params['nas_identifier'] = "nas2.w1.fi"
params['r1_key_holder'] = "000102030406"
params['r0kh'] = ["02:00:00:00:03:00 nas1.w1.fi 200102030405060708090a0b0c0d0ef1200102030405060708090a0b0c0d0ef1",
"02:00:00:00:04:00 nas2.w1.fi 000102030405060708090a0b0c0d0ef2000102030405060708090a0b0c0d0ef2"]
params['r1kh'] = "02:00:00:00:03:00 00:01:02:03:04:05 300102030405060708090a0b0c0d0ef3300102030405060708090a0b0c0d0ef3"
return params
def ft_params2_r0kh_mismatch(rsn=True, ssid=None, passphrase=None):
params = ft_params(rsn, ssid, passphrase)
params['nas_identifier'] = "nas2.w1.fi"
params['r1_key_holder'] = "000102030406"
params['r0kh'] = ["12:00:00:00:03:00 nas1.w1.fi 200102030405060708090a0b0c0d0e0f200102030405060708090a0b0c0d0e0f",
"02:00:00:00:04:00 nas2.w1.fi 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"]
params['r1kh'] = "12:00:00:00:03:00 10:01:02:03:04:05 300102030405060708090a0b0c0d0e0f300102030405060708090a0b0c0d0e0f"
return params
def run_roams(dev, apdev, hapd0, hapd1, ssid, passphrase, over_ds=False,
sae=False, eap=False, fail_test=False, roams=1,
pairwise_cipher="CCMP", group_cipher="CCMP", ptk_rekey="0",
test_connectivity=True, eap_identity="gpsk user", conndev=False,
force_initial_conn_to_first_ap=False, sha384=False,
group_mgmt=None, ocv=None, sae_password=None,
sae_password_id=None, sae_and_psk=False, pmksa_caching=False,
roam_with_reassoc=False, also_non_ft=False, only_one_way=False,
wait_before_roam=0, return_after_initial=False, ieee80211w="1",
sae_transition=False):
logger.info("Connect to first AP")
copts = {}
copts["proto"] = "WPA2"
copts["ieee80211w"] = ieee80211w
copts["scan_freq"] = "2412"
copts["pairwise"] = pairwise_cipher
copts["group"] = group_cipher
copts["wpa_ptk_rekey"] = ptk_rekey
if group_mgmt:
copts["group_mgmt"] = group_mgmt
if ocv:
copts["ocv"] = ocv
if eap:
if pmksa_caching:
copts["ft_eap_pmksa_caching"] = "1"
if also_non_ft:
copts["key_mgmt"] = "WPA-EAP-SUITE-B-192 FT-EAP-SHA384" if sha384 else "WPA-EAP FT-EAP"
else:
copts["key_mgmt"] = "FT-EAP-SHA384" if sha384 else "FT-EAP"
copts["eap"] = "GPSK"
copts["identity"] = eap_identity
copts["password"] = "abcdefghijklmnop0123456789abcdef"
else:
if sae_transition:
copts["key_mgmt"] = "FT-SAE FT-PSK"
elif sae:
copts["key_mgmt"] = "SAE FT-SAE" if sae_and_psk else "FT-SAE"
else:
copts["key_mgmt"] = "FT-PSK"
if passphrase:
copts["psk"] = passphrase
if sae_password:
copts["sae_password"] = sae_password
if sae_password_id:
copts["sae_password_id"] = sae_password_id
if force_initial_conn_to_first_ap:
copts["bssid"] = apdev[0]['bssid']
netw = dev.connect(ssid, **copts)
if pmksa_caching:
if dev.get_status_field('bssid') == apdev[0]['bssid']:
hapd0.wait_sta()
else:
hapd1.wait_sta()
dev.request("DISCONNECT")
dev.wait_disconnected()
dev.request("RECONNECT")
ev = dev.wait_event(["CTRL-EVENT-CONNECTED",
"CTRL-EVENT-DISCONNECTED",
"CTRL-EVENT-EAP-STARTED"],
timeout=15)
if ev is None:
raise Exception("Reconnect timed out")
if "CTRL-EVENT-DISCONNECTED" in ev:
raise Exception("Unexpected disconnection after RECONNECT")
if "CTRL-EVENT-EAP-STARTED" in ev:
raise Exception("Unexpected EAP start after RECONNECT")
if dev.get_status_field('bssid') == apdev[0]['bssid']:
ap1 = apdev[0]
ap2 = apdev[1]
hapd1ap = hapd0
hapd2ap = hapd1
else:
ap1 = apdev[1]
ap2 = apdev[0]
hapd1ap = hapd1
hapd2ap = hapd0
if test_connectivity:
hapd1ap.wait_sta()
if conndev:
hwsim_utils.test_connectivity_iface(dev, hapd1ap, conndev)
else:
hwsim_utils.test_connectivity(dev, hapd1ap)
if return_after_initial:
return ap2['bssid']
if wait_before_roam:
time.sleep(wait_before_roam)
dev.scan_for_bss(ap2['bssid'], freq="2412")
for i in range(0, roams):
dev.dump_monitor()
hapd1ap.dump_monitor()
hapd2ap.dump_monitor()
# Roaming artificially fast can make data test fail because the key is
# set later.
time.sleep(0.01)
logger.info("Roam to the second AP")
if roam_with_reassoc:
dev.set_network(netw, "bssid", ap2['bssid'])
dev.request("REASSOCIATE")
dev.wait_connected()
elif over_ds:
dev.roam_over_ds(ap2['bssid'], fail_test=fail_test)
else:
dev.roam(ap2['bssid'], fail_test=fail_test)
if fail_test:
return
if dev.get_status_field('bssid') != ap2['bssid']:
raise Exception("Did not connect to correct AP")
if (i == 0 or i == roams - 1) and test_connectivity:
hapd2ap.wait_sta()
dev.dump_monitor()
hapd1ap.dump_monitor()
hapd2ap.dump_monitor()
if conndev:
hwsim_utils.test_connectivity_iface(dev, hapd2ap, conndev)
else:
hwsim_utils.test_connectivity(dev, hapd2ap)
dev.dump_monitor()
hapd1ap.dump_monitor()
hapd2ap.dump_monitor()
if only_one_way:
return
# Roaming artificially fast can make data test fail because the key is
# set later.
time.sleep(0.01)
logger.info("Roam back to the first AP")
if roam_with_reassoc:
dev.set_network(netw, "bssid", ap1['bssid'])
dev.request("REASSOCIATE")
dev.wait_connected()
elif over_ds:
dev.roam_over_ds(ap1['bssid'])
else:
dev.roam(ap1['bssid'])
if dev.get_status_field('bssid') != ap1['bssid']:
raise Exception("Did not connect to correct AP")
if (i == 0 or i == roams - 1) and test_connectivity:
hapd1ap.wait_sta()
dev.dump_monitor()
hapd1ap.dump_monitor()
hapd2ap.dump_monitor()
if conndev:
hwsim_utils.test_connectivity_iface(dev, hapd1ap, conndev)
else:
hwsim_utils.test_connectivity(dev, hapd1ap)
def test_ap_ft(dev, apdev):
"""WPA2-PSK-FT AP"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase)
if "[WPA2-FT/PSK-CCMP]" not in dev[0].request("SCAN_RESULTS"):
raise Exception("Scan results missing RSN element info")
def test_ap_ft_old_key(dev, apdev):
"""WPA2-PSK-FT AP (old key)"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1_old_key(ssid=ssid, passphrase=passphrase)
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2_old_key(ssid=ssid, passphrase=passphrase)
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase)
def test_ap_ft_multi_akm(dev, apdev):
"""WPA2-PSK-FT AP with non-FT AKMs enabled"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["wpa_key_mgmt"] = "FT-PSK WPA-PSK WPA-PSK-SHA256"
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params["wpa_key_mgmt"] = "FT-PSK WPA-PSK WPA-PSK-SHA256"
hapd1 = hostapd.add_ap(apdev[1], params)
Wlantest.setup(hapd0)
wt = Wlantest()
wt.flush()
wt.add_passphrase(passphrase)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase)
if "[WPA2-PSK+FT/PSK+PSK-SHA256-CCMP]" not in dev[0].request("SCAN_RESULTS"):
raise Exception("Scan results missing RSN element info")
dev[1].connect(ssid, psk=passphrase, scan_freq="2412")
dev[2].connect(ssid, psk=passphrase, key_mgmt="WPA-PSK-SHA256",
scan_freq="2412")
def test_ap_ft_local_key_gen(dev, apdev):
"""WPA2-PSK-FT AP with local key generation (without pull/push)"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1a(ssid=ssid, passphrase=passphrase)
params['ft_psk_generate_local'] = "1"
del params['pmk_r1_push']
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2a(ssid=ssid, passphrase=passphrase)
params['ft_psk_generate_local'] = "1"
del params['pmk_r1_push']
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase)
if "[WPA2-FT/PSK-CCMP]" not in dev[0].request("SCAN_RESULTS"):
raise Exception("Scan results missing RSN element info")
def test_ap_ft_vlan(dev, apdev):
"""WPA2-PSK-FT AP with VLAN"""
ssid = "test-ft"
passphrase = "12345678"
filename = hostapd.acl_file(dev, apdev, 'hostapd.accept')
hostapd.send_file(apdev[0], filename, filename)
hostapd.send_file(apdev[1], filename, filename)
params = ft_params1(ssid=ssid, passphrase=passphrase)
params['dynamic_vlan'] = "1"
params['accept_mac_file'] = filename
hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params['dynamic_vlan'] = "1"
params['accept_mac_file'] = filename
hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, conndev="brvlan1")
if "[WPA2-FT/PSK-CCMP]" not in dev[0].request("SCAN_RESULTS"):
raise Exception("Scan results missing RSN element info")
if filename.startswith('/tmp/'):
os.unlink(filename)
def test_ap_ft_vlan_disconnected(dev, apdev):
"""WPA2-PSK-FT AP with VLAN and local key generation"""
ssid = "test-ft"
passphrase = "12345678"
filename = hostapd.acl_file(dev, apdev, 'hostapd.accept')
hostapd.send_file(apdev[0], filename, filename)
hostapd.send_file(apdev[1], filename, filename)
params = ft_params1a(ssid=ssid, passphrase=passphrase)
params['dynamic_vlan'] = "1"
params['accept_mac_file'] = filename
params['ft_psk_generate_local'] = "1"
hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
params = ft_params2a(ssid=ssid, passphrase=passphrase)
params['dynamic_vlan'] = "1"
params['accept_mac_file'] = filename
params['ft_psk_generate_local'] = "1"
hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, conndev="brvlan1")
if "[WPA2-FT/PSK-CCMP]" not in dev[0].request("SCAN_RESULTS"):
raise Exception("Scan results missing RSN element info")
if filename.startswith('/tmp/'):
os.unlink(filename)
def test_ap_ft_vlan_2(dev, apdev):
"""WPA2-PSK-FT AP with VLAN and dest-AP does not have VLAN info locally"""
ssid = "test-ft"
passphrase = "12345678"
filename = hostapd.acl_file(dev, apdev, 'hostapd.accept')
hostapd.send_file(apdev[0], filename, filename)
params = ft_params1(ssid=ssid, passphrase=passphrase)
params['dynamic_vlan'] = "1"
params['accept_mac_file'] = filename
hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params['dynamic_vlan'] = "1"
hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, conndev="brvlan1",
force_initial_conn_to_first_ap=True)
if "[WPA2-FT/PSK-CCMP]" not in dev[0].request("SCAN_RESULTS"):
raise Exception("Scan results missing RSN element info")
if filename.startswith('/tmp/'):
os.unlink(filename)
def test_ap_ft_many(dev, apdev):
"""WPA2-PSK-FT AP multiple times"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, roams=50)
def test_ap_ft_many_vlan(dev, apdev):
"""WPA2-PSK-FT AP with VLAN multiple times"""
ssid = "test-ft"
passphrase = "12345678"
filename = hostapd.acl_file(dev, apdev, 'hostapd.accept')
hostapd.send_file(apdev[0], filename, filename)
hostapd.send_file(apdev[1], filename, filename)
params = ft_params1(ssid=ssid, passphrase=passphrase)
params['dynamic_vlan'] = "1"
params['accept_mac_file'] = filename
hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params['dynamic_vlan'] = "1"
params['accept_mac_file'] = filename
hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, roams=50,
conndev="brvlan1")
if filename.startswith('/tmp/'):
os.unlink(filename)
def test_ap_ft_mixed(dev, apdev):
"""WPA2-PSK-FT mixed-mode AP"""
skip_without_tkip(dev[0])
ssid = "test-ft-mixed"
passphrase = "12345678"
params = ft_params1(rsn=False, ssid=ssid, passphrase=passphrase)
hapd = hostapd.add_ap(apdev[0], params)
key_mgmt = hapd.get_config()['key_mgmt']
vals = key_mgmt.split(' ')
if vals[0] != "WPA-PSK" or vals[1] != "FT-PSK":
raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
params = ft_params2(rsn=False, ssid=ssid, passphrase=passphrase)
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd, hapd1, ssid, passphrase,
group_cipher="TKIP CCMP")
def test_ap_ft_pmf(dev, apdev):
"""WPA2-PSK-FT AP with PMF"""
run_ap_ft_pmf(dev, apdev, "1")
def test_ap_ft_pmf_over_ds(dev, apdev):
"""WPA2-PSK-FT AP with PMF (over DS)"""
run_ap_ft_pmf(dev, apdev, "1", over_ds=True)
def test_ap_ft_pmf_required(dev, apdev):
"""WPA2-PSK-FT AP with PMF required on STA"""
run_ap_ft_pmf(dev, apdev, "2")
def test_ap_ft_pmf_required_over_ds(dev, apdev):
"""WPA2-PSK-FT AP with PMF required on STA (over DS)"""
run_ap_ft_pmf(dev, apdev, "2", over_ds=True)
def run_ap_ft_pmf(dev, apdev, ieee80211w, over_ds=False):
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
hapd1 = hostapd.add_ap(apdev[1], params)
Wlantest.setup(hapd0)
wt = Wlantest()
wt.flush()
wt.add_passphrase(passphrase)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase,
ieee80211w=ieee80211w, over_ds=over_ds)
def test_ap_ft_pmf_required_mismatch(dev, apdev):
"""WPA2-PSK-FT AP with PMF required on STA but AP2 not enabling PMF"""
run_ap_ft_pmf_required_mismatch(dev, apdev)
def test_ap_ft_pmf_required_mismatch_over_ds(dev, apdev):
"""WPA2-PSK-FT AP with PMF required on STA but AP2 not enabling PMF (over DS)"""
run_ap_ft_pmf_required_mismatch(dev, apdev, over_ds=True)
def run_ap_ft_pmf_required_mismatch(dev, apdev, over_ds=False):
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "0"
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, ieee80211w="2",
force_initial_conn_to_first_ap=True, fail_test=True,
over_ds=over_ds)
def test_ap_ft_pmf_bip_cmac_128(dev, apdev):
"""WPA2-PSK-FT AP with PMF/BIP-CMAC-128"""
run_ap_ft_pmf_bip(dev, apdev, "AES-128-CMAC")
def test_ap_ft_pmf_bip_gmac_128(dev, apdev):
"""WPA2-PSK-FT AP with PMF/BIP-GMAC-128"""
run_ap_ft_pmf_bip(dev, apdev, "BIP-GMAC-128")
def test_ap_ft_pmf_bip_gmac_256(dev, apdev):
"""WPA2-PSK-FT AP with PMF/BIP-GMAC-256"""
run_ap_ft_pmf_bip(dev, apdev, "BIP-GMAC-256")
def test_ap_ft_pmf_bip_cmac_256(dev, apdev):
"""WPA2-PSK-FT AP with PMF/BIP-CMAC-256"""
run_ap_ft_pmf_bip(dev, apdev, "BIP-CMAC-256")
def run_ap_ft_pmf_bip(dev, apdev, cipher):
if cipher not in dev[0].get_capability("group_mgmt"):
raise HwsimSkip("Cipher %s not supported" % cipher)
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
params["group_mgmt_cipher"] = cipher
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
params["group_mgmt_cipher"] = cipher
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase,
group_mgmt=cipher)
def test_ap_ft_ocv(dev, apdev):
"""WPA2-PSK-FT AP with OCV"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
params["ocv"] = "1"
try:
hapd0 = hostapd.add_ap(apdev[0], params)
except Exception as e:
if "Failed to set hostapd parameter ocv" in str(e):
raise HwsimSkip("OCV not supported")
raise
params = ft_params2(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
params["ocv"] = "1"
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, ocv="1")
def test_ap_ft_over_ds(dev, apdev):
"""WPA2-PSK-FT AP over DS"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True)
check_mib(dev[0], [("dot11RSNAAuthenticationSuiteRequested", "00-0f-ac-4"),
("dot11RSNAAuthenticationSuiteSelected", "00-0f-ac-4")])
def cleanup_ap_ft_separate_hostapd():
subprocess.call(["brctl", "delif", "br0ft", "veth0"],
stderr=open('/dev/null', 'w'))
subprocess.call(["brctl", "delif", "br1ft", "veth1"],
stderr=open('/dev/null', 'w'))
subprocess.call(["ip", "link", "del", "veth0"],
stderr=open('/dev/null', 'w'))
subprocess.call(["ip", "link", "del", "veth1"],
stderr=open('/dev/null', 'w'))
for ifname in ['br0ft', 'br1ft', 'br-ft']:
subprocess.call(['ip', 'link', 'set', 'dev', ifname, 'down'],
stderr=open('/dev/null', 'w'))
subprocess.call(['brctl', 'delbr', ifname],
stderr=open('/dev/null', 'w'))
def test_ap_ft_separate_hostapd(dev, apdev, params):
"""WPA2-PSK-FT AP and separate hostapd process"""
try:
run_ap_ft_separate_hostapd(dev, apdev, params, False)
finally:
cleanup_ap_ft_separate_hostapd()
def test_ap_ft_over_ds_separate_hostapd(dev, apdev, params):
"""WPA2-PSK-FT AP over DS and separate hostapd process"""
try:
run_ap_ft_separate_hostapd(dev, apdev, params, True)
finally:
cleanup_ap_ft_separate_hostapd()
def run_ap_ft_separate_hostapd(dev, apdev, params, over_ds):
ssid = "test-ft"
passphrase = "12345678"
logdir = params['logdir']
pidfile = os.path.join(logdir, 'ap_ft_over_ds_separate_hostapd.pid')
logfile = os.path.join(logdir, 'ap_ft_over_ds_separate_hostapd.hapd')
global_ctrl = '/var/run/hostapd-ft'
br_ifname = 'br-ft'
try:
subprocess.check_call(['brctl', 'addbr', br_ifname])
subprocess.check_call(['brctl', 'setfd', br_ifname, '0'])
subprocess.check_call(['ip', 'link', 'set', 'dev', br_ifname, 'up'])
subprocess.check_call(["ip", "link", "add", "veth0", "type", "veth",
"peer", "name", "veth0br"])
subprocess.check_call(["ip", "link", "add", "veth1", "type", "veth",
"peer", "name", "veth1br"])
subprocess.check_call(['ip', 'link', 'set', 'dev', 'veth0br', 'up'])
subprocess.check_call(['ip', 'link', 'set', 'dev', 'veth1br', 'up'])
subprocess.check_call(['brctl', 'addif', br_ifname, 'veth0br'])
subprocess.check_call(['brctl', 'addif', br_ifname, 'veth1br'])
subprocess.check_call(['brctl', 'addbr', 'br0ft'])
subprocess.check_call(['brctl', 'setfd', 'br0ft', '0'])
subprocess.check_call(['ip', 'link', 'set', 'dev', 'br0ft', 'up'])
subprocess.check_call(['ip', 'link', 'set', 'dev', 'veth0', 'up'])
subprocess.check_call(['brctl', 'addif', 'br0ft', 'veth0'])
subprocess.check_call(['brctl', 'addbr', 'br1ft'])
subprocess.check_call(['brctl', 'setfd', 'br1ft', '0'])
subprocess.check_call(['ip', 'link', 'set', 'dev', 'br1ft', 'up'])
subprocess.check_call(['ip', 'link', 'set', 'dev', 'veth1', 'up'])
subprocess.check_call(['brctl', 'addif', 'br1ft', 'veth1'])
except subprocess.CalledProcessError:
raise HwsimSkip("Bridge or veth not supported (kernel CONFIG_VETH)")
with HWSimRadio() as (radio, iface):
prg = os.path.join(logdir, 'alt-hostapd/hostapd/hostapd')
if not os.path.exists(prg):
prg = '../../hostapd/hostapd'
cmd = [prg, '-B', '-ddKt',
'-P', pidfile, '-f', logfile, '-g', global_ctrl]
subprocess.check_call(cmd)
hglobal = hostapd.HostapdGlobal(global_ctrl_override=global_ctrl)
apdev_ft = {'ifname': iface}
apdev2 = [apdev_ft, apdev[1]]
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["r0kh"] = "ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
params["r1kh"] = "00:00:00:00:00:00 00:00:00:00:00:00 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
params['bridge'] = 'br0ft'
hapd0 = hostapd.add_ap(apdev2[0], params,
global_ctrl_override=global_ctrl)
apdev2[0]['bssid'] = hapd0.own_addr()
params = ft_params2(ssid=ssid, passphrase=passphrase)
params["r0kh"] = "ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
params["r1kh"] = "00:00:00:00:00:00 00:00:00:00:00:00 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
params['bridge'] = 'br1ft'
hapd1 = hostapd.add_ap(apdev2[1], params)
run_roams(dev[0], apdev2, hapd0, hapd1, ssid, passphrase,
over_ds=over_ds, test_connectivity=False, roams=2)
hglobal.terminate()
if os.path.exists(pidfile):
with open(pidfile, 'r') as f:
pid = int(f.read())
f.close()
os.kill(pid, signal.SIGTERM)
def test_ap_ft_over_ds_ocv(dev, apdev):
"""WPA2-PSK-FT AP over DS"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
params["ocv"] = "1"
try:
hapd0 = hostapd.add_ap(apdev[0], params)
except Exception as e:
if "Failed to set hostapd parameter ocv" in str(e):
raise HwsimSkip("OCV not supported")
raise
params = ft_params2(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
params["ocv"] = "1"
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
ocv="1")
def test_ap_ft_over_ds_disabled(dev, apdev):
"""WPA2-PSK-FT AP over DS disabled"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params['ft_over_ds'] = '0'
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params['ft_over_ds'] = '0'
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
fail_test=True)
def test_ap_ft_vlan_over_ds(dev, apdev):
"""WPA2-PSK-FT AP over DS with VLAN"""
ssid = "test-ft"
passphrase = "12345678"
filename = hostapd.acl_file(dev, apdev, 'hostapd.accept')
hostapd.send_file(apdev[0], filename, filename)
hostapd.send_file(apdev[1], filename, filename)
params = ft_params1(ssid=ssid, passphrase=passphrase)
params['dynamic_vlan'] = "1"
params['accept_mac_file'] = filename
hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params['dynamic_vlan'] = "1"
params['accept_mac_file'] = filename
hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
conndev="brvlan1")
check_mib(dev[0], [("dot11RSNAAuthenticationSuiteRequested", "00-0f-ac-4"),
("dot11RSNAAuthenticationSuiteSelected", "00-0f-ac-4")])
if filename.startswith('/tmp/'):
os.unlink(filename)
def test_ap_ft_over_ds_many(dev, apdev):
"""WPA2-PSK-FT AP over DS multiple times"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
roams=50)
def test_ap_ft_vlan_over_ds_many(dev, apdev):
"""WPA2-PSK-FT AP over DS with VLAN multiple times"""
ssid = "test-ft"
passphrase = "12345678"
filename = hostapd.acl_file(dev, apdev, 'hostapd.accept')
hostapd.send_file(apdev[0], filename, filename)
hostapd.send_file(apdev[1], filename, filename)
params = ft_params1(ssid=ssid, passphrase=passphrase)
params['dynamic_vlan'] = "1"
params['accept_mac_file'] = filename
hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params['dynamic_vlan'] = "1"
params['accept_mac_file'] = filename
hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
roams=50, conndev="brvlan1")
if filename.startswith('/tmp/'):
os.unlink(filename)
@remote_compatible
def test_ap_ft_over_ds_unknown_target(dev, apdev):
"""WPA2-PSK-FT AP"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
hapd0 = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
dev[0].roam_over_ds("02:11:22:33:44:55", fail_test=True)
@remote_compatible
def test_ap_ft_over_ds_unexpected(dev, apdev):
"""WPA2-PSK-FT AP over DS and unexpected response"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
hapd1 = hostapd.add_ap(apdev[1], params)
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
if dev[0].get_status_field('bssid') == apdev[0]['bssid']:
ap1 = apdev[0]
ap2 = apdev[1]
hapd1ap = hapd0
hapd2ap = hapd1
else:
ap1 = apdev[1]
ap2 = apdev[0]
hapd1ap = hapd1
hapd2ap = hapd0
addr = dev[0].own_addr()
hapd1ap.set("ext_mgmt_frame_handling", "1")
logger.info("Foreign STA address")
msg = {}
msg['fc'] = 13 << 4
msg['da'] = addr
msg['sa'] = ap1['bssid']
msg['bssid'] = ap1['bssid']
msg['payload'] = binascii.unhexlify("06021122334455660102030405060000")
hapd1ap.mgmt_tx(msg)
logger.info("No over-the-DS in progress")
msg['payload'] = binascii.unhexlify("0602" + addr.replace(':', '') + "0102030405060000")
hapd1ap.mgmt_tx(msg)
logger.info("Non-zero status code")
msg['payload'] = binascii.unhexlify("0602" + addr.replace(':', '') + "0102030405060100")
hapd1ap.mgmt_tx(msg)
hapd1ap.dump_monitor()
dev[0].scan_for_bss(ap2['bssid'], freq="2412")
if "OK" not in dev[0].request("FT_DS " + ap2['bssid']):
raise Exception("FT_DS failed")
req = hapd1ap.mgmt_rx()
logger.info("Foreign Target AP")
msg['payload'] = binascii.unhexlify("0602" + addr.replace(':', '') + "0102030405060000")
hapd1ap.mgmt_tx(msg)
addrs = addr.replace(':', '') + ap2['bssid'].replace(':', '')
logger.info("No IEs")
msg['payload'] = binascii.unhexlify("0602" + addrs + "0000")
hapd1ap.mgmt_tx(msg)
logger.info("Invalid IEs (trigger parsing failure)")
msg['payload'] = binascii.unhexlify("0602" + addrs + "00003700")
hapd1ap.mgmt_tx(msg)
logger.info("Too short MDIE")
msg['payload'] = binascii.unhexlify("0602" + addrs + "000036021122")
hapd1ap.mgmt_tx(msg)
logger.info("Mobility domain mismatch")
msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603112201")
hapd1ap.mgmt_tx(msg)
logger.info("No FTIE")
msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603a1b201")
hapd1ap.mgmt_tx(msg)
logger.info("FTIE SNonce mismatch")
msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603a1b201375e0000" + "00000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "1000000000000000000000000000000000000000000000000000000000000001" + "030a6e6173322e77312e6669")
hapd1ap.mgmt_tx(msg)
logger.info("No R0KH-ID subelem in FTIE")
snonce = binascii.hexlify(req['payload'][111:111+32]).decode()
msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603a1b20137520000" + "00000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + snonce)
hapd1ap.mgmt_tx(msg)
logger.info("No R0KH-ID subelem mismatch in FTIE")
snonce = binascii.hexlify(req['payload'][111:111+32]).decode()
msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603a1b201375e0000" + "00000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + snonce + "030a11223344556677889900")
hapd1ap.mgmt_tx(msg)
logger.info("No R1KH-ID subelem in FTIE")
r0khid = binascii.hexlify(req['payload'][145:145+10]).decode()
msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603a1b201375e0000" + "00000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + snonce + "030a" + r0khid)
hapd1ap.mgmt_tx(msg)
logger.info("No RSNE")
r0khid = binascii.hexlify(req['payload'][145:145+10]).decode()
msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603a1b20137660000" + "00000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + snonce + "030a" + r0khid + "0106000102030405")
hapd1ap.mgmt_tx(msg)
def test_ap_ft_pmf_over_ds(dev, apdev):
"""WPA2-PSK-FT AP over DS with PMF"""
run_ap_ft_pmf_bip_over_ds(dev, apdev, None)
def test_ap_ft_pmf_bip_cmac_128_over_ds(dev, apdev):
"""WPA2-PSK-FT AP over DS with PMF/BIP-CMAC-128"""
run_ap_ft_pmf_bip_over_ds(dev, apdev, "AES-128-CMAC")
def test_ap_ft_pmf_bip_gmac_128_over_ds(dev, apdev):
"""WPA2-PSK-FT AP over DS with PMF/BIP-GMAC-128"""
run_ap_ft_pmf_bip_over_ds(dev, apdev, "BIP-GMAC-128")
def test_ap_ft_pmf_bip_gmac_256_over_ds(dev, apdev):
"""WPA2-PSK-FT AP over DS with PMF/BIP-GMAC-256"""
run_ap_ft_pmf_bip_over_ds(dev, apdev, "BIP-GMAC-256")
def test_ap_ft_pmf_bip_cmac_256_over_ds(dev, apdev):
"""WPA2-PSK-FT AP over DS with PMF/BIP-CMAC-256"""
run_ap_ft_pmf_bip_over_ds(dev, apdev, "BIP-CMAC-256")
def run_ap_ft_pmf_bip_over_ds(dev, apdev, cipher):
if cipher and cipher not in dev[0].get_capability("group_mgmt"):
raise HwsimSkip("Cipher %s not supported" % cipher)
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
if cipher:
params["group_mgmt_cipher"] = cipher
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
if cipher:
params["group_mgmt_cipher"] = cipher
hapd1 = hostapd.add_ap(apdev[1], params)
Wlantest.setup(hapd0)
wt = Wlantest()
wt.flush()
wt.add_passphrase(passphrase)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
group_mgmt=cipher)
def test_ap_ft_over_ds_pull(dev, apdev):
"""WPA2-PSK-FT AP over DS (pull PMK)"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["pmk_r1_push"] = "0"
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params["pmk_r1_push"] = "0"
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True)
def test_ap_ft_over_ds_pull_old_key(dev, apdev):
"""WPA2-PSK-FT AP over DS (pull PMK; old key)"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1_old_key(ssid=ssid, passphrase=passphrase)
params["pmk_r1_push"] = "0"
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2_old_key(ssid=ssid, passphrase=passphrase)
params["pmk_r1_push"] = "0"
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True)
def test_ap_ft_over_ds_pull_vlan(dev, apdev):
"""WPA2-PSK-FT AP over DS (pull PMK) with VLAN"""
ssid = "test-ft"
passphrase = "12345678"
filename = hostapd.acl_file(dev, apdev, 'hostapd.accept')
hostapd.send_file(apdev[0], filename, filename)
hostapd.send_file(apdev[1], filename, filename)
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["pmk_r1_push"] = "0"
params['dynamic_vlan'] = "1"
params['accept_mac_file'] = filename
hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params["pmk_r1_push"] = "0"
params['dynamic_vlan'] = "1"
params['accept_mac_file'] = filename
hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
conndev="brvlan1")
if filename.startswith('/tmp/'):
os.unlink(filename)
def start_ft_sae(dev, apdev, wpa_ptk_rekey=None, sae_pwe=None,
rsne_override=None, rsnxe_override=None,
no_beacon_rsnxe2=False, ext_key_id=False,
skip_prune_assoc=False, ft_rsnxe_used=False,
sae_transition=False):
if "SAE" not in dev.get_capability("auth_alg"):
raise HwsimSkip("SAE not supported")
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params['wpa_key_mgmt'] = "FT-SAE"
if wpa_ptk_rekey:
params['wpa_ptk_rekey'] = str(wpa_ptk_rekey)
if sae_pwe is not None:
params['sae_pwe'] = sae_pwe
if rsne_override:
params['rsne_override_ft'] = rsne_override
if rsnxe_override:
params['rsnxe_override_ft'] = rsnxe_override
if ext_key_id:
params['extended_key_id'] = '1'
if skip_prune_assoc:
params['skip_prune_assoc'] = '1'
if ft_rsnxe_used:
params['ft_rsnxe_used'] = '1'
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
if not sae_transition:
params['wpa_key_mgmt'] = "FT-SAE"
if wpa_ptk_rekey:
params['wpa_ptk_rekey'] = str(wpa_ptk_rekey)
if sae_pwe is not None:
params['sae_pwe'] = sae_pwe
if rsne_override:
params['rsne_override_ft'] = rsne_override
if rsnxe_override:
params['rsnxe_override_ft'] = rsnxe_override
if no_beacon_rsnxe2:
params['no_beacon_rsnxe'] = "1"
if ext_key_id:
params['extended_key_id'] = '1'
if skip_prune_assoc:
params['skip_prune_assoc'] = '1'
if ft_rsnxe_used:
params['ft_rsnxe_used'] = '1'
hapd1 = hostapd.add_ap(apdev[1], params)
key_mgmt = hapd1.get_config()['key_mgmt']
if key_mgmt.split(' ')[0] != "FT-SAE" and not sae_transition:
raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
dev.request("SET sae_groups ")
return hapd0, hapd1
def test_ap_ft_sae(dev, apdev):
"""WPA2-PSK-FT-SAE AP"""
hapd0, hapd1 = start_ft_sae(dev[0], apdev)
run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True)
def test_ap_ft_sae_transition(dev, apdev):
"""WPA2-PSK-FT-SAE/PSK AP"""
hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_transition=True)
run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678",
sae_transition=True)
def test_ap_ft_sae_h2e(dev, apdev):
"""WPA2-PSK-FT-SAE AP (H2E)"""
try:
dev[0].set("sae_pwe", "2")
hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2")
run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True)
finally:
dev[0].set("sae_pwe", "0")
def test_ap_ft_sae_h2e_and_loop(dev, apdev):
"""WPA2-PSK-FT-SAE AP (AP H2E, STA loop)"""
dev[0].set("sae_pwe", "0")
hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2")
run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True)
def test_ap_ft_sae_h2e_and_loop2(dev, apdev):
"""WPA2-PSK-FT-SAE AP (AP loop, STA H2E)"""
try:
dev[0].set("sae_pwe", "2")
hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="0")
run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True)
finally:
dev[0].set("sae_pwe", "0")
def test_ap_ft_sae_h2e_downgrade_attack(dev, apdev):
"""WPA2-PSK-FT-SAE AP (H2E downgrade attack)"""
try:
dev[0].set("sae_pwe", "2")
hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2",
no_beacon_rsnxe2=True)
run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
force_initial_conn_to_first_ap=True,
return_after_initial=True)
dev[0].scan_for_bss(hapd1.own_addr(), freq="2412")
if "OK" not in dev[0].request("ROAM " + hapd1.own_addr()):
raise Exception("ROAM command failed")
# The target AP is expected to discard Reassociation Response frame due
# to RSNXE Used mismatch. This will result in roaming timeout and
# returning back to the old AP.
ev = dev[0].wait_event(["CTRL-EVENT-ASSOC-REJECT",
"CTRL-EVENT-CONNECTED"], timeout=10)
if ev and "CTRL-EVENT-ASSOC-REJECT" in ev:
pass
elif ev and hapd1.own_addr() in ev:
raise Exception("Roaming succeeded unexpectedly")
finally:
dev[0].set("sae_pwe", "0")
def test_ap_ft_sae_ptk_rekey0(dev, apdev):
"""WPA2-PSK-FT-SAE AP and PTK rekey triggered by station"""
hapd0, hapd1 = start_ft_sae(dev[0], apdev)
run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
ptk_rekey="1", roams=0)
check_ptk_rekey(dev[0], hapd0, hapd1)
def test_ap_ft_sae_ptk_rekey1(dev, apdev):
"""WPA2-PSK-FT-SAE AP and PTK rekey triggered by station"""
hapd0, hapd1 = start_ft_sae(dev[0], apdev)
run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
ptk_rekey="1", only_one_way=True)
check_ptk_rekey(dev[0], hapd0, hapd1)
def test_ap_ft_sae_ptk_rekey_ap(dev, apdev):
"""WPA2-PSK-FT-SAE AP and PTK rekey triggered by AP"""
hapd0, hapd1 = start_ft_sae(dev[0], apdev, wpa_ptk_rekey=2)
run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
only_one_way=True)
check_ptk_rekey(dev[0], hapd0, hapd1)
def test_ap_ft_sae_ptk_rekey_ap_ext_key_id(dev, apdev):
"""WPA2-PSK-FT-SAE AP and PTK rekey triggered by AP (Ext Key ID)"""
check_ext_key_id_capa(dev[0])
try:
dev[0].set("extended_key_id", "1")
hapd0, hapd1 = start_ft_sae(dev[0], apdev, wpa_ptk_rekey=2,
ext_key_id=True)
check_ext_key_id_capa(hapd0)
check_ext_key_id_capa(hapd1)
run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
only_one_way=True)
check_ptk_rekey(dev[0], hapd0, hapd1)
idx = int(dev[0].request("GET last_tk_key_idx"))
if idx != 1:
raise Exception("Unexpected Key ID after TK rekey: %d" % idx)
finally:
dev[0].set("extended_key_id", "0")
def test_ap_ft_sae_over_ds(dev, apdev):
"""WPA2-PSK-FT-SAE AP over DS"""
hapd0, hapd1 = start_ft_sae(dev[0], apdev)
run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
over_ds=True)
def test_ap_ft_sae_over_ds_ptk_rekey0(dev, apdev):
"""WPA2-PSK-FT-SAE AP over DS and PTK rekey triggered by station"""
hapd0, hapd1 = start_ft_sae(dev[0], apdev)
run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
over_ds=True, ptk_rekey="1", roams=0)
check_ptk_rekey(dev[0], hapd0, hapd1)
def test_ap_ft_sae_over_ds_ptk_rekey1(dev, apdev):
"""WPA2-PSK-FT-SAE AP over DS and PTK rekey triggered by station"""
hapd0, hapd1 = start_ft_sae(dev[0], apdev)
run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
over_ds=True, ptk_rekey="1", only_one_way=True)
check_ptk_rekey(dev[0], hapd0, hapd1)
def test_ap_ft_sae_over_ds_ptk_rekey_ap(dev, apdev):
"""WPA2-PSK-FT-SAE AP over DS and PTK rekey triggered by AP"""
hapd0, hapd1 = start_ft_sae(dev[0], apdev, wpa_ptk_rekey=2)
run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
over_ds=True, only_one_way=True)
check_ptk_rekey(dev[0], hapd0, hapd1)
def test_ap_ft_sae_h2e_rsne_override(dev, apdev):
"""WPA2-PSK-FT-SAE AP (H2E) and RSNE override (same value)"""
try:
dev[0].set("sae_pwe", "2")
hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2",
rsne_override="30260100000fac040100000fac040100000fac090c000100" + 16*"ff")
run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True)
finally:
dev[0].set("sae_pwe", "0")
def test_ap_ft_sae_h2e_rsnxe_override(dev, apdev):
"""WPA2-PSK-FT-SAE AP (H2E) and RSNXE override (same value)"""
try:
dev[0].set("sae_pwe", "2")
hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2",
rsnxe_override="F40120")
run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True)
finally:
dev[0].set("sae_pwe", "0")
def test_ap_ft_sae_h2e_rsne_mismatch(dev, apdev):
"""WPA2-PSK-FT-SAE AP (H2E) and RSNE mismatch"""
try:
dev[0].set("sae_pwe", "2")
hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2",
rsne_override="30260100000fac040100000fac040100000fac090c010100" + 16*"ff")
run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
fail_test=True)
finally:
dev[0].set("sae_pwe", "0")
def test_ap_ft_sae_h2e_rsne_mismatch_pmkr1name(dev, apdev):
"""WPA2-PSK-FT-SAE AP (H2E) and RSNE mismatch in PMKR1Name"""
try:
dev[0].set("sae_pwe", "2")
hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2",
rsne_override="30260100000fac040100000fac040100000fac090c000100" + 16*"00")
run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
fail_test=True)
finally:
dev[0].set("sae_pwe", "0")
def test_ap_ft_sae_h2e_rsnxe_mismatch(dev, apdev):
"""WPA2-PSK-FT-SAE AP (H2E) and RSNXE mismatch"""
try:
dev[0].set("sae_pwe", "2")
hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2",
rsnxe_override="F40160")
run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
fail_test=True)
finally:
dev[0].set("sae_pwe", "0")
def test_ap_ft_sae_rsnxe_used_mismatch(dev, apdev):
"""FT-SAE AP and unexpected RSNXE Used in ReassocReq"""
try:
hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2")
dev[0].set("sae_pwe", "0")
dev[0].set("ft_rsnxe_used", "1")
next = run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678",
sae=True, return_after_initial=True)
if "OK" not in dev[0].request("ROAM " + next):
raise Exception("ROAM command failed")
# The target AP is expected to discard Reassociation Request frame due
# to RSNXE Used mismatch. This will result in roaming timeout and
# returning back to the old AP.
ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=5)
if ev and next in ev:
raise Exception("Roaming succeeded unexpectedly")
finally:
dev[0].set("sae_pwe", "0")
def test_ap_ft_sae_rsnxe_used_mismatch2(dev, apdev):
"""FT-SAE AP and unexpected RSNXE Used in ReassocResp"""
try:
hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="0",
ft_rsnxe_used=True)
dev[0].set("sae_pwe", "2")
next = run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678",
sae=True, return_after_initial=True)
if "OK" not in dev[0].request("ROAM " + next):
raise Exception("ROAM command failed")
# The STA is expected to discard Reassociation Response frame due to
# RSNXE Used mismatch. This will result in returning back to the old AP.
ev = dev[0].wait_disconnected()
if next not in ev:
raise Exception("Unexpected disconnection BSSID: " + ev)
if "reason=13 locally_generated=1" not in ev:
raise Exception("Unexpected disconnection reason: " + ev)
ev = dev[0].wait_connected()
if next in ev:
raise Exception("Roaming succeeded unexpectedly")
hapd0.set("ft_rsnxe_used", "0")
hapd1.set("ft_rsnxe_used", "0")
dev[0].roam(next);
finally:
dev[0].set("sae_pwe", "0")
def test_ap_ft_sae_pw_id(dev, apdev):
"""FT-SAE with Password Identifier"""
if "SAE" not in dev[0].get_capability("auth_alg"):
raise HwsimSkip("SAE not supported")
ssid = "test-ft"
params = ft_params1(ssid=ssid)
params["ieee80211w"] = "2"
params['wpa_key_mgmt'] = "FT-SAE"
params['sae_password'] = 'secret|id=pwid'
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid)
params["ieee80211w"] = "2"
params['wpa_key_mgmt'] = "FT-SAE"
params['sae_password'] = 'secret|id=pwid'
hapd = hostapd.add_ap(apdev[1], params)
dev[0].request("SET sae_groups ")
run_roams(dev[0], apdev, hapd0, hapd, ssid, passphrase=None, sae=True,
sae_password="secret", sae_password_id="pwid")
def test_ap_ft_sae_with_both_akms(dev, apdev):
"""SAE + FT-SAE configuration"""
if "SAE" not in dev[0].get_capability("auth_alg"):
raise HwsimSkip("SAE not supported")
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params['wpa_key_mgmt'] = "FT-SAE SAE"
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params['wpa_key_mgmt'] = "FT-SAE SAE"
hapd = hostapd.add_ap(apdev[1], params)
key_mgmt = hapd.get_config()['key_mgmt']
if key_mgmt.split(' ')[0] != "FT-SAE":
raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
dev[0].request("SET sae_groups ")
run_roams(dev[0], apdev, hapd0, hapd, ssid, passphrase, sae=True,
sae_and_psk=True)
def test_ap_ft_sae_pmksa_caching(dev, apdev):
"""WPA2-FT-SAE AP and PMKSA caching for initial mobility domain association"""
if "SAE" not in dev[0].get_capability("auth_alg"):
raise HwsimSkip("SAE not supported")
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params['wpa_key_mgmt'] = "FT-SAE"
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params['wpa_key_mgmt'] = "FT-SAE"
hapd = hostapd.add_ap(apdev[1], params)
key_mgmt = hapd.get_config()['key_mgmt']
if key_mgmt.split(' ')[0] != "FT-SAE":
raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
dev[0].request("SET sae_groups ")
run_roams(dev[0], apdev, hapd0, hapd, ssid, passphrase, sae=True,
pmksa_caching=True)
def test_ap_ft_sae_pmksa_caching_pwe(dev, apdev):
"""WPA2-FT-SAE AP and PMKSA caching for initial mobility domain association (STA PWE both)"""
if "SAE" not in dev[0].get_capability("auth_alg"):
raise HwsimSkip("SAE not supported")
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params['wpa_key_mgmt'] = "FT-SAE"
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params['wpa_key_mgmt'] = "FT-SAE"
hapd = hostapd.add_ap(apdev[1], params)
key_mgmt = hapd.get_config()['key_mgmt']
if key_mgmt.split(' ')[0] != "FT-SAE":
raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
try:
dev[0].request("SET sae_groups ")
dev[0].set("sae_pwe", "2")
run_roams(dev[0], apdev, hapd0, hapd, ssid, passphrase, sae=True,
pmksa_caching=True)
finally:
dev[0].set("sae_groups", "")
dev[0].set("sae_pwe", "0")
def test_ap_ft_sae_pmksa_caching_h2e(dev, apdev):
"""WPA2-FT-SAE AP and PMKSA caching for initial mobility domain association (H2E)"""
if "SAE" not in dev[0].get_capability("auth_alg"):
raise HwsimSkip("SAE not supported")
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params['wpa_key_mgmt'] = "FT-SAE"
params['sae_pwe'] = "1"
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params['wpa_key_mgmt'] = "FT-SAE"
params['sae_pwe'] = "1"
hapd = hostapd.add_ap(apdev[1], params)
key_mgmt = hapd.get_config()['key_mgmt']
if key_mgmt.split(' ')[0] != "FT-SAE":
raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
try:
dev[0].request("SET sae_groups ")
dev[0].set("sae_pwe", "1")
run_roams(dev[0], apdev, hapd0, hapd, ssid, passphrase, sae=True,
pmksa_caching=True)
finally:
dev[0].set("sae_groups", "")
dev[0].set("sae_pwe", "0")
def generic_ap_ft_eap(dev, apdev, vlan=False, cui=False, over_ds=False,
discovery=False, roams=1, wpa_ptk_rekey=0,
only_one_way=False):
ssid = "test-ft"
passphrase = "12345678"
if vlan:
identity = "gpsk-vlan1"
conndev = "brvlan1"
elif cui:
identity = "gpsk-cui"
conndev = False
else:
identity = "gpsk user"
conndev = False
radius = hostapd.radius_params()
params = ft_params1(ssid=ssid, passphrase=passphrase, discovery=discovery)
params['wpa_key_mgmt'] = "FT-EAP"
params["ieee8021x"] = "1"
if vlan:
params["dynamic_vlan"] = "1"
params = dict(list(radius.items()) + list(params.items()))
hapd = hostapd.add_ap(apdev[0], params)
key_mgmt = hapd.get_config()['key_mgmt']
if key_mgmt.split(' ')[0] != "FT-EAP":
raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
params = ft_params2(ssid=ssid, passphrase=passphrase, discovery=discovery)
params['wpa_key_mgmt'] = "FT-EAP"
params["ieee8021x"] = "1"
if vlan:
params["dynamic_vlan"] = "1"
if wpa_ptk_rekey:
params["wpa_ptk_rekey"] = str(wpa_ptk_rekey)
params = dict(list(radius.items()) + list(params.items()))
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd, hapd1, ssid, passphrase, eap=True,
over_ds=over_ds, roams=roams, eap_identity=identity,
conndev=conndev, only_one_way=only_one_way)
if "[WPA2-FT/EAP-CCMP]" not in dev[0].request("SCAN_RESULTS"):
raise Exception("Scan results missing RSN element info")
check_mib(dev[0], [("dot11RSNAAuthenticationSuiteRequested", "00-0f-ac-3"),
("dot11RSNAAuthenticationSuiteSelected", "00-0f-ac-3")])
if only_one_way:
return
# Verify EAPOL reauthentication after FT protocol
if dev[0].get_status_field('bssid') == apdev[0]['bssid']:
ap = hapd
else:
ap = hapd1
ap.request("EAPOL_REAUTH " + dev[0].own_addr())
ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
if ev is None:
raise Exception("EAP authentication did not start")
ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=5)
if ev is None:
raise Exception("EAP authentication did not succeed")
time.sleep(0.1)
if conndev:
hwsim_utils.test_connectivity_iface(dev[0], ap, conndev)
else:
hwsim_utils.test_connectivity(dev[0], ap)
def test_ap_ft_eap(dev, apdev):
"""WPA2-EAP-FT AP"""
generic_ap_ft_eap(dev, apdev)
def test_ap_ft_eap_cui(dev, apdev):
"""WPA2-EAP-FT AP with CUI"""
generic_ap_ft_eap(dev, apdev, vlan=False, cui=True)
def test_ap_ft_eap_vlan(dev, apdev):
"""WPA2-EAP-FT AP with VLAN"""
generic_ap_ft_eap(dev, apdev, vlan=True)
def test_ap_ft_eap_vlan_multi(dev, apdev):
"""WPA2-EAP-FT AP with VLAN"""
generic_ap_ft_eap(dev, apdev, vlan=True, roams=50)
def test_ap_ft_eap_over_ds(dev, apdev):
"""WPA2-EAP-FT AP using over-the-DS"""
generic_ap_ft_eap(dev, apdev, over_ds=True)
def test_ap_ft_eap_dis(dev, apdev):
"""WPA2-EAP-FT AP with AP discovery"""
generic_ap_ft_eap(dev, apdev, discovery=True)
def test_ap_ft_eap_dis_over_ds(dev, apdev):
"""WPA2-EAP-FT AP with AP discovery and over-the-DS"""
generic_ap_ft_eap(dev, apdev, over_ds=True, discovery=True)
def test_ap_ft_eap_vlan(dev, apdev):
"""WPA2-EAP-FT AP with VLAN"""
generic_ap_ft_eap(dev, apdev, vlan=True)
def test_ap_ft_eap_vlan_multi(dev, apdev):
"""WPA2-EAP-FT AP with VLAN"""
generic_ap_ft_eap(dev, apdev, vlan=True, roams=50)
def test_ap_ft_eap_vlan_over_ds(dev, apdev):
"""WPA2-EAP-FT AP with VLAN + over_ds"""
generic_ap_ft_eap(dev, apdev, vlan=True, over_ds=True)
def test_ap_ft_eap_vlan_over_ds_multi(dev, apdev):
"""WPA2-EAP-FT AP with VLAN + over_ds"""
generic_ap_ft_eap(dev, apdev, vlan=True, over_ds=True, roams=50)
def generic_ap_ft_eap_pull(dev, apdev, vlan=False):
"""WPA2-EAP-FT AP (pull PMK)"""
ssid = "test-ft"
passphrase = "12345678"
if vlan:
identity = "gpsk-vlan1"
conndev = "brvlan1"
else:
identity = "gpsk user"
conndev = False
radius = hostapd.radius_params()
params = ft_params1(ssid=ssid, passphrase=passphrase)
params['wpa_key_mgmt'] = "FT-EAP"
params["ieee8021x"] = "1"
params["pmk_r1_push"] = "0"
if vlan:
params["dynamic_vlan"] = "1"
params = dict(list(radius.items()) + list(params.items()))
hapd = hostapd.add_ap(apdev[0], params)
key_mgmt = hapd.get_config()['key_mgmt']
if key_mgmt.split(' ')[0] != "FT-EAP":
raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params['wpa_key_mgmt'] = "FT-EAP"
params["ieee8021x"] = "1"
params["pmk_r1_push"] = "0"
if vlan:
params["dynamic_vlan"] = "1"
params = dict(list(radius.items()) + list(params.items()))
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd, hapd1, ssid, passphrase, eap=True,
eap_identity=identity, conndev=conndev)
def test_ap_ft_eap_pull(dev, apdev):
"""WPA2-EAP-FT AP (pull PMK)"""
generic_ap_ft_eap_pull(dev, apdev)
def test_ap_ft_eap_pull_vlan(dev, apdev):
"""WPA2-EAP-FT AP (pull PMK) - with VLAN"""
generic_ap_ft_eap_pull(dev, apdev, vlan=True)
def test_ap_ft_eap_pull_wildcard(dev, apdev):
"""WPA2-EAP-FT AP (pull PMK) - wildcard R0KH/R1KH"""
ssid = "test-ft"
passphrase = "12345678"
radius = hostapd.radius_params()
params = ft_params1(ssid=ssid, passphrase=passphrase, discovery=True)
params['wpa_key_mgmt'] = "WPA-EAP FT-EAP"
params["ieee8021x"] = "1"
params["pmk_r1_push"] = "0"
params["r0kh"] = "ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
params["r1kh"] = "00:00:00:00:00:00 00:00:00:00:00:00 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
params["ft_psk_generate_local"] = "1"
params["eap_server"] = "0"
params["rkh_pos_timeout"] = "100"
params["rkh_neg_timeout"] = "50"
params["rkh_pull_timeout"] = "1234"
params["rkh_pull_retries"] = "10"
params = dict(list(radius.items()) + list(params.items()))
hapd = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase, discovery=True)
params['wpa_key_mgmt'] = "WPA-EAP FT-EAP"
params["ieee8021x"] = "1"
params["pmk_r1_push"] = "0"
params["r0kh"] = "ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
params["r1kh"] = "00:00:00:00:00:00 00:00:00:00:00:00 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
params["ft_psk_generate_local"] = "1"
params["eap_server"] = "0"
params = dict(list(radius.items()) + list(params.items()))
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd, hapd1, ssid, passphrase, eap=True)
def test_ap_ft_eap_pull_wildcard_multi_bss(dev, apdev, params):
"""WPA2-EAP-FT AP (pull PMK) - wildcard R0KH/R1KH with multiple BSSs"""
bssconf = os.path.join(params['logdir'],
'ap_ft_eap_pull_wildcard_multi_bss.bss.conf')
ssid = "test-ft"
passphrase = "12345678"
radius = hostapd.radius_params()
params = ft_params1(ssid=ssid, passphrase=passphrase, discovery=True)
params['wpa_key_mgmt'] = "WPA-EAP FT-EAP"
params["ieee8021x"] = "1"
params["pmk_r1_push"] = "0"
params["r0kh"] = "ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
params["r1kh"] = "00:00:00:00:00:00 00:00:00:00:00:00 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
params["eap_server"] = "0"
params = dict(list(radius.items()) + list(params.items()))
hapd = hostapd.add_ap(apdev[0], params)
ifname2 = apdev[0]['ifname'] + "-2"
bssid2 = "02:00:00:00:03:01"
params['nas_identifier'] = "nas1b.w1.fi"
params['r1_key_holder'] = "000102030415"
with open(bssconf, 'w') as f:
f.write("driver=nl80211\n")
f.write("hw_mode=g\n")
f.write("channel=1\n")
f.write("ieee80211n=1\n")
f.write("interface=%s\n" % ifname2)
f.write("bssid=%s\n" % bssid2)
f.write("ctrl_interface=/var/run/hostapd\n")
fields = ["ssid", "wpa_passphrase", "nas_identifier", "wpa_key_mgmt",
"wpa", "rsn_pairwise", "auth_server_addr"]
for name in fields:
f.write("%s=%s\n" % (name, params[name]))
for name, val in params.items():
if name in fields:
continue
f.write("%s=%s\n" % (name, val))
hapd2 = hostapd.add_bss(apdev[0], ifname2, bssconf)
params = ft_params2(ssid=ssid, passphrase=passphrase, discovery=True)
params['wpa_key_mgmt'] = "WPA-EAP FT-EAP"
params["ieee8021x"] = "1"
params["pmk_r1_push"] = "0"
params["r0kh"] = "ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
params["r1kh"] = "00:00:00:00:00:00 00:00:00:00:00:00 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
params["eap_server"] = "0"
params = dict(list(radius.items()) + list(params.items()))
hapd1 = hostapd.add_ap(apdev[1], params)
# The first iteration of the roaming test will use wildcard R0KH discovery
# and RRB sequence number synchronization while the second iteration shows
# the clean RRB exchange where those extra steps are not needed.
for i in range(2):
hapd.note("Test iteration %d" % i)
dev[0].note("Test iteration %d" % i)
id = dev[0].connect(ssid, key_mgmt="FT-EAP", eap="GPSK",
identity="gpsk user",
password="abcdefghijklmnop0123456789abcdef",
bssid=bssid2,
scan_freq="2412")
res = dev[0].get_status_field("bssid")
if res != bssid2:
raise Exception("Unexpected BSSID after initial connection: " + res)
dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
dev[0].set_network(id, "bssid", "00:00:00:00:00:00")
dev[0].roam(apdev[1]['bssid'])
res = dev[0].get_status_field("bssid")
if res != apdev[1]['bssid']:
raise Exception("Unexpected BSSID after first roam: " + res)
dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
dev[0].roam(apdev[0]['bssid'])
res = dev[0].get_status_field("bssid")
if res != apdev[0]['bssid']:
raise Exception("Unexpected BSSID after second roam: " + res)
dev[0].request("REMOVE_NETWORK all")
dev[0].wait_disconnected()
dev[0].dump_monitor()
hapd.dump_monitor()
hapd2.dump_monitor()
@remote_compatible
def test_ap_ft_mismatching_rrb_key_push(dev, apdev):
"""WPA2-PSK-FT AP over DS with mismatching RRB key (push)"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2_incorrect_rrb_key(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
fail_test=True)
@remote_compatible
def test_ap_ft_mismatching_rrb_key_pull(dev, apdev):
"""WPA2-PSK-FT AP over DS with mismatching RRB key (pull)"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["pmk_r1_push"] = "0"
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2_incorrect_rrb_key(ssid=ssid, passphrase=passphrase)
params["pmk_r1_push"] = "0"
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
fail_test=True)
@remote_compatible
def test_ap_ft_mismatching_r0kh_id_pull(dev, apdev):
"""WPA2-PSK-FT AP over DS with mismatching R0KH-ID (pull)"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["pmk_r1_push"] = "0"
params["nas_identifier"] = "nas0.w1.fi"
hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
params = ft_params2(ssid=ssid, passphrase=passphrase)
params["pmk_r1_push"] = "0"
hostapd.add_ap(apdev[1], params)
dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
dev[0].roam_over_ds(apdev[1]['bssid'], fail_test=True)
@remote_compatible
def test_ap_ft_mismatching_rrb_r0kh_push(dev, apdev):
"""WPA2-PSK-FT AP over DS with mismatching R0KH key (push)"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2_r0kh_mismatch(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
fail_test=True)
@remote_compatible
def test_ap_ft_mismatching_rrb_r0kh_pull(dev, apdev):
"""WPA2-PSK-FT AP over DS with mismatching R0KH key (pull)"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1_r0kh_mismatch(ssid=ssid, passphrase=passphrase)
params["pmk_r1_push"] = "0"
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params["pmk_r1_push"] = "0"
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
fail_test=True)
def test_ap_ft_mismatching_rrb_key_push_eap(dev, apdev):
"""WPA2-EAP-FT AP over DS with mismatching RRB key (push)"""
ssid = "test-ft"
passphrase = "12345678"
radius = hostapd.radius_params()
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
params['wpa_key_mgmt'] = "FT-EAP"
params["ieee8021x"] = "1"
params = dict(list(radius.items()) + list(params.items()))
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2_incorrect_rrb_key(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
params['wpa_key_mgmt'] = "FT-EAP"
params["ieee8021x"] = "1"
params = dict(list(radius.items()) + list(params.items()))
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
fail_test=True, eap=True)
def test_ap_ft_mismatching_rrb_key_pull_eap(dev, apdev):
"""WPA2-EAP-FT AP over DS with mismatching RRB key (pull)"""
ssid = "test-ft"
passphrase = "12345678"
radius = hostapd.radius_params()
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["pmk_r1_push"] = "0"
params['wpa_key_mgmt'] = "FT-EAP"
params["ieee8021x"] = "1"
params = dict(list(radius.items()) + list(params.items()))
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2_incorrect_rrb_key(ssid=ssid, passphrase=passphrase)
params["pmk_r1_push"] = "0"
params['wpa_key_mgmt'] = "FT-EAP"
params["ieee8021x"] = "1"
params = dict(list(radius.items()) + list(params.items()))
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
fail_test=True, eap=True)
def test_ap_ft_mismatching_r0kh_id_pull_eap(dev, apdev):
"""WPA2-EAP-FT AP over DS with mismatching R0KH-ID (pull)"""
ssid = "test-ft"
passphrase = "12345678"
radius = hostapd.radius_params()
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["pmk_r1_push"] = "0"
params["nas_identifier"] = "nas0.w1.fi"
params['wpa_key_mgmt'] = "FT-EAP"
params["ieee8021x"] = "1"
params = dict(list(radius.items()) + list(params.items()))
hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, key_mgmt="FT-EAP", proto="WPA2", ieee80211w="1",
eap="GPSK", identity="gpsk user",
password="abcdefghijklmnop0123456789abcdef",
scan_freq="2412")
params = ft_params2(ssid=ssid, passphrase=passphrase)
params["pmk_r1_push"] = "0"
params['wpa_key_mgmt'] = "FT-EAP"
params["ieee8021x"] = "1"
params = dict(list(radius.items()) + list(params.items()))
hostapd.add_ap(apdev[1], params)
dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
dev[0].roam_over_ds(apdev[1]['bssid'], fail_test=True)
def test_ap_ft_mismatching_rrb_r0kh_push_eap(dev, apdev):
"""WPA2-EAP-FT AP over DS with mismatching R0KH key (push)"""
ssid = "test-ft"
passphrase = "12345678"
radius = hostapd.radius_params()
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
params['wpa_key_mgmt'] = "FT-EAP"
params["ieee8021x"] = "1"
params = dict(list(radius.items()) + list(params.items()))
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2_r0kh_mismatch(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
params['wpa_key_mgmt'] = "FT-EAP"
params["ieee8021x"] = "1"
params = dict(list(radius.items()) + list(params.items()))
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
fail_test=True, eap=True)
def test_ap_ft_mismatching_rrb_r0kh_pull_eap(dev, apdev):
"""WPA2-EAP-FT AP over DS with mismatching R0KH key (pull)"""
ssid = "test-ft"
passphrase = "12345678"
radius = hostapd.radius_params()
params = ft_params1_r0kh_mismatch(ssid=ssid, passphrase=passphrase)
params["pmk_r1_push"] = "0"
params['wpa_key_mgmt'] = "FT-EAP"
params["ieee8021x"] = "1"
params = dict(list(radius.items()) + list(params.items()))
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params["pmk_r1_push"] = "0"
params['wpa_key_mgmt'] = "FT-EAP"
params["ieee8021x"] = "1"
params = dict(list(radius.items()) + list(params.items()))
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
fail_test=True, eap=True)
def test_ap_ft_gtk_rekey(dev, apdev):
"""WPA2-PSK-FT AP and GTK rekey"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params['wpa_group_rekey'] = '1'
hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
ieee80211w="1", scan_freq="2412")
ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=2)
if ev is None:
raise Exception("GTK rekey timed out after initial association")
hwsim_utils.test_connectivity(dev[0], hapd)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params['wpa_group_rekey'] = '1'
hapd1 = hostapd.add_ap(apdev[1], params)
dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
dev[0].roam(apdev[1]['bssid'])
if dev[0].get_status_field('bssid') != apdev[1]['bssid']:
raise Exception("Did not connect to correct AP")
hwsim_utils.test_connectivity(dev[0], hapd1)
ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=2)
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], p)
p = ft_params2(ssid=ssid, passphrase=passphrase)
hapd1 = hostapd.add_ap(apdev[1], p)
pid = find_wpas_process(dev[0])
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
# The decrypted copy of GTK is freed only after the CTRL-EVENT-CONNECTED
# event has been delivered, so verify that wpa_supplicant has returned to
# eloop before reading process memory.
time.sleep(1)
dev[0].ping()
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: KCK - hexdump" in l:
val = l.strip().split(':')[3].replace(' ', '')
kck = binascii.unhexlify(val)
if "FT: KEK - hexdump" in l:
val = l.strip().split(':')[3].replace(' ', '')
kek = binascii.unhexlify(val)
if "FT: TK - hexdump" in l:
val = l.strip().split(':')[3].replace(' ', '')
tk = 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 kck or not kek or not tk or not gtk:
raise Exception("Could not find keys from debug log")
if len(gtk) != 16:
raise Exception("Unexpected GTK length")
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:
raise HwsimSkip("PMK not found while associated")
if pmkr0 not in buf:
raise HwsimSkip("PMK-R0 not found while associated")
if pmkr1 not in buf:
raise HwsimSkip("PMK-R1 not found while associated")
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")
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")
if gtk in buf:
get_key_locations(buf, gtk, "GTK")
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")
@remote_compatible
def test_ap_ft_invalid_resp(dev, apdev):
"""WPA2-PSK-FT AP and invalid response IEs"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
hapd0 = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
params = ft_params2(ssid=ssid, passphrase=passphrase)
hapd1 = hostapd.add_ap(apdev[1], params)
tests = [
# Various IEs for test coverage. The last one is FTIE with invalid
# R1KH-ID subelement.
"020002000000" + "3800" + "38051122334455" + "3754000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010100",
# FTIE with invalid R0KH-ID subelement (len=0).
"020002000000" + "3754000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010300",
# FTIE with invalid R0KH-ID subelement (len=49).
"020002000000" + "378500010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001033101020304050607080910111213141516171819202122232425262728293031323334353637383940414243444546474849",
# Invalid RSNE.
"020002000000" + "3000",
# Required IEs missing from protected IE count.
"020002000000" + "3603a1b201" + "375200010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001" + "3900",
# RIC missing from protected IE count.
"020002000000" + "3603a1b201" + "375200020203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001" + "3900",
# Protected IE missing.
"020002000000" + "3603a1b201" + "375200ff0203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001" + "3900" + "0000"]
for t in tests:
dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
hapd1.set("ext_mgmt_frame_handling", "1")
hapd1.dump_monitor()
if "OK" not in dev[0].request("ROAM " + apdev[1]['bssid']):
raise Exception("ROAM failed")
auth = None
for i in range(20):
msg = hapd1.mgmt_rx()
if msg['subtype'] == 11:
auth = msg
break
if not auth:
raise Exception("Authentication frame not seen")
resp = {}
resp['fc'] = auth['fc']
resp['da'] = auth['sa']
resp['sa'] = auth['da']
resp['bssid'] = auth['bssid']
resp['payload'] = binascii.unhexlify(t)
hapd1.mgmt_tx(resp)
hapd1.set("ext_mgmt_frame_handling", "0")
dev[0].wait_disconnected()
dev[0].request("RECONNECT")
dev[0].wait_connected()
def test_ap_ft_gcmp_256(dev, apdev):
"""WPA2-PSK-FT AP with GCMP-256 cipher"""
if "GCMP-256" not in dev[0].get_capability("pairwise"):
raise HwsimSkip("Cipher GCMP-256 not supported")
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params['rsn_pairwise'] = "GCMP-256"
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params['rsn_pairwise'] = "GCMP-256"
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase,
pairwise_cipher="GCMP-256", group_cipher="GCMP-256")
def setup_ap_ft_oom(dev, apdev):
skip_with_fips(dev[0])
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
hapd1 = hostapd.add_ap(apdev[1], params)
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
if dev[0].get_status_field('bssid') == apdev[0]['bssid']:
dst = apdev[1]['bssid']
else:
dst = apdev[0]['bssid']
dev[0].scan_for_bss(dst, freq="2412")
return dst
def test_ap_ft_oom(dev, apdev):
"""WPA2-PSK-FT and OOM"""
dst = setup_ap_ft_oom(dev, apdev)
with alloc_fail(dev[0], 1, "wpa_ft_gen_req_ies"):
dev[0].roam(dst, check_bssid=False, fail_test=True)
def test_ap_ft_oom2(dev, apdev):
"""WPA2-PSK-FT and OOM (2)"""
dst = setup_ap_ft_oom(dev, apdev)
with fail_test(dev[0], 1, "wpa_ft_mic"):
dev[0].roam(dst, fail_test=True, assoc_reject_ok=True)
def test_ap_ft_oom3(dev, apdev):
"""WPA2-PSK-FT and OOM (3)"""
dst = setup_ap_ft_oom(dev, apdev)
with fail_test(dev[0], 1, "os_get_random;wpa_ft_prepare_auth_request"):
dev[0].roam(dst)
def test_ap_ft_oom4(dev, apdev):
"""WPA2-PSK-FT and OOM (4)"""
ssid = "test-ft"
passphrase = "12345678"
dst = setup_ap_ft_oom(dev, apdev)
dev[0].request("REMOVE_NETWORK all")
with alloc_fail(dev[0], 1, "=sme_update_ft_ies"):
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
def test_ap_ft_ap_oom(dev, apdev):
"""WPA2-PSK-FT and AP OOM"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
hapd0 = hostapd.add_ap(apdev[0], params)
bssid0 = hapd0.own_addr()
dev[0].scan_for_bss(bssid0, freq="2412")
with alloc_fail(hapd0, 1, "wpa_ft_store_pmk_r0"):
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
params = ft_params2(ssid=ssid, passphrase=passphrase)
hapd1 = hostapd.add_ap(apdev[1], params)
bssid1 = hapd1.own_addr()
dev[0].scan_for_bss(bssid1, freq="2412")
# This roam will fail due to missing PMK-R0 (OOM prevented storing it)
dev[0].roam(bssid1, check_bssid=False)
def test_ap_ft_ap_oom2(dev, apdev):
"""WPA2-PSK-FT and AP OOM 2"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
hapd0 = hostapd.add_ap(apdev[0], params)
bssid0 = hapd0.own_addr()
dev[0].scan_for_bss(bssid0, freq="2412")
with alloc_fail(hapd0, 1, "wpa_ft_store_pmk_r1"):
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
params = ft_params2(ssid=ssid, passphrase=passphrase)
hapd1 = hostapd.add_ap(apdev[1], params)
bssid1 = hapd1.own_addr()
dev[0].scan_for_bss(bssid1, freq="2412")
dev[0].roam(bssid1)
if dev[0].get_status_field('bssid') != bssid1:
raise Exception("Did not roam to AP1")
# This roam will fail due to missing PMK-R1 (OOM prevented storing it)
dev[0].roam(bssid0)
def test_ap_ft_ap_oom3(dev, apdev):
"""WPA2-PSK-FT and AP OOM 3"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
hapd0 = hostapd.add_ap(apdev[0], params)
bssid0 = hapd0.own_addr()
dev[0].scan_for_bss(bssid0, freq="2412")
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
params = ft_params2(ssid=ssid, passphrase=passphrase)
hapd1 = hostapd.add_ap(apdev[1], params)
bssid1 = hapd1.own_addr()
dev[0].scan_for_bss(bssid1, freq="2412")
with alloc_fail(hapd1, 1, "wpa_ft_pull_pmk_r1"):
# This will fail due to not being able to send out PMK-R1 pull request
dev[0].roam(bssid1, check_bssid=False)
with fail_test(hapd1, 2, "os_get_random;wpa_ft_pull_pmk_r1"):
# This will fail due to not being able to send out PMK-R1 pull request
dev[0].roam(bssid1, check_bssid=False)
with fail_test(hapd1, 2, "aes_siv_encrypt;wpa_ft_pull_pmk_r1"):
# This will fail due to not being able to send out PMK-R1 pull request
dev[0].roam(bssid1, check_bssid=False)
def test_ap_ft_ap_oom3b(dev, apdev):
"""WPA2-PSK-FT and AP OOM 3b"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
hapd0 = hostapd.add_ap(apdev[0], params)
bssid0 = hapd0.own_addr()
dev[0].scan_for_bss(bssid0, freq="2412")
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
params = ft_params2(ssid=ssid, passphrase=passphrase)
hapd1 = hostapd.add_ap(apdev[1], params)
bssid1 = hapd1.own_addr()
dev[0].scan_for_bss(bssid1, freq="2412")
with fail_test(hapd1, 1, "os_get_random;wpa_ft_pull_pmk_r1"):
# This will fail due to not being able to send out PMK-R1 pull request
dev[0].roam(bssid1)
def test_ap_ft_ap_oom4(dev, apdev):
"""WPA2-PSK-FT and AP OOM 4"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
hapd0 = hostapd.add_ap(apdev[0], params)
bssid0 = hapd0.own_addr()
dev[0].scan_for_bss(bssid0, freq="2412")
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
params = ft_params2(ssid=ssid, passphrase=passphrase)
hapd1 = hostapd.add_ap(apdev[1], params)
bssid1 = hapd1.own_addr()
dev[0].scan_for_bss(bssid1, freq="2412")
with alloc_fail(hapd1, 1, "wpa_ft_gtk_subelem"):
dev[0].roam(bssid1)
if dev[0].get_status_field('bssid') != bssid1:
raise Exception("Did not roam to AP1")
with fail_test(hapd0, 1, "i802_get_seqnum;wpa_ft_gtk_subelem"):
dev[0].roam(bssid0)
if dev[0].get_status_field('bssid') != bssid0:
raise Exception("Did not roam to AP0")
with fail_test(hapd0, 1, "aes_wrap;wpa_ft_gtk_subelem"):
dev[0].roam(bssid1)
if dev[0].get_status_field('bssid') != bssid1:
raise Exception("Did not roam to AP1")
def test_ap_ft_ap_oom5(dev, apdev):
"""WPA2-PSK-FT and AP OOM 5"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
hapd0 = hostapd.add_ap(apdev[0], params)
bssid0 = hapd0.own_addr()
dev[0].scan_for_bss(bssid0, freq="2412")
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
params = ft_params2(ssid=ssid, passphrase=passphrase)
hapd1 = hostapd.add_ap(apdev[1], params)
bssid1 = hapd1.own_addr()
dev[0].scan_for_bss(bssid1, freq="2412")
with alloc_fail(hapd1, 1, "=wpa_ft_process_auth_req"):
# This will fail to roam
dev[0].roam(bssid1, check_bssid=False)
with fail_test(hapd1, 1, "os_get_random;wpa_ft_process_auth_req"):
# This will fail to roam
dev[0].roam(bssid1, check_bssid=False)
with fail_test(hapd1, 1, "sha256_prf_bits;wpa_pmk_r1_to_ptk;wpa_ft_process_auth_req"):
# This will fail to roam
dev[0].roam(bssid1, check_bssid=False)
with fail_test(hapd1, 3, "wpa_pmk_r1_to_ptk;wpa_ft_process_auth_req"):
# This will fail to roam
dev[0].roam(bssid1, check_bssid=False)
with fail_test(hapd1, 1, "wpa_derive_pmk_r1_name;wpa_ft_process_auth_req"):
# This will fail to roam
dev[0].roam(bssid1, check_bssid=False)
def test_ap_ft_ap_oom6(dev, apdev):
"""WPA2-PSK-FT and AP OOM 6"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
hapd0 = hostapd.add_ap(apdev[0], params)
bssid0 = hapd0.own_addr()
dev[0].scan_for_bss(bssid0, freq="2412")
with fail_test(hapd0, 1, "wpa_derive_pmk_r0;wpa_auth_derive_ptk_ft"):
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
dev[0].request("REMOVE_NETWORK all")
dev[0].wait_disconnected()
with fail_test(hapd0, 1, "wpa_derive_pmk_r1;wpa_auth_derive_ptk_ft"):
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
dev[0].request("REMOVE_NETWORK all")
dev[0].wait_disconnected()
with fail_test(hapd0, 1, "wpa_pmk_r1_to_ptk;wpa_auth_derive_ptk_ft"):
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
def test_ap_ft_ap_oom7a(dev, apdev):
"""WPA2-PSK-FT and AP OOM 7a"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
hapd0 = hostapd.add_ap(apdev[0], params)
bssid0 = hapd0.own_addr()
dev[0].scan_for_bss(bssid0, freq="2412")
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
ieee80211w="2", scan_freq="2412")
params = ft_params2(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
hapd1 = hostapd.add_ap(apdev[1], params)
bssid1 = hapd1.own_addr()
dev[0].scan_for_bss(bssid1, freq="2412")
with alloc_fail(hapd1, 1, "wpa_ft_igtk_subelem"):
# This will fail to roam
dev[0].roam(bssid1)
def test_ap_ft_ap_oom7b(dev, apdev):
"""WPA2-PSK-FT and AP OOM 7b"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
hapd0 = hostapd.add_ap(apdev[0], params)
bssid0 = hapd0.own_addr()
dev[0].scan_for_bss(bssid0, freq="2412")
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
ieee80211w="2", scan_freq="2412")
params = ft_params2(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
hapd1 = hostapd.add_ap(apdev[1], params)
bssid1 = hapd1.own_addr()
dev[0].scan_for_bss(bssid1, freq="2412")
with fail_test(hapd1, 1, "aes_wrap;wpa_ft_igtk_subelem"):
# This will fail to roam
dev[0].roam(bssid1)
def test_ap_ft_ap_oom7c(dev, apdev):
"""WPA2-PSK-FT and AP OOM 7c"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
hapd0 = hostapd.add_ap(apdev[0], params)
bssid0 = hapd0.own_addr()
dev[0].scan_for_bss(bssid0, freq="2412")
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
ieee80211w="2", scan_freq="2412")
params = ft_params2(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
hapd1 = hostapd.add_ap(apdev[1], params)
bssid1 = hapd1.own_addr()
dev[0].scan_for_bss(bssid1, freq="2412")
with alloc_fail(hapd1, 1, "=wpa_sm_write_assoc_resp_ies"):
# This will fail to roam
dev[0].roam(bssid1)
def test_ap_ft_ap_oom7d(dev, apdev):
"""WPA2-PSK-FT and AP OOM 7d"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
hapd0 = hostapd.add_ap(apdev[0], params)
bssid0 = hapd0.own_addr()
dev[0].scan_for_bss(bssid0, freq="2412")
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
ieee80211w="2", scan_freq="2412")
params = ft_params2(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
hapd1 = hostapd.add_ap(apdev[1], params)
bssid1 = hapd1.own_addr()
dev[0].scan_for_bss(bssid1, freq="2412")
with fail_test(hapd1, 1, "wpa_ft_mic;wpa_sm_write_assoc_resp_ies"):
# This will fail to roam
dev[0].roam(bssid1)
def test_ap_ft_ap_oom8(dev, apdev):
"""WPA2-PSK-FT and AP OOM 8"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params['ft_psk_generate_local'] = "1"
hapd0 = hostapd.add_ap(apdev[0], params)
bssid0 = hapd0.own_addr()
dev[0].scan_for_bss(bssid0, freq="2412")
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
params = ft_params2(ssid=ssid, passphrase=passphrase)
params['ft_psk_generate_local'] = "1"
hapd1 = hostapd.add_ap(apdev[1], params)
bssid1 = hapd1.own_addr()
dev[0].scan_for_bss(bssid1, freq="2412")
with fail_test(hapd1, 1, "wpa_derive_pmk_r0;wpa_ft_psk_pmk_r1"):
# This will fail to roam
dev[0].roam(bssid1, check_bssid=False)
with fail_test(hapd1, 1, "wpa_derive_pmk_r1;wpa_ft_psk_pmk_r1"):
# This will fail to roam
dev[0].roam(bssid1, check_bssid=False)
def test_ap_ft_ap_oom9(dev, apdev):
"""WPA2-PSK-FT and AP OOM 9"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
hapd0 = hostapd.add_ap(apdev[0], params)
bssid0 = hapd0.own_addr()
dev[0].scan_for_bss(bssid0, freq="2412")
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
params = ft_params2(ssid=ssid, passphrase=passphrase)
hapd1 = hostapd.add_ap(apdev[1], params)
bssid1 = hapd1.own_addr()
dev[0].scan_for_bss(bssid1, freq="2412")
with alloc_fail(hapd0, 1, "wpa_ft_action_rx"):
# This will fail to roam
if "OK" not in dev[0].request("FT_DS " + bssid1):
raise Exception("FT_DS failed")
wait_fail_trigger(hapd0, "GET_ALLOC_FAIL")
with alloc_fail(hapd1, 1, "wpa_ft_rrb_rx_request"):
# This will fail to roam
if "OK" not in dev[0].request("FT_DS " + bssid1):
raise Exception("FT_DS failed")
wait_fail_trigger(hapd1, "GET_ALLOC_FAIL")
with alloc_fail(hapd1, 1, "wpa_ft_send_rrb_auth_resp"):
# This will fail to roam
if "OK" not in dev[0].request("FT_DS " + bssid1):
raise Exception("FT_DS failed")
wait_fail_trigger(hapd1, "GET_ALLOC_FAIL")
def test_ap_ft_ap_oom10(dev, apdev):
"""WPA2-PSK-FT and AP OOM 10"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
hapd0 = hostapd.add_ap(apdev[0], params)
bssid0 = hapd0.own_addr()
dev[0].scan_for_bss(bssid0, freq="2412")
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
params = ft_params2(ssid=ssid, passphrase=passphrase)
hapd1 = hostapd.add_ap(apdev[1], params)
bssid1 = hapd1.own_addr()
dev[0].scan_for_bss(bssid1, freq="2412")
with fail_test(hapd0, 1, "aes_siv_decrypt;wpa_ft_rrb_rx_pull"):
# This will fail to roam
if "OK" not in dev[0].request("FT_DS " + bssid1):
raise Exception("FT_DS failed")
wait_fail_trigger(hapd0, "GET_FAIL")
with fail_test(hapd0, 1, "wpa_derive_pmk_r1;wpa_ft_rrb_rx_pull"):
# This will fail to roam
if "OK" not in dev[0].request("FT_DS " + bssid1):
raise Exception("FT_DS failed")
wait_fail_trigger(hapd0, "GET_FAIL")
with fail_test(hapd0, 1, "aes_siv_encrypt;wpa_ft_rrb_rx_pull"):
# This will fail to roam
if "OK" not in dev[0].request("FT_DS " + bssid1):
raise Exception("FT_DS failed")
wait_fail_trigger(hapd0, "GET_FAIL")
with fail_test(hapd1, 1, "aes_siv_decrypt;wpa_ft_rrb_rx_resp"):
# This will fail to roam
if "OK" not in dev[0].request("FT_DS " + bssid1):
raise Exception("FT_DS failed")
wait_fail_trigger(hapd1, "GET_FAIL")
def test_ap_ft_ap_oom11(dev, apdev):
"""WPA2-PSK-FT and AP OOM 11"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
hapd0 = hostapd.add_ap(apdev[0], params)
bssid0 = hapd0.own_addr()
dev[0].scan_for_bss(bssid0, freq="2412")
with fail_test(hapd0, 1, "wpa_derive_pmk_r1;wpa_ft_generate_pmk_r1"):
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
wait_fail_trigger(hapd0, "GET_FAIL")
dev[1].scan_for_bss(bssid0, freq="2412")
with fail_test(hapd0, 1, "aes_siv_encrypt;wpa_ft_generate_pmk_r1"):
dev[1].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
wait_fail_trigger(hapd0, "GET_FAIL")
def test_ap_ft_over_ds_proto_ap(dev, apdev):
"""WPA2-PSK-FT AP over DS protocol testing for AP processing"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
hapd0 = hostapd.add_ap(apdev[0], params)
bssid0 = hapd0.own_addr()
_bssid0 = bssid0.replace(':', '')
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
addr = dev[0].own_addr()
_addr = addr.replace(':', '')
params = ft_params2(ssid=ssid, passphrase=passphrase)
hapd1 = hostapd.add_ap(apdev[1], params)
bssid1 = hapd1.own_addr()
_bssid1 = bssid1.replace(':', '')
hapd0.set("ext_mgmt_frame_handling", "1")
hdr = "d0003a01" + _bssid0 + _addr + _bssid0 + "1000"
valid = "0601" + _addr + _bssid1
tests = ["0601",
"0601" + _addr,
"0601" + _addr + _bssid0,
"0601" + _addr + "ffffffffffff",
"0601" + _bssid0 + _bssid0,
valid,
valid + "01",
valid + "3700",
valid + "3600",
valid + "3603ffffff",
valid + "3603a1b2ff",
valid + "3603a1b2ff" + "3700",
valid + "3603a1b2ff" + "37520000" + 16*"00" + 32*"00" + 32*"00",
valid + "3603a1b2ff" + "37520001" + 16*"00" + 32*"00" + 32*"00",
valid + "3603a1b2ff" + "37550000" + 16*"00" + 32*"00" + 32*"00" + "0301aa",
valid + "3603a1b2ff" + "37550000" + 16*"00" + 32*"00" + 32*"00" + "0301aa" + "3000",
valid + "3603a1b2ff" + "37550000" + 16*"00" + 32*"00" + 32*"00" + "0301aa" + "30260100000fac040100000fac040100000facff00000100a225368fe0983b5828a37a0acb37f253",
valid + "3603a1b2ff" + "37550000" + 16*"00" + 32*"00" + 32*"00" + "0301aa" + "30260100000fac040100000fac030100000fac0400000100a225368fe0983b5828a37a0acb37f253",
valid + "3603a1b2ff" + "37550000" + 16*"00" + 32*"00" + 32*"00" + "0301aa" + "30260100000fac040100000fac040100000fac0400000100a225368fe0983b5828a37a0acb37f253",
valid + "0001"]
for t in tests:
hapd0.dump_monitor()
if "OK" not in hapd0.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + t):
raise Exception("MGMT_RX_PROCESS failed")
hapd0.set("ext_mgmt_frame_handling", "0")
def test_ap_ft_over_ds_proto(dev, apdev):
"""WPA2-PSK-FT AP over DS protocol testing"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
hapd0 = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
# FT Action Response while no FT-over-DS in progress
msg = {}
msg['fc'] = 13 << 4
msg['da'] = dev[0].own_addr()
msg['sa'] = apdev[0]['bssid']
msg['bssid'] = apdev[0]['bssid']
msg['payload'] = binascii.unhexlify("06020200000000000200000004000000")
hapd0.mgmt_tx(msg)
params = ft_params2(ssid=ssid, passphrase=passphrase)
hapd1 = hostapd.add_ap(apdev[1], params)
dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
hapd0.set("ext_mgmt_frame_handling", "1")
hapd0.dump_monitor()
dev[0].request("FT_DS " + apdev[1]['bssid'])
for i in range(0, 10):
req = hapd0.mgmt_rx()
if req is None:
raise Exception("MGMT RX wait timed out")
if req['subtype'] == 13:
break
req = None
if not req:
raise Exception("FT Action frame not received")
# FT Action Response for unexpected Target AP
msg['payload'] = binascii.unhexlify("0602020000000000" + "f20000000400" + "0000")
hapd0.mgmt_tx(msg)
# FT Action Response without MDIE
msg['payload'] = binascii.unhexlify("0602020000000000" + "020000000400" + "0000")
hapd0.mgmt_tx(msg)
# FT Action Response without FTIE
msg['payload'] = binascii.unhexlify("0602020000000000" + "020000000400" + "0000" + "3603a1b201")
hapd0.mgmt_tx(msg)
# FT Action Response with FTIE SNonce mismatch
msg['payload'] = binascii.unhexlify("0602020000000000" + "020000000400" + "0000" + "3603a1b201" + "3766000000000000000000000000000000000000c4e67ac1999bebd00ff4ae4d5dcaf87896bb060b469f7c78d49623fb395c3455ffffff6b693fe6f8d8c5dfac0a22344750775bd09437f98b238c9f87b97f790c0106000102030406030a6e6173312e77312e6669")
hapd0.mgmt_tx(msg)
@remote_compatible
def test_ap_ft_rrb(dev, apdev):
"""WPA2-PSK-FT RRB protocol testing"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
hapd0 = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
_dst_ll = binascii.unhexlify(apdev[0]['bssid'].replace(':', ''))
_src_ll = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
proto = b'\x89\x0d'
ehdr = _dst_ll + _src_ll + proto
# Too short RRB frame
pkt = ehdr + b'\x01'
if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
raise Exception("DATA_TEST_FRAME failed")
# RRB discarded frame wikth unrecognized type
pkt = ehdr + b'\x02' + b'\x02' + b'\x01\x00' + _src_ll
if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
raise Exception("DATA_TEST_FRAME failed")
# RRB frame too short for action frame
pkt = ehdr + b'\x01' + b'\x02' + b'\x01\x00' + _src_ll
if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
raise Exception("DATA_TEST_FRAME failed")
# Too short RRB frame (not enough room for Action Frame body)
pkt = ehdr + b'\x01' + b'\x02' + b'\x00\x00' + _src_ll
if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
raise Exception("DATA_TEST_FRAME failed")
# Unexpected Action frame category
pkt = ehdr + b'\x01' + b'\x02' + b'\x0e\x00' + _src_ll + b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
raise Exception("DATA_TEST_FRAME failed")
# Unexpected Action in RRB Request
pkt = ehdr + b'\x01' + b'\x00' + b'\x0e\x00' + _src_ll + b'\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
raise Exception("DATA_TEST_FRAME failed")
# Target AP address in RRB Request does not match with own address
pkt = ehdr + b'\x01' + b'\x00' + b'\x0e\x00' + _src_ll + b'\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
raise Exception("DATA_TEST_FRAME failed")
# Not enough room for status code in RRB Response
pkt = ehdr + b'\x01' + b'\x01' + b'\x0e\x00' + _src_ll + b'\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
raise Exception("DATA_TEST_FRAME failed")
# RRB discarded frame with unknown packet_type
pkt = ehdr + b'\x01' + b'\x02' + b'\x0e\x00' + _src_ll + b'\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
raise Exception("DATA_TEST_FRAME failed")
# RRB Response with non-zero status code; no STA match
pkt = ehdr + b'\x01' + b'\x01' + b'\x10\x00' + _src_ll + b'\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + b'\xff\xff'
if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
raise Exception("DATA_TEST_FRAME failed")
# RRB Response with zero status code and extra data; STA match
pkt = ehdr + b'\x01' + b'\x01' + b'\x11\x00' + _src_ll + b'\x06\x01' + _src_ll + b'\x00\x00\x00\x00\x00\x00' + b'\x00\x00' + b'\x00'
if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
raise Exception("DATA_TEST_FRAME failed")
# Too short PMK-R1 pull
pkt = ehdr + b'\x01' + b'\xc8' + b'\x0e\x00' + _src_ll + b'\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
raise Exception("DATA_TEST_FRAME failed")
# Too short PMK-R1 resp
pkt = ehdr + b'\x01' + b'\xc9' + b'\x0e\x00' + _src_ll + b'\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
raise Exception("DATA_TEST_FRAME failed")
# Too short PMK-R1 push
pkt = ehdr + b'\x01' + b'\xca' + b'\x0e\x00' + _src_ll + b'\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
raise Exception("DATA_TEST_FRAME failed")
# No matching R0KH address found for PMK-R0 pull response
pkt = ehdr + b'\x01' + b'\xc9' + b'\x5a\x00' + _src_ll + b'\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + 76 * b'\00'
if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
raise Exception("DATA_TEST_FRAME failed")
@remote_compatible
def test_rsn_ie_proto_ft_psk_sta(dev, apdev):
"""RSN element protocol testing for FT-PSK + PMF cases on STA side"""
bssid = apdev[0]['bssid']
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "1"
# This is the RSN element used normally by hostapd
params['own_ie_override'] = '30140100000fac040100000fac040100000fac048c00' + '3603a1b201'
hapd = hostapd.add_ap(apdev[0], params)
id = dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
ieee80211w="1", scan_freq="2412",
pairwise="CCMP", group="CCMP")
tests = [('PMKIDCount field included',
'30160100000fac040100000fac040100000fac048c000000' + '3603a1b201'),
('Extra IE before RSNE',
'dd0400000000' + '30140100000fac040100000fac040100000fac048c00' + '3603a1b201'),
('PMKIDCount and Group Management Cipher suite fields included',
'301a0100000fac040100000fac040100000fac048c000000000fac06' + '3603a1b201'),
('Extra octet after defined fields (future extensibility)',
'301b0100000fac040100000fac040100000fac048c000000000fac0600' + '3603a1b201'),
('No RSN Capabilities field (PMF disabled in practice)',
'30120100000fac040100000fac040100000fac04' + '3603a1b201')]
for txt, ie in tests:
dev[0].request("DISCONNECT")
dev[0].wait_disconnected()
logger.info(txt)
hapd.disable()
hapd.set('own_ie_override', ie)
hapd.enable()
dev[0].request("BSS_FLUSH 0")
dev[0].scan_for_bss(bssid, 2412, force_scan=True, only_new=True)
dev[0].select_network(id, freq=2412)
dev[0].wait_connected()
dev[0].request("DISCONNECT")
dev[0].wait_disconnected()
logger.info('Invalid RSNE causing internal hostapd error')
hapd.disable()
hapd.set('own_ie_override', '30130100000fac040100000fac040100000fac048c' + '3603a1b201')
hapd.enable()
dev[0].request("BSS_FLUSH 0")
dev[0].scan_for_bss(bssid, 2412, force_scan=True, only_new=True)
dev[0].select_network(id, freq=2412)
# hostapd fails to generate EAPOL-Key msg 3/4, so this connection cannot
# complete.
ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
if ev is not None:
raise Exception("Unexpected connection")
dev[0].request("DISCONNECT")
def start_ft(apdev, wpa_ptk_rekey=None):
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
if wpa_ptk_rekey:
params['wpa_ptk_rekey'] = str(wpa_ptk_rekey)
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
if wpa_ptk_rekey:
params['wpa_ptk_rekey'] = str(wpa_ptk_rekey)
hapd1 = hostapd.add_ap(apdev[1], params)
return hapd0, hapd1
def check_ptk_rekey(dev, hapd0=None, hapd1=None):
ev = dev.wait_event(["CTRL-EVENT-DISCONNECTED",
"WPA: Key negotiation completed"], timeout=5)
if ev is None:
raise Exception("No event received after roam")
if "CTRL-EVENT-DISCONNECTED" in ev:
raise Exception("Unexpected disconnection after roam")
if not hapd0 or not hapd1:
return
if dev.get_status_field('bssid') == hapd0.own_addr():
hapd = hapd0
else:
hapd = hapd1
time.sleep(0.1)
hwsim_utils.test_connectivity(dev, hapd)
def test_ap_ft_ptk_rekey(dev, apdev):
"""WPA2-PSK-FT PTK rekeying triggered by station after roam"""
hapd0, hapd1 = start_ft(apdev)
run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", ptk_rekey="1")
check_ptk_rekey(dev[0], hapd0, hapd1)
def test_ap_ft_ptk_rekey2(dev, apdev):
"""WPA2-PSK-FT PTK rekeying triggered by station after one roam"""
hapd0, hapd1 = start_ft(apdev)
run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", ptk_rekey="1",
only_one_way=True)
check_ptk_rekey(dev[0], hapd0, hapd1)
def test_ap_ft_ptk_rekey_ap(dev, apdev):
"""WPA2-PSK-FT PTK rekeying triggered by AP after roam"""
hapd0, hapd1 = start_ft(apdev, wpa_ptk_rekey=2)
run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678")
check_ptk_rekey(dev[0], hapd0, hapd1)
def test_ap_ft_ptk_rekey_ap2(dev, apdev):
"""WPA2-PSK-FT PTK rekeying triggered by AP after one roam"""
hapd0, hapd1 = start_ft(apdev, wpa_ptk_rekey=2)
run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678",
only_one_way=True)
check_ptk_rekey(dev[0], hapd0, hapd1)
def test_ap_ft_eap_ptk_rekey_ap(dev, apdev):
"""WPA2-EAP-FT PTK rekeying triggered by AP"""
generic_ap_ft_eap(dev, apdev, only_one_way=True, wpa_ptk_rekey=2)
check_ptk_rekey(dev[0])
def test_ap_ft_internal_rrb_check(dev, apdev):
"""RRB internal delivery only to WPA enabled BSS"""
ssid = "test-ft"
passphrase = "12345678"
radius = hostapd.radius_params()
params = ft_params1(ssid=ssid, passphrase=passphrase)
params['wpa_key_mgmt'] = "FT-EAP"
params["ieee8021x"] = "1"
params = dict(list(radius.items()) + list(params.items()))
hapd = hostapd.add_ap(apdev[0], params)
key_mgmt = hapd.get_config()['key_mgmt']
if key_mgmt.split(' ')[0] != "FT-EAP":
raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
hapd1 = hostapd.add_ap(apdev[1], {"ssid": ssid})
# Connect to WPA enabled AP
dev[0].connect(ssid, key_mgmt="FT-EAP", proto="WPA2", ieee80211w="1",
eap="GPSK", identity="gpsk user",
password="abcdefghijklmnop0123456789abcdef",
scan_freq="2412")
# Try over_ds roaming to non-WPA-enabled AP.
# If hostapd does not check hapd->wpa_auth internally, it will crash now.
dev[0].roam_over_ds(apdev[1]['bssid'], fail_test=True)
def test_ap_ft_extra_ie(dev, apdev):
"""WPA2-PSK-FT AP with WPA2-PSK enabled and unexpected MDE"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["wpa_key_mgmt"] = "WPA-PSK FT-PSK"
hapd0 = hostapd.add_ap(apdev[0], params)
dev[1].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
dev[2].connect(ssid, psk=passphrase, key_mgmt="WPA-PSK", proto="WPA2",
scan_freq="2412")
try:
# Add Mobility Domain element to test AP validation code.
dev[0].request("VENDOR_ELEM_ADD 13 3603a1b201")
dev[0].connect(ssid, psk=passphrase, key_mgmt="WPA-PSK", proto="WPA2",
scan_freq="2412", wait_connect=False)
ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
"CTRL-EVENT-ASSOC-REJECT"], timeout=10)
if ev is None:
raise Exception("No connection result")
if "CTRL-EVENT-CONNECTED" in ev:
raise Exception("Non-FT association accepted with MDE")
if "status_code=43" not in ev:
raise Exception("Unexpected status code: " + ev)
dev[0].request("DISCONNECT")
finally:
dev[0].request("VENDOR_ELEM_REMOVE 13 *")
def test_ap_ft_ric(dev, apdev):
"""WPA2-PSK-FT AP and RIC"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
hapd1 = hostapd.add_ap(apdev[1], params)
dev[0].set("ric_ies", "")
dev[0].set("ric_ies", '""')
if "FAIL" not in dev[0].request("SET ric_ies q"):
raise Exception("Invalid ric_ies value accepted")
tests = ["3900",
"3900ff04eeeeeeee",
"390400000000",
"390400000000" + "390400000000",
"390400000000" + "dd050050f20202",
"390400000000" + "dd3d0050f2020201" + 55*"00",
"390400000000" + "dd3d0050f2020201aa300010270000000000000000000000000000000000000000000000000000ffffff7f00000000000000000000000040420f00ffff0000",
"390401010000" + "dd3d0050f2020201aa3000dc050000000000000000000000000000000000000000000000000000dc050000000000000000000000000000808d5b0028230000"]
for t in tests:
dev[0].set("ric_ies", t)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase,
test_connectivity=False)
dev[0].request("REMOVE_NETWORK all")
dev[0].wait_disconnected()
dev[0].dump_monitor()
def ie_hex(ies, id):
return binascii.hexlify(struct.pack('BB', id, len(ies[id])) + ies[id]).decode()
def test_ap_ft_reassoc_proto(dev, apdev):
"""WPA2-PSK-FT AP Reassociation Request frame parsing"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
hapd1 = hostapd.add_ap(apdev[1], params)
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
ieee80211w="1", scan_freq="2412")
if dev[0].get_status_field('bssid') == hapd0.own_addr():
hapd1ap = hapd0
hapd2ap = hapd1
else:
hapd1ap = hapd1
hapd2ap = hapd0
dev[0].scan_for_bss(hapd2ap.own_addr(), freq="2412")
hapd2ap.set("ext_mgmt_frame_handling", "1")
dev[0].request("ROAM " + hapd2ap.own_addr())
while True:
req = hapd2ap.mgmt_rx()
hapd2ap.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
if req['subtype'] == 11:
break
while True:
req = hapd2ap.mgmt_rx()
if req['subtype'] == 2:
break
hapd2ap.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
# IEEE 802.11 header + fixed fields before IEs
hdr = binascii.hexlify(req['frame'][0:34]).decode()
ies = parse_ie(binascii.hexlify(req['frame'][34:]))
# First elements: SSID, Supported Rates, Extended Supported Rates
ies1 = ie_hex(ies, 0) + ie_hex(ies, 1) + ie_hex(ies, 50)
rsne = ie_hex(ies, 48)
mde = ie_hex(ies, 54)
fte = ie_hex(ies, 55)
tests = []
# RSN: Trying to use FT, but MDIE not included
tests += [rsne]
# RSN: Attempted to use unknown MDIE
tests += [rsne + "3603000000"]
# Invalid RSN pairwise cipher
tests += ["30260100000fac040100000fac030100000fac040000010029208a42cd25c85aa571567dce10dae3"]
# FT: No PMKID in RSNIE
tests += ["30160100000fac040100000fac040100000fac0400000000" + ie_hex(ies, 54)]
# FT: Invalid FTIE
tests += [rsne + mde]
# FT: RIC IE(s) in the frame, but not included in protected IE count
# FT: Failed to parse FT IEs
tests += [rsne + mde + fte + "3900"]
# FT: SNonce mismatch in FTIE
tests += [rsne + mde + "37520000" + 16*"00" + 32*"00" + 32*"00"]
# FT: ANonce mismatch in FTIE
tests += [rsne + mde + fte[0:40] + 32*"00" + fte[104:]]
# FT: No R0KH-ID subelem in FTIE
tests += [rsne + mde + "3752" + fte[4:168]]
# FT: R0KH-ID in FTIE did not match with the current R0KH-ID
tests += [rsne + mde + "3755" + fte[4:168] + "0301ff"]
# FT: No R1KH-ID subelem in FTIE
tests += [rsne + mde + "375e" + fte[4:168] + "030a" + binascii.hexlify(b"nas1.w1.fi").decode()]
# FT: Unknown R1KH-ID used in ReassocReq
tests += [rsne + mde + "3766" + fte[4:168] + "030a" + binascii.hexlify(b"nas1.w1.fi").decode() + "0106000000000000"]
# FT: PMKID in Reassoc Req did not match with the PMKR1Name derived from auth request
tests += [rsne[:-32] + 16*"00" + mde + fte]
# Invalid MIC in FTIE
tests += [rsne + mde + fte[0:8] + 16*"00" + fte[40:]]
for t in tests:
hapd2ap.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + ies1 + t)
def test_ap_ft_reassoc_local_fail(dev, apdev):
"""WPA2-PSK-FT AP Reassociation Request frame and local failure"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
hapd1 = hostapd.add_ap(apdev[1], params)
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
ieee80211w="1", scan_freq="2412")
if dev[0].get_status_field('bssid') == hapd0.own_addr():
hapd1ap = hapd0
hapd2ap = hapd1
else:
hapd1ap = hapd1
hapd2ap = hapd0
dev[0].scan_for_bss(hapd2ap.own_addr(), freq="2412")
# FT: Failed to calculate MIC
with fail_test(hapd2ap, 1, "wpa_ft_validate_reassoc"):
dev[0].request("ROAM " + hapd2ap.own_addr())
ev = dev[0].wait_event(["CTRL-EVENT-ASSOC-REJECT"], timeout=10)
dev[0].request("DISCONNECT")
if ev is None:
raise Exception("Association reject not seen")
def test_ap_ft_reassoc_replay(dev, apdev, params):
"""WPA2-PSK-FT AP and replayed Reassociation Request frame"""
capfile = os.path.join(params['logdir'], "hwsim0.pcapng")
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
hapd1 = hostapd.add_ap(apdev[1], params)
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
if dev[0].get_status_field('bssid') == hapd0.own_addr():
hapd1ap = hapd0
hapd2ap = hapd1
else:
hapd1ap = hapd1
hapd2ap = hapd0
dev[0].scan_for_bss(hapd2ap.own_addr(), freq="2412")
hapd2ap.set("ext_mgmt_frame_handling", "1")
dev[0].dump_monitor()
if "OK" not in dev[0].request("ROAM " + hapd2ap.own_addr()):
raise Exception("ROAM failed")
reassocreq = None
count = 0
while count < 100:
req = hapd2ap.mgmt_rx()
count += 1
hapd2ap.dump_monitor()
hapd2ap.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
if req['subtype'] == 2:
reassocreq = req
ev = hapd2ap.wait_event(["MGMT-TX-STATUS"], timeout=5)
if ev is None:
raise Exception("No TX status seen")
cmd = "MGMT_TX_STATUS_PROCESS %s" % (" ".join(ev.split(' ')[1:4]))
if "OK" not in hapd2ap.request(cmd):
raise Exception("MGMT_TX_STATUS_PROCESS failed")
break
hapd2ap.set("ext_mgmt_frame_handling", "0")
if reassocreq is None:
raise Exception("No Reassociation Request frame seen")
dev[0].wait_connected()
dev[0].dump_monitor()
hapd2ap.dump_monitor()
hwsim_utils.test_connectivity(dev[0], hapd2ap)
logger.info("Replay the last Reassociation Request frame")
hapd2ap.dump_monitor()
hapd2ap.set("ext_mgmt_frame_handling", "1")
hapd2ap.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
ev = hapd2ap.wait_event(["MGMT-TX-STATUS"], timeout=5)
if ev is None:
raise Exception("No TX status seen")
cmd = "MGMT_TX_STATUS_PROCESS %s" % (" ".join(ev.split(' ')[1:4]))
if "OK" not in hapd2ap.request(cmd):
raise Exception("MGMT_TX_STATUS_PROCESS failed")
hapd2ap.set("ext_mgmt_frame_handling", "0")
try:
hwsim_utils.test_connectivity(dev[0], hapd2ap)
ok = True
except:
ok = False
ap = hapd2ap.own_addr()
sta = dev[0].own_addr()
filt = "wlan.fc.type == 2 && " + \
"wlan.da == " + sta + " && " + \
"wlan.sa == " + ap + " && " + \
"wlan.fc.protected == 1"
fields = ["wlan.ccmp.extiv"]
res = run_tshark(capfile, filt, fields)
vals = res.splitlines()
logger.info("CCMP PN: " + str(vals))
if len(vals) < 2:
raise Exception("Could not find all CCMP protected frames from capture")
if len(set(vals)) < len(vals):
raise Exception("Duplicate CCMP PN used")
if not ok:
raise Exception("The second hwsim connectivity test failed")
def test_ap_ft_psk_file(dev, apdev):
"""WPA2-PSK-FT AP with PSK from a file"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1a(ssid=ssid, passphrase=passphrase)
params['wpa_psk_file'] = 'hostapd.wpa_psk'
hapd = hostapd.add_ap(apdev[0], params)
dev[1].connect(ssid, psk="very secret",
key_mgmt="FT-PSK", proto="WPA2", ieee80211w="1",
scan_freq="2412", wait_connect=False)
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
ieee80211w="1", scan_freq="2412")
dev[0].request("REMOVE_NETWORK all")
dev[0].wait_disconnected()
dev[0].connect(ssid, psk="very secret", key_mgmt="FT-PSK", proto="WPA2",
ieee80211w="1", scan_freq="2412")
dev[0].request("REMOVE_NETWORK all")
dev[0].wait_disconnected()
dev[0].connect(ssid, psk="secret passphrase",
key_mgmt="FT-PSK", proto="WPA2", ieee80211w="1",
scan_freq="2412")
dev[2].connect(ssid, psk="another passphrase for all STAs",
key_mgmt="FT-PSK", proto="WPA2", ieee80211w="1",
scan_freq="2412")
ev = dev[1].wait_event(["WPA: 4-Way Handshake failed"], timeout=10)
if ev is None:
raise Exception("Timed out while waiting for failure report")
dev[1].request("REMOVE_NETWORK all")
def test_ap_ft_eap_ap_config_change(dev, apdev):
"""WPA2-EAP-FT AP changing from 802.1X-only to FT-only"""
ssid = "test-ft"
passphrase = "12345678"
bssid = apdev[0]['bssid']
radius = hostapd.radius_params()
params = ft_params1(ssid=ssid, passphrase=passphrase, discovery=True)
params['wpa_key_mgmt'] = "WPA-EAP"
params["ieee8021x"] = "1"
params["pmk_r1_push"] = "0"
params["r0kh"] = "ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
params["r1kh"] = "00:00:00:00:00:00 00:00:00:00:00:00 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
params["eap_server"] = "0"
params = dict(list(radius.items()) + list(params.items()))
hapd = hostapd.add_ap(apdev[0], params)
dev[0].connect(ssid, key_mgmt="FT-EAP WPA-EAP", proto="WPA2",
eap="GPSK", identity="gpsk user",
password="abcdefghijklmnop0123456789abcdef",
scan_freq="2412")
dev[0].request("DISCONNECT")
dev[0].wait_disconnected()
dev[0].dump_monitor()
hapd.disable()
hapd.set('wpa_key_mgmt', "FT-EAP")
hapd.enable()
dev[0].request("BSS_FLUSH 0")
dev[0].scan_for_bss(bssid, 2412, force_scan=True, only_new=True)
dev[0].request("RECONNECT")
dev[0].wait_connected()
def test_ap_ft_eap_sha384(dev, apdev):
"""WPA2-EAP-FT with SHA384"""
ssid = "test-ft"
passphrase = "12345678"
radius = hostapd.radius_params()
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
params['wpa_key_mgmt'] = "FT-EAP-SHA384"
params["ieee8021x"] = "1"
params = dict(list(radius.items()) + list(params.items()))
hapd0 = hostapd.add_ap(apdev[0], params)
conf = hapd0.request("GET_CONFIG")
if "key_mgmt=FT-EAP-SHA384" not in conf.splitlines():
logger.info("GET_CONFIG:\n" + conf)
raise Exception("GET_CONFIG did not report correct key_mgmt")
params = ft_params2(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
params['wpa_key_mgmt'] = "FT-EAP-SHA384"
params["ieee8021x"] = "1"
params = dict(list(radius.items()) + list(params.items()))
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, eap=True,
sha384=True)
def test_ap_ft_eap_sha384_reassoc(dev, apdev):
"""WPA2-EAP-FT with SHA384 using REASSOCIATE"""
check_suite_b_192_capa(dev)
ssid = "test-ft"
passphrase = "12345678"
radius = hostapd.radius_params()
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
params['wpa_key_mgmt'] = "WPA-EAP-SUITE-B-192 FT-EAP-SHA384"
params["ieee8021x"] = "1"
params = dict(list(radius.items()) + list(params.items()))
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
params['wpa_key_mgmt'] = "WPA-EAP-SUITE-B-192 FT-EAP-SHA384"
params["ieee8021x"] = "1"
params = dict(list(radius.items()) + list(params.items()))
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, eap=True,
sha384=True, also_non_ft=True, roam_with_reassoc=True)
def test_ap_ft_eap_sha384_over_ds(dev, apdev):
"""WPA2-EAP-FT with SHA384 over DS"""
ssid = "test-ft"
passphrase = "12345678"
radius = hostapd.radius_params()
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
params['wpa_key_mgmt'] = "FT-EAP-SHA384"
params["ieee8021x"] = "1"
params = dict(list(radius.items()) + list(params.items()))
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params["ieee80211w"] = "2"
params['wpa_key_mgmt'] = "FT-EAP-SHA384"
params["ieee8021x"] = "1"
params = dict(list(radius.items()) + list(params.items()))
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
eap=True, sha384=True)
def test_ap_ft_roam_rrm(dev, apdev):
"""WPA2-PSK-FT AP and radio measurement request"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params["rrm_beacon_report"] = "1"
hapd0 = hostapd.add_ap(apdev[0], params)
bssid0 = hapd0.own_addr()
addr = dev[0].own_addr()
dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
scan_freq="2412")
check_beacon_req(hapd0, addr, 1)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params["rrm_beacon_report"] = "1"
hapd1 = hostapd.add_ap(apdev[1], params)
bssid1 = hapd1.own_addr()
dev[0].scan_for_bss(bssid1, freq=2412)
dev[0].roam(bssid1)
check_beacon_req(hapd1, addr, 2)
dev[0].scan_for_bss(bssid0, freq=2412)
dev[0].roam(bssid0)
check_beacon_req(hapd0, addr, 3)
def test_ap_ft_pmksa_caching(dev, apdev):
"""FT-EAP and PMKSA caching for initial mobility domain association"""
ssid = "test-ft"
identity = "gpsk user"
radius = hostapd.radius_params()
params = ft_params1(ssid=ssid)
params['wpa_key_mgmt'] = "FT-EAP"
params["ieee8021x"] = "1"
params["mobility_domain"] = "c3d4"
params = dict(list(radius.items()) + list(params.items()))
hapd = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid)
params['wpa_key_mgmt'] = "FT-EAP"
params["ieee8021x"] = "1"
params["mobility_domain"] = "c3d4"
params = dict(list(radius.items()) + list(params.items()))
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd, hapd1, ssid, None, eap=True,
eap_identity=identity, pmksa_caching=True)
def test_ap_ft_pmksa_caching_sha384(dev, apdev):
"""FT-EAP-SHA384 and PMKSA caching for initial mobility domain association"""
ssid = "test-ft"
identity = "gpsk user"
radius = hostapd.radius_params()
params = ft_params1(ssid=ssid)
params['wpa_key_mgmt'] = "FT-EAP-SHA384"
params["ieee8021x"] = "1"
params["mobility_domain"] = "c3d4"
params = dict(list(radius.items()) + list(params.items()))
hapd = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid)
params['wpa_key_mgmt'] = "FT-EAP-SHA384"
params["ieee8021x"] = "1"
params["mobility_domain"] = "c3d4"
params = dict(list(radius.items()) + list(params.items()))
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd, hapd1, ssid, None, eap=True,
eap_identity=identity, pmksa_caching=True, sha384=True)
def test_ap_ft_r1_key_expiration(dev, apdev):
"""WPA2-PSK-FT and PMK-R1 expiration"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params['r1_max_key_lifetime'] = "2"
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params['r1_max_key_lifetime'] = "2"
hapd1 = hostapd.add_ap(apdev[1], params)
# This succeeds, but results in having to run another PMK-R1 pull before the
# second AP can complete FT protocol.
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, wait_before_roam=4)
def test_ap_ft_r0_key_expiration(dev, apdev):
"""WPA2-PSK-FT and PMK-R0 expiration"""
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
params.pop('r0_key_lifetime', None)
params['ft_r0_key_lifetime'] = "2"
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
params.pop('r0_key_lifetime', None)
params['ft_r0_key_lifetime'] = "2"
hapd1 = hostapd.add_ap(apdev[1], params)
bssid2 = run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase,
return_after_initial=True)
time.sleep(4)
dev[0].scan_for_bss(bssid2, freq="2412")
if "OK" not in dev[0].request("ROAM " + bssid2):
raise Exception("ROAM failed")
ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
"CTRL-EVENT-AUTH-REJECT",
"CTRL-EVENT-ASSOC-REJECT"], timeout=5)
dev[0].request("DISCONNECT")
if ev is None or "CTRL-EVENT-AUTH-REJECT" not in ev:
raise Exception("FT protocol failure not reported")
if "status_code=53" not in ev:
raise Exception("Unexpected status in FT protocol failure: " + ev)
# Generate a new PMK-R0
dev[0].dump_monitor()
dev[0].request("RECONNECT")
dev[0].wait_connected()
def test_ap_ft_no_full_ap_client_state(dev, apdev):
"""WPA2-PSK-FT AP with full_ap_client_state=0"""
run_ap_ft_skip_prune_assoc(dev, apdev, False, False)
def test_ap_ft_skip_prune_assoc(dev, apdev):
"""WPA2-PSK-FT AP with skip_prune_assoc"""
run_ap_ft_skip_prune_assoc(dev, apdev, True, True)
def test_ap_ft_skip_prune_assoc2(dev, apdev):
"""WPA2-PSK-FT AP with skip_prune_assoc (disable full_ap_client_state)"""
run_ap_ft_skip_prune_assoc(dev, apdev, True, False, test_connectivity=False)
def test_ap_ft_skip_prune_assoc_pmf(dev, apdev):
"""WPA2-PSK-FT/PMF AP with skip_prune_assoc"""
run_ap_ft_skip_prune_assoc(dev, apdev, True, True, pmf=True)
def test_ap_ft_skip_prune_assoc_pmf_over_ds(dev, apdev):
"""WPA2-PSK-FT/PMF AP with skip_prune_assoc (over DS)"""
run_ap_ft_skip_prune_assoc(dev, apdev, True, True, pmf=True, over_ds=True)
def run_ap_ft_skip_prune_assoc(dev, apdev, skip_prune_assoc,
full_ap_client_state, test_connectivity=True,
pmf=False, over_ds=False):
ssid = "test-ft"
passphrase = "12345678"
params = ft_params1(ssid=ssid, passphrase=passphrase)
if skip_prune_assoc:
params['skip_prune_assoc'] = '1'
if not full_ap_client_state:
params['driver_params'] = "full_ap_client_state=0"
if pmf:
params["ieee80211w"] = "2"
hapd0 = hostapd.add_ap(apdev[0], params)
params = ft_params2(ssid=ssid, passphrase=passphrase)
if skip_prune_assoc:
params['skip_prune_assoc'] = '1'
if not full_ap_client_state:
params['driver_params'] = "full_ap_client_state=0"
if pmf:
params["ieee80211w"] = "2"
hapd1 = hostapd.add_ap(apdev[1], params)
run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase,
ieee80211w="2" if pmf else "0",
over_ds=over_ds, test_connectivity=test_connectivity)
def test_ap_ft_sae_skip_prune_assoc(dev, apdev):
"""WPA2-PSK-FT-SAE AP with skip_prune_assoc"""
hapd0, hapd1 = start_ft_sae(dev[0], apdev, skip_prune_assoc=True)
run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True)