X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fhostap.git;a=blobdiff_plain;f=tests%2Fhwsim%2Ftest_ap_ft.py;h=1556158292e1b47e4b5ba6f4afdd2c5eefe41fd8;hp=7a2dfd9543851a03a3aade7bbde15234279554e1;hb=12de14907133a9cc710a8bfd9329a6aa321a604c;hpb=cdf539101310f986f68596f60621e338138c3d77 diff --git a/tests/hwsim/test_ap_ft.py b/tests/hwsim/test_ap_ft.py index 7a2dfd954..155615829 100644 --- a/tests/hwsim/test_ap_ft.py +++ b/tests/hwsim/test_ap_ft.py @@ -22,6 +22,7 @@ from utils import HwsimSkip, alloc_fail, fail_test, wait_fail_trigger, skip_with 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", @@ -133,12 +134,14 @@ def run_roams(dev, apdev, hapd0, hapd1, ssid, passphrase, over_ds=False, 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): + 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"): logger.info("Connect to first AP") copts = {} copts["proto"] = "WPA2" - copts["ieee80211w"] = "1" + copts["ieee80211w"] = ieee80211w copts["scan_freq"] = "2412" copts["pairwise"] = pairwise_cipher copts["group"] = group_cipher @@ -148,7 +151,12 @@ def run_roams(dev, apdev, hapd0, hapd1, ssid, passphrase, over_ds=False, if ocv: copts["ocv"] = ocv if eap: - copts["key_mgmt"] = "FT-EAP-SHA384" if sha384 else "FT-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" @@ -165,7 +173,21 @@ def run_roams(dev, apdev, hapd0, hapd1, ssid, passphrase, over_ds=False, copts["sae_password_id"] = sae_password_id if force_initial_conn_to_first_ap: copts["bssid"] = apdev[0]['bssid'] - dev.connect(ssid, **copts) + netw = dev.connect(ssid, **copts) + if pmksa_caching: + 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] @@ -178,11 +200,17 @@ def run_roams(dev, apdev, hapd0, hapd1, ssid, passphrase, over_ds=False, 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): @@ -190,7 +218,11 @@ def run_roams(dev, apdev, hapd0, hapd1, ssid, passphrase, over_ds=False, # set later. time.sleep(0.01) logger.info("Roam to the second AP") - if over_ds: + 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) @@ -199,22 +231,30 @@ def run_roams(dev, apdev, hapd0, hapd1, ssid, passphrase, over_ds=False, 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() if conndev: hwsim_utils.test_connectivity_iface(dev, hapd2ap, conndev) else: hwsim_utils.test_connectivity(dev, hapd2ap) + 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 over_ds: + 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() if conndev: hwsim_utils.test_connectivity_iface(dev, hapd1ap, conndev) else: @@ -395,6 +435,21 @@ def test_ap_ft_mixed(dev, apdev): 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" @@ -405,7 +460,36 @@ def test_ap_ft_pmf(dev, apdev): params["ieee80211w"] = "2" hapd1 = hostapd.add_ap(apdev[1], params) - run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase) + 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""" @@ -871,44 +955,82 @@ def test_ap_ft_over_ds_pull_vlan(dev, apdev): run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True, conndev="brvlan1") -def test_ap_ft_sae(dev, apdev): - """WPA2-PSK-FT-SAE AP""" - if "SAE" not in dev[0].get_capability("auth_alg"): +def start_ft_sae(dev, apdev, wpa_ptk_rekey=None): + 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) 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 wpa_ptk_rekey: + params['wpa_ptk_rekey'] = str(wpa_ptk_rekey) + hapd1 = hostapd.add_ap(apdev[1], params) + key_mgmt = hapd1.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) + 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_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_over_ds(dev, apdev): """WPA2-PSK-FT-SAE AP over DS""" - 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" - hapd1 = hostapd.add_ap(apdev[1], params) - - dev[0].request("SET sae_groups ") - run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, sae=True, + 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_pw_id(dev, apdev): """FT-SAE with Password Identifier""" if "SAE" not in dev[0].get_capability("auth_alg"): @@ -951,8 +1073,30 @@ def test_ap_ft_sae_with_both_akms(dev, apdev): 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 generic_ap_ft_eap(dev, apdev, vlan=False, cui=False, over_ds=False, - discovery=False, roams=1): + discovery=False, roams=1, wpa_ptk_rekey=0, + only_one_way=False): ssid = "test-ft" passphrase = "12345678" if vlan: @@ -981,16 +1125,20 @@ def generic_ap_ft_eap(dev, apdev, vlan=False, cui=False, over_ds=False, 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) + 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']: @@ -1110,6 +1258,10 @@ def test_ap_ft_eap_pull_wildcard(dev, apdev): 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) @@ -2255,57 +2407,68 @@ def test_rsn_ie_proto_ft_psk_sta(dev, apdev): raise Exception("Unexpected connection") dev[0].request("DISCONNECT") -def test_ap_ft_ptk_rekey(dev, apdev): - """WPA2-PSK-FT PTK rekeying triggered by station after roam""" +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) - run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, ptk_rekey="1") + return hapd0, hapd1 - ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED", - "WPA: Key negotiation completed"], timeout=5) +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 dev[0].get_status_field('bssid') == apdev[0]['bssid']: + if not hapd0 or not hapd1: + return + if dev.get_status_field('bssid') == hapd0.own_addr(): hapd = hapd0 else: hapd = hapd1 - hwsim_utils.test_connectivity(dev[0], hapd) - -def test_ap_ft_ptk_rekey_ap(dev, apdev): - """WPA2-PSK-FT PTK rekeying triggered by AP after roam""" - ssid = "test-ft" - passphrase = "12345678" - - params = ft_params1(ssid=ssid, passphrase=passphrase) - params['wpa_ptk_rekey'] = '2' - hapd0 = hostapd.add_ap(apdev[0], params) - params = ft_params2(ssid=ssid, passphrase=passphrase) - params['wpa_ptk_rekey'] = '2' - hapd1 = hostapd.add_ap(apdev[1], params) + time.sleep(0.1) + hwsim_utils.test_connectivity(dev, hapd) - run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase) +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) - ev = dev[0].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") +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) - if dev[0].get_status_field('bssid') == apdev[0]['bssid']: - hapd = hapd0 - else: - hapd = hapd1 - hwsim_utils.test_connectivity(dev[0], hapd) +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""" @@ -2575,7 +2738,8 @@ def test_ap_ft_reassoc_replay(dev, apdev, params): sta = dev[0].own_addr() filt = "wlan.fc.type == 2 && " + \ "wlan.da == " + sta + " && " + \ - "wlan.sa == " + ap + "wlan.sa == " + ap + " && " + \ + "wlan.fc.protected == 1" fields = ["wlan.ccmp.extiv"] res = run_tshark(capfile, filt, fields) vals = res.splitlines() @@ -2676,6 +2840,29 @@ def test_ap_ft_eap_sha384(dev, apdev): 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" @@ -2725,3 +2912,97 @@ def test_ap_ft_roam_rrm(dev, apdev): 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['ft_r0_key_lifetime'] = "2" + hapd0 = hostapd.add_ap(apdev[0], params) + params = ft_params2(ssid=ssid, passphrase=passphrase) + 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()