1# Fast BSS Transition tests
2# Copyright (c) 2013-2024, Jouni Malinen <j@w1.fi>
3#
4# This software may be distributed under the terms of the BSD license.
5# See README for more details.
6
7from remotehost import remote_compatible
8import binascii
9import os
10import time
11import logging
12logger = logging.getLogger()
13import signal
14import struct
15import subprocess
16import tempfile
17
18import hwsim_utils
19from hwsim import HWSimRadio
20import hostapd
21from tshark import run_tshark
22from utils import *
23from wlantest import Wlantest
24from test_ap_psk import check_mib, find_wpas_process, read_process_memory, verify_not_present, get_key_locations
25from test_rrm import check_beacon_req
26from test_suite_b import check_suite_b_192_capa
27
28def ft_base_rsn():
29    params = {"wpa": "2",
30              "wpa_key_mgmt": "FT-PSK",
31              "rsn_pairwise": "CCMP"}
32    return params
33
34def ft_base_mixed():
35    params = {"wpa": "3",
36              "wpa_key_mgmt": "WPA-PSK FT-PSK",
37              "wpa_pairwise": "TKIP",
38              "rsn_pairwise": "CCMP"}
39    return params
40
41def ft_params(rsn=True, ssid=None, passphrase=None, mobility_domain="a1b2"):
42    if rsn:
43        params = ft_base_rsn()
44    else:
45        params = ft_base_mixed()
46    if ssid:
47        params["ssid"] = ssid
48    if passphrase:
49        params["wpa_passphrase"] = passphrase
50
51    params["mobility_domain"] = mobility_domain
52    params["r0_key_lifetime"] = "10000"
53    params["pmk_r1_push"] = "1"
54    params["reassociation_deadline"] = "1000"
55    return params
56
57def ft_params1a(rsn=True, ssid=None, passphrase=None):
58    params = ft_params(rsn, ssid, passphrase)
59    params['nas_identifier'] = "nas1.w1.fi"
60    params['r1_key_holder'] = "000102030405"
61    return params
62
63def ft_params1(rsn=True, ssid=None, passphrase=None, discovery=False):
64    params = ft_params1a(rsn, ssid, passphrase)
65    if discovery:
66        params['r0kh'] = "ff:ff:ff:ff:ff:ff * 100102030405060708090a0b0c0d0e0f100102030405060708090a0b0c0d0e0f"
67        params['r1kh'] = "00:00:00:00:00:00 00:00:00:00:00:00 100102030405060708090a0b0c0d0e0f100102030405060708090a0b0c0d0e0f"
68    else:
69        params['r0kh'] = ["02:00:00:00:03:00 nas1.w1.fi 100102030405060708090a0b0c0d0e0f100102030405060708090a0b0c0d0e0f",
70                          "02:00:00:00:04:00 nas2.w1.fi 300102030405060708090a0b0c0d0e0f300102030405060708090a0b0c0d0e0f"]
71        params['r1kh'] = "02:00:00:00:04:00 00:01:02:03:04:06 200102030405060708090a0b0c0d0e0f200102030405060708090a0b0c0d0e0f"
72    return params
73
74def ft_params1_old_key(rsn=True, ssid=None, passphrase=None):
75    params = ft_params1a(rsn, ssid, passphrase)
76    params['r0kh'] = ["02:00:00:00:03:00 nas1.w1.fi 100102030405060708090a0b0c0d0e0f",
77                      "02:00:00:00:04:00 nas2.w1.fi 300102030405060708090a0b0c0d0e0f"]
78    params['r1kh'] = "02:00:00:00:04:00 00:01:02:03:04:06 200102030405060708090a0b0c0d0e0f"
79    return params
80
81def ft_params2a(rsn=True, ssid=None, passphrase=None, mobility_domain="a1b2"):
82    params = ft_params(rsn, ssid, passphrase, mobility_domain)
83    params['nas_identifier'] = "nas2.w1.fi"
84    params['r1_key_holder'] = "000102030406"
85    return params
86
87def ft_params2(rsn=True, ssid=None, passphrase=None, discovery=False,
88               mobility_domain="a1b2"):
89    params = ft_params2a(rsn, ssid, passphrase, mobility_domain)
90    if discovery:
91        params['r0kh'] = "ff:ff:ff:ff:ff:ff * 100102030405060708090a0b0c0d0e0f100102030405060708090a0b0c0d0e0f"
92        params['r1kh'] = "00:00:00:00:00:00 00:00:00:00:00:00 100102030405060708090a0b0c0d0e0f100102030405060708090a0b0c0d0e0f"
93    else:
94        params['r0kh'] = ["02:00:00:00:03:00 nas1.w1.fi 200102030405060708090a0b0c0d0e0f200102030405060708090a0b0c0d0e0f",
95                          "02:00:00:00:04:00 nas2.w1.fi 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"]
96        params['r1kh'] = "02:00:00:00:03:00 00:01:02:03:04:05 300102030405060708090a0b0c0d0e0f300102030405060708090a0b0c0d0e0f"
97    return params
98
99def ft_params2_old_key(rsn=True, ssid=None, passphrase=None):
100    params = ft_params2a(rsn, ssid, passphrase)
101    params['r0kh'] = ["02:00:00:00:03:00 nas1.w1.fi 200102030405060708090a0b0c0d0e0f",
102                      "02:00:00:00:04:00 nas2.w1.fi 000102030405060708090a0b0c0d0e0f"]
103    params['r1kh'] = "02:00:00:00:03:00 00:01:02:03:04:05 300102030405060708090a0b0c0d0e0f"
104    return params
105
106def ft_params1_r0kh_mismatch(rsn=True, ssid=None, passphrase=None):
107    params = ft_params(rsn, ssid, passphrase)
108    params['nas_identifier'] = "nas1.w1.fi"
109    params['r1_key_holder'] = "000102030405"
110    params['r0kh'] = ["02:00:00:00:03:00 nas1.w1.fi 100102030405060708090a0b0c0d0e0f100102030405060708090a0b0c0d0e0f",
111                      "12:00:00:00:04:00 nas2.w1.fi 300102030405060708090a0b0c0d0e0f300102030405060708090a0b0c0d0e0f"]
112    params['r1kh'] = "12:00:00:00:04:00 10:01:02:03:04:06 200102030405060708090a0b0c0d0e0f200102030405060708090a0b0c0d0e0f"
113    return params
114
115def ft_params2_incorrect_rrb_key(rsn=True, ssid=None, passphrase=None):
116    params = ft_params(rsn, ssid, passphrase)
117    params['nas_identifier'] = "nas2.w1.fi"
118    params['r1_key_holder'] = "000102030406"
119    params['r0kh'] = ["02:00:00:00:03:00 nas1.w1.fi 200102030405060708090a0b0c0d0ef1200102030405060708090a0b0c0d0ef1",
120                      "02:00:00:00:04:00 nas2.w1.fi 000102030405060708090a0b0c0d0ef2000102030405060708090a0b0c0d0ef2"]
121    params['r1kh'] = "02:00:00:00:03:00 00:01:02:03:04:05 300102030405060708090a0b0c0d0ef3300102030405060708090a0b0c0d0ef3"
122    return params
123
124def ft_params2_r0kh_mismatch(rsn=True, ssid=None, passphrase=None):
125    params = ft_params(rsn, ssid, passphrase)
126    params['nas_identifier'] = "nas2.w1.fi"
127    params['r1_key_holder'] = "000102030406"
128    params['r0kh'] = ["12:00:00:00:03:00 nas1.w1.fi 200102030405060708090a0b0c0d0e0f200102030405060708090a0b0c0d0e0f",
129                      "02:00:00:00:04:00 nas2.w1.fi 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"]
130    params['r1kh'] = "12:00:00:00:03:00 10:01:02:03:04:05 300102030405060708090a0b0c0d0e0f300102030405060708090a0b0c0d0e0f"
131    return params
132
133def run_roams(dev, apdev, hapd0, hapd1, ssid, passphrase, over_ds=False,
134              sae=False, eap=False, fail_test=False, roams=1,
135              pairwise_cipher="CCMP", group_cipher="CCMP", ptk_rekey="0",
136              test_connectivity=True, eap_identity="gpsk user", conndev=False,
137              force_initial_conn_to_first_ap=False, sha384=False,
138              group_mgmt=None, ocv=None, sae_password=None,
139              sae_password_id=None, sae_and_psk=False, pmksa_caching=False,
140              roam_with_reassoc=False, also_non_ft=False, only_one_way=False,
141              wait_before_roam=0, return_after_initial=False, ieee80211w="1",
142              sae_transition=False, beacon_prot=False, sae_ext_key=False,
143              check_ssid=False):
144    logger.info("Connect to first AP")
145
146    copts = {}
147    copts["proto"] = "WPA2"
148    copts["ieee80211w"] = ieee80211w
149    copts["scan_freq"] = "2412"
150    copts["pairwise"] = pairwise_cipher
151    copts["group"] = group_cipher
152    copts["wpa_ptk_rekey"] = ptk_rekey
153    if group_mgmt:
154        copts["group_mgmt"] = group_mgmt
155    if ocv:
156        copts["ocv"] = ocv
157    if beacon_prot:
158        copts["beacon_prot"] = "1"
159    if eap:
160        if pmksa_caching:
161            copts["ft_eap_pmksa_caching"] = "1"
162        if also_non_ft:
163            copts["key_mgmt"] = "WPA-EAP-SUITE-B-192 FT-EAP-SHA384" if sha384 else "WPA-EAP FT-EAP"
164        else:
165            copts["key_mgmt"] = "FT-EAP-SHA384" if sha384 else "FT-EAP"
166        copts["eap"] = "GPSK"
167        copts["identity"] = eap_identity
168        copts["password"] = "abcdefghijklmnop0123456789abcdef"
169    else:
170        if sae_ext_key:
171            copts["key_mgmt"] = "FT-SAE-EXT-KEY"
172        elif sae_transition:
173            copts["key_mgmt"] = "FT-SAE FT-PSK"
174        elif sae:
175            copts["key_mgmt"] = "SAE FT-SAE" if sae_and_psk else "FT-SAE"
176        else:
177            copts["key_mgmt"] = "FT-PSK"
178        if passphrase:
179            copts["psk"] = passphrase
180        if sae_password:
181            copts["sae_password"] = sae_password
182        if sae_password_id:
183            copts["sae_password_id"] = sae_password_id
184    if force_initial_conn_to_first_ap:
185        copts["bssid"] = apdev[0]['bssid']
186    netw = dev.connect(ssid, **copts)
187    if pmksa_caching:
188        if dev.get_status_field('bssid') == apdev[0]['bssid']:
189            hapd0.wait_sta()
190        else:
191            hapd1.wait_sta()
192        if check_ssid and dev[0].get_status_field("ssid_verified") == "1":
193            raise Exception("Unexpected ssid_verified=1 in STATUS")
194        dev.request("DISCONNECT")
195        dev.wait_disconnected()
196        dev.request("RECONNECT")
197        ev = dev.wait_event(["CTRL-EVENT-CONNECTED",
198                             "CTRL-EVENT-DISCONNECTED",
199                             "CTRL-EVENT-EAP-STARTED"],
200                            timeout=15)
201        if ev is None:
202            raise Exception("Reconnect timed out")
203        if "CTRL-EVENT-DISCONNECTED" in ev:
204            raise Exception("Unexpected disconnection after RECONNECT")
205        if "CTRL-EVENT-EAP-STARTED" in ev:
206            raise Exception("Unexpected EAP start after RECONNECT")
207
208    if dev.get_status_field('bssid') == apdev[0]['bssid']:
209        ap1 = apdev[0]
210        ap2 = apdev[1]
211        hapd1ap = hapd0
212        hapd2ap = hapd1
213    else:
214        ap1 = apdev[1]
215        ap2 = apdev[0]
216        hapd1ap = hapd1
217        hapd2ap = hapd0
218    if test_connectivity:
219        hapd1ap.wait_sta()
220        if conndev:
221            hwsim_utils.test_connectivity_iface(dev, hapd1ap, conndev)
222        else:
223            hwsim_utils.test_connectivity(dev, hapd1ap)
224
225    if return_after_initial:
226        return ap2['bssid']
227
228    if wait_before_roam:
229        time.sleep(wait_before_roam)
230    dev.scan_for_bss(ap2['bssid'], freq="2412")
231
232    for i in range(0, roams):
233        dev.dump_monitor()
234        hapd1ap.dump_monitor()
235        hapd2ap.dump_monitor()
236
237        # Roaming artificially fast can make data test fail because the key is
238        # set later.
239        time.sleep(0.01)
240        logger.info("Roam to the second AP")
241        if roam_with_reassoc:
242            dev.set_network(netw, "bssid", ap2['bssid'])
243            dev.request("REASSOCIATE")
244            dev.wait_connected()
245        elif over_ds:
246            dev.roam_over_ds(ap2['bssid'], fail_test=fail_test)
247        else:
248            dev.roam(ap2['bssid'], fail_test=fail_test)
249        if fail_test:
250            return
251        if dev.get_status_field('bssid') != ap2['bssid']:
252            raise Exception("Did not connect to correct AP")
253        if check_ssid and dev.get_status_field("ssid_verified") != "1":
254            raise Exception("ssid_verified=1 not in STATUS")
255
256        if (i == 0 or i == roams - 1) and test_connectivity:
257            hapd2ap.wait_sta()
258            dev.dump_monitor()
259            hapd1ap.dump_monitor()
260            hapd2ap.dump_monitor()
261            if conndev:
262                hwsim_utils.test_connectivity_iface(dev, hapd2ap, conndev)
263            else:
264                hwsim_utils.test_connectivity(dev, hapd2ap)
265
266        dev.dump_monitor()
267        hapd1ap.dump_monitor()
268        hapd2ap.dump_monitor()
269
270        if only_one_way:
271            return
272        # Roaming artificially fast can make data test fail because the key is
273        # set later.
274        time.sleep(0.01)
275        logger.info("Roam back to the first AP")
276        if roam_with_reassoc:
277            dev.set_network(netw, "bssid", ap1['bssid'])
278            dev.request("REASSOCIATE")
279            dev.wait_connected()
280        elif over_ds:
281            dev.roam_over_ds(ap1['bssid'])
282        else:
283            dev.roam(ap1['bssid'])
284        if dev.get_status_field('bssid') != ap1['bssid']:
285            raise Exception("Did not connect to correct AP")
286        if check_ssid and dev.get_status_field("ssid_verified") != "1":
287            raise Exception("ssid_verified=1 not in STATUS")
288        if (i == 0 or i == roams - 1) and test_connectivity:
289            hapd1ap.wait_sta()
290            dev.dump_monitor()
291            hapd1ap.dump_monitor()
292            hapd2ap.dump_monitor()
293            if conndev:
294                hwsim_utils.test_connectivity_iface(dev, hapd1ap, conndev)
295            else:
296                hwsim_utils.test_connectivity(dev, hapd1ap)
297
298def test_ap_ft(dev, apdev):
299    """WPA2-PSK-FT AP"""
300    ssid = "test-ft"
301    passphrase = "12345678"
302
303    params = ft_params1(ssid=ssid, passphrase=passphrase)
304    hapd0 = hostapd.add_ap(apdev[0], params)
305    params = ft_params2(ssid=ssid, passphrase=passphrase)
306    hapd1 = hostapd.add_ap(apdev[1], params)
307
308    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase)
309    if "[WPA2-FT/PSK-CCMP]" not in dev[0].request("SCAN_RESULTS"):
310        raise Exception("Scan results missing RSN element info")
311
312def test_ap_ft_old_key(dev, apdev):
313    """WPA2-PSK-FT AP (old key)"""
314    ssid = "test-ft"
315    passphrase = "12345678"
316
317    params = ft_params1_old_key(ssid=ssid, passphrase=passphrase)
318    hapd0 = hostapd.add_ap(apdev[0], params)
319    params = ft_params2_old_key(ssid=ssid, passphrase=passphrase)
320    hapd1 = hostapd.add_ap(apdev[1], params)
321
322    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase)
323
324def test_ap_ft_multi_akm(dev, apdev):
325    """WPA2-PSK-FT AP with non-FT AKMs enabled"""
326    ssid = "test-ft"
327    passphrase = "12345678"
328
329    params = ft_params1(ssid=ssid, passphrase=passphrase)
330    params["wpa_key_mgmt"] = "FT-PSK WPA-PSK WPA-PSK-SHA256"
331    hapd0 = hostapd.add_ap(apdev[0], params)
332    params = ft_params2(ssid=ssid, passphrase=passphrase)
333    params["wpa_key_mgmt"] = "FT-PSK WPA-PSK WPA-PSK-SHA256"
334    hapd1 = hostapd.add_ap(apdev[1], params)
335
336    Wlantest.setup(hapd0)
337    wt = Wlantest()
338    wt.flush()
339    wt.add_passphrase(passphrase)
340
341    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase)
342    if "[WPA2-PSK+FT/PSK+PSK-SHA256-CCMP]" not in dev[0].request("SCAN_RESULTS"):
343        raise Exception("Scan results missing RSN element info")
344    dev[1].connect(ssid, psk=passphrase, scan_freq="2412")
345    dev[2].connect(ssid, psk=passphrase, key_mgmt="WPA-PSK-SHA256",
346                   scan_freq="2412")
347
348def test_ap_ft_local_key_gen(dev, apdev):
349    """WPA2-PSK-FT AP with local key generation (without pull/push)"""
350    ssid = "test-ft"
351    passphrase = "12345678"
352
353    params = ft_params1a(ssid=ssid, passphrase=passphrase)
354    params['ft_psk_generate_local'] = "1"
355    del params['pmk_r1_push']
356    hapd0 = hostapd.add_ap(apdev[0], params)
357    params = ft_params2a(ssid=ssid, passphrase=passphrase)
358    params['ft_psk_generate_local'] = "1"
359    del params['pmk_r1_push']
360    hapd1 = hostapd.add_ap(apdev[1], params)
361
362    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase)
363    if "[WPA2-FT/PSK-CCMP]" not in dev[0].request("SCAN_RESULTS"):
364        raise Exception("Scan results missing RSN element info")
365
366def test_ap_ft_vlan(dev, apdev):
367    """WPA2-PSK-FT AP with VLAN"""
368    ssid = "test-ft"
369    passphrase = "12345678"
370    filename = hostapd.acl_file(dev, apdev, 'hostapd.accept')
371    hostapd.send_file(apdev[0], filename, filename)
372    hostapd.send_file(apdev[1], filename, filename)
373
374    params = ft_params1(ssid=ssid, passphrase=passphrase)
375    params['dynamic_vlan'] = "1"
376    params['accept_mac_file'] = filename
377    hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
378
379    params = ft_params2(ssid=ssid, passphrase=passphrase)
380    params['dynamic_vlan'] = "1"
381    params['accept_mac_file'] = filename
382    hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
383
384    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, conndev="brvlan1")
385    if "[WPA2-FT/PSK-CCMP]" not in dev[0].request("SCAN_RESULTS"):
386        raise Exception("Scan results missing RSN element info")
387    if filename.startswith('/tmp/'):
388        os.unlink(filename)
389
390    sta = hapd0.get_sta(dev[0].own_addr())
391    if not (sta and "vlan_id" in sta):
392        raise Exception("VLAN information not in STA output")
393    vlan_id = int(sta["vlan_id"])
394    if vlan_id != 1:
395        raise Exception("Unexpected vlan_id %d" % vlan_id)
396
397    sta = hapd1.get_sta(dev[0].own_addr())
398    if not (sta and "vlan_id" in sta):
399        raise Exception("VLAN information not in STA output")
400    vlan_id = int(sta["vlan_id"])
401    if vlan_id != 1:
402        raise Exception("Unexpected vlan_id %d" % vlan_id)
403
404def test_ap_ft_vlan_disconnected(dev, apdev):
405    """WPA2-PSK-FT AP with VLAN and local key generation"""
406    ssid = "test-ft"
407    passphrase = "12345678"
408    filename = hostapd.acl_file(dev, apdev, 'hostapd.accept')
409    hostapd.send_file(apdev[0], filename, filename)
410    hostapd.send_file(apdev[1], filename, filename)
411
412    params = ft_params1a(ssid=ssid, passphrase=passphrase)
413    params['dynamic_vlan'] = "1"
414    params['accept_mac_file'] = filename
415    params['ft_psk_generate_local'] = "1"
416    hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
417
418    params = ft_params2a(ssid=ssid, passphrase=passphrase)
419    params['dynamic_vlan'] = "1"
420    params['accept_mac_file'] = filename
421    params['ft_psk_generate_local'] = "1"
422    hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
423
424    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, conndev="brvlan1")
425    if "[WPA2-FT/PSK-CCMP]" not in dev[0].request("SCAN_RESULTS"):
426        raise Exception("Scan results missing RSN element info")
427    if filename.startswith('/tmp/'):
428        os.unlink(filename)
429
430def test_ap_ft_vlan_2(dev, apdev):
431    """WPA2-PSK-FT AP with VLAN and dest-AP does not have VLAN info locally"""
432    ssid = "test-ft"
433    passphrase = "12345678"
434    filename = hostapd.acl_file(dev, apdev, 'hostapd.accept')
435    hostapd.send_file(apdev[0], filename, filename)
436
437    params = ft_params1(ssid=ssid, passphrase=passphrase)
438    params['dynamic_vlan'] = "1"
439    params['accept_mac_file'] = filename
440    hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
441
442    params = ft_params2(ssid=ssid, passphrase=passphrase)
443    params['dynamic_vlan'] = "1"
444    hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
445
446    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, conndev="brvlan1",
447              force_initial_conn_to_first_ap=True)
448    if "[WPA2-FT/PSK-CCMP]" not in dev[0].request("SCAN_RESULTS"):
449        raise Exception("Scan results missing RSN element info")
450    if filename.startswith('/tmp/'):
451        os.unlink(filename)
452
453def test_ap_ft_vlan_psk_file(dev, apdev, params):
454    """WPA2-PSK-FT AP with PSK and VLAN from a file"""
455    ssid = "test-ft"
456    passphrase = "12345678"
457    psk = params['prefix'] + '.wpa_psk'
458
459    with open(psk, 'w') as f:
460        f.write("00:00:00:00:00:00 default-passphrase\n")
461        f.write("vlanid=1 00:00:00:00:00:00 vlan-passphrase\n")
462
463    params = ft_params1(ssid=ssid, passphrase=passphrase)
464    params['dynamic_vlan'] = "1"
465    params['wpa_psk_file'] = psk
466    hapd0 = hostapd.add_ap(apdev[0], params)
467
468    params = ft_params2(ssid=ssid, passphrase=passphrase)
469    params['dynamic_vlan'] = "1"
470    params['wpa_psk_file'] = psk
471    hapd1 = hostapd.add_ap(apdev[1], params)
472
473    run_roams(dev[0], apdev, hapd0, hapd1, ssid, "vlan-passphrase",
474              conndev="brvlan1", force_initial_conn_to_first_ap=True,
475              test_connectivity=False)
476    run_roams(dev[1], apdev, hapd0, hapd1, ssid, "default-passphrase",
477              force_initial_conn_to_first_ap=True)
478
479    sta = hapd0.get_sta(dev[0].own_addr())
480    if not (sta and "vlan_id" in sta):
481        raise Exception("VLAN information not in STA output (hapd0)")
482    vlan_id = int(sta["vlan_id"])
483    if vlan_id != 1:
484        raise Exception("Unexpected vlan_id %d (hapd0)" % vlan_id)
485
486    sta = hapd1.get_sta(dev[0].own_addr())
487    if not (sta and "vlan_id" in sta):
488        raise Exception("VLAN information not in STA output (hapd1)")
489    vlan_id = int(sta["vlan_id"])
490    if vlan_id != 1:
491        raise Exception("Unexpected vlan_id %d (hapd1)" % vlan_id)
492
493    sta = hapd0.get_sta(dev[1].own_addr())
494    if "vlan_id" in sta:
495        raise Exception("Unexpected vlan_id hapd0/dev1")
496    sta = hapd1.get_sta(dev[1].own_addr())
497    if "vlan_id" in sta:
498        raise Exception("Unexpected vlan_id hapd1/dev1")
499
500def test_ap_ft_many(dev, apdev):
501    """WPA2-PSK-FT AP multiple times"""
502    ssid = "test-ft"
503    passphrase = "12345678"
504
505    params = ft_params1(ssid=ssid, passphrase=passphrase)
506    hapd0 = hostapd.add_ap(apdev[0], params)
507    params = ft_params2(ssid=ssid, passphrase=passphrase)
508    hapd1 = hostapd.add_ap(apdev[1], params)
509
510    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, roams=50)
511
512def test_ap_ft_many_vlan(dev, apdev):
513    """WPA2-PSK-FT AP with VLAN multiple times"""
514    ssid = "test-ft"
515    passphrase = "12345678"
516    filename = hostapd.acl_file(dev, apdev, 'hostapd.accept')
517    hostapd.send_file(apdev[0], filename, filename)
518    hostapd.send_file(apdev[1], filename, filename)
519
520    params = ft_params1(ssid=ssid, passphrase=passphrase)
521    params['dynamic_vlan'] = "1"
522    params['accept_mac_file'] = filename
523    hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
524
525    params = ft_params2(ssid=ssid, passphrase=passphrase)
526    params['dynamic_vlan'] = "1"
527    params['accept_mac_file'] = filename
528    hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
529
530    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, roams=50,
531              conndev="brvlan1")
532    if filename.startswith('/tmp/'):
533        os.unlink(filename)
534
535def test_ap_ft_mixed(dev, apdev):
536    """WPA2-PSK-FT mixed-mode AP"""
537    skip_without_tkip(dev[0])
538    ssid = "test-ft-mixed"
539    passphrase = "12345678"
540
541    params = ft_params1(rsn=False, ssid=ssid, passphrase=passphrase)
542    hapd = hostapd.add_ap(apdev[0], params)
543    key_mgmt = hapd.get_config()['key_mgmt']
544    vals = key_mgmt.split(' ')
545    if vals[0] != "WPA-PSK" or vals[1] != "FT-PSK":
546        raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
547    params = ft_params2(rsn=False, ssid=ssid, passphrase=passphrase)
548    hapd1 = hostapd.add_ap(apdev[1], params)
549
550    run_roams(dev[0], apdev, hapd, hapd1, ssid, passphrase,
551              group_cipher="TKIP CCMP")
552
553def test_ap_ft_pmf(dev, apdev):
554    """WPA2-PSK-FT AP with PMF"""
555    run_ap_ft_pmf(dev, apdev, "1")
556
557def test_ap_ft_pmf_over_ds(dev, apdev):
558    """WPA2-PSK-FT AP with PMF (over DS)"""
559    run_ap_ft_pmf(dev, apdev, "1", over_ds=True)
560
561def test_ap_ft_pmf_required(dev, apdev):
562    """WPA2-PSK-FT AP with PMF required on STA"""
563    run_ap_ft_pmf(dev, apdev, "2")
564
565def test_ap_ft_pmf_required_over_ds(dev, apdev):
566    """WPA2-PSK-FT AP with PMF required on STA (over DS)"""
567    run_ap_ft_pmf(dev, apdev, "2", over_ds=True)
568
569def test_ap_ft_pmf_beacon_prot(dev, apdev):
570    """WPA2-PSK-FT AP with PMF and beacon protection"""
571    run_ap_ft_pmf(dev, apdev, "1", beacon_prot=True)
572    ev = dev[0].wait_event(["CTRL-EVENT-BEACON-LOSS"], timeout=5)
573    if ev is not None:
574        raise Exception("Beacon loss detected")
575
576def run_ap_ft_pmf(dev, apdev, ieee80211w, over_ds=False, beacon_prot=False):
577    ssid = "test-ft"
578    passphrase = "12345678"
579
580    params = ft_params1(ssid=ssid, passphrase=passphrase)
581    params["ieee80211w"] = "2"
582    if beacon_prot:
583        params["beacon_prot"] = "1"
584    hapd0 = hostapd.add_ap(apdev[0], params)
585    params = ft_params2(ssid=ssid, passphrase=passphrase)
586    params["ieee80211w"] = "2"
587    if beacon_prot:
588        params["beacon_prot"] = "1"
589    hapd1 = hostapd.add_ap(apdev[1], params)
590
591    Wlantest.setup(hapd0)
592    wt = Wlantest()
593    wt.flush()
594    wt.add_passphrase(passphrase)
595
596    dev[0].flush_scan_cache()
597    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase,
598              ieee80211w=ieee80211w, over_ds=over_ds, beacon_prot=beacon_prot)
599
600def test_ap_ft_pmf_required_mismatch(dev, apdev):
601    """WPA2-PSK-FT AP with PMF required on STA but AP2 not enabling PMF"""
602    run_ap_ft_pmf_required_mismatch(dev, apdev)
603
604def test_ap_ft_pmf_required_mismatch_over_ds(dev, apdev):
605    """WPA2-PSK-FT AP with PMF required on STA but AP2 not enabling PMF (over DS)"""
606    run_ap_ft_pmf_required_mismatch(dev, apdev, over_ds=True)
607
608def run_ap_ft_pmf_required_mismatch(dev, apdev, over_ds=False):
609    ssid = "test-ft"
610    passphrase = "12345678"
611
612    params = ft_params1(ssid=ssid, passphrase=passphrase)
613    params["ieee80211w"] = "2"
614    hapd0 = hostapd.add_ap(apdev[0], params)
615    params = ft_params2(ssid=ssid, passphrase=passphrase)
616    params["ieee80211w"] = "0"
617    hapd1 = hostapd.add_ap(apdev[1], params)
618
619    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, ieee80211w="2",
620              force_initial_conn_to_first_ap=True, fail_test=True,
621              over_ds=over_ds)
622
623def test_ap_ft_pmf_bip_cmac_128(dev, apdev):
624    """WPA2-PSK-FT AP with PMF/BIP-CMAC-128"""
625    run_ap_ft_pmf_bip(dev, apdev, "AES-128-CMAC")
626
627def test_ap_ft_pmf_bip_gmac_128(dev, apdev):
628    """WPA2-PSK-FT AP with PMF/BIP-GMAC-128"""
629    run_ap_ft_pmf_bip(dev, apdev, "BIP-GMAC-128")
630
631def test_ap_ft_pmf_bip_gmac_256(dev, apdev):
632    """WPA2-PSK-FT AP with PMF/BIP-GMAC-256"""
633    run_ap_ft_pmf_bip(dev, apdev, "BIP-GMAC-256")
634
635def test_ap_ft_pmf_bip_cmac_256(dev, apdev):
636    """WPA2-PSK-FT AP with PMF/BIP-CMAC-256"""
637    run_ap_ft_pmf_bip(dev, apdev, "BIP-CMAC-256")
638
639def run_ap_ft_pmf_bip(dev, apdev, cipher):
640    if cipher not in dev[0].get_capability("group_mgmt"):
641        raise HwsimSkip("Cipher %s not supported" % cipher)
642
643    ssid = "test-ft"
644    passphrase = "12345678"
645
646    params = ft_params1(ssid=ssid, passphrase=passphrase)
647    params["ieee80211w"] = "2"
648    params["group_mgmt_cipher"] = cipher
649    hapd0 = hostapd.add_ap(apdev[0], params)
650    params = ft_params2(ssid=ssid, passphrase=passphrase)
651    params["ieee80211w"] = "2"
652    params["group_mgmt_cipher"] = cipher
653    hapd1 = hostapd.add_ap(apdev[1], params)
654
655    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase,
656              group_mgmt=cipher)
657
658def test_ap_ft_ocv(dev, apdev):
659    """WPA2-PSK-FT AP with OCV"""
660    ssid = "test-ft"
661    passphrase = "12345678"
662
663    params = ft_params1(ssid=ssid, passphrase=passphrase)
664    params["ieee80211w"] = "2"
665    params["ocv"] = "1"
666    try:
667        hapd0 = hostapd.add_ap(apdev[0], params)
668    except Exception as e:
669        if "Failed to set hostapd parameter ocv" in str(e):
670            raise HwsimSkip("OCV not supported")
671        raise
672    params = ft_params2(ssid=ssid, passphrase=passphrase)
673    params["ieee80211w"] = "2"
674    params["ocv"] = "1"
675    hapd1 = hostapd.add_ap(apdev[1], params)
676
677    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, ocv="1")
678
679def test_ap_ft_ocv_change(dev, apdev):
680    """WPA2-PSK-FT and different OCV capability between APs"""
681    ssid = "test-ft"
682    passphrase = "12345678"
683
684    params = ft_params1(ssid=ssid, passphrase=passphrase)
685    params["ieee80211w"] = "2"
686    params["ocv"] = "1"
687    try:
688        hapd0 = hostapd.add_ap(apdev[0], params)
689    except Exception as e:
690        if "Failed to set hostapd parameter ocv" in str(e):
691            raise HwsimSkip("OCV not supported")
692        raise
693    params = ft_params2(ssid=ssid, passphrase=passphrase)
694    params["ieee80211w"] = "2"
695    params["ocv"] = "0"
696    hapd1 = hostapd.add_ap(apdev[1], params)
697
698    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, ocv="1")
699
700def test_ap_ft_over_ds(dev, apdev):
701    """WPA2-PSK-FT AP over DS"""
702    ssid = "test-ft"
703    passphrase = "12345678"
704
705    params = ft_params1(ssid=ssid, passphrase=passphrase)
706    hapd0 = hostapd.add_ap(apdev[0], params)
707    params = ft_params2(ssid=ssid, passphrase=passphrase)
708    hapd1 = hostapd.add_ap(apdev[1], params)
709
710    dev[0].flush_scan_cache()
711    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True)
712    check_mib(dev[0], [("dot11RSNAAuthenticationSuiteRequested", "00-0f-ac-4"),
713                       ("dot11RSNAAuthenticationSuiteSelected", "00-0f-ac-4")])
714
715def cleanup_ap_ft_separate_hostapd():
716    subprocess.call(["brctl", "delif", "br0ft", "veth0"],
717                    stderr=open('/dev/null', 'w'))
718    subprocess.call(["brctl", "delif", "br1ft", "veth1"],
719                    stderr=open('/dev/null', 'w'))
720    subprocess.call(["ip", "link", "del", "veth0"],
721                    stderr=open('/dev/null', 'w'))
722    subprocess.call(["ip", "link", "del", "veth1"],
723                    stderr=open('/dev/null', 'w'))
724    for ifname in ['br0ft', 'br1ft', 'br-ft']:
725        subprocess.call(['ip', 'link', 'set', 'dev', ifname, 'down'],
726                        stderr=open('/dev/null', 'w'))
727        subprocess.call(['brctl', 'delbr', ifname],
728                        stderr=open('/dev/null', 'w'))
729
730def test_ap_ft_separate_hostapd(dev, apdev, params):
731    """WPA2-PSK-FT AP and separate hostapd process"""
732    try:
733        run_ap_ft_separate_hostapd(dev, apdev, params, False)
734    finally:
735        cleanup_ap_ft_separate_hostapd()
736
737def test_ap_ft_over_ds_separate_hostapd(dev, apdev, params):
738    """WPA2-PSK-FT AP over DS and separate hostapd process"""
739    try:
740        run_ap_ft_separate_hostapd(dev, apdev, params, True)
741    finally:
742        cleanup_ap_ft_separate_hostapd()
743
744def run_ap_ft_separate_hostapd(dev, apdev, params, over_ds):
745    ssid = "test-ft"
746    passphrase = "12345678"
747    logdir = params['logdir']
748    pidfile = os.path.join(logdir, 'ap_ft_over_ds_separate_hostapd.pid')
749    logfile = os.path.join(logdir, 'ap_ft_over_ds_separate_hostapd.hapd')
750    global_ctrl = '/var/run/hostapd-ft'
751    br_ifname = 'br-ft'
752
753    try:
754        subprocess.check_call(['brctl', 'addbr', br_ifname])
755        subprocess.check_call(['brctl', 'setfd', br_ifname, '0'])
756        subprocess.check_call(['ip', 'link', 'set', 'dev', br_ifname, 'up'])
757
758        subprocess.check_call(["ip", "link", "add", "veth0", "type", "veth",
759                               "peer", "name", "veth0br"])
760        subprocess.check_call(["ip", "link", "add", "veth1", "type", "veth",
761                               "peer", "name", "veth1br"])
762        subprocess.check_call(['ip', 'link', 'set', 'dev', 'veth0br', 'up'])
763        subprocess.check_call(['ip', 'link', 'set', 'dev', 'veth1br', 'up'])
764        subprocess.check_call(['brctl', 'addif', br_ifname, 'veth0br'])
765        subprocess.check_call(['brctl', 'addif', br_ifname, 'veth1br'])
766
767        subprocess.check_call(['brctl', 'addbr', 'br0ft'])
768        subprocess.check_call(['brctl', 'setfd', 'br0ft', '0'])
769        subprocess.check_call(['ip', 'link', 'set', 'dev', 'br0ft', 'up'])
770        subprocess.check_call(['ip', 'link', 'set', 'dev', 'veth0', 'up'])
771        subprocess.check_call(['brctl', 'addif', 'br0ft', 'veth0'])
772        subprocess.check_call(['brctl', 'addbr', 'br1ft'])
773        subprocess.check_call(['brctl', 'setfd', 'br1ft', '0'])
774        subprocess.check_call(['ip', 'link', 'set', 'dev', 'br1ft', 'up'])
775        subprocess.check_call(['ip', 'link', 'set', 'dev', 'veth1', 'up'])
776        subprocess.check_call(['brctl', 'addif', 'br1ft', 'veth1'])
777    except subprocess.CalledProcessError:
778        raise HwsimSkip("Bridge or veth not supported (kernel CONFIG_VETH)")
779
780    with HWSimRadio() as (radio, iface):
781        prg = os.path.join(logdir, 'alt-hostapd/hostapd/hostapd')
782        if not os.path.exists(prg):
783            prg = '../../hostapd/hostapd'
784        cmd = [prg, '-B', '-ddKt',
785               '-P', pidfile, '-f', logfile, '-g', global_ctrl]
786        subprocess.check_call(cmd)
787
788        hglobal = hostapd.HostapdGlobal(global_ctrl_override=global_ctrl)
789        apdev_ft = {'ifname': iface}
790        apdev2 = [apdev_ft, apdev[1]]
791
792        params = ft_params1(ssid=ssid, passphrase=passphrase)
793        params["r0kh"] = "ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
794        params["r1kh"] = "00:00:00:00:00:00 00:00:00:00:00:00 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
795        params['bridge'] = 'br0ft'
796        hapd0 = hostapd.add_ap(apdev2[0], params,
797                               global_ctrl_override=global_ctrl)
798        apdev2[0]['bssid'] = hapd0.own_addr()
799        params = ft_params2(ssid=ssid, passphrase=passphrase)
800        params["r0kh"] = "ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
801        params["r1kh"] = "00:00:00:00:00:00 00:00:00:00:00:00 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
802        params['bridge'] = 'br1ft'
803        hapd1 = hostapd.add_ap(apdev2[1], params)
804
805        run_roams(dev[0], apdev2, hapd0, hapd1, ssid, passphrase,
806                  over_ds=over_ds, test_connectivity=False, roams=2)
807
808        hglobal.terminate()
809
810    if os.path.exists(pidfile):
811        with open(pidfile, 'r') as f:
812            pid = int(f.read())
813            f.close()
814        os.kill(pid, signal.SIGTERM)
815
816def test_ap_ft_over_ds_ocv(dev, apdev):
817    """WPA2-PSK-FT AP over DS"""
818    ssid = "test-ft"
819    passphrase = "12345678"
820
821    params = ft_params1(ssid=ssid, passphrase=passphrase)
822    params["ieee80211w"] = "2"
823    params["ocv"] = "1"
824    try:
825        hapd0 = hostapd.add_ap(apdev[0], params)
826    except Exception as e:
827        if "Failed to set hostapd parameter ocv" in str(e):
828            raise HwsimSkip("OCV not supported")
829        raise
830    params = ft_params2(ssid=ssid, passphrase=passphrase)
831    params["ieee80211w"] = "2"
832    params["ocv"] = "1"
833    hapd1 = hostapd.add_ap(apdev[1], params)
834
835    dev[0].flush_scan_cache()
836    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
837              ocv="1")
838
839def test_ap_ft_over_ds_disabled(dev, apdev):
840    """WPA2-PSK-FT AP over DS disabled"""
841    ssid = "test-ft"
842    passphrase = "12345678"
843
844    params = ft_params1(ssid=ssid, passphrase=passphrase)
845    params['ft_over_ds'] = '0'
846    hapd0 = hostapd.add_ap(apdev[0], params)
847    params = ft_params2(ssid=ssid, passphrase=passphrase)
848    params['ft_over_ds'] = '0'
849    hapd1 = hostapd.add_ap(apdev[1], params)
850
851    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
852              fail_test=True)
853
854def test_ap_ft_vlan_over_ds(dev, apdev):
855    """WPA2-PSK-FT AP over DS with VLAN"""
856    ssid = "test-ft"
857    passphrase = "12345678"
858    filename = hostapd.acl_file(dev, apdev, 'hostapd.accept')
859    hostapd.send_file(apdev[0], filename, filename)
860    hostapd.send_file(apdev[1], filename, filename)
861
862    params = ft_params1(ssid=ssid, passphrase=passphrase)
863    params['dynamic_vlan'] = "1"
864    params['accept_mac_file'] = filename
865    hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
866    params = ft_params2(ssid=ssid, passphrase=passphrase)
867    params['dynamic_vlan'] = "1"
868    params['accept_mac_file'] = filename
869    hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
870
871    dev[0].flush_scan_cache()
872    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
873              conndev="brvlan1")
874    check_mib(dev[0], [("dot11RSNAAuthenticationSuiteRequested", "00-0f-ac-4"),
875                       ("dot11RSNAAuthenticationSuiteSelected", "00-0f-ac-4")])
876    if filename.startswith('/tmp/'):
877        os.unlink(filename)
878
879def test_ap_ft_over_ds_many(dev, apdev):
880    """WPA2-PSK-FT AP over DS multiple times"""
881    ssid = "test-ft"
882    passphrase = "12345678"
883
884    params = ft_params1(ssid=ssid, passphrase=passphrase)
885    hapd0 = hostapd.add_ap(apdev[0], params)
886    params = ft_params2(ssid=ssid, passphrase=passphrase)
887    hapd1 = hostapd.add_ap(apdev[1], params)
888
889    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
890              roams=50)
891
892def test_ap_ft_vlan_over_ds_many(dev, apdev):
893    """WPA2-PSK-FT AP over DS with VLAN multiple times"""
894    ssid = "test-ft"
895    passphrase = "12345678"
896    filename = hostapd.acl_file(dev, apdev, 'hostapd.accept')
897    hostapd.send_file(apdev[0], filename, filename)
898    hostapd.send_file(apdev[1], filename, filename)
899
900    params = ft_params1(ssid=ssid, passphrase=passphrase)
901    params['dynamic_vlan'] = "1"
902    params['accept_mac_file'] = filename
903    hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
904    params = ft_params2(ssid=ssid, passphrase=passphrase)
905    params['dynamic_vlan'] = "1"
906    params['accept_mac_file'] = filename
907    hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
908
909    dev[0].flush_scan_cache()
910    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
911              roams=50, conndev="brvlan1")
912    if filename.startswith('/tmp/'):
913        os.unlink(filename)
914
915@remote_compatible
916def test_ap_ft_over_ds_unknown_target(dev, apdev):
917    """WPA2-PSK-FT AP"""
918    ssid = "test-ft"
919    passphrase = "12345678"
920
921    params = ft_params1(ssid=ssid, passphrase=passphrase)
922    hapd0 = hostapd.add_ap(apdev[0], params)
923
924    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
925                   scan_freq="2412")
926    dev[0].roam_over_ds("02:11:22:33:44:55", fail_test=True, force=True)
927
928@remote_compatible
929def test_ap_ft_over_ds_unexpected(dev, apdev):
930    """WPA2-PSK-FT AP over DS and unexpected response"""
931    ssid = "test-ft"
932    passphrase = "12345678"
933
934    params = ft_params1(ssid=ssid, passphrase=passphrase)
935    hapd0 = hostapd.add_ap(apdev[0], params)
936    params = ft_params2(ssid=ssid, passphrase=passphrase)
937    hapd1 = hostapd.add_ap(apdev[1], params)
938
939    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
940                   scan_freq="2412")
941    if dev[0].get_status_field('bssid') == apdev[0]['bssid']:
942        ap1 = apdev[0]
943        ap2 = apdev[1]
944        hapd1ap = hapd0
945        hapd2ap = hapd1
946    else:
947        ap1 = apdev[1]
948        ap2 = apdev[0]
949        hapd1ap = hapd1
950        hapd2ap = hapd0
951
952    addr = dev[0].own_addr()
953    hapd1ap.set("ext_mgmt_frame_handling", "1")
954    logger.info("Foreign STA address")
955    msg = {}
956    msg['fc'] = 13 << 4
957    msg['da'] = addr
958    msg['sa'] = ap1['bssid']
959    msg['bssid'] = ap1['bssid']
960    msg['payload'] = binascii.unhexlify("06021122334455660102030405060000")
961    hapd1ap.mgmt_tx(msg)
962
963    logger.info("No over-the-DS in progress")
964    msg['payload'] = binascii.unhexlify("0602" + addr.replace(':', '') + "0102030405060000")
965    hapd1ap.mgmt_tx(msg)
966
967    logger.info("Non-zero status code")
968    msg['payload'] = binascii.unhexlify("0602" + addr.replace(':', '') + "0102030405060100")
969    hapd1ap.mgmt_tx(msg)
970
971    hapd1ap.dump_monitor()
972
973    dev[0].scan_for_bss(ap2['bssid'], freq="2412")
974    if "OK" not in dev[0].request("FT_DS " + ap2['bssid']):
975            raise Exception("FT_DS failed")
976
977    req = hapd1ap.mgmt_rx()
978
979    logger.info("Foreign Target AP")
980    msg['payload'] = binascii.unhexlify("0602" + addr.replace(':', '') + "0102030405060000")
981    hapd1ap.mgmt_tx(msg)
982
983    addrs = addr.replace(':', '') + ap2['bssid'].replace(':', '')
984
985    logger.info("No IEs")
986    msg['payload'] = binascii.unhexlify("0602" + addrs + "0000")
987    hapd1ap.mgmt_tx(msg)
988
989    logger.info("Invalid IEs (trigger parsing failure)")
990    msg['payload'] = binascii.unhexlify("0602" + addrs + "00003700")
991    hapd1ap.mgmt_tx(msg)
992
993    logger.info("Too short MDIE")
994    msg['payload'] = binascii.unhexlify("0602" + addrs + "000036021122")
995    hapd1ap.mgmt_tx(msg)
996
997    logger.info("Mobility domain mismatch")
998    msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603112201")
999    hapd1ap.mgmt_tx(msg)
1000
1001    logger.info("No FTIE")
1002    msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603a1b201")
1003    hapd1ap.mgmt_tx(msg)
1004
1005    logger.info("FTIE SNonce mismatch")
1006    msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603a1b201375e0000" + "00000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "1000000000000000000000000000000000000000000000000000000000000001" + "030a6e6173322e77312e6669")
1007    hapd1ap.mgmt_tx(msg)
1008
1009    logger.info("No R0KH-ID subelem in FTIE")
1010    snonce = binascii.hexlify(req['payload'][111:111+32]).decode()
1011    msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603a1b20137520000" + "00000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + snonce)
1012    hapd1ap.mgmt_tx(msg)
1013
1014    logger.info("No R0KH-ID subelem mismatch in FTIE")
1015    snonce = binascii.hexlify(req['payload'][111:111+32]).decode()
1016    msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603a1b201375e0000" + "00000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + snonce + "030a11223344556677889900")
1017    hapd1ap.mgmt_tx(msg)
1018
1019    logger.info("No R1KH-ID subelem in FTIE")
1020    r0khid = binascii.hexlify(req['payload'][145:145+10]).decode()
1021    msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603a1b201375e0000" + "00000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + snonce + "030a" + r0khid)
1022    hapd1ap.mgmt_tx(msg)
1023
1024    logger.info("No RSNE")
1025    r0khid = binascii.hexlify(req['payload'][145:145+10]).decode()
1026    msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603a1b20137660000" + "00000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + snonce + "030a" + r0khid + "0106000102030405")
1027    hapd1ap.mgmt_tx(msg)
1028
1029def test_ap_ft_pmf_bip_over_ds(dev, apdev):
1030    """WPA2-PSK-FT AP over DS with PMF/BIP"""
1031    run_ap_ft_pmf_bip_over_ds(dev, apdev, None)
1032
1033def test_ap_ft_pmf_bip_cmac_128_over_ds(dev, apdev):
1034    """WPA2-PSK-FT AP over DS with PMF/BIP-CMAC-128"""
1035    run_ap_ft_pmf_bip_over_ds(dev, apdev, "AES-128-CMAC")
1036
1037def test_ap_ft_pmf_bip_gmac_128_over_ds(dev, apdev):
1038    """WPA2-PSK-FT AP over DS with PMF/BIP-GMAC-128"""
1039    run_ap_ft_pmf_bip_over_ds(dev, apdev, "BIP-GMAC-128")
1040
1041def test_ap_ft_pmf_bip_gmac_256_over_ds(dev, apdev):
1042    """WPA2-PSK-FT AP over DS with PMF/BIP-GMAC-256"""
1043    run_ap_ft_pmf_bip_over_ds(dev, apdev, "BIP-GMAC-256")
1044
1045def test_ap_ft_pmf_bip_cmac_256_over_ds(dev, apdev):
1046    """WPA2-PSK-FT AP over DS with PMF/BIP-CMAC-256"""
1047    run_ap_ft_pmf_bip_over_ds(dev, apdev, "BIP-CMAC-256")
1048
1049def run_ap_ft_pmf_bip_over_ds(dev, apdev, cipher):
1050    if cipher and cipher not in dev[0].get_capability("group_mgmt"):
1051        raise HwsimSkip("Cipher %s not supported" % cipher)
1052
1053    ssid = "test-ft"
1054    passphrase = "12345678"
1055
1056    params = ft_params1(ssid=ssid, passphrase=passphrase)
1057    params["ieee80211w"] = "2"
1058    if cipher:
1059        params["group_mgmt_cipher"] = cipher
1060    hapd0 = hostapd.add_ap(apdev[0], params)
1061    params = ft_params2(ssid=ssid, passphrase=passphrase)
1062    params["ieee80211w"] = "2"
1063    if cipher:
1064        params["group_mgmt_cipher"] = cipher
1065    hapd1 = hostapd.add_ap(apdev[1], params)
1066
1067    Wlantest.setup(hapd0)
1068    wt = Wlantest()
1069    wt.flush()
1070    wt.add_passphrase(passphrase)
1071
1072    dev[0].flush_scan_cache()
1073    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
1074              group_mgmt=cipher)
1075
1076def test_ap_ft_over_ds_pull(dev, apdev):
1077    """WPA2-PSK-FT AP over DS (pull PMK)"""
1078    ssid = "test-ft"
1079    passphrase = "12345678"
1080
1081    params = ft_params1(ssid=ssid, passphrase=passphrase)
1082    params["pmk_r1_push"] = "0"
1083    hapd0 = hostapd.add_ap(apdev[0], params)
1084    params = ft_params2(ssid=ssid, passphrase=passphrase)
1085    params["pmk_r1_push"] = "0"
1086    hapd1 = hostapd.add_ap(apdev[1], params)
1087
1088    dev[0].flush_scan_cache()
1089    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True)
1090
1091def test_ap_ft_over_ds_pull_old_key(dev, apdev):
1092    """WPA2-PSK-FT AP over DS (pull PMK; old key)"""
1093    ssid = "test-ft"
1094    passphrase = "12345678"
1095
1096    params = ft_params1_old_key(ssid=ssid, passphrase=passphrase)
1097    params["pmk_r1_push"] = "0"
1098    hapd0 = hostapd.add_ap(apdev[0], params)
1099    params = ft_params2_old_key(ssid=ssid, passphrase=passphrase)
1100    params["pmk_r1_push"] = "0"
1101    hapd1 = hostapd.add_ap(apdev[1], params)
1102
1103    dev[0].flush_scan_cache()
1104    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True)
1105
1106def test_ap_ft_over_ds_pull_vlan(dev, apdev):
1107    """WPA2-PSK-FT AP over DS (pull PMK) with VLAN"""
1108    ssid = "test-ft"
1109    passphrase = "12345678"
1110    filename = hostapd.acl_file(dev, apdev, 'hostapd.accept')
1111    hostapd.send_file(apdev[0], filename, filename)
1112    hostapd.send_file(apdev[1], filename, filename)
1113
1114    params = ft_params1(ssid=ssid, passphrase=passphrase)
1115    params["pmk_r1_push"] = "0"
1116    params['dynamic_vlan'] = "1"
1117    params['accept_mac_file'] = filename
1118    hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
1119    params = ft_params2(ssid=ssid, passphrase=passphrase)
1120    params["pmk_r1_push"] = "0"
1121    params['dynamic_vlan'] = "1"
1122    params['accept_mac_file'] = filename
1123    hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
1124
1125    dev[0].flush_scan_cache()
1126    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
1127              conndev="brvlan1")
1128    if filename.startswith('/tmp/'):
1129        os.unlink(filename)
1130
1131def start_ft_sae(dev, apdev, wpa_ptk_rekey=None, sae_pwe=None,
1132                 rsne_override=None, rsnxe_override=None,
1133                 no_beacon_rsnxe2=False, ext_key_id=False,
1134                 skip_prune_assoc=False, ft_rsnxe_used=False,
1135                 sae_transition=False, ext_key=False, sae_groups=None):
1136    check_sae_capab(dev)
1137    ssid = "test-ft"
1138    passphrase = "12345678"
1139
1140    key_mgmt = "FT-SAE-EXT-KEY" if ext_key else "FT-SAE"
1141
1142    params = ft_params1(ssid=ssid, passphrase=passphrase)
1143    params['wpa_key_mgmt'] = key_mgmt
1144    if wpa_ptk_rekey:
1145        params['wpa_ptk_rekey'] = str(wpa_ptk_rekey)
1146    if sae_pwe is not None:
1147        params['sae_pwe'] = sae_pwe
1148    if rsne_override:
1149        params['rsne_override_ft'] = rsne_override
1150    if rsnxe_override:
1151        params['rsnxe_override_ft'] = rsnxe_override
1152    if ext_key_id:
1153        params['extended_key_id'] = '1'
1154    if skip_prune_assoc:
1155        params['skip_prune_assoc'] = '1'
1156    if ft_rsnxe_used:
1157        params['ft_rsnxe_used'] = '1'
1158    if sae_groups:
1159        params['sae_groups'] = sae_groups
1160    hapd0 = hostapd.add_ap(apdev[0], params)
1161    params = ft_params2(ssid=ssid, passphrase=passphrase)
1162    if not sae_transition:
1163        params['wpa_key_mgmt'] = key_mgmt
1164    if wpa_ptk_rekey:
1165        params['wpa_ptk_rekey'] = str(wpa_ptk_rekey)
1166    if sae_pwe is not None:
1167        params['sae_pwe'] = sae_pwe
1168    if rsne_override:
1169        params['rsne_override_ft'] = rsne_override
1170    if rsnxe_override:
1171        params['rsnxe_override_ft'] = rsnxe_override
1172    if no_beacon_rsnxe2:
1173        params['no_beacon_rsnxe'] = "1"
1174    if ext_key_id:
1175        params['extended_key_id'] = '1'
1176    if skip_prune_assoc:
1177        params['skip_prune_assoc'] = '1'
1178    if ft_rsnxe_used:
1179        params['ft_rsnxe_used'] = '1'
1180    if sae_groups:
1181        params['sae_groups'] = sae_groups
1182    hapd1 = hostapd.add_ap(apdev[1], params)
1183    key_mgmt = hapd1.get_config()['key_mgmt']
1184    if key_mgmt.split(' ')[0] != key_mgmt and not sae_transition:
1185        raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
1186
1187    dev.request("SET sae_groups ")
1188    return hapd0, hapd1
1189
1190def test_ap_ft_sae(dev, apdev):
1191    """WPA2-PSK-FT-SAE AP"""
1192    hapd0, hapd1 = start_ft_sae(dev[0], apdev)
1193    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True)
1194
1195def test_ap_ft_sae_transition(dev, apdev):
1196    """WPA2-PSK-FT-SAE/PSK AP"""
1197    hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_transition=True)
1198    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678",
1199              sae_transition=True)
1200
1201def test_ap_ft_sae_h2e(dev, apdev):
1202    """WPA2-PSK-FT-SAE AP (H2E)"""
1203    try:
1204        dev[0].set("sae_pwe", "2")
1205        hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2")
1206        run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True)
1207    finally:
1208        dev[0].set("sae_pwe", "0")
1209
1210def test_ap_ft_sae_h2e_and_loop(dev, apdev):
1211    """WPA2-PSK-FT-SAE AP (AP H2E, STA loop)"""
1212    dev[0].set("sae_pwe", "0")
1213    hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2")
1214    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True)
1215
1216def test_ap_ft_sae_h2e_and_loop2(dev, apdev):
1217    """WPA2-PSK-FT-SAE AP (AP loop, STA H2E)"""
1218    try:
1219        dev[0].set("sae_pwe", "2")
1220        hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="0")
1221        run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True)
1222    finally:
1223        dev[0].set("sae_pwe", "0")
1224
1225def test_ap_ft_sae_h2e_downgrade_attack(dev, apdev):
1226    """WPA2-PSK-FT-SAE AP (H2E downgrade attack)"""
1227    try:
1228        dev[0].set("sae_pwe", "2")
1229        hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2",
1230                                    no_beacon_rsnxe2=True)
1231        run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1232                  force_initial_conn_to_first_ap=True,
1233                  return_after_initial=True)
1234        dev[0].scan_for_bss(hapd1.own_addr(), freq="2412")
1235        if "OK" not in dev[0].request("ROAM " + hapd1.own_addr()):
1236            raise Exception("ROAM command failed")
1237        # The target AP is expected to discard Reassociation Response frame due
1238        # to RSNXE Used mismatch. This will result in roaming timeout and
1239        # returning back to the old AP.
1240        ev = dev[0].wait_event(["CTRL-EVENT-ASSOC-REJECT",
1241                                "CTRL-EVENT-CONNECTED"], timeout=10)
1242        if ev and "CTRL-EVENT-ASSOC-REJECT" in ev:
1243            pass
1244        elif ev and hapd1.own_addr() in ev:
1245            raise Exception("Roaming succeeded unexpectedly")
1246    finally:
1247        dev[0].set("sae_pwe", "0")
1248
1249def test_ap_ft_sae_ptk_rekey0(dev, apdev):
1250    """WPA2-PSK-FT-SAE AP and PTK rekey triggered by station"""
1251    hapd0, hapd1 = start_ft_sae(dev[0], apdev)
1252    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1253              ptk_rekey="1", roams=0)
1254    check_ptk_rekey(dev[0], hapd0, hapd1)
1255
1256def test_ap_ft_sae_ptk_rekey1(dev, apdev):
1257    """WPA2-PSK-FT-SAE AP and PTK rekey triggered by station"""
1258    hapd0, hapd1 = start_ft_sae(dev[0], apdev)
1259    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1260              ptk_rekey="1", only_one_way=True)
1261    check_ptk_rekey(dev[0], hapd0, hapd1)
1262
1263def test_ap_ft_sae_ptk_rekey_ap(dev, apdev):
1264    """WPA2-PSK-FT-SAE AP and PTK rekey triggered by AP"""
1265    hapd0, hapd1 = start_ft_sae(dev[0], apdev, wpa_ptk_rekey=2)
1266    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1267              only_one_way=True)
1268    check_ptk_rekey(dev[0], hapd0, hapd1)
1269
1270def test_ap_ft_sae_ptk_rekey_ap_ext_key_id(dev, apdev):
1271    """WPA2-PSK-FT-SAE AP and PTK rekey triggered by AP (Ext Key ID)"""
1272    check_ext_key_id_capa(dev[0])
1273    try:
1274        dev[0].set("extended_key_id", "1")
1275        hapd0, hapd1 = start_ft_sae(dev[0], apdev, wpa_ptk_rekey=2,
1276                                    ext_key_id=True)
1277        check_ext_key_id_capa(hapd0)
1278        check_ext_key_id_capa(hapd1)
1279        run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1280                  only_one_way=True)
1281        check_ptk_rekey(dev[0], hapd0, hapd1)
1282        idx = int(dev[0].request("GET last_tk_key_idx"))
1283        if idx != 1:
1284            raise Exception("Unexpected Key ID after TK rekey: %d" % idx)
1285    finally:
1286        dev[0].set("extended_key_id", "0")
1287
1288def test_ap_ft_sae_over_ds(dev, apdev):
1289    """WPA2-PSK-FT-SAE AP over DS"""
1290    hapd0, hapd1 = start_ft_sae(dev[0], apdev)
1291    dev[0].flush_scan_cache()
1292    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1293              over_ds=True)
1294
1295def test_ap_ft_sae_over_ds_ptk_rekey0(dev, apdev):
1296    """WPA2-PSK-FT-SAE AP over DS and PTK rekey triggered by station"""
1297    hapd0, hapd1 = start_ft_sae(dev[0], apdev)
1298    dev[0].flush_scan_cache()
1299    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1300              over_ds=True, ptk_rekey="1", roams=0)
1301    check_ptk_rekey(dev[0], hapd0, hapd1)
1302
1303def test_ap_ft_sae_over_ds_ptk_rekey1(dev, apdev):
1304    """WPA2-PSK-FT-SAE AP over DS and PTK rekey triggered by station"""
1305    hapd0, hapd1 = start_ft_sae(dev[0], apdev)
1306    dev[0].flush_scan_cache()
1307    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1308              over_ds=True, ptk_rekey="1", only_one_way=True)
1309    check_ptk_rekey(dev[0], hapd0, hapd1)
1310
1311def test_ap_ft_sae_over_ds_ptk_rekey_ap(dev, apdev):
1312    """WPA2-PSK-FT-SAE AP over DS and PTK rekey triggered by AP"""
1313    hapd0, hapd1 = start_ft_sae(dev[0], apdev, wpa_ptk_rekey=2)
1314    dev[0].flush_scan_cache()
1315    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1316              over_ds=True, only_one_way=True)
1317    check_ptk_rekey(dev[0], hapd0, hapd1)
1318
1319def test_ap_ft_sae_h2e_rsne_override(dev, apdev):
1320    """WPA2-PSK-FT-SAE AP (H2E) and RSNE override (same value)"""
1321    try:
1322        dev[0].set("sae_pwe", "2")
1323        hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2",
1324                                    rsne_override="30260100000fac040100000fac040100000fac090c000100" + 16*"ff")
1325        run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True)
1326    finally:
1327        dev[0].set("sae_pwe", "0")
1328
1329def test_ap_ft_sae_h2e_rsnxe_override(dev, apdev):
1330    """WPA2-PSK-FT-SAE AP (H2E) and RSNXE override (same value)"""
1331    try:
1332        dev[0].set("sae_pwe", "2")
1333        hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2",
1334                                    rsnxe_override="F40120")
1335        run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True)
1336    finally:
1337        dev[0].set("sae_pwe", "0")
1338
1339def test_ap_ft_sae_h2e_rsne_mismatch(dev, apdev):
1340    """WPA2-PSK-FT-SAE AP (H2E) and RSNE mismatch"""
1341    try:
1342        dev[0].set("sae_pwe", "2")
1343        hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2",
1344                                    rsne_override="30260100000fac040100000fac040100000fac090c010100" + 16*"ff")
1345        run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1346                  fail_test=True)
1347    finally:
1348        dev[0].set("sae_pwe", "0")
1349
1350def test_ap_ft_sae_h2e_rsne_mismatch_pmkr1name(dev, apdev):
1351    """WPA2-PSK-FT-SAE AP (H2E) and RSNE mismatch in PMKR1Name"""
1352    try:
1353        dev[0].set("sae_pwe", "2")
1354        hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2",
1355                                    rsne_override="30260100000fac040100000fac040100000fac090c000100" + 16*"00")
1356        run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1357                  fail_test=True)
1358    finally:
1359        dev[0].set("sae_pwe", "0")
1360
1361def test_ap_ft_sae_h2e_rsnxe_mismatch(dev, apdev):
1362    """WPA2-PSK-FT-SAE AP (H2E) and RSNXE mismatch"""
1363    try:
1364        dev[0].set("sae_pwe", "2")
1365        hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2",
1366                                    rsnxe_override="F40160")
1367        run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1368                  fail_test=True)
1369    finally:
1370        dev[0].set("sae_pwe", "0")
1371
1372def test_ap_ft_sae_rsnxe_used_mismatch(dev, apdev):
1373    """FT-SAE AP and unexpected RSNXE Used in ReassocReq"""
1374    try:
1375        hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2")
1376        dev[0].set("sae_pwe", "0")
1377        dev[0].set("ft_rsnxe_used", "1")
1378        next = run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678",
1379                         sae=True, return_after_initial=True)
1380        if "OK" not in dev[0].request("ROAM " + next):
1381            raise Exception("ROAM command failed")
1382        # The target AP is expected to discard Reassociation Request frame due
1383        # to RSNXE Used mismatch. This will result in roaming timeout and
1384        # returning back to the old AP.
1385        ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=5)
1386        if ev and next in ev:
1387            raise Exception("Roaming succeeded unexpectedly")
1388    finally:
1389        dev[0].set("sae_pwe", "0")
1390
1391def test_ap_ft_sae_rsnxe_used_mismatch2(dev, apdev):
1392    """FT-SAE AP and unexpected RSNXE Used in ReassocResp"""
1393    try:
1394        hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="0",
1395                                    ft_rsnxe_used=True)
1396        dev[0].set("sae_pwe", "2")
1397        next = run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678",
1398                         sae=True, return_after_initial=True)
1399        if "OK" not in dev[0].request("ROAM " + next):
1400            raise Exception("ROAM command failed")
1401        # The STA is expected to discard Reassociation Response frame due to
1402        # RSNXE Used mismatch. This will result in returning back to the old AP.
1403        ev = dev[0].wait_disconnected()
1404        if next not in ev:
1405            raise Exception("Unexpected disconnection BSSID: " + ev)
1406        if "reason=13 locally_generated=1" not in ev:
1407            raise Exception("Unexpected disconnection reason: " + ev)
1408        ev = dev[0].wait_connected()
1409        if next in ev:
1410            raise Exception("Roaming succeeded unexpectedly")
1411
1412        hapd0.set("ft_rsnxe_used", "0")
1413        hapd1.set("ft_rsnxe_used", "0")
1414        dev[0].roam(next);
1415    finally:
1416        dev[0].set("sae_pwe", "0")
1417
1418def test_ap_ft_sae_pw_id(dev, apdev):
1419    """FT-SAE with Password Identifier"""
1420    check_sae_capab(dev[0])
1421    ssid = "test-ft"
1422
1423    params = ft_params1(ssid=ssid)
1424    params["ieee80211w"] = "2"
1425    params['wpa_key_mgmt'] = "FT-SAE"
1426    params['sae_password'] = 'secret|id=pwid'
1427    hapd0 = hostapd.add_ap(apdev[0], params)
1428    params = ft_params2(ssid=ssid)
1429    params["ieee80211w"] = "2"
1430    params['wpa_key_mgmt'] = "FT-SAE"
1431    params['sae_password'] = 'secret|id=pwid'
1432    hapd = hostapd.add_ap(apdev[1], params)
1433
1434    dev[0].request("SET sae_groups ")
1435    run_roams(dev[0], apdev, hapd0, hapd, ssid, passphrase=None, sae=True,
1436              sae_password="secret", sae_password_id="pwid")
1437
1438def test_ap_ft_sae_with_both_akms(dev, apdev):
1439    """SAE + FT-SAE configuration"""
1440    check_sae_capab(dev[0])
1441    ssid = "test-ft"
1442    passphrase = "12345678"
1443
1444    params = ft_params1(ssid=ssid, passphrase=passphrase)
1445    params['wpa_key_mgmt'] = "FT-SAE SAE"
1446    hapd0 = hostapd.add_ap(apdev[0], params)
1447    params = ft_params2(ssid=ssid, passphrase=passphrase)
1448    params['wpa_key_mgmt'] = "FT-SAE SAE"
1449    hapd = hostapd.add_ap(apdev[1], params)
1450    key_mgmt = hapd.get_config()['key_mgmt']
1451    if key_mgmt.split(' ')[0] != "FT-SAE":
1452        raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
1453
1454    dev[0].request("SET sae_groups ")
1455    run_roams(dev[0], apdev, hapd0, hapd, ssid, passphrase, sae=True,
1456              sae_and_psk=True)
1457
1458def test_ap_ft_sae_pmksa_caching(dev, apdev):
1459    """WPA2-FT-SAE AP and PMKSA caching for initial mobility domain association"""
1460    check_sae_capab(dev[0])
1461    ssid = "test-ft"
1462    passphrase = "12345678"
1463
1464    params = ft_params1(ssid=ssid, passphrase=passphrase)
1465    params['wpa_key_mgmt'] = "FT-SAE"
1466    hapd0 = hostapd.add_ap(apdev[0], params)
1467    params = ft_params2(ssid=ssid, passphrase=passphrase)
1468    params['wpa_key_mgmt'] = "FT-SAE"
1469    hapd = hostapd.add_ap(apdev[1], params)
1470    key_mgmt = hapd.get_config()['key_mgmt']
1471    if key_mgmt.split(' ')[0] != "FT-SAE":
1472        raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
1473
1474    dev[0].request("SET sae_groups ")
1475    run_roams(dev[0], apdev, hapd0, hapd, ssid, passphrase, sae=True,
1476              pmksa_caching=True)
1477
1478def test_ap_ft_sae_pmksa_caching_pwe(dev, apdev):
1479    """WPA2-FT-SAE AP and PMKSA caching for initial mobility domain association (STA PWE both)"""
1480    check_sae_capab(dev[0])
1481    ssid = "test-ft"
1482    passphrase = "12345678"
1483
1484    params = ft_params1(ssid=ssid, passphrase=passphrase)
1485    params['wpa_key_mgmt'] = "FT-SAE"
1486    hapd0 = hostapd.add_ap(apdev[0], params)
1487    params = ft_params2(ssid=ssid, passphrase=passphrase)
1488    params['wpa_key_mgmt'] = "FT-SAE"
1489    hapd = hostapd.add_ap(apdev[1], params)
1490    key_mgmt = hapd.get_config()['key_mgmt']
1491    if key_mgmt.split(' ')[0] != "FT-SAE":
1492        raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
1493
1494    try:
1495        dev[0].request("SET sae_groups ")
1496        dev[0].set("sae_pwe", "2")
1497        run_roams(dev[0], apdev, hapd0, hapd, ssid, passphrase, sae=True,
1498                  pmksa_caching=True)
1499    finally:
1500        dev[0].set("sae_groups", "")
1501        dev[0].set("sae_pwe", "0")
1502
1503def test_ap_ft_sae_pmksa_caching_h2e(dev, apdev):
1504    """WPA2-FT-SAE AP and PMKSA caching for initial mobility domain association (H2E)"""
1505    run_ap_ft_sae_pmksa_caching_h2e(dev, apdev)
1506
1507def test_ap_ft_sae_pmksa_caching_h2e_prepend_pmkid(dev, apdev):
1508    """FT-SAE and PMKSA caching for initial mobility domain association (H2E, prepend PMKID)"""
1509    try:
1510        dev[0].set("ft_prepend_pmkid", "1")
1511        run_ap_ft_sae_pmksa_caching_h2e(dev, apdev)
1512    finally:
1513        dev[0].set("ft_prepend_pmkid", "0")
1514
1515def run_ap_ft_sae_pmksa_caching_h2e(dev, apdev):
1516    check_sae_capab(dev[0])
1517    ssid = "test-ft"
1518    passphrase = "12345678"
1519
1520    params = ft_params1(ssid=ssid, passphrase=passphrase)
1521    params['wpa_key_mgmt'] = "FT-SAE"
1522    params['sae_pwe'] = "1"
1523    hapd0 = hostapd.add_ap(apdev[0], params)
1524    params = ft_params2(ssid=ssid, passphrase=passphrase)
1525    params['wpa_key_mgmt'] = "FT-SAE"
1526    params['sae_pwe'] = "1"
1527    hapd = hostapd.add_ap(apdev[1], params)
1528    key_mgmt = hapd.get_config()['key_mgmt']
1529    if key_mgmt.split(' ')[0] != "FT-SAE":
1530        raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
1531
1532    try:
1533        dev[0].request("SET sae_groups ")
1534        dev[0].set("sae_pwe", "1")
1535        run_roams(dev[0], apdev, hapd0, hapd, ssid, passphrase, sae=True,
1536                  pmksa_caching=True)
1537    finally:
1538        dev[0].set("sae_groups", "")
1539        dev[0].set("sae_pwe", "0")
1540
1541def test_ap_ft_sae_ext_key_19(dev, apdev):
1542    """WPA2-FT-SAE-EXT-KEY AP (group 19)"""
1543    hapd0, hapd1 = start_ft_sae(dev[0], apdev, ext_key=True,
1544                                sae_groups="19")
1545    dev[0].set("sae_groups", "19")
1546    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1547              sae_ext_key=True)
1548    dev[0].set("sae_groups", "")
1549
1550def test_ap_ft_sae_ext_key_20(dev, apdev):
1551    """WPA2-FT-SAE-EXT-KEY AP (group 20)"""
1552    hapd0, hapd1 = start_ft_sae(dev[0], apdev, ext_key=True,
1553                                sae_groups="20")
1554    dev[0].set("sae_groups", "20")
1555    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1556              sae_ext_key=True)
1557    dev[0].set("sae_groups", "")
1558
1559def test_ap_ft_sae_ext_key_21(dev, apdev):
1560    """WPA2-FT-SAE-EXT-KEY AP (group 21)"""
1561    hapd0, hapd1 = start_ft_sae(dev[0], apdev, ext_key=True,
1562                                sae_groups="21")
1563    dev[0].set("sae_groups", "21")
1564    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1565              sae_ext_key=True)
1566    dev[0].set("sae_groups", "")
1567
1568def test_ap_ft_sae_ext_key_19_over_ds(dev, apdev):
1569    """WPA2-FT-SAE-EXT-KEY AP over DS (group 19)"""
1570    hapd0, hapd1 = start_ft_sae(dev[0], apdev, ext_key=True,
1571                                sae_groups="19")
1572    dev[0].set("sae_groups", "19")
1573    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1574              sae_ext_key=True, over_ds=True)
1575    dev[0].set("sae_groups", "")
1576
1577def test_ap_ft_sae_ext_key_20_over_ds(dev, apdev):
1578    """WPA2-FT-SAE-EXT-KEY AP over DS (group 20)"""
1579    hapd0, hapd1 = start_ft_sae(dev[0], apdev, ext_key=True,
1580                                sae_groups="20")
1581    dev[0].set("sae_groups", "20")
1582    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1583              sae_ext_key=True, over_ds=True)
1584    dev[0].set("sae_groups", "")
1585
1586def test_ap_ft_sae_ext_key_21_over_ds(dev, apdev):
1587    """WPA2-FT-SAE-EXT-KEY AP over DS (group 21)"""
1588    hapd0, hapd1 = start_ft_sae(dev[0], apdev, ext_key=True,
1589                                sae_groups="21")
1590    dev[0].set("sae_groups", "21")
1591    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1592              sae_ext_key=True, over_ds=True)
1593    dev[0].set("sae_groups", "")
1594
1595def generic_ap_ft_eap(dev, apdev, vlan=False, cui=False, over_ds=False,
1596                      discovery=False, roams=1, wpa_ptk_rekey=0,
1597                      only_one_way=False):
1598    ssid = "test-ft"
1599    passphrase = "12345678"
1600    if vlan:
1601        identity = "gpsk-vlan1"
1602        conndev = "brvlan1"
1603    elif cui:
1604        identity = "gpsk-cui"
1605        conndev = False
1606    else:
1607        identity = "gpsk user"
1608        conndev = False
1609
1610    radius = hostapd.radius_params()
1611    params = ft_params1(ssid=ssid, passphrase=passphrase, discovery=discovery)
1612    params['wpa_key_mgmt'] = "FT-EAP"
1613    params["ieee8021x"] = "1"
1614    if vlan:
1615        params["dynamic_vlan"] = "1"
1616    params = dict(list(radius.items()) + list(params.items()))
1617    hapd = hostapd.add_ap(apdev[0], params)
1618    key_mgmt = hapd.get_config()['key_mgmt']
1619    if key_mgmt.split(' ')[0] != "FT-EAP":
1620        raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
1621    params = ft_params2(ssid=ssid, passphrase=passphrase, discovery=discovery)
1622    params['wpa_key_mgmt'] = "FT-EAP"
1623    params["ieee8021x"] = "1"
1624    if vlan:
1625        params["dynamic_vlan"] = "1"
1626    if wpa_ptk_rekey:
1627        params["wpa_ptk_rekey"] = str(wpa_ptk_rekey)
1628    params = dict(list(radius.items()) + list(params.items()))
1629    hapd1 = hostapd.add_ap(apdev[1], params)
1630
1631    dev[0].flush_scan_cache()
1632    run_roams(dev[0], apdev, hapd, hapd1, ssid, passphrase, eap=True,
1633              over_ds=over_ds, roams=roams, eap_identity=identity,
1634              conndev=conndev, only_one_way=only_one_way)
1635    if "[WPA2-FT/EAP-CCMP]" not in dev[0].request("SCAN_RESULTS"):
1636        raise Exception("Scan results missing RSN element info")
1637    check_mib(dev[0], [("dot11RSNAAuthenticationSuiteRequested", "00-0f-ac-3"),
1638                       ("dot11RSNAAuthenticationSuiteSelected", "00-0f-ac-3")])
1639    if only_one_way:
1640        return
1641
1642    # Verify EAPOL reauthentication after FT protocol
1643    if dev[0].get_status_field('bssid') == apdev[0]['bssid']:
1644        ap = hapd
1645    else:
1646        ap = hapd1
1647    ap.request("EAPOL_REAUTH " + dev[0].own_addr())
1648    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
1649    if ev is None:
1650        raise Exception("EAP authentication did not start")
1651    ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=5)
1652    if ev is None:
1653        raise Exception("EAP authentication did not succeed")
1654    time.sleep(0.1)
1655    if conndev:
1656        hwsim_utils.test_connectivity_iface(dev[0], ap, conndev)
1657    else:
1658        hwsim_utils.test_connectivity(dev[0], ap)
1659
1660def test_ap_ft_eap(dev, apdev):
1661    """WPA2-EAP-FT AP"""
1662    generic_ap_ft_eap(dev, apdev)
1663
1664def test_ap_ft_eap_cui(dev, apdev):
1665    """WPA2-EAP-FT AP with CUI"""
1666    generic_ap_ft_eap(dev, apdev, vlan=False, cui=True)
1667
1668def test_ap_ft_eap_vlan(dev, apdev):
1669    """WPA2-EAP-FT AP with VLAN"""
1670    generic_ap_ft_eap(dev, apdev, vlan=True)
1671
1672def test_ap_ft_eap_vlan_multi(dev, apdev):
1673    """WPA2-EAP-FT AP with VLAN"""
1674    generic_ap_ft_eap(dev, apdev, vlan=True, roams=50)
1675
1676def test_ap_ft_eap_over_ds(dev, apdev):
1677    """WPA2-EAP-FT AP using over-the-DS"""
1678    generic_ap_ft_eap(dev, apdev, over_ds=True)
1679
1680def test_ap_ft_eap_dis(dev, apdev):
1681    """WPA2-EAP-FT AP with AP discovery"""
1682    generic_ap_ft_eap(dev, apdev, discovery=True)
1683
1684def test_ap_ft_eap_dis_over_ds(dev, apdev):
1685    """WPA2-EAP-FT AP with AP discovery and over-the-DS"""
1686    generic_ap_ft_eap(dev, apdev, over_ds=True, discovery=True)
1687
1688def test_ap_ft_eap_vlan(dev, apdev):
1689    """WPA2-EAP-FT AP with VLAN"""
1690    generic_ap_ft_eap(dev, apdev, vlan=True)
1691
1692def test_ap_ft_eap_vlan_multi(dev, apdev):
1693    """WPA2-EAP-FT AP with VLAN"""
1694    generic_ap_ft_eap(dev, apdev, vlan=True, roams=50)
1695
1696def test_ap_ft_eap_vlan_over_ds(dev, apdev):
1697    """WPA2-EAP-FT AP with VLAN + over_ds"""
1698    generic_ap_ft_eap(dev, apdev, vlan=True, over_ds=True)
1699
1700def test_ap_ft_eap_vlan_over_ds_multi(dev, apdev):
1701    """WPA2-EAP-FT AP with VLAN + over_ds"""
1702    generic_ap_ft_eap(dev, apdev, vlan=True, over_ds=True, roams=50)
1703
1704def generic_ap_ft_eap_pull(dev, apdev, vlan=False):
1705    """WPA2-EAP-FT AP (pull PMK)"""
1706    ssid = "test-ft"
1707    passphrase = "12345678"
1708    if vlan:
1709        identity = "gpsk-vlan1"
1710        conndev = "brvlan1"
1711    else:
1712        identity = "gpsk user"
1713        conndev = False
1714
1715    radius = hostapd.radius_params()
1716    params = ft_params1(ssid=ssid, passphrase=passphrase)
1717    params['wpa_key_mgmt'] = "FT-EAP"
1718    params["ieee8021x"] = "1"
1719    params["pmk_r1_push"] = "0"
1720    if vlan:
1721        params["dynamic_vlan"] = "1"
1722    params = dict(list(radius.items()) + list(params.items()))
1723    hapd = hostapd.add_ap(apdev[0], params)
1724    key_mgmt = hapd.get_config()['key_mgmt']
1725    if key_mgmt.split(' ')[0] != "FT-EAP":
1726        raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
1727    params = ft_params2(ssid=ssid, passphrase=passphrase)
1728    params['wpa_key_mgmt'] = "FT-EAP"
1729    params["ieee8021x"] = "1"
1730    params["pmk_r1_push"] = "0"
1731    if vlan:
1732        params["dynamic_vlan"] = "1"
1733    params = dict(list(radius.items()) + list(params.items()))
1734    hapd1 = hostapd.add_ap(apdev[1], params)
1735
1736    run_roams(dev[0], apdev, hapd, hapd1, ssid, passphrase, eap=True,
1737              eap_identity=identity, conndev=conndev)
1738
1739def test_ap_ft_eap_pull(dev, apdev):
1740    """WPA2-EAP-FT AP (pull PMK)"""
1741    generic_ap_ft_eap_pull(dev, apdev)
1742
1743def test_ap_ft_eap_pull_vlan(dev, apdev):
1744    """WPA2-EAP-FT AP (pull PMK) - with VLAN"""
1745    generic_ap_ft_eap_pull(dev, apdev, vlan=True)
1746
1747def test_ap_ft_eap_pull_wildcard(dev, apdev):
1748    """WPA2-EAP-FT AP (pull PMK) - wildcard R0KH/R1KH"""
1749    ssid = "test-ft"
1750    passphrase = "12345678"
1751
1752    radius = hostapd.radius_params()
1753    params = ft_params1(ssid=ssid, passphrase=passphrase, discovery=True)
1754    params['wpa_key_mgmt'] = "WPA-EAP FT-EAP"
1755    params["ieee8021x"] = "1"
1756    params["pmk_r1_push"] = "0"
1757    params["r0kh"] = "ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
1758    params["r1kh"] = "00:00:00:00:00:00 00:00:00:00:00:00 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
1759    params["ft_psk_generate_local"] = "1"
1760    params["eap_server"] = "0"
1761    params["rkh_pos_timeout"] = "100"
1762    params["rkh_neg_timeout"] = "50"
1763    params["rkh_pull_timeout"] = "1234"
1764    params["rkh_pull_retries"] = "10"
1765    params = dict(list(radius.items()) + list(params.items()))
1766    hapd = hostapd.add_ap(apdev[0], params)
1767    params = ft_params2(ssid=ssid, passphrase=passphrase, discovery=True)
1768    params['wpa_key_mgmt'] = "WPA-EAP FT-EAP"
1769    params["ieee8021x"] = "1"
1770    params["pmk_r1_push"] = "0"
1771    params["r0kh"] = "ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
1772    params["r1kh"] = "00:00:00:00:00:00 00:00:00:00:00:00 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
1773    params["ft_psk_generate_local"] = "1"
1774    params["eap_server"] = "0"
1775    params = dict(list(radius.items()) + list(params.items()))
1776    hapd1 = hostapd.add_ap(apdev[1], params)
1777
1778    run_roams(dev[0], apdev, hapd, hapd1, ssid, passphrase, eap=True)
1779
1780def test_ap_ft_eap_pull_wildcard_multi_bss(dev, apdev, params):
1781    """WPA2-EAP-FT AP (pull PMK) - wildcard R0KH/R1KH with multiple BSSs"""
1782    bssconf = os.path.join(params['logdir'],
1783                           'ap_ft_eap_pull_wildcard_multi_bss.bss.conf')
1784    ssid = "test-ft"
1785    passphrase = "12345678"
1786    radius = hostapd.radius_params()
1787
1788    params = ft_params1(ssid=ssid, passphrase=passphrase, discovery=True)
1789    params['wpa_key_mgmt'] = "WPA-EAP FT-EAP"
1790    params["ieee8021x"] = "1"
1791    params["pmk_r1_push"] = "0"
1792    params["r0kh"] = "ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
1793    params["r1kh"] = "00:00:00:00:00:00 00:00:00:00:00:00 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
1794    params["eap_server"] = "0"
1795    params = dict(list(radius.items()) + list(params.items()))
1796    hapd = hostapd.add_ap(apdev[0], params)
1797    ifname2 = apdev[0]['ifname'] + "-2"
1798    bssid2 = "02:00:00:00:03:01"
1799    params['nas_identifier'] = "nas1b.w1.fi"
1800    params['r1_key_holder'] = "000102030415"
1801    with open(bssconf, 'w') as f:
1802        f.write("driver=nl80211\n")
1803        f.write("hw_mode=g\n")
1804        f.write("channel=1\n")
1805        f.write("ieee80211n=1\n")
1806        f.write("interface=%s\n" % ifname2)
1807        f.write("bssid=%s\n" % bssid2)
1808        f.write("ctrl_interface=/var/run/hostapd\n")
1809
1810        fields = ["ssid", "wpa_passphrase", "nas_identifier", "wpa_key_mgmt",
1811                  "wpa", "rsn_pairwise", "auth_server_addr"]
1812        for name in fields:
1813            f.write("%s=%s\n" % (name, params[name]))
1814        for name, val in params.items():
1815            if name in fields:
1816                continue
1817            f.write("%s=%s\n" % (name, val))
1818    hapd2 = hostapd.add_bss(apdev[0], ifname2, bssconf)
1819
1820    params = ft_params2(ssid=ssid, passphrase=passphrase, discovery=True)
1821    params['wpa_key_mgmt'] = "WPA-EAP FT-EAP"
1822    params["ieee8021x"] = "1"
1823    params["pmk_r1_push"] = "0"
1824    params["r0kh"] = "ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
1825    params["r1kh"] = "00:00:00:00:00:00 00:00:00:00:00:00 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
1826    params["eap_server"] = "0"
1827    params = dict(list(radius.items()) + list(params.items()))
1828    hapd1 = hostapd.add_ap(apdev[1], params)
1829
1830    # The first iteration of the roaming test will use wildcard R0KH discovery
1831    # and RRB sequence number synchronization while the second iteration shows
1832    # the clean RRB exchange where those extra steps are not needed.
1833    for i in range(2):
1834        hapd.note("Test iteration %d" % i)
1835        dev[0].note("Test iteration %d" % i)
1836
1837        id = dev[0].connect(ssid, key_mgmt="FT-EAP", eap="GPSK",
1838                            identity="gpsk user",
1839                            password="abcdefghijklmnop0123456789abcdef",
1840                            bssid=bssid2,
1841                            scan_freq="2412")
1842        res = dev[0].get_status_field("bssid")
1843        if res != bssid2:
1844            raise Exception("Unexpected BSSID after initial connection: " + res)
1845
1846        dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
1847        dev[0].set_network(id, "bssid", "00:00:00:00:00:00")
1848        dev[0].roam(apdev[1]['bssid'])
1849        res = dev[0].get_status_field("bssid")
1850        if res != apdev[1]['bssid']:
1851            raise Exception("Unexpected BSSID after first roam: " + res)
1852
1853        dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
1854        dev[0].roam(apdev[0]['bssid'])
1855        res = dev[0].get_status_field("bssid")
1856        if res != apdev[0]['bssid']:
1857            raise Exception("Unexpected BSSID after second roam: " + res)
1858
1859        dev[0].request("REMOVE_NETWORK all")
1860        dev[0].wait_disconnected()
1861        dev[0].dump_monitor()
1862        hapd.dump_monitor()
1863        hapd2.dump_monitor()
1864
1865@remote_compatible
1866def test_ap_ft_mismatching_rrb_key_push(dev, apdev):
1867    """WPA2-PSK-FT AP over DS with mismatching RRB key (push)"""
1868    ssid = "test-ft"
1869    passphrase = "12345678"
1870
1871    params = ft_params1(ssid=ssid, passphrase=passphrase)
1872    params["ieee80211w"] = "2"
1873    hapd0 = hostapd.add_ap(apdev[0], params)
1874    params = ft_params2_incorrect_rrb_key(ssid=ssid, passphrase=passphrase)
1875    params["ieee80211w"] = "2"
1876    hapd1 = hostapd.add_ap(apdev[1], params)
1877
1878    dev[0].flush_scan_cache()
1879    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
1880              fail_test=True)
1881
1882@remote_compatible
1883def test_ap_ft_mismatching_rrb_key_pull(dev, apdev):
1884    """WPA2-PSK-FT AP over DS with mismatching RRB key (pull)"""
1885    ssid = "test-ft"
1886    passphrase = "12345678"
1887
1888    params = ft_params1(ssid=ssid, passphrase=passphrase)
1889    params["pmk_r1_push"] = "0"
1890    hapd0 = hostapd.add_ap(apdev[0], params)
1891    params = ft_params2_incorrect_rrb_key(ssid=ssid, passphrase=passphrase)
1892    params["pmk_r1_push"] = "0"
1893    hapd1 = hostapd.add_ap(apdev[1], params)
1894
1895    dev[0].flush_scan_cache()
1896    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
1897              fail_test=True)
1898
1899@remote_compatible
1900def test_ap_ft_mismatching_r0kh_id_pull(dev, apdev):
1901    """WPA2-PSK-FT AP over DS with mismatching R0KH-ID (pull)"""
1902    ssid = "test-ft"
1903    passphrase = "12345678"
1904
1905    params = ft_params1(ssid=ssid, passphrase=passphrase)
1906    params["pmk_r1_push"] = "0"
1907    params["nas_identifier"] = "nas0.w1.fi"
1908    hostapd.add_ap(apdev[0], params)
1909    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
1910                   scan_freq="2412")
1911
1912    params = ft_params2(ssid=ssid, passphrase=passphrase)
1913    params["pmk_r1_push"] = "0"
1914    hostapd.add_ap(apdev[1], params)
1915
1916    dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
1917    dev[0].roam_over_ds(apdev[1]['bssid'], fail_test=True)
1918
1919@remote_compatible
1920def test_ap_ft_mismatching_rrb_r0kh_push(dev, apdev):
1921    """WPA2-PSK-FT AP over DS with mismatching R0KH key (push)"""
1922    ssid = "test-ft"
1923    passphrase = "12345678"
1924
1925    params = ft_params1(ssid=ssid, passphrase=passphrase)
1926    params["ieee80211w"] = "2"
1927    hapd0 = hostapd.add_ap(apdev[0], params)
1928    params = ft_params2_r0kh_mismatch(ssid=ssid, passphrase=passphrase)
1929    params["ieee80211w"] = "2"
1930    hapd1 = hostapd.add_ap(apdev[1], params)
1931
1932    dev[0].flush_scan_cache()
1933    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
1934              fail_test=True)
1935
1936@remote_compatible
1937def test_ap_ft_mismatching_rrb_r0kh_pull(dev, apdev):
1938    """WPA2-PSK-FT AP over DS with mismatching R0KH key (pull)"""
1939    ssid = "test-ft"
1940    passphrase = "12345678"
1941
1942    params = ft_params1_r0kh_mismatch(ssid=ssid, passphrase=passphrase)
1943    params["pmk_r1_push"] = "0"
1944    hapd0 = hostapd.add_ap(apdev[0], params)
1945    params = ft_params2(ssid=ssid, passphrase=passphrase)
1946    params["pmk_r1_push"] = "0"
1947    hapd1 = hostapd.add_ap(apdev[1], params)
1948
1949    dev[0].flush_scan_cache()
1950    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
1951              fail_test=True)
1952
1953def test_ap_ft_mismatching_rrb_key_push_eap(dev, apdev):
1954    """WPA2-EAP-FT AP over DS with mismatching RRB key (push)"""
1955    ssid = "test-ft"
1956    passphrase = "12345678"
1957
1958    radius = hostapd.radius_params()
1959    params = ft_params1(ssid=ssid, passphrase=passphrase)
1960    params["ieee80211w"] = "2"
1961    params['wpa_key_mgmt'] = "FT-EAP"
1962    params["ieee8021x"] = "1"
1963    params = dict(list(radius.items()) + list(params.items()))
1964    hapd0 = hostapd.add_ap(apdev[0], params)
1965    params = ft_params2_incorrect_rrb_key(ssid=ssid, passphrase=passphrase)
1966    params["ieee80211w"] = "2"
1967    params['wpa_key_mgmt'] = "FT-EAP"
1968    params["ieee8021x"] = "1"
1969    params = dict(list(radius.items()) + list(params.items()))
1970    hapd1 = hostapd.add_ap(apdev[1], params)
1971
1972    dev[0].flush_scan_cache()
1973    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
1974              fail_test=True, eap=True)
1975
1976def test_ap_ft_mismatching_rrb_key_pull_eap(dev, apdev):
1977    """WPA2-EAP-FT AP over DS with mismatching RRB key (pull)"""
1978    ssid = "test-ft"
1979    passphrase = "12345678"
1980
1981    radius = hostapd.radius_params()
1982    params = ft_params1(ssid=ssid, passphrase=passphrase)
1983    params["pmk_r1_push"] = "0"
1984    params['wpa_key_mgmt'] = "FT-EAP"
1985    params["ieee8021x"] = "1"
1986    params = dict(list(radius.items()) + list(params.items()))
1987    hapd0 = hostapd.add_ap(apdev[0], params)
1988    params = ft_params2_incorrect_rrb_key(ssid=ssid, passphrase=passphrase)
1989    params["pmk_r1_push"] = "0"
1990    params['wpa_key_mgmt'] = "FT-EAP"
1991    params["ieee8021x"] = "1"
1992    params = dict(list(radius.items()) + list(params.items()))
1993    hapd1 = hostapd.add_ap(apdev[1], params)
1994
1995    dev[0].flush_scan_cache()
1996    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
1997              fail_test=True, eap=True)
1998
1999def test_ap_ft_mismatching_r0kh_id_pull_eap(dev, apdev):
2000    """WPA2-EAP-FT AP over DS with mismatching R0KH-ID (pull)"""
2001    ssid = "test-ft"
2002    passphrase = "12345678"
2003
2004    radius = hostapd.radius_params()
2005    params = ft_params1(ssid=ssid, passphrase=passphrase)
2006    params["pmk_r1_push"] = "0"
2007    params["nas_identifier"] = "nas0.w1.fi"
2008    params['wpa_key_mgmt'] = "FT-EAP"
2009    params["ieee8021x"] = "1"
2010    params = dict(list(radius.items()) + list(params.items()))
2011    hostapd.add_ap(apdev[0], params)
2012    dev[0].connect(ssid, key_mgmt="FT-EAP", proto="WPA2", ieee80211w="1",
2013                   eap="GPSK", identity="gpsk user",
2014                   password="abcdefghijklmnop0123456789abcdef",
2015                   scan_freq="2412")
2016
2017    params = ft_params2(ssid=ssid, passphrase=passphrase)
2018    params["pmk_r1_push"] = "0"
2019    params['wpa_key_mgmt'] = "FT-EAP"
2020    params["ieee8021x"] = "1"
2021    params = dict(list(radius.items()) + list(params.items()))
2022    hostapd.add_ap(apdev[1], params)
2023
2024    dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
2025    dev[0].roam_over_ds(apdev[1]['bssid'], fail_test=True)
2026
2027def test_ap_ft_mismatching_rrb_r0kh_push_eap(dev, apdev):
2028    """WPA2-EAP-FT AP over DS with mismatching R0KH key (push)"""
2029    ssid = "test-ft"
2030    passphrase = "12345678"
2031
2032    radius = hostapd.radius_params()
2033    params = ft_params1(ssid=ssid, passphrase=passphrase)
2034    params["ieee80211w"] = "2"
2035    params['wpa_key_mgmt'] = "FT-EAP"
2036    params["ieee8021x"] = "1"
2037    params = dict(list(radius.items()) + list(params.items()))
2038    hapd0 = hostapd.add_ap(apdev[0], params)
2039    params = ft_params2_r0kh_mismatch(ssid=ssid, passphrase=passphrase)
2040    params["ieee80211w"] = "2"
2041    params['wpa_key_mgmt'] = "FT-EAP"
2042    params["ieee8021x"] = "1"
2043    params = dict(list(radius.items()) + list(params.items()))
2044    hapd1 = hostapd.add_ap(apdev[1], params)
2045
2046    dev[0].flush_scan_cache()
2047    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
2048              fail_test=True, eap=True)
2049
2050def test_ap_ft_mismatching_rrb_r0kh_pull_eap(dev, apdev):
2051    """WPA2-EAP-FT AP over DS with mismatching R0KH key (pull)"""
2052    ssid = "test-ft"
2053    passphrase = "12345678"
2054
2055    radius = hostapd.radius_params()
2056    params = ft_params1_r0kh_mismatch(ssid=ssid, passphrase=passphrase)
2057    params["pmk_r1_push"] = "0"
2058    params['wpa_key_mgmt'] = "FT-EAP"
2059    params["ieee8021x"] = "1"
2060    params = dict(list(radius.items()) + list(params.items()))
2061    hapd0 = hostapd.add_ap(apdev[0], params)
2062    params = ft_params2(ssid=ssid, passphrase=passphrase)
2063    params["pmk_r1_push"] = "0"
2064    params['wpa_key_mgmt'] = "FT-EAP"
2065    params["ieee8021x"] = "1"
2066    params = dict(list(radius.items()) + list(params.items()))
2067    hapd1 = hostapd.add_ap(apdev[1], params)
2068
2069    dev[0].flush_scan_cache()
2070    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
2071              fail_test=True, eap=True)
2072
2073def test_ap_ft_gtk_rekey(dev, apdev):
2074    """WPA2-PSK-FT AP and GTK rekey"""
2075    ssid = "test-ft"
2076    passphrase = "12345678"
2077
2078    params = ft_params1(ssid=ssid, passphrase=passphrase)
2079    params['wpa_group_rekey'] = '1'
2080    hapd = hostapd.add_ap(apdev[0], params)
2081
2082    dev[0].flush_scan_cache()
2083    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2084                   ieee80211w="1", scan_freq="2412")
2085
2086    ev = dev[0].wait_event(["RSN: Group rekeying completed"], timeout=2)
2087    if ev is None:
2088        raise Exception("GTK rekey timed out after initial association")
2089    hwsim_utils.test_connectivity(dev[0], hapd)
2090
2091    params = ft_params2(ssid=ssid, passphrase=passphrase)
2092    params['wpa_group_rekey'] = '1'
2093    hapd1 = hostapd.add_ap(apdev[1], params)
2094
2095    dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
2096    dev[0].roam(apdev[1]['bssid'])
2097    if dev[0].get_status_field('bssid') != apdev[1]['bssid']:
2098        raise Exception("Did not connect to correct AP")
2099    hwsim_utils.test_connectivity(dev[0], hapd1)
2100
2101    ev = dev[0].wait_event(["RSN: Group rekeying completed"], timeout=2)
2102    if ev is None:
2103        raise Exception("GTK rekey timed out after FT protocol")
2104    hwsim_utils.test_connectivity(dev[0], hapd1)
2105
2106def test_ft_psk_key_lifetime_in_memory(dev, apdev, params):
2107    """WPA2-PSK-FT and key lifetime in memory"""
2108    ssid = "test-ft"
2109    passphrase = "04c2726b4b8d5f1b4db9c07aa4d9e9d8f765cb5d25ec817e6cc4fcdd5255db0"
2110    psk = '93c90846ff67af9037ed83fb72b63dbeddaa81d47f926c20909b5886f1d9358d'
2111    pmk = binascii.unhexlify(psk)
2112    p = ft_params1(ssid=ssid, passphrase=passphrase)
2113    hapd0 = hostapd.add_ap(apdev[0], p)
2114    p = ft_params2(ssid=ssid, passphrase=passphrase)
2115    hapd1 = hostapd.add_ap(apdev[1], p)
2116
2117    pid = find_wpas_process(dev[0])
2118
2119    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2120                   scan_freq="2412")
2121    # The decrypted copy of GTK is freed only after the CTRL-EVENT-CONNECTED
2122    # event has been delivered, so verify that wpa_supplicant has returned to
2123    # eloop before reading process memory.
2124    time.sleep(1)
2125    dev[0].ping()
2126
2127    buf = read_process_memory(pid, pmk)
2128
2129    dev[0].request("DISCONNECT")
2130    dev[0].wait_disconnected()
2131
2132    dev[0].relog()
2133    pmkr0 = None
2134    pmkr1 = None
2135    ptk = None
2136    gtk = None
2137    with open(os.path.join(params['logdir'], 'log0'), 'r') as f:
2138        for l in f.readlines():
2139            if "FT: PMK-R0 - hexdump" in l:
2140                val = l.strip().split(':')[3].replace(' ', '')
2141                pmkr0 = binascii.unhexlify(val)
2142            if "FT: PMK-R1 - hexdump" in l:
2143                val = l.strip().split(':')[3].replace(' ', '')
2144                pmkr1 = binascii.unhexlify(val)
2145            if "FT: KCK - hexdump" in l:
2146                val = l.strip().split(':')[3].replace(' ', '')
2147                kck = binascii.unhexlify(val)
2148            if "FT: KEK - hexdump" in l:
2149                val = l.strip().split(':')[3].replace(' ', '')
2150                kek = binascii.unhexlify(val)
2151            if "FT: TK - hexdump" in l:
2152                val = l.strip().split(':')[3].replace(' ', '')
2153                tk = binascii.unhexlify(val)
2154            if "WPA: Group Key - hexdump" in l:
2155                val = l.strip().split(':')[3].replace(' ', '')
2156                gtk = binascii.unhexlify(val)
2157    if not pmkr0 or not pmkr1 or not kck or not kek or not tk or not gtk:
2158        raise Exception("Could not find keys from debug log")
2159    if len(gtk) != 16:
2160        raise Exception("Unexpected GTK length")
2161
2162    logger.info("Checking keys in memory while associated")
2163    get_key_locations(buf, pmk, "PMK")
2164    get_key_locations(buf, pmkr0, "PMK-R0")
2165    get_key_locations(buf, pmkr1, "PMK-R1")
2166    if pmk not in buf:
2167        raise HwsimSkip("PMK not found while associated")
2168    if pmkr0 not in buf:
2169        raise HwsimSkip("PMK-R0 not found while associated")
2170    if pmkr1 not in buf:
2171        raise HwsimSkip("PMK-R1 not found while associated")
2172    if kck not in buf:
2173        raise Exception("KCK not found while associated")
2174    if kek not in buf:
2175        raise Exception("KEK not found while associated")
2176    #if tk in buf:
2177    #    raise Exception("TK found from memory")
2178
2179    logger.info("Checking keys in memory after disassociation")
2180    buf = read_process_memory(pid, pmk)
2181    get_key_locations(buf, pmk, "PMK")
2182    get_key_locations(buf, pmkr0, "PMK-R0")
2183    get_key_locations(buf, pmkr1, "PMK-R1")
2184
2185    # Note: PMK/PSK is still present in network configuration
2186
2187    fname = os.path.join(params['logdir'],
2188                         'ft_psk_key_lifetime_in_memory.memctx-')
2189    verify_not_present(buf, pmkr0, fname, "PMK-R0")
2190    verify_not_present(buf, pmkr1, fname, "PMK-R1")
2191    verify_not_present(buf, kck, fname, "KCK")
2192    verify_not_present(buf, kek, fname, "KEK")
2193    verify_not_present(buf, tk, fname, "TK")
2194    if gtk in buf:
2195        get_key_locations(buf, gtk, "GTK")
2196    verify_not_present(buf, gtk, fname, "GTK")
2197
2198    dev[0].request("REMOVE_NETWORK all")
2199
2200    logger.info("Checking keys in memory after network profile removal")
2201    buf = read_process_memory(pid, pmk)
2202    get_key_locations(buf, pmk, "PMK")
2203    get_key_locations(buf, pmkr0, "PMK-R0")
2204    get_key_locations(buf, pmkr1, "PMK-R1")
2205
2206    verify_not_present(buf, pmk, fname, "PMK")
2207    verify_not_present(buf, pmkr0, fname, "PMK-R0")
2208    verify_not_present(buf, pmkr1, fname, "PMK-R1")
2209    verify_not_present(buf, kck, fname, "KCK")
2210    verify_not_present(buf, kek, fname, "KEK")
2211    verify_not_present(buf, tk, fname, "TK")
2212    verify_not_present(buf, gtk, fname, "GTK")
2213
2214@remote_compatible
2215def test_ap_ft_invalid_resp(dev, apdev):
2216    """WPA2-PSK-FT AP and invalid response IEs"""
2217    ssid = "test-ft"
2218    passphrase = "12345678"
2219
2220    params = ft_params1(ssid=ssid, passphrase=passphrase)
2221    hapd0 = hostapd.add_ap(apdev[0], params)
2222    dev[0].flush_scan_cache()
2223    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2224                   scan_freq="2412")
2225
2226    params = ft_params2(ssid=ssid, passphrase=passphrase)
2227    hapd1 = hostapd.add_ap(apdev[1], params)
2228
2229    tests = [
2230        # Various IEs for test coverage. The last one is FTIE with invalid
2231        # R1KH-ID subelement.
2232        "020002000000" + "3800" + "38051122334455" + "3754000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010100",
2233        # FTIE with invalid R0KH-ID subelement (len=0).
2234        "020002000000" + "3754000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010300",
2235        # FTIE with invalid R0KH-ID subelement (len=49).
2236        "020002000000" + "378500010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001033101020304050607080910111213141516171819202122232425262728293031323334353637383940414243444546474849",
2237        # Invalid RSNE.
2238        "020002000000" + "3000",
2239        # Required IEs missing from protected IE count.
2240        "020002000000" + "3603a1b201" + "375200010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001" + "3900",
2241        # RIC missing from protected IE count.
2242        "020002000000" + "3603a1b201" + "375200020203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001" + "3900",
2243        # Protected IE missing.
2244        "020002000000" + "3603a1b201" + "375200ff0203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001" + "3900" + "0000"]
2245    for t in tests:
2246        dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
2247        hapd1.set("ext_mgmt_frame_handling", "1")
2248        hapd1.dump_monitor()
2249        if "OK" not in dev[0].request("ROAM " + apdev[1]['bssid']):
2250            raise Exception("ROAM failed")
2251        auth = None
2252        for i in range(20):
2253            msg = hapd1.mgmt_rx()
2254            if msg['subtype'] == 11:
2255                auth = msg
2256                break
2257        if not auth:
2258            raise Exception("Authentication frame not seen")
2259
2260        resp = {}
2261        resp['fc'] = auth['fc']
2262        resp['da'] = auth['sa']
2263        resp['sa'] = auth['da']
2264        resp['bssid'] = auth['bssid']
2265        resp['payload'] = binascii.unhexlify(t)
2266        hapd1.mgmt_tx(resp)
2267        hapd1.set("ext_mgmt_frame_handling", "0")
2268        dev[0].wait_disconnected()
2269
2270        dev[0].request("RECONNECT")
2271        dev[0].wait_connected()
2272
2273def test_ap_ft_gcmp_256(dev, apdev):
2274    """WPA2-PSK-FT AP with GCMP-256 cipher"""
2275    if "GCMP-256" not in dev[0].get_capability("pairwise"):
2276        raise HwsimSkip("Cipher GCMP-256 not supported")
2277    ssid = "test-ft"
2278    passphrase = "12345678"
2279
2280    params = ft_params1(ssid=ssid, passphrase=passphrase)
2281    params['rsn_pairwise'] = "GCMP-256"
2282    hapd0 = hostapd.add_ap(apdev[0], params)
2283    params = ft_params2(ssid=ssid, passphrase=passphrase)
2284    params['rsn_pairwise'] = "GCMP-256"
2285    hapd1 = hostapd.add_ap(apdev[1], params)
2286
2287    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase,
2288              pairwise_cipher="GCMP-256", group_cipher="GCMP-256")
2289
2290def setup_ap_ft_oom(dev, apdev):
2291    skip_with_fips(dev[0])
2292    ssid = "test-ft"
2293    passphrase = "12345678"
2294
2295    params = ft_params1(ssid=ssid, passphrase=passphrase)
2296    hapd0 = hostapd.add_ap(apdev[0], params)
2297    params = ft_params2(ssid=ssid, passphrase=passphrase)
2298    hapd1 = hostapd.add_ap(apdev[1], params)
2299
2300    dev[0].flush_scan_cache()
2301    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2302                   scan_freq="2412")
2303    if dev[0].get_status_field('bssid') == apdev[0]['bssid']:
2304        dst = apdev[1]['bssid']
2305    else:
2306        dst = apdev[0]['bssid']
2307
2308    dev[0].scan_for_bss(dst, freq="2412")
2309
2310    return dst
2311
2312def test_ap_ft_oom(dev, apdev):
2313    """WPA2-PSK-FT and OOM"""
2314    dst = setup_ap_ft_oom(dev, apdev)
2315    with alloc_fail(dev[0], 1, "wpa_ft_gen_req_ies"):
2316        dev[0].roam(dst, check_bssid=False, fail_test=True)
2317
2318def test_ap_ft_oom2(dev, apdev):
2319    """WPA2-PSK-FT and OOM (2)"""
2320    dst = setup_ap_ft_oom(dev, apdev)
2321    with fail_test(dev[0], 1, "wpa_ft_mic"):
2322        dev[0].roam(dst, fail_test=True, assoc_reject_ok=True)
2323
2324def test_ap_ft_oom3(dev, apdev):
2325    """WPA2-PSK-FT and OOM (3)"""
2326    dst = setup_ap_ft_oom(dev, apdev)
2327    with fail_test(dev[0], 1, "os_get_random;wpa_ft_prepare_auth_request"):
2328        dev[0].roam(dst)
2329
2330def test_ap_ft_oom4(dev, apdev):
2331    """WPA2-PSK-FT and OOM (4)"""
2332    ssid = "test-ft"
2333    passphrase = "12345678"
2334    dst = setup_ap_ft_oom(dev, apdev)
2335    dev[0].request("REMOVE_NETWORK all")
2336    with alloc_fail(dev[0], 1, "=sme_update_ft_ies"):
2337        dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2338                       scan_freq="2412")
2339
2340def test_ap_ft_ap_oom(dev, apdev):
2341    """WPA2-PSK-FT and AP OOM"""
2342    ssid = "test-ft"
2343    passphrase = "12345678"
2344
2345    params = ft_params1(ssid=ssid, passphrase=passphrase)
2346    hapd0 = hostapd.add_ap(apdev[0], params)
2347    bssid0 = hapd0.own_addr()
2348
2349    dev[0].flush_scan_cache()
2350    dev[0].scan_for_bss(bssid0, freq="2412")
2351    with alloc_fail(hapd0, 1, "wpa_ft_store_pmk_r0"):
2352        dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2353                       scan_freq="2412")
2354
2355    params = ft_params2(ssid=ssid, passphrase=passphrase)
2356    hapd1 = hostapd.add_ap(apdev[1], params)
2357    bssid1 = hapd1.own_addr()
2358    dev[0].scan_for_bss(bssid1, freq="2412")
2359    # This roam will fail due to missing PMK-R0 (OOM prevented storing it)
2360    dev[0].roam(bssid1, check_bssid=False)
2361
2362def test_ap_ft_ap_oom2(dev, apdev):
2363    """WPA2-PSK-FT and AP OOM 2"""
2364    ssid = "test-ft"
2365    passphrase = "12345678"
2366
2367    params = ft_params1(ssid=ssid, passphrase=passphrase)
2368    hapd0 = hostapd.add_ap(apdev[0], params)
2369    bssid0 = hapd0.own_addr()
2370
2371    dev[0].flush_scan_cache()
2372    dev[0].scan_for_bss(bssid0, freq="2412")
2373    with alloc_fail(hapd0, 1, "wpa_ft_store_pmk_r1"):
2374        dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2375                       scan_freq="2412")
2376
2377    params = ft_params2(ssid=ssid, passphrase=passphrase)
2378    hapd1 = hostapd.add_ap(apdev[1], params)
2379    bssid1 = hapd1.own_addr()
2380    dev[0].scan_for_bss(bssid1, freq="2412")
2381    dev[0].roam(bssid1)
2382    if dev[0].get_status_field('bssid') != bssid1:
2383        raise Exception("Did not roam to AP1")
2384    # This roam will fail due to missing PMK-R1 (OOM prevented storing it)
2385    dev[0].roam(bssid0)
2386
2387def test_ap_ft_ap_oom3(dev, apdev):
2388    """WPA2-PSK-FT and AP OOM 3"""
2389    ssid = "test-ft"
2390    passphrase = "12345678"
2391
2392    params = ft_params1(ssid=ssid, passphrase=passphrase)
2393    hapd0 = hostapd.add_ap(apdev[0], params)
2394    bssid0 = hapd0.own_addr()
2395
2396    dev[0].flush_scan_cache()
2397    dev[0].scan_for_bss(bssid0, freq="2412")
2398    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2399                   scan_freq="2412")
2400
2401    params = ft_params2(ssid=ssid, passphrase=passphrase)
2402    hapd1 = hostapd.add_ap(apdev[1], params)
2403    bssid1 = hapd1.own_addr()
2404    dev[0].scan_for_bss(bssid1, freq="2412")
2405    with alloc_fail(hapd1, 1, "wpa_ft_pull_pmk_r1"):
2406        # This will fail due to not being able to send out PMK-R1 pull request
2407        dev[0].roam(bssid1, check_bssid=False)
2408
2409    with fail_test(hapd1, 2, "os_get_random;wpa_ft_pull_pmk_r1"):
2410        # This will fail due to not being able to send out PMK-R1 pull request
2411        dev[0].roam(bssid1, check_bssid=False)
2412
2413    with fail_test(hapd1, 2, "aes_siv_encrypt;wpa_ft_pull_pmk_r1"):
2414        # This will fail due to not being able to send out PMK-R1 pull request
2415        dev[0].roam(bssid1, check_bssid=False)
2416
2417def test_ap_ft_ap_oom3b(dev, apdev):
2418    """WPA2-PSK-FT and AP OOM 3b"""
2419    ssid = "test-ft"
2420    passphrase = "12345678"
2421
2422    params = ft_params1(ssid=ssid, passphrase=passphrase)
2423    hapd0 = hostapd.add_ap(apdev[0], params)
2424    bssid0 = hapd0.own_addr()
2425
2426    dev[0].scan_for_bss(bssid0, freq="2412")
2427    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2428                   scan_freq="2412")
2429
2430    params = ft_params2(ssid=ssid, passphrase=passphrase)
2431    hapd1 = hostapd.add_ap(apdev[1], params)
2432    bssid1 = hapd1.own_addr()
2433    dev[0].scan_for_bss(bssid1, freq="2412")
2434    with fail_test(hapd1, 1, "os_get_random;wpa_ft_pull_pmk_r1"):
2435        # This will fail due to not being able to send out PMK-R1 pull request
2436        dev[0].roam(bssid1)
2437
2438def test_ap_ft_ap_oom4(dev, apdev):
2439    """WPA2-PSK-FT and AP OOM 4"""
2440    ssid = "test-ft"
2441    passphrase = "12345678"
2442
2443    params = ft_params1(ssid=ssid, passphrase=passphrase)
2444    hapd0 = hostapd.add_ap(apdev[0], params)
2445    bssid0 = hapd0.own_addr()
2446
2447    dev[0].flush_scan_cache()
2448    dev[0].scan_for_bss(bssid0, freq="2412")
2449    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2450                   scan_freq="2412")
2451
2452    params = ft_params2(ssid=ssid, passphrase=passphrase)
2453    hapd1 = hostapd.add_ap(apdev[1], params)
2454    bssid1 = hapd1.own_addr()
2455    dev[0].scan_for_bss(bssid1, freq="2412")
2456    with alloc_fail(hapd1, 1, "wpa_ft_gtk_subelem"):
2457        dev[0].roam(bssid1)
2458        if dev[0].get_status_field('bssid') != bssid1:
2459            raise Exception("Did not roam to AP1")
2460
2461    with fail_test(hapd0, 1, "i802_get_seqnum;wpa_ft_gtk_subelem"):
2462        dev[0].roam(bssid0)
2463        if dev[0].get_status_field('bssid') != bssid0:
2464            raise Exception("Did not roam to AP0")
2465
2466    with fail_test(hapd0, 1, "aes_wrap;wpa_ft_gtk_subelem"):
2467        dev[0].roam(bssid1)
2468        if dev[0].get_status_field('bssid') != bssid1:
2469            raise Exception("Did not roam to AP1")
2470
2471def test_ap_ft_ap_oom5(dev, apdev):
2472    """WPA2-PSK-FT and AP OOM 5"""
2473    ssid = "test-ft"
2474    passphrase = "12345678"
2475
2476    params = ft_params1(ssid=ssid, passphrase=passphrase)
2477    hapd0 = hostapd.add_ap(apdev[0], params)
2478    bssid0 = hapd0.own_addr()
2479
2480    dev[0].flush_scan_cache()
2481    dev[0].scan_for_bss(bssid0, freq="2412")
2482    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2483                   scan_freq="2412")
2484
2485    params = ft_params2(ssid=ssid, passphrase=passphrase)
2486    hapd1 = hostapd.add_ap(apdev[1], params)
2487    bssid1 = hapd1.own_addr()
2488    dev[0].scan_for_bss(bssid1, freq="2412")
2489    with alloc_fail(hapd1, 1, "=wpa_ft_process_auth_req"):
2490        # This will fail to roam
2491        dev[0].roam(bssid1, check_bssid=False)
2492
2493    with fail_test(hapd1, 1, "os_get_random;wpa_ft_process_auth_req"):
2494        # This will fail to roam
2495        dev[0].roam(bssid1, check_bssid=False)
2496
2497    with fail_test(hapd1, 1, "sha256_prf_bits;wpa_pmk_r1_to_ptk;wpa_ft_process_auth_req"):
2498        # This will fail to roam
2499        dev[0].roam(bssid1, check_bssid=False)
2500
2501    with fail_test(hapd1, 3, "wpa_pmk_r1_to_ptk;wpa_ft_process_auth_req"):
2502        # This will fail to roam
2503        dev[0].roam(bssid1, check_bssid=False)
2504
2505    with fail_test(hapd1, 1, "wpa_derive_pmk_r1_name;wpa_ft_process_auth_req"):
2506        # This will fail to roam
2507        dev[0].roam(bssid1, check_bssid=False)
2508
2509def test_ap_ft_ap_oom6(dev, apdev):
2510    """WPA2-PSK-FT and AP OOM 6"""
2511    ssid = "test-ft"
2512    passphrase = "12345678"
2513
2514    params = ft_params1(ssid=ssid, passphrase=passphrase)
2515    hapd0 = hostapd.add_ap(apdev[0], params)
2516    bssid0 = hapd0.own_addr()
2517
2518    dev[0].scan_for_bss(bssid0, freq="2412")
2519    with fail_test(hapd0, 1, "wpa_derive_pmk_r0;wpa_auth_derive_ptk_ft"):
2520        dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2521                       scan_freq="2412")
2522    dev[0].request("REMOVE_NETWORK all")
2523    dev[0].wait_disconnected()
2524    with fail_test(hapd0, 1, "wpa_derive_pmk_r1;wpa_auth_derive_ptk_ft"):
2525        dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2526                       scan_freq="2412")
2527    dev[0].request("REMOVE_NETWORK all")
2528    dev[0].wait_disconnected()
2529    with fail_test(hapd0, 1, "wpa_pmk_r1_to_ptk;wpa_auth_derive_ptk_ft"):
2530        dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2531                       scan_freq="2412")
2532
2533def test_ap_ft_ap_oom7a(dev, apdev):
2534    """WPA2-PSK-FT and AP OOM 7a"""
2535    ssid = "test-ft"
2536    passphrase = "12345678"
2537
2538    params = ft_params1(ssid=ssid, passphrase=passphrase)
2539    params["ieee80211w"] = "2"
2540    hapd0 = hostapd.add_ap(apdev[0], params)
2541    bssid0 = hapd0.own_addr()
2542
2543    dev[0].flush_scan_cache()
2544    dev[0].scan_for_bss(bssid0, freq="2412")
2545    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2546                   ieee80211w="2", scan_freq="2412")
2547
2548    params = ft_params2(ssid=ssid, passphrase=passphrase)
2549    params["ieee80211w"] = "2"
2550    hapd1 = hostapd.add_ap(apdev[1], params)
2551    bssid1 = hapd1.own_addr()
2552    dev[0].scan_for_bss(bssid1, freq="2412")
2553    with alloc_fail(hapd1, 1, "wpa_ft_igtk_subelem"):
2554        # This will fail to roam
2555        dev[0].roam(bssid1)
2556
2557def test_ap_ft_ap_oom7b(dev, apdev):
2558    """WPA2-PSK-FT and AP OOM 7b"""
2559    ssid = "test-ft"
2560    passphrase = "12345678"
2561
2562    params = ft_params1(ssid=ssid, passphrase=passphrase)
2563    params["ieee80211w"] = "2"
2564    hapd0 = hostapd.add_ap(apdev[0], params)
2565    bssid0 = hapd0.own_addr()
2566
2567    dev[0].flush_scan_cache()
2568    dev[0].scan_for_bss(bssid0, freq="2412")
2569    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2570                   ieee80211w="2", scan_freq="2412")
2571
2572    params = ft_params2(ssid=ssid, passphrase=passphrase)
2573    params["ieee80211w"] = "2"
2574    hapd1 = hostapd.add_ap(apdev[1], params)
2575    bssid1 = hapd1.own_addr()
2576    dev[0].scan_for_bss(bssid1, freq="2412")
2577    with fail_test(hapd1, 1, "aes_wrap;wpa_ft_igtk_subelem"):
2578        # This will fail to roam
2579        dev[0].roam(bssid1)
2580
2581def test_ap_ft_ap_oom7c(dev, apdev):
2582    """WPA2-PSK-FT and AP OOM 7c"""
2583    ssid = "test-ft"
2584    passphrase = "12345678"
2585
2586    params = ft_params1(ssid=ssid, passphrase=passphrase)
2587    params["ieee80211w"] = "2"
2588    hapd0 = hostapd.add_ap(apdev[0], params)
2589    bssid0 = hapd0.own_addr()
2590
2591    dev[0].flush_scan_cache()
2592    dev[0].scan_for_bss(bssid0, freq="2412")
2593    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2594                   ieee80211w="2", scan_freq="2412")
2595
2596    params = ft_params2(ssid=ssid, passphrase=passphrase)
2597    params["ieee80211w"] = "2"
2598    hapd1 = hostapd.add_ap(apdev[1], params)
2599    bssid1 = hapd1.own_addr()
2600    dev[0].scan_for_bss(bssid1, freq="2412")
2601    with alloc_fail(hapd1, 1, "=wpa_sm_write_assoc_resp_ies"):
2602        # This will fail to roam
2603        dev[0].roam(bssid1)
2604
2605def test_ap_ft_ap_oom7d(dev, apdev):
2606    """WPA2-PSK-FT and AP OOM 7d"""
2607    ssid = "test-ft"
2608    passphrase = "12345678"
2609
2610    params = ft_params1(ssid=ssid, passphrase=passphrase)
2611    params["ieee80211w"] = "2"
2612    hapd0 = hostapd.add_ap(apdev[0], params)
2613    bssid0 = hapd0.own_addr()
2614
2615    dev[0].flush_scan_cache()
2616    dev[0].scan_for_bss(bssid0, freq="2412")
2617    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2618                   ieee80211w="2", scan_freq="2412")
2619
2620    params = ft_params2(ssid=ssid, passphrase=passphrase)
2621    params["ieee80211w"] = "2"
2622    hapd1 = hostapd.add_ap(apdev[1], params)
2623    bssid1 = hapd1.own_addr()
2624    dev[0].scan_for_bss(bssid1, freq="2412")
2625    with fail_test(hapd1, 1, "wpa_ft_mic;wpa_sm_write_assoc_resp_ies"):
2626        # This will fail to roam
2627        dev[0].roam(bssid1)
2628
2629def test_ap_ft_ap_oom8(dev, apdev):
2630    """WPA2-PSK-FT and AP OOM 8"""
2631    ssid = "test-ft"
2632    passphrase = "12345678"
2633
2634    params = ft_params1(ssid=ssid, passphrase=passphrase)
2635    params['ft_psk_generate_local'] = "1"
2636    hapd0 = hostapd.add_ap(apdev[0], params)
2637    bssid0 = hapd0.own_addr()
2638
2639    dev[0].flush_scan_cache()
2640    dev[0].scan_for_bss(bssid0, freq="2412")
2641    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2642                   scan_freq="2412")
2643
2644    params = ft_params2(ssid=ssid, passphrase=passphrase)
2645    params['ft_psk_generate_local'] = "1"
2646    hapd1 = hostapd.add_ap(apdev[1], params)
2647    bssid1 = hapd1.own_addr()
2648    dev[0].scan_for_bss(bssid1, freq="2412")
2649    with fail_test(hapd1, 1, "wpa_derive_pmk_r0;wpa_ft_psk_pmk_r1"):
2650        # This will fail to roam
2651        dev[0].roam(bssid1, check_bssid=False)
2652    with fail_test(hapd1, 1, "wpa_derive_pmk_r1;wpa_ft_psk_pmk_r1"):
2653        # This will fail to roam
2654        dev[0].roam(bssid1, check_bssid=False)
2655
2656def test_ap_ft_ap_oom9(dev, apdev):
2657    """WPA2-PSK-FT and AP OOM 9"""
2658    ssid = "test-ft"
2659    passphrase = "12345678"
2660
2661    params = ft_params1(ssid=ssid, passphrase=passphrase)
2662    hapd0 = hostapd.add_ap(apdev[0], params)
2663    bssid0 = hapd0.own_addr()
2664
2665    dev[0].scan_for_bss(bssid0, freq="2412")
2666    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2667                   scan_freq="2412")
2668
2669    params = ft_params2(ssid=ssid, passphrase=passphrase)
2670    hapd1 = hostapd.add_ap(apdev[1], params)
2671    bssid1 = hapd1.own_addr()
2672    dev[0].scan_for_bss(bssid1, freq="2412")
2673
2674    with alloc_fail(hapd0, 1, "wpa_ft_action_rx"):
2675        # This will fail to roam
2676        if "OK" not in dev[0].request("FT_DS " + bssid1):
2677            raise Exception("FT_DS failed")
2678        wait_fail_trigger(hapd0, "GET_ALLOC_FAIL")
2679
2680    with alloc_fail(hapd1, 1, "wpa_ft_rrb_rx_request"):
2681        # This will fail to roam
2682        if "OK" not in dev[0].request("FT_DS " + bssid1):
2683            raise Exception("FT_DS failed")
2684        wait_fail_trigger(hapd1, "GET_ALLOC_FAIL")
2685
2686    with alloc_fail(hapd1, 1, "wpa_ft_send_rrb_auth_resp"):
2687        # This will fail to roam
2688        if "OK" not in dev[0].request("FT_DS " + bssid1):
2689            raise Exception("FT_DS failed")
2690        wait_fail_trigger(hapd1, "GET_ALLOC_FAIL")
2691
2692def test_ap_ft_ap_oom10(dev, apdev):
2693    """WPA2-PSK-FT and AP OOM 10"""
2694    ssid = "test-ft"
2695    passphrase = "12345678"
2696
2697    params = ft_params1(ssid=ssid, passphrase=passphrase)
2698    hapd0 = hostapd.add_ap(apdev[0], params)
2699    bssid0 = hapd0.own_addr()
2700
2701    dev[0].scan_for_bss(bssid0, freq="2412")
2702    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2703                   scan_freq="2412")
2704
2705    params = ft_params2(ssid=ssid, passphrase=passphrase)
2706    hapd1 = hostapd.add_ap(apdev[1], params)
2707    bssid1 = hapd1.own_addr()
2708    dev[0].scan_for_bss(bssid1, freq="2412")
2709
2710    with fail_test(hapd0, 1, "aes_siv_decrypt;wpa_ft_rrb_rx_pull"):
2711        # This will fail to roam
2712        if "OK" not in dev[0].request("FT_DS " + bssid1):
2713            raise Exception("FT_DS failed")
2714        wait_fail_trigger(hapd0, "GET_FAIL")
2715
2716    with fail_test(hapd0, 1, "wpa_derive_pmk_r1;wpa_ft_rrb_rx_pull"):
2717        # This will fail to roam
2718        if "OK" not in dev[0].request("FT_DS " + bssid1):
2719            raise Exception("FT_DS failed")
2720        wait_fail_trigger(hapd0, "GET_FAIL")
2721
2722    with fail_test(hapd0, 1, "aes_siv_encrypt;wpa_ft_rrb_rx_pull"):
2723        # This will fail to roam
2724        if "OK" not in dev[0].request("FT_DS " + bssid1):
2725            raise Exception("FT_DS failed")
2726        wait_fail_trigger(hapd0, "GET_FAIL")
2727
2728    with fail_test(hapd1, 1, "aes_siv_decrypt;wpa_ft_rrb_rx_resp"):
2729        # This will fail to roam
2730        if "OK" not in dev[0].request("FT_DS " + bssid1):
2731            raise Exception("FT_DS failed")
2732        wait_fail_trigger(hapd1, "GET_FAIL")
2733
2734def test_ap_ft_ap_oom11(dev, apdev):
2735    """WPA2-PSK-FT and AP OOM 11"""
2736    ssid = "test-ft"
2737    passphrase = "12345678"
2738
2739    params = ft_params1(ssid=ssid, passphrase=passphrase)
2740    hapd0 = hostapd.add_ap(apdev[0], params)
2741    bssid0 = hapd0.own_addr()
2742
2743    dev[0].scan_for_bss(bssid0, freq="2412")
2744    with fail_test(hapd0, 1, "wpa_derive_pmk_r1;wpa_ft_generate_pmk_r1"):
2745        dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2746                       scan_freq="2412")
2747        wait_fail_trigger(hapd0, "GET_FAIL")
2748
2749    dev[1].scan_for_bss(bssid0, freq="2412")
2750    with fail_test(hapd0, 1, "aes_siv_encrypt;wpa_ft_generate_pmk_r1"):
2751        dev[1].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2752                       scan_freq="2412")
2753        wait_fail_trigger(hapd0, "GET_FAIL")
2754
2755def test_ap_ft_over_ds_proto_ap(dev, apdev):
2756    """WPA2-PSK-FT AP over DS protocol testing for AP processing"""
2757    ssid = "test-ft"
2758    passphrase = "12345678"
2759
2760    params = ft_params1(ssid=ssid, passphrase=passphrase)
2761    hapd0 = hostapd.add_ap(apdev[0], params)
2762    bssid0 = hapd0.own_addr()
2763    _bssid0 = bssid0.replace(':', '')
2764    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2765                   scan_freq="2412")
2766    addr = dev[0].own_addr()
2767    _addr = addr.replace(':', '')
2768
2769    params = ft_params2(ssid=ssid, passphrase=passphrase)
2770    hapd1 = hostapd.add_ap(apdev[1], params)
2771    bssid1 = hapd1.own_addr()
2772    _bssid1 = bssid1.replace(':', '')
2773
2774    hapd0.set("ext_mgmt_frame_handling", "1")
2775    hdr = "d0003a01" + _bssid0 + _addr + _bssid0 + "1000"
2776    valid = "0601" + _addr + _bssid1
2777    tests = ["0601",
2778             "0601" + _addr,
2779             "0601" + _addr + _bssid0,
2780             "0601" + _addr + "ffffffffffff",
2781             "0601" + _bssid0 + _bssid0,
2782             valid,
2783             valid + "01",
2784             valid + "3700",
2785             valid + "3600",
2786             valid + "3603ffffff",
2787             valid + "3603a1b2ff",
2788             valid + "3603a1b2ff" + "3700",
2789             valid + "3603a1b2ff" + "37520000" + 16*"00" + 32*"00" + 32*"00",
2790             valid + "3603a1b2ff" + "37520001" + 16*"00" + 32*"00" + 32*"00",
2791             valid + "3603a1b2ff" + "37550000" + 16*"00" + 32*"00" + 32*"00" + "0301aa",
2792             valid + "3603a1b2ff" + "37550000" + 16*"00" + 32*"00" + 32*"00" + "0301aa" + "3000",
2793             valid + "3603a1b2ff" + "37550000" + 16*"00" + 32*"00" + 32*"00" + "0301aa" + "30260100000fac040100000fac040100000facff00000100a225368fe0983b5828a37a0acb37f253",
2794             valid + "3603a1b2ff" + "37550000" + 16*"00" + 32*"00" + 32*"00" + "0301aa" + "30260100000fac040100000fac030100000fac0400000100a225368fe0983b5828a37a0acb37f253",
2795             valid + "3603a1b2ff" + "37550000" + 16*"00" + 32*"00" + 32*"00" + "0301aa" + "30260100000fac040100000fac040100000fac0400000100a225368fe0983b5828a37a0acb37f253",
2796             valid + "0001"]
2797    for t in tests:
2798        hapd0.dump_monitor()
2799        if "OK" not in hapd0.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + t):
2800            raise Exception("MGMT_RX_PROCESS failed")
2801
2802    hapd0.set("ext_mgmt_frame_handling", "0")
2803
2804def test_ap_ft_over_ds_proto(dev, apdev):
2805    """WPA2-PSK-FT AP over DS protocol testing"""
2806    ssid = "test-ft"
2807    passphrase = "12345678"
2808
2809    params = ft_params1(ssid=ssid, passphrase=passphrase)
2810    hapd0 = hostapd.add_ap(apdev[0], params)
2811    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2812                   scan_freq="2412")
2813
2814    # FT Action Response while no FT-over-DS in progress
2815    msg = {}
2816    msg['fc'] = 13 << 4
2817    msg['da'] = dev[0].own_addr()
2818    msg['sa'] = apdev[0]['bssid']
2819    msg['bssid'] = apdev[0]['bssid']
2820    msg['payload'] = binascii.unhexlify("06020200000000000200000004000000")
2821    hapd0.mgmt_tx(msg)
2822
2823    params = ft_params2(ssid=ssid, passphrase=passphrase)
2824    hapd1 = hostapd.add_ap(apdev[1], params)
2825    dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
2826    hapd0.set("ext_mgmt_frame_handling", "1")
2827    hapd0.dump_monitor()
2828    dev[0].request("FT_DS " + apdev[1]['bssid'])
2829    for i in range(0, 10):
2830        req = hapd0.mgmt_rx()
2831        if req is None:
2832            raise Exception("MGMT RX wait timed out")
2833        if req['subtype'] == 13:
2834            break
2835        req = None
2836    if not req:
2837        raise Exception("FT Action frame not received")
2838
2839    # FT Action Response for unexpected Target AP
2840    msg['payload'] = binascii.unhexlify("0602020000000000" + "f20000000400" + "0000")
2841    hapd0.mgmt_tx(msg)
2842
2843    # FT Action Response without MDIE
2844    msg['payload'] = binascii.unhexlify("0602020000000000" + "020000000400" + "0000")
2845    hapd0.mgmt_tx(msg)
2846
2847    # FT Action Response without FTIE
2848    msg['payload'] = binascii.unhexlify("0602020000000000" + "020000000400" + "0000" + "3603a1b201")
2849    hapd0.mgmt_tx(msg)
2850
2851    # FT Action Response with FTIE SNonce mismatch
2852    msg['payload'] = binascii.unhexlify("0602020000000000" + "020000000400" + "0000" + "3603a1b201" + "3766000000000000000000000000000000000000c4e67ac1999bebd00ff4ae4d5dcaf87896bb060b469f7c78d49623fb395c3455ffffff6b693fe6f8d8c5dfac0a22344750775bd09437f98b238c9f87b97f790c0106000102030406030a6e6173312e77312e6669")
2853    hapd0.mgmt_tx(msg)
2854
2855@remote_compatible
2856def test_ap_ft_rrb(dev, apdev):
2857    """WPA2-PSK-FT RRB protocol testing"""
2858    ssid = "test-ft"
2859    passphrase = "12345678"
2860
2861    params = ft_params1(ssid=ssid, passphrase=passphrase)
2862    hapd0 = hostapd.add_ap(apdev[0], params)
2863
2864    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2865                   scan_freq="2412")
2866
2867    _dst_ll = binascii.unhexlify(apdev[0]['bssid'].replace(':', ''))
2868    _src_ll = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
2869    proto = b'\x89\x0d'
2870    ehdr = _dst_ll + _src_ll + proto
2871
2872    # Too short RRB frame
2873    pkt = ehdr + b'\x01'
2874    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2875        raise Exception("DATA_TEST_FRAME failed")
2876
2877    # RRB discarded frame wikth unrecognized type
2878    pkt = ehdr + b'\x02' + b'\x02' + b'\x01\x00' + _src_ll
2879    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2880        raise Exception("DATA_TEST_FRAME failed")
2881
2882    # RRB frame too short for action frame
2883    pkt = ehdr + b'\x01' + b'\x02' + b'\x01\x00' + _src_ll
2884    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2885        raise Exception("DATA_TEST_FRAME failed")
2886
2887    # Too short RRB frame (not enough room for Action Frame body)
2888    pkt = ehdr + b'\x01' + b'\x02' + b'\x00\x00' + _src_ll
2889    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2890        raise Exception("DATA_TEST_FRAME failed")
2891
2892    # Unexpected Action frame category
2893    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'
2894    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2895        raise Exception("DATA_TEST_FRAME failed")
2896
2897    # Unexpected Action in RRB Request
2898    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'
2899    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2900        raise Exception("DATA_TEST_FRAME failed")
2901
2902    # Target AP address in RRB Request does not match with own address
2903    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'
2904    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2905        raise Exception("DATA_TEST_FRAME failed")
2906
2907    # Not enough room for status code in RRB Response
2908    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'
2909    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2910        raise Exception("DATA_TEST_FRAME failed")
2911
2912    # RRB discarded frame with unknown packet_type
2913    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'
2914    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2915        raise Exception("DATA_TEST_FRAME failed")
2916
2917    # RRB Response with non-zero status code; no STA match
2918    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'
2919    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2920        raise Exception("DATA_TEST_FRAME failed")
2921
2922    # RRB Response with zero status code and extra data; STA match
2923    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'
2924    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2925        raise Exception("DATA_TEST_FRAME failed")
2926
2927    # Too short PMK-R1 pull
2928    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'
2929    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2930        raise Exception("DATA_TEST_FRAME failed")
2931
2932    # Too short PMK-R1 resp
2933    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'
2934    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2935        raise Exception("DATA_TEST_FRAME failed")
2936
2937    # Too short PMK-R1 push
2938    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'
2939    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2940        raise Exception("DATA_TEST_FRAME failed")
2941
2942    # No matching R0KH address found for PMK-R0 pull response
2943    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'
2944    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2945        raise Exception("DATA_TEST_FRAME failed")
2946
2947@remote_compatible
2948def test_rsn_ie_proto_ft_psk_sta(dev, apdev):
2949    """RSN element protocol testing for FT-PSK + PMF cases on STA side"""
2950    bssid = apdev[0]['bssid']
2951    ssid = "test-ft"
2952    passphrase = "12345678"
2953
2954    params = ft_params1(ssid=ssid, passphrase=passphrase)
2955    params["ieee80211w"] = "1"
2956    # This is the RSN element used normally by hostapd
2957    params['own_ie_override'] = '30140100000fac040100000fac040100000fac048c00' + '3603a1b201'
2958    hapd = hostapd.add_ap(apdev[0], params)
2959    id = dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2960                        ieee80211w="1", scan_freq="2412",
2961                        pairwise="CCMP", group="CCMP")
2962
2963    tests = [('PMKIDCount field included',
2964              '30160100000fac040100000fac040100000fac048c000000' + '3603a1b201'),
2965             ('Extra IE before RSNE',
2966              'dd0400000000' + '30140100000fac040100000fac040100000fac048c00' + '3603a1b201'),
2967             ('PMKIDCount and Group Management Cipher suite fields included',
2968              '301a0100000fac040100000fac040100000fac048c000000000fac06' + '3603a1b201'),
2969             ('Extra octet after defined fields (future extensibility)',
2970              '301b0100000fac040100000fac040100000fac048c000000000fac0600' + '3603a1b201'),
2971             ('No RSN Capabilities field (PMF disabled in practice)',
2972              '30120100000fac040100000fac040100000fac04' + '3603a1b201')]
2973    for txt, ie in tests:
2974        dev[0].request("DISCONNECT")
2975        dev[0].wait_disconnected()
2976        logger.info(txt)
2977        hapd.disable()
2978        hapd.set('own_ie_override', ie)
2979        hapd.enable()
2980        dev[0].request("BSS_FLUSH 0")
2981        dev[0].scan_for_bss(bssid, 2412, force_scan=True, only_new=True)
2982        dev[0].select_network(id, freq=2412)
2983        dev[0].wait_connected()
2984
2985    dev[0].request("DISCONNECT")
2986    dev[0].wait_disconnected()
2987
2988    logger.info('Invalid RSNE causing internal hostapd error')
2989    hapd.disable()
2990    hapd.set('own_ie_override', '30130100000fac040100000fac040100000fac048c' + '3603a1b201')
2991    hapd.enable()
2992    dev[0].request("BSS_FLUSH 0")
2993    dev[0].scan_for_bss(bssid, 2412, force_scan=True, only_new=True)
2994    dev[0].select_network(id, freq=2412)
2995    # hostapd fails to generate EAPOL-Key msg 3/4, so this connection cannot
2996    # complete.
2997    ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
2998    if ev is not None:
2999        raise Exception("Unexpected connection")
3000    dev[0].request("DISCONNECT")
3001
3002def start_ft(apdev, wpa_ptk_rekey=None):
3003    ssid = "test-ft"
3004    passphrase = "12345678"
3005
3006    params = ft_params1(ssid=ssid, passphrase=passphrase)
3007    if wpa_ptk_rekey:
3008        params['wpa_ptk_rekey'] = str(wpa_ptk_rekey)
3009    hapd0 = hostapd.add_ap(apdev[0], params)
3010    params = ft_params2(ssid=ssid, passphrase=passphrase)
3011    if wpa_ptk_rekey:
3012        params['wpa_ptk_rekey'] = str(wpa_ptk_rekey)
3013    hapd1 = hostapd.add_ap(apdev[1], params)
3014
3015    return hapd0, hapd1
3016
3017def check_ptk_rekey(dev, hapd0=None, hapd1=None):
3018    ev = dev.wait_event(["CTRL-EVENT-DISCONNECTED",
3019                         "WPA: Key negotiation completed"], timeout=5)
3020    if ev is None:
3021        raise Exception("No event received after roam")
3022    if "CTRL-EVENT-DISCONNECTED" in ev:
3023        raise Exception("Unexpected disconnection after roam")
3024
3025    if not hapd0 or not hapd1:
3026        return
3027    if dev.get_status_field('bssid') == hapd0.own_addr():
3028        hapd = hapd0
3029    else:
3030        hapd = hapd1
3031    time.sleep(0.1)
3032    hwsim_utils.test_connectivity(dev, hapd)
3033
3034def test_ap_ft_ptk_rekey(dev, apdev):
3035    """WPA2-PSK-FT PTK rekeying triggered by station after roam"""
3036    hapd0, hapd1 = start_ft(apdev)
3037    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", ptk_rekey="1")
3038    check_ptk_rekey(dev[0], hapd0, hapd1)
3039
3040def test_ap_ft_ptk_rekey2(dev, apdev):
3041    """WPA2-PSK-FT PTK rekeying triggered by station after one roam"""
3042    hapd0, hapd1 = start_ft(apdev)
3043    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", ptk_rekey="1",
3044              only_one_way=True)
3045    check_ptk_rekey(dev[0], hapd0, hapd1)
3046
3047def test_ap_ft_ptk_rekey_ap(dev, apdev):
3048    """WPA2-PSK-FT PTK rekeying triggered by AP after roam"""
3049    hapd0, hapd1 = start_ft(apdev, wpa_ptk_rekey=2)
3050    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678")
3051    check_ptk_rekey(dev[0], hapd0, hapd1)
3052
3053def test_ap_ft_ptk_rekey_ap2(dev, apdev):
3054    """WPA2-PSK-FT PTK rekeying triggered by AP after one roam"""
3055    hapd0, hapd1 = start_ft(apdev, wpa_ptk_rekey=2)
3056    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678",
3057              only_one_way=True)
3058    check_ptk_rekey(dev[0], hapd0, hapd1)
3059
3060def test_ap_ft_eap_ptk_rekey_ap(dev, apdev):
3061    """WPA2-EAP-FT PTK rekeying triggered by AP"""
3062    generic_ap_ft_eap(dev, apdev, only_one_way=True, wpa_ptk_rekey=2)
3063    check_ptk_rekey(dev[0])
3064
3065def test_ap_ft_internal_rrb_check(dev, apdev):
3066    """RRB internal delivery only to WPA enabled BSS"""
3067    ssid = "test-ft"
3068    passphrase = "12345678"
3069
3070    radius = hostapd.radius_params()
3071    params = ft_params1(ssid=ssid, passphrase=passphrase)
3072    params['wpa_key_mgmt'] = "FT-EAP"
3073    params["ieee8021x"] = "1"
3074    params = dict(list(radius.items()) + list(params.items()))
3075    hapd = hostapd.add_ap(apdev[0], params)
3076    key_mgmt = hapd.get_config()['key_mgmt']
3077    if key_mgmt.split(' ')[0] != "FT-EAP":
3078        raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
3079
3080    hapd1 = hostapd.add_ap(apdev[1], {"ssid": ssid})
3081
3082    # Connect to WPA enabled AP
3083    dev[0].connect(ssid, key_mgmt="FT-EAP", proto="WPA2", ieee80211w="1",
3084                   eap="GPSK", identity="gpsk user",
3085                   password="abcdefghijklmnop0123456789abcdef",
3086                   scan_freq="2412")
3087
3088    # Try over_ds roaming to non-WPA-enabled AP.
3089    # If hostapd does not check hapd->wpa_auth internally, it will crash now.
3090    dev[0].roam_over_ds(apdev[1]['bssid'], fail_test=True, force=True)
3091
3092def test_ap_ft_extra_ie(dev, apdev):
3093    """WPA2-PSK-FT AP with WPA2-PSK enabled and unexpected MDE"""
3094    ssid = "test-ft"
3095    passphrase = "12345678"
3096
3097    params = ft_params1(ssid=ssid, passphrase=passphrase)
3098    params["wpa_key_mgmt"] = "WPA-PSK FT-PSK"
3099    hapd0 = hostapd.add_ap(apdev[0], params)
3100    dev[1].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
3101                   scan_freq="2412")
3102    dev[2].connect(ssid, psk=passphrase, key_mgmt="WPA-PSK", proto="WPA2",
3103                   scan_freq="2412")
3104    try:
3105        # Add Mobility Domain element to test AP validation code.
3106        dev[0].request("VENDOR_ELEM_ADD 13 3603a1b201")
3107        dev[0].connect(ssid, psk=passphrase, key_mgmt="WPA-PSK", proto="WPA2",
3108                       scan_freq="2412", wait_connect=False)
3109        ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
3110                                "CTRL-EVENT-ASSOC-REJECT"], timeout=10)
3111        if ev is None:
3112            raise Exception("No connection result")
3113        if "CTRL-EVENT-CONNECTED" in ev:
3114            raise Exception("Non-FT association accepted with MDE")
3115        if "status_code=43" not in ev:
3116            raise Exception("Unexpected status code: " + ev)
3117        dev[0].request("DISCONNECT")
3118    finally:
3119        dev[0].request("VENDOR_ELEM_REMOVE 13 *")
3120
3121def test_ap_ft_ric(dev, apdev):
3122    """WPA2-PSK-FT AP and RIC"""
3123    ssid = "test-ft"
3124    passphrase = "12345678"
3125
3126    params = ft_params1(ssid=ssid, passphrase=passphrase)
3127    hapd0 = hostapd.add_ap(apdev[0], params)
3128    params = ft_params2(ssid=ssid, passphrase=passphrase)
3129    hapd1 = hostapd.add_ap(apdev[1], params)
3130
3131    dev[0].set("ric_ies", "")
3132    dev[0].set("ric_ies", '""')
3133    if "FAIL" not in dev[0].request("SET ric_ies q"):
3134        raise Exception("Invalid ric_ies value accepted")
3135
3136    tests = ["3900",
3137             "3900ff04eeeeeeee",
3138             "390400000000",
3139             "390400000000" + "390400000000",
3140             "390400000000" + "dd050050f20202",
3141             "390400000000" + "dd3d0050f2020201" + 55*"00",
3142             "390400000000" + "dd3d0050f2020201aa300010270000000000000000000000000000000000000000000000000000ffffff7f00000000000000000000000040420f00ffff0000",
3143             "390401010000" + "dd3d0050f2020201aa3000dc050000000000000000000000000000000000000000000000000000dc050000000000000000000000000000808d5b0028230000"]
3144    for t in tests:
3145        dev[0].set("ric_ies", t)
3146        run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase,
3147                  test_connectivity=False)
3148        dev[0].request("REMOVE_NETWORK all")
3149        dev[0].wait_disconnected()
3150        dev[0].dump_monitor()
3151
3152def ie_hex(ies, id):
3153    return binascii.hexlify(struct.pack('BB', id, len(ies[id])) + ies[id]).decode()
3154
3155def test_ap_ft_reassoc_proto(dev, apdev):
3156    """WPA2-PSK-FT AP Reassociation Request frame parsing"""
3157    ssid = "test-ft"
3158    passphrase = "12345678"
3159
3160    params = ft_params1(ssid=ssid, passphrase=passphrase)
3161    hapd0 = hostapd.add_ap(apdev[0], params)
3162    params = ft_params2(ssid=ssid, passphrase=passphrase)
3163    hapd1 = hostapd.add_ap(apdev[1], params)
3164
3165    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
3166                   ieee80211w="1", scan_freq="2412")
3167    if dev[0].get_status_field('bssid') == hapd0.own_addr():
3168        hapd1ap = hapd0
3169        hapd2ap = hapd1
3170    else:
3171        hapd1ap = hapd1
3172        hapd2ap = hapd0
3173
3174    dev[0].scan_for_bss(hapd2ap.own_addr(), freq="2412")
3175    hapd2ap.set("ext_mgmt_frame_handling", "1")
3176    dev[0].request("ROAM " + hapd2ap.own_addr())
3177
3178    while True:
3179        req = hapd2ap.mgmt_rx()
3180        hapd2ap.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
3181        if req['subtype'] == 11:
3182            break
3183
3184    while True:
3185        req = hapd2ap.mgmt_rx()
3186        if req['subtype'] == 2:
3187            break
3188        hapd2ap.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
3189
3190    # IEEE 802.11 header + fixed fields before IEs
3191    hdr = binascii.hexlify(req['frame'][0:34]).decode()
3192    ies = parse_ie(binascii.hexlify(req['frame'][34:]))
3193    # First elements: SSID, Supported Rates, Extended Supported Rates
3194    ies1 = ie_hex(ies, 0) + ie_hex(ies, 1) + ie_hex(ies, 50)
3195
3196    rsne = ie_hex(ies, 48)
3197    mde = ie_hex(ies, 54)
3198    fte = ie_hex(ies, 55)
3199    tests = []
3200    # RSN: Trying to use FT, but MDIE not included
3201    tests += [rsne]
3202    # RSN: Attempted to use unknown MDIE
3203    tests += [rsne + "3603000000"]
3204    # Invalid RSN pairwise cipher
3205    tests += ["30260100000fac040100000fac030100000fac040000010029208a42cd25c85aa571567dce10dae3"]
3206    # FT: No PMKID in RSNIE
3207    tests += ["30160100000fac040100000fac040100000fac0400000000" + ie_hex(ies, 54)]
3208    # FT: Invalid FTIE
3209    tests += [rsne + mde]
3210    # FT: RIC IE(s) in the frame, but not included in protected IE count
3211    # FT: Failed to parse FT IEs
3212    tests += [rsne + mde + fte + "3900"]
3213    # FT: SNonce mismatch in FTIE
3214    tests += [rsne + mde + "37520000" + 16*"00" + 32*"00" + 32*"00"]
3215    # FT: ANonce mismatch in FTIE
3216    tests += [rsne + mde + fte[0:40] + 32*"00" + fte[104:]]
3217    # FT: No R0KH-ID subelem in FTIE
3218    tests += [rsne + mde + "3752" + fte[4:168]]
3219    # FT: R0KH-ID in FTIE did not match with the current R0KH-ID
3220    tests += [rsne + mde + "3755" + fte[4:168] + "0301ff"]
3221    # FT: No R1KH-ID subelem in FTIE
3222    tests += [rsne + mde + "375e" + fte[4:168] + "030a" + binascii.hexlify(b"nas1.w1.fi").decode()]
3223    # FT: Unknown R1KH-ID used in ReassocReq
3224    tests += [rsne + mde + "3766" + fte[4:168] + "030a" + binascii.hexlify(b"nas1.w1.fi").decode() + "0106000000000000"]
3225    # FT: PMKID in Reassoc Req did not match with the PMKR1Name derived from auth request
3226    tests += [rsne[:-32] + 16*"00" + mde + fte]
3227    # Invalid MIC in FTIE
3228    tests += [rsne + mde + fte[0:8] + 16*"00" + fte[40:]]
3229    for t in tests:
3230        hapd2ap.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + ies1 + t)
3231
3232    # Do not leave dev[0] in state where it is waiting for
3233    # NL80211_CMD_ASSOCIATE to complete since that might deliver
3234    # an ASSOC_TIMED_OUT event to the next test case.
3235    dev[0].request("DISCONNECT")
3236    time.sleep(0.2)
3237
3238def test_ap_ft_reassoc_local_fail(dev, apdev):
3239    """WPA2-PSK-FT AP Reassociation Request frame and local failure"""
3240    ssid = "test-ft"
3241    passphrase = "12345678"
3242
3243    params = ft_params1(ssid=ssid, passphrase=passphrase)
3244    hapd0 = hostapd.add_ap(apdev[0], params)
3245    params = ft_params2(ssid=ssid, passphrase=passphrase)
3246    hapd1 = hostapd.add_ap(apdev[1], params)
3247
3248    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
3249                   ieee80211w="1", scan_freq="2412")
3250    if dev[0].get_status_field('bssid') == hapd0.own_addr():
3251        hapd1ap = hapd0
3252        hapd2ap = hapd1
3253    else:
3254        hapd1ap = hapd1
3255        hapd2ap = hapd0
3256
3257    dev[0].scan_for_bss(hapd2ap.own_addr(), freq="2412")
3258    # FT: Failed to calculate MIC
3259    with fail_test(hapd2ap, 1, "wpa_ft_validate_reassoc"):
3260        dev[0].request("ROAM " + hapd2ap.own_addr())
3261        ev = dev[0].wait_event(["CTRL-EVENT-ASSOC-REJECT"], timeout=10)
3262        dev[0].request("DISCONNECT")
3263        if ev is None:
3264            raise Exception("Association reject not seen")
3265
3266def test_ap_ft_reassoc_replay(dev, apdev, params):
3267    """WPA2-PSK-FT AP and replayed Reassociation Request frame"""
3268    capfile = os.path.join(params['logdir'], "hwsim0.pcapng")
3269    ssid = "test-ft"
3270    passphrase = "12345678"
3271
3272    params = ft_params1(ssid=ssid, passphrase=passphrase)
3273    hapd0 = hostapd.add_ap(apdev[0], params)
3274    params = ft_params2(ssid=ssid, passphrase=passphrase)
3275    hapd1 = hostapd.add_ap(apdev[1], params)
3276
3277    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
3278                   scan_freq="2412")
3279    if dev[0].get_status_field('bssid') == hapd0.own_addr():
3280        hapd1ap = hapd0
3281        hapd2ap = hapd1
3282    else:
3283        hapd1ap = hapd1
3284        hapd2ap = hapd0
3285
3286    dev[0].scan_for_bss(hapd2ap.own_addr(), freq="2412")
3287    hapd2ap.set("ext_mgmt_frame_handling", "1")
3288    dev[0].dump_monitor()
3289    if "OK" not in dev[0].request("ROAM " + hapd2ap.own_addr()):
3290        raise Exception("ROAM failed")
3291
3292    reassocreq = None
3293    count = 0
3294    while count < 100:
3295        req = hapd2ap.mgmt_rx()
3296        count += 1
3297        hapd2ap.dump_monitor()
3298        hapd2ap.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
3299        if req['subtype'] == 2:
3300            reassocreq = req
3301            ev = hapd2ap.wait_event(["MGMT-TX-STATUS"], timeout=5)
3302            if ev is None:
3303                raise Exception("No TX status seen")
3304            cmd = "MGMT_TX_STATUS_PROCESS %s" % (" ".join(ev.split(' ')[1:4]))
3305            if "OK" not in hapd2ap.request(cmd):
3306                raise Exception("MGMT_TX_STATUS_PROCESS failed")
3307            break
3308    hapd2ap.set("ext_mgmt_frame_handling", "0")
3309    if reassocreq is None:
3310        raise Exception("No Reassociation Request frame seen")
3311    dev[0].wait_connected()
3312    dev[0].dump_monitor()
3313    hapd2ap.dump_monitor()
3314
3315    hwsim_utils.test_connectivity(dev[0], hapd2ap)
3316
3317    logger.info("Replay the last Reassociation Request frame")
3318    hapd2ap.dump_monitor()
3319    hapd2ap.set("ext_mgmt_frame_handling", "1")
3320    hapd2ap.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
3321    ev = hapd2ap.wait_event(["MGMT-TX-STATUS"], timeout=5)
3322    if ev is None:
3323        raise Exception("No TX status seen")
3324    cmd = "MGMT_TX_STATUS_PROCESS %s" % (" ".join(ev.split(' ')[1:4]))
3325    if "OK" not in hapd2ap.request(cmd):
3326        raise Exception("MGMT_TX_STATUS_PROCESS failed")
3327    hapd2ap.set("ext_mgmt_frame_handling", "0")
3328
3329    try:
3330        hwsim_utils.test_connectivity(dev[0], hapd2ap)
3331        ok = True
3332    except:
3333        ok = False
3334
3335    ap = hapd2ap.own_addr()
3336    sta = dev[0].own_addr()
3337    filt = "wlan.fc.type == 2 && " + \
3338           "wlan.da == " + sta + " && " + \
3339           "wlan.sa == " + ap + " && " + \
3340           "wlan.fc.protected == 1"
3341    fields = ["wlan.ccmp.extiv"]
3342    res = run_tshark(capfile, filt, fields)
3343    vals = res.splitlines()
3344    logger.info("CCMP PN: " + str(vals))
3345    if len(vals) < 2:
3346        raise Exception("Could not find all CCMP protected frames from capture")
3347    if len(set(vals)) < len(vals):
3348        raise Exception("Duplicate CCMP PN used")
3349
3350    if not ok:
3351        raise Exception("The second hwsim connectivity test failed")
3352
3353def test_ap_ft_psk_file(dev, apdev):
3354    """WPA2-PSK-FT AP with PSK from a file"""
3355    ssid = "test-ft"
3356    passphrase = "12345678"
3357
3358    params = ft_params1a(ssid=ssid, passphrase=passphrase)
3359    params['wpa_psk_file'] = 'hostapd.wpa_psk'
3360    hapd = hostapd.add_ap(apdev[0], params)
3361
3362    dev[1].connect(ssid, psk="very secret",
3363                   key_mgmt="FT-PSK", proto="WPA2", ieee80211w="1",
3364                   scan_freq="2412", wait_connect=False)
3365    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
3366                   ieee80211w="1", scan_freq="2412")
3367    dev[0].request("REMOVE_NETWORK all")
3368    dev[0].wait_disconnected()
3369    dev[0].connect(ssid, psk="very secret", key_mgmt="FT-PSK", proto="WPA2",
3370                   ieee80211w="1", scan_freq="2412")
3371    dev[0].request("REMOVE_NETWORK all")
3372    dev[0].wait_disconnected()
3373    dev[0].connect(ssid, psk="secret passphrase",
3374                   key_mgmt="FT-PSK", proto="WPA2", ieee80211w="1",
3375                   scan_freq="2412")
3376    dev[2].connect(ssid, psk="another passphrase for all STAs",
3377                   key_mgmt="FT-PSK", proto="WPA2", ieee80211w="1",
3378                   scan_freq="2412")
3379    ev = dev[1].wait_event(["WPA: 4-Way Handshake failed"], timeout=10)
3380    if ev is None:
3381        raise Exception("Timed out while waiting for failure report")
3382    dev[1].request("REMOVE_NETWORK all")
3383
3384def test_ap_ft_eap_ap_config_change(dev, apdev):
3385    """WPA2-EAP-FT AP changing from 802.1X-only to FT-only"""
3386    ssid = "test-ft"
3387    passphrase = "12345678"
3388    bssid = apdev[0]['bssid']
3389
3390    radius = hostapd.radius_params()
3391    params = ft_params1(ssid=ssid, passphrase=passphrase, discovery=True)
3392    params['wpa_key_mgmt'] = "WPA-EAP"
3393    params["ieee8021x"] = "1"
3394    params["pmk_r1_push"] = "0"
3395    params["r0kh"] = "ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
3396    params["r1kh"] = "00:00:00:00:00:00 00:00:00:00:00:00 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
3397    params["eap_server"] = "0"
3398    params = dict(list(radius.items()) + list(params.items()))
3399    hapd = hostapd.add_ap(apdev[0], params)
3400
3401    dev[0].connect(ssid, key_mgmt="FT-EAP WPA-EAP", proto="WPA2",
3402                   eap="GPSK", identity="gpsk user",
3403                   password="abcdefghijklmnop0123456789abcdef",
3404                   scan_freq="2412")
3405    dev[0].request("DISCONNECT")
3406    dev[0].wait_disconnected()
3407    dev[0].dump_monitor()
3408
3409    hapd.disable()
3410    hapd.set('wpa_key_mgmt', "FT-EAP")
3411    hapd.enable()
3412
3413    dev[0].request("BSS_FLUSH 0")
3414    dev[0].scan_for_bss(bssid, 2412, force_scan=True, only_new=True)
3415
3416    dev[0].request("RECONNECT")
3417    dev[0].wait_connected()
3418
3419def test_ap_ft_eap_sha384(dev, apdev):
3420    """WPA2-EAP-FT with SHA384"""
3421    ssid = "test-ft"
3422    passphrase = "12345678"
3423
3424    radius = hostapd.radius_params()
3425    params = ft_params1(ssid=ssid, passphrase=passphrase)
3426    params["ieee80211w"] = "2"
3427    params['wpa_key_mgmt'] = "FT-EAP-SHA384"
3428    params["ieee8021x"] = "1"
3429    params = dict(list(radius.items()) + list(params.items()))
3430    hapd0 = hostapd.add_ap(apdev[0], params)
3431    conf = hapd0.request("GET_CONFIG")
3432    if "key_mgmt=FT-EAP-SHA384" not in conf.splitlines():
3433        logger.info("GET_CONFIG:\n" + conf)
3434        raise Exception("GET_CONFIG did not report correct key_mgmt")
3435    params = ft_params2(ssid=ssid, passphrase=passphrase)
3436    params["ieee80211w"] = "2"
3437    params['wpa_key_mgmt'] = "FT-EAP-SHA384"
3438    params["ieee8021x"] = "1"
3439    params = dict(list(radius.items()) + list(params.items()))
3440    hapd1 = hostapd.add_ap(apdev[1], params)
3441
3442    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, eap=True,
3443              sha384=True)
3444
3445def test_ap_ft_eap_sha384_reassoc(dev, apdev):
3446    """WPA2-EAP-FT with SHA384 using REASSOCIATE"""
3447    check_suite_b_192_capa(dev)
3448    ssid = "test-ft"
3449    passphrase = "12345678"
3450
3451    radius = hostapd.radius_params()
3452    params = ft_params1(ssid=ssid, passphrase=passphrase)
3453    params["ieee80211w"] = "2"
3454    params['wpa_key_mgmt'] = "WPA-EAP-SUITE-B-192 FT-EAP-SHA384"
3455    params["ieee8021x"] = "1"
3456    params = dict(list(radius.items()) + list(params.items()))
3457    hapd0 = hostapd.add_ap(apdev[0], params)
3458    params = ft_params2(ssid=ssid, passphrase=passphrase)
3459    params["ieee80211w"] = "2"
3460    params['wpa_key_mgmt'] = "WPA-EAP-SUITE-B-192 FT-EAP-SHA384"
3461    params["ieee8021x"] = "1"
3462    params = dict(list(radius.items()) + list(params.items()))
3463    hapd1 = hostapd.add_ap(apdev[1], params)
3464
3465    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, eap=True,
3466              sha384=True, also_non_ft=True, roam_with_reassoc=True)
3467
3468def test_ap_ft_eap_sha384_over_ds(dev, apdev):
3469    """WPA2-EAP-FT with SHA384 over DS"""
3470    ssid = "test-ft"
3471    passphrase = "12345678"
3472
3473    radius = hostapd.radius_params()
3474    params = ft_params1(ssid=ssid, passphrase=passphrase)
3475    params["ieee80211w"] = "2"
3476    params['wpa_key_mgmt'] = "FT-EAP-SHA384"
3477    params["ieee8021x"] = "1"
3478    params = dict(list(radius.items()) + list(params.items()))
3479    hapd0 = hostapd.add_ap(apdev[0], params)
3480    params = ft_params2(ssid=ssid, passphrase=passphrase)
3481    params["ieee80211w"] = "2"
3482    params['wpa_key_mgmt'] = "FT-EAP-SHA384"
3483    params["ieee8021x"] = "1"
3484    params = dict(list(radius.items()) + list(params.items()))
3485    hapd1 = hostapd.add_ap(apdev[1], params)
3486
3487    dev[0].flush_scan_cache()
3488    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
3489              eap=True, sha384=True)
3490
3491def test_ap_ft_roam_rrm(dev, apdev):
3492    """WPA2-PSK-FT AP and radio measurement request"""
3493    ssid = "test-ft"
3494    passphrase = "12345678"
3495
3496    params = ft_params1(ssid=ssid, passphrase=passphrase)
3497    params["rrm_beacon_report"] = "1"
3498    hapd0 = hostapd.add_ap(apdev[0], params)
3499    bssid0 = hapd0.own_addr()
3500
3501    addr = dev[0].own_addr()
3502    dev[0].flush_scan_cache()
3503    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
3504                   scan_freq="2412")
3505    hapd0.wait_sta()
3506    check_beacon_req(hapd0, addr, 1)
3507
3508    params = ft_params2(ssid=ssid, passphrase=passphrase)
3509    params["rrm_beacon_report"] = "1"
3510    hapd1 = hostapd.add_ap(apdev[1], params)
3511    bssid1 = hapd1.own_addr()
3512
3513    dev[0].scan_for_bss(bssid1, freq=2412)
3514    dev[0].roam(bssid1)
3515    hapd1.wait_sta()
3516    check_beacon_req(hapd1, addr, 2)
3517
3518    dev[0].scan_for_bss(bssid0, freq=2412)
3519    dev[0].roam(bssid0)
3520    hapd0.wait_sta()
3521    check_beacon_req(hapd0, addr, 3)
3522
3523def test_ap_ft_pmksa_caching(dev, apdev):
3524    """FT-EAP and PMKSA caching for initial mobility domain association"""
3525    ssid = "test-ft"
3526    identity = "gpsk user"
3527
3528    radius = hostapd.radius_params()
3529    params = ft_params1(ssid=ssid)
3530    params['wpa_key_mgmt'] = "FT-EAP"
3531    params["ieee8021x"] = "1"
3532    params["mobility_domain"] = "c3d4"
3533    params = dict(list(radius.items()) + list(params.items()))
3534    hapd = hostapd.add_ap(apdev[0], params)
3535
3536    params = ft_params2(ssid=ssid)
3537    params['wpa_key_mgmt'] = "FT-EAP"
3538    params["ieee8021x"] = "1"
3539    params["mobility_domain"] = "c3d4"
3540    params = dict(list(radius.items()) + list(params.items()))
3541    hapd1 = hostapd.add_ap(apdev[1], params)
3542
3543    run_roams(dev[0], apdev, hapd, hapd1, ssid, None, eap=True,
3544              eap_identity=identity, pmksa_caching=True)
3545
3546def test_ap_ft_pmksa_caching_sha384(dev, apdev):
3547    """FT-EAP-SHA384 and PMKSA caching for initial mobility domain association"""
3548    ssid = "test-ft"
3549    identity = "gpsk user"
3550
3551    radius = hostapd.radius_params()
3552    params = ft_params1(ssid=ssid)
3553    params['wpa_key_mgmt'] = "FT-EAP-SHA384"
3554    params["ieee8021x"] = "1"
3555    params["mobility_domain"] = "c3d4"
3556    params = dict(list(radius.items()) + list(params.items()))
3557    hapd = hostapd.add_ap(apdev[0], params)
3558
3559    params = ft_params2(ssid=ssid)
3560    params['wpa_key_mgmt'] = "FT-EAP-SHA384"
3561    params["ieee8021x"] = "1"
3562    params["mobility_domain"] = "c3d4"
3563    params = dict(list(radius.items()) + list(params.items()))
3564    hapd1 = hostapd.add_ap(apdev[1], params)
3565
3566    run_roams(dev[0], apdev, hapd, hapd1, ssid, None, eap=True,
3567              eap_identity=identity, pmksa_caching=True, sha384=True)
3568
3569def test_ap_ft_r1_key_expiration(dev, apdev):
3570    """WPA2-PSK-FT and PMK-R1 expiration"""
3571    ssid = "test-ft"
3572    passphrase = "12345678"
3573
3574    params = ft_params1(ssid=ssid, passphrase=passphrase)
3575    params['r1_max_key_lifetime'] = "2"
3576    hapd0 = hostapd.add_ap(apdev[0], params)
3577    params = ft_params2(ssid=ssid, passphrase=passphrase)
3578    params['r1_max_key_lifetime'] = "2"
3579    hapd1 = hostapd.add_ap(apdev[1], params)
3580
3581    # This succeeds, but results in having to run another PMK-R1 pull before the
3582    # second AP can complete FT protocol.
3583    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, wait_before_roam=4)
3584
3585def test_ap_ft_r0_key_expiration(dev, apdev):
3586    """WPA2-PSK-FT and PMK-R0 expiration"""
3587    ssid = "test-ft"
3588    passphrase = "12345678"
3589
3590    params = ft_params1(ssid=ssid, passphrase=passphrase)
3591    params.pop('r0_key_lifetime', None)
3592    params['ft_r0_key_lifetime'] = "2"
3593    hapd0 = hostapd.add_ap(apdev[0], params)
3594    params = ft_params2(ssid=ssid, passphrase=passphrase)
3595    params.pop('r0_key_lifetime', None)
3596    params['ft_r0_key_lifetime'] = "2"
3597    hapd1 = hostapd.add_ap(apdev[1], params)
3598
3599    bssid2 = run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase,
3600                       return_after_initial=True)
3601    time.sleep(4)
3602    dev[0].scan_for_bss(bssid2, freq="2412")
3603    if "OK" not in dev[0].request("ROAM " + bssid2):
3604        raise Exception("ROAM failed")
3605    ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
3606                            "CTRL-EVENT-AUTH-REJECT",
3607                            "CTRL-EVENT-ASSOC-REJECT"], timeout=5)
3608    dev[0].request("DISCONNECT")
3609    if ev is None or "CTRL-EVENT-AUTH-REJECT" not in ev:
3610        raise Exception("FT protocol failure not reported")
3611    if "status_code=53" not in ev:
3612        raise Exception("Unexpected status in FT protocol failure: " + ev)
3613
3614    # Generate a new PMK-R0
3615    dev[0].dump_monitor()
3616    dev[0].request("RECONNECT")
3617    dev[0].wait_connected()
3618
3619def test_ap_ft_no_full_ap_client_state(dev, apdev):
3620    """WPA2-PSK-FT AP with full_ap_client_state=0"""
3621    run_ap_ft_skip_prune_assoc(dev, apdev, False, False)
3622
3623def test_ap_ft_skip_prune_assoc(dev, apdev):
3624    """WPA2-PSK-FT AP with skip_prune_assoc"""
3625    run_ap_ft_skip_prune_assoc(dev, apdev, True, True)
3626
3627def test_ap_ft_skip_prune_assoc2(dev, apdev):
3628    """WPA2-PSK-FT AP with skip_prune_assoc (disable full_ap_client_state)"""
3629    run_ap_ft_skip_prune_assoc(dev, apdev, True, False, test_connectivity=False)
3630
3631def test_ap_ft_skip_prune_assoc_pmf(dev, apdev):
3632    """WPA2-PSK-FT/PMF AP with skip_prune_assoc"""
3633    run_ap_ft_skip_prune_assoc(dev, apdev, True, True, pmf=True)
3634
3635def test_ap_ft_skip_prune_assoc_pmf_over_ds(dev, apdev):
3636    """WPA2-PSK-FT/PMF AP with skip_prune_assoc (over DS)"""
3637    dev[0].flush_scan_cache()
3638    run_ap_ft_skip_prune_assoc(dev, apdev, True, True, pmf=True, over_ds=True)
3639
3640def run_ap_ft_skip_prune_assoc(dev, apdev, skip_prune_assoc,
3641                               full_ap_client_state, test_connectivity=True,
3642                               pmf=False, over_ds=False):
3643    ssid = "test-ft"
3644    passphrase = "12345678"
3645
3646    params = ft_params1(ssid=ssid, passphrase=passphrase)
3647    if skip_prune_assoc:
3648        params['skip_prune_assoc'] = '1'
3649    if not full_ap_client_state:
3650        params['driver_params'] = "full_ap_client_state=0"
3651    if pmf:
3652        params["ieee80211w"] = "2"
3653    hapd0 = hostapd.add_ap(apdev[0], params)
3654    params = ft_params2(ssid=ssid, passphrase=passphrase)
3655    if skip_prune_assoc:
3656        params['skip_prune_assoc'] = '1'
3657    if not full_ap_client_state:
3658        params['driver_params'] = "full_ap_client_state=0"
3659    if pmf:
3660        params["ieee80211w"] = "2"
3661    hapd1 = hostapd.add_ap(apdev[1], params)
3662
3663    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase,
3664              ieee80211w="2" if pmf else "0",
3665              over_ds=over_ds, test_connectivity=test_connectivity)
3666
3667def test_ap_ft_sae_skip_prune_assoc(dev, apdev):
3668    """WPA2-PSK-FT-SAE AP with skip_prune_assoc"""
3669    hapd0, hapd1 = start_ft_sae(dev[0], apdev, skip_prune_assoc=True)
3670    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True)
3671
3672def test_ap_ft_diff_mobility_domain(dev, apdev):
3673    """WPA2-PSK-FT AP and different mobility domain"""
3674    ssid = "test-ft"
3675    passphrase = "12345678"
3676
3677    params = ft_params1(ssid=ssid, passphrase=passphrase)
3678    hapd0 = hostapd.add_ap(apdev[0], params)
3679    params = ft_params2(ssid=ssid, passphrase=passphrase,
3680                        mobility_domain="c3d4")
3681    hapd1 = hostapd.add_ap(apdev[1], params)
3682
3683    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase)
3684
3685def test_ap_ft_diff_mobility_domain_over_ds(dev, apdev):
3686    """WPA2-PSK-FT AP and different mobility domain (over DS)"""
3687    ssid = "test-ft"
3688    passphrase = "12345678"
3689
3690    params = ft_params1(ssid=ssid, passphrase=passphrase)
3691    hapd0 = hostapd.add_ap(apdev[0], params)
3692    params = ft_params2(ssid=ssid, passphrase=passphrase,
3693                        mobility_domain="c3d4")
3694    hapd1 = hostapd.add_ap(apdev[1], params)
3695
3696    dev[0].connect(ssid, proto="WPA2", key_mgmt="FT-PSK", psk=passphrase,
3697                   scan_freq="2412")
3698    if dev[0].get_status_field('bssid') == apdev[0]['bssid']:
3699        dst = apdev[1]['bssid']
3700    else:
3701        dst = apdev[0]['bssid']
3702    dev[0].scan_for_bss(dst, freq="2412")
3703    if "FAIL" not in dev[0].request("FT_DS " + dst):
3704        raise Exception("FT_DS to another mobility domain accepted")
3705
3706def test_ap_ft_eap_dynamic_rxkhs(dev, apdev):
3707    """FT with dynamic RxKHs configuration"""
3708    fd1, fn1 = tempfile.mkstemp()
3709    fd2, fn2 = tempfile.mkstemp()
3710    try:
3711        f1 = os.fdopen(fd1, 'w')
3712        f2 = os.fdopen(fd2, 'w')
3713        run_ap_ft_eap_dynamic_rxkhs(dev, apdev, f1, fn1, f2, fn2)
3714    finally:
3715        os.unlink(fn1)
3716        os.unlink(fn2)
3717
3718def run_ap_ft_eap_dynamic_rxkhs(dev, apdev, f1, fn1, f2, fn2):
3719    ssid = "test-ft"
3720    passphrase = "12345678"
3721
3722    bssid0 = apdev[0]['bssid']
3723    bssid1 = apdev[1]['bssid']
3724
3725    radius = hostapd.radius_params()
3726
3727    f1.write('r0kh=' + bssid1 + ' nas2.w1.fi 300102030405060708090a0b0c0d0e0f300102030405060708090a0b0c0d0e0f\n')
3728    f1.write('r1kh=' + bssid1 + ' 00:01:02:03:04:06 200102030405060708090a0b0c0d0e0f200102030405060708090a0b0c0d0e0f\n')
3729    f1.close()
3730
3731    params = ft_params1a(rsn=True, ssid=ssid, passphrase=passphrase)
3732    params["ieee80211w"] = "2"
3733    params['wpa_key_mgmt'] = "FT-EAP"
3734    params["ieee8021x"] = "1"
3735    params["rxkh_file"] = fn1
3736    params = dict(list(radius.items()) + list(params.items()))
3737    hapd0 = hostapd.add_ap(apdev[0], params)
3738
3739    if len(hapd0.request("GET_RXKHS").splitlines()) != 2:
3740        raise Exception("Unexpected number of RxKHs (AP0)")
3741
3742    params = ft_params2a(rsn=True, ssid=ssid, passphrase=passphrase)
3743    params["ieee80211w"] = "2"
3744    params['wpa_key_mgmt'] = "FT-EAP"
3745    params["ieee8021x"] = "1"
3746    params["rxkh_file"] = fn2
3747    params = dict(list(radius.items()) + list(params.items()))
3748    hapd1 = hostapd.add_ap(apdev[1], params)
3749
3750    if len(hapd1.request("GET_RXKHS").splitlines()) != 0:
3751        raise Exception("Unexpected number of RxKHs (AP1a)")
3752
3753    bssid = run_roams(dev[1], apdev, hapd0, hapd1, ssid, passphrase, eap=True,
3754                      return_after_initial=True)
3755    # This roam attempt fails since the APs did not yet have matching RxKH
3756    # configuration.
3757    dev[1].roam(bssid, check_bssid=False)
3758
3759    f2.write('r0kh=' + bssid0 + ' nas1.w1.fi 200102030405060708090a0b0c0d0e0f200102030405060708090a0b0c0d0e0f\n')
3760    f2.write('r1kh=' + bssid0 + ' 00:01:02:03:04:05 300102030405060708090a0b0c0d0e0f300102030405060708090a0b0c0d0e0f\n')
3761    f2.close()
3762    if "OK" not in hapd1.request("RELOAD_RXKHS"):
3763        raise Exception("Failed to reload RxKHs")
3764
3765    if len(hapd1.request("GET_RXKHS").splitlines()) != 2:
3766        raise Exception("Unexpected number of RxKHs (AP1b)")
3767
3768    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, eap=True)
3769
3770def test_ap_ft_ssid_verified(dev, apdev):
3771    """WPA2-PSK-FT and ssid_verified=1 indication"""
3772    hapd0, hapd1 = start_ft(apdev)
3773    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678",
3774              check_ssid=True)
3775