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], 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], 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], 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], 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], params)
441
442    params = ft_params2(ssid=ssid, passphrase=passphrase)
443    params['dynamic_vlan'] = "1"
444    hapd1 = hostapd.add_ap(apdev[1], 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], 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], 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], 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], 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], 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], 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], 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], 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_rsnxe_only_from_sta(dev, apdev):
1226    """FT with RSNXE only from STA"""
1227    hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="0")
1228    hapd1.disable()
1229    dev[0].scan_for_bss(hapd0.own_addr(), freq=2412)
1230    hapd0.set("ext_mgmt_frame_handling", "1")
1231    dev[0].connect("test-ft", key_mgmt="FT-SAE", sae_password="12345678",
1232                   sae_pwe="2", wait_connect=False)
1233
1234    for j in range(2):
1235        for i in range(0, 10):
1236            req = hapd0.mgmt_rx()
1237            if req is None:
1238                raise Exception("MGMT RX wait timed out (authentication)")
1239            if req['subtype'] == 11:
1240                break
1241            req = None
1242        if not req:
1243            raise Exception("Authentication frame not received")
1244
1245        hapd0.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
1246
1247    for i in range(0, 10):
1248        req = hapd0.mgmt_rx()
1249        if req is None:
1250            raise Exception("MGMT RX wait timed out (association)")
1251        if req['subtype'] == 0:
1252            break
1253        req = None
1254    if not req:
1255        raise Exception("Association Request frame not received")
1256
1257    hapd0.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
1258    ev = hapd0.wait_event(["MGMT-TX-STATUS"], timeout=5)
1259    if ev is None:
1260        raise Exception("Management frame TX status not reported (1)")
1261    if "stype=1 ok=1" not in ev:
1262        raise Exception("Unexpected management frame TX status (1): " + ev)
1263    cmd = "MGMT_TX_STATUS_PROCESS %s" % (" ".join(ev.split(' ')[1:4]))
1264    if "OK" not in hapd0.request(cmd):
1265        raise Exception("MGMT_TX_STATUS_PROCESS failed")
1266
1267    dev[0].wait_connected()
1268    hapd0.set("ext_mgmt_frame_handling", "0")
1269
1270    ies = parse_ie(binascii.hexlify(req['payload'][4:]))
1271    if 244 not in ies:
1272        raise Exception("RSNXE not included in Association Request frame for initial mobility domain association")
1273
1274def test_ap_ft_sae_h2e_downgrade_attack(dev, apdev):
1275    """WPA2-PSK-FT-SAE AP (H2E downgrade attack)"""
1276    try:
1277        dev[0].set("sae_pwe", "2")
1278        hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2",
1279                                    no_beacon_rsnxe2=True)
1280        run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1281                  force_initial_conn_to_first_ap=True,
1282                  return_after_initial=True)
1283        dev[0].scan_for_bss(hapd1.own_addr(), freq="2412")
1284        if "OK" not in dev[0].request("ROAM " + hapd1.own_addr()):
1285            raise Exception("ROAM command failed")
1286        # The target AP is expected to discard Reassociation Response frame due
1287        # to RSNXE Used mismatch. This will result in roaming timeout and
1288        # returning back to the old AP.
1289        ev = dev[0].wait_event(["CTRL-EVENT-ASSOC-REJECT",
1290                                "CTRL-EVENT-CONNECTED"], timeout=10)
1291        if ev and "CTRL-EVENT-ASSOC-REJECT" in ev:
1292            pass
1293        elif ev and hapd1.own_addr() in ev:
1294            raise Exception("Roaming succeeded unexpectedly")
1295    finally:
1296        dev[0].set("sae_pwe", "0")
1297
1298def test_ap_ft_sae_ptk_rekey0(dev, apdev):
1299    """WPA2-PSK-FT-SAE AP and PTK rekey triggered by station"""
1300    hapd0, hapd1 = start_ft_sae(dev[0], apdev)
1301    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1302              ptk_rekey="1", roams=0)
1303    check_ptk_rekey(dev[0], hapd0, hapd1)
1304
1305def test_ap_ft_sae_ptk_rekey1(dev, apdev):
1306    """WPA2-PSK-FT-SAE AP and PTK rekey triggered by station"""
1307    hapd0, hapd1 = start_ft_sae(dev[0], apdev)
1308    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1309              ptk_rekey="1", only_one_way=True)
1310    check_ptk_rekey(dev[0], hapd0, hapd1)
1311
1312def test_ap_ft_sae_ptk_rekey_ap(dev, apdev):
1313    """WPA2-PSK-FT-SAE AP and PTK rekey triggered by AP"""
1314    hapd0, hapd1 = start_ft_sae(dev[0], apdev, wpa_ptk_rekey=2)
1315    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1316              only_one_way=True)
1317    check_ptk_rekey(dev[0], hapd0, hapd1)
1318
1319def test_ap_ft_sae_ptk_rekey_ap_ext_key_id(dev, apdev):
1320    """WPA2-PSK-FT-SAE AP and PTK rekey triggered by AP (Ext Key ID)"""
1321    check_ext_key_id_capa(dev[0])
1322    try:
1323        dev[0].set("extended_key_id", "1")
1324        hapd0, hapd1 = start_ft_sae(dev[0], apdev, wpa_ptk_rekey=2,
1325                                    ext_key_id=True)
1326        check_ext_key_id_capa(hapd0)
1327        check_ext_key_id_capa(hapd1)
1328        run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1329                  only_one_way=True)
1330        check_ptk_rekey(dev[0], hapd0, hapd1)
1331        idx = int(dev[0].request("GET last_tk_key_idx"))
1332        if idx != 1:
1333            raise Exception("Unexpected Key ID after TK rekey: %d" % idx)
1334    finally:
1335        dev[0].set("extended_key_id", "0")
1336
1337def test_ap_ft_sae_over_ds(dev, apdev):
1338    """WPA2-PSK-FT-SAE AP over DS"""
1339    hapd0, hapd1 = start_ft_sae(dev[0], apdev)
1340    dev[0].flush_scan_cache()
1341    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1342              over_ds=True)
1343
1344def test_ap_ft_sae_over_ds_ptk_rekey0(dev, apdev):
1345    """WPA2-PSK-FT-SAE AP over DS and PTK rekey triggered by station"""
1346    hapd0, hapd1 = start_ft_sae(dev[0], apdev)
1347    dev[0].flush_scan_cache()
1348    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1349              over_ds=True, ptk_rekey="1", roams=0)
1350    check_ptk_rekey(dev[0], hapd0, hapd1)
1351
1352def test_ap_ft_sae_over_ds_ptk_rekey1(dev, apdev):
1353    """WPA2-PSK-FT-SAE AP over DS and PTK rekey triggered by station"""
1354    hapd0, hapd1 = start_ft_sae(dev[0], apdev)
1355    dev[0].flush_scan_cache()
1356    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1357              over_ds=True, ptk_rekey="1", only_one_way=True)
1358    check_ptk_rekey(dev[0], hapd0, hapd1)
1359
1360def test_ap_ft_sae_over_ds_ptk_rekey_ap(dev, apdev):
1361    """WPA2-PSK-FT-SAE AP over DS and PTK rekey triggered by AP"""
1362    hapd0, hapd1 = start_ft_sae(dev[0], apdev, wpa_ptk_rekey=2)
1363    dev[0].flush_scan_cache()
1364    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1365              over_ds=True, only_one_way=True)
1366    check_ptk_rekey(dev[0], hapd0, hapd1)
1367
1368def test_ap_ft_sae_h2e_rsne_override(dev, apdev):
1369    """WPA2-PSK-FT-SAE AP (H2E) and RSNE override (same value)"""
1370    try:
1371        dev[0].set("sae_pwe", "2")
1372        hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2",
1373                                    rsne_override="30260100000fac040100000fac040100000fac090c000100" + 16*"ff")
1374        run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True)
1375    finally:
1376        dev[0].set("sae_pwe", "0")
1377
1378def test_ap_ft_sae_h2e_rsnxe_override(dev, apdev):
1379    """WPA2-PSK-FT-SAE AP (H2E) and RSNXE override (same value)"""
1380    try:
1381        dev[0].set("sae_pwe", "2")
1382        hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2",
1383                                    rsnxe_override="F40120")
1384        run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True)
1385    finally:
1386        dev[0].set("sae_pwe", "0")
1387
1388def test_ap_ft_sae_h2e_rsne_mismatch(dev, apdev):
1389    """WPA2-PSK-FT-SAE AP (H2E) and RSNE mismatch"""
1390    try:
1391        dev[0].set("sae_pwe", "2")
1392        hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2",
1393                                    rsne_override="30260100000fac040100000fac040100000fac090c010100" + 16*"ff")
1394        run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1395                  fail_test=True)
1396    finally:
1397        dev[0].set("sae_pwe", "0")
1398
1399def test_ap_ft_sae_h2e_rsne_mismatch_pmkr1name(dev, apdev):
1400    """WPA2-PSK-FT-SAE AP (H2E) and RSNE mismatch in PMKR1Name"""
1401    try:
1402        dev[0].set("sae_pwe", "2")
1403        hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2",
1404                                    rsne_override="30260100000fac040100000fac040100000fac090c000100" + 16*"00")
1405        run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1406                  fail_test=True)
1407    finally:
1408        dev[0].set("sae_pwe", "0")
1409
1410def test_ap_ft_sae_h2e_rsnxe_mismatch(dev, apdev):
1411    """WPA2-PSK-FT-SAE AP (H2E) and RSNXE mismatch"""
1412    try:
1413        dev[0].set("sae_pwe", "2")
1414        hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2",
1415                                    rsnxe_override="F40160")
1416        run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1417                  fail_test=True)
1418    finally:
1419        dev[0].set("sae_pwe", "0")
1420
1421def test_ap_ft_sae_rsnxe_used_mismatch(dev, apdev):
1422    """FT-SAE AP and unexpected RSNXE Used in ReassocReq"""
1423    try:
1424        hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="2")
1425        dev[0].set("sae_pwe", "0")
1426        dev[0].set("ft_rsnxe_used", "1")
1427        next = run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678",
1428                         sae=True, return_after_initial=True)
1429        if "OK" not in dev[0].request("ROAM " + next):
1430            raise Exception("ROAM command failed")
1431        # The target AP is expected to discard Reassociation Request frame due
1432        # to RSNXE Used mismatch. This will result in roaming timeout and
1433        # returning back to the old AP.
1434        ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=5)
1435        if ev and next in ev:
1436            raise Exception("Roaming succeeded unexpectedly")
1437    finally:
1438        dev[0].set("sae_pwe", "0")
1439
1440def test_ap_ft_sae_rsnxe_used_mismatch2(dev, apdev):
1441    """FT-SAE AP and unexpected RSNXE Used in ReassocResp"""
1442    try:
1443        hapd0, hapd1 = start_ft_sae(dev[0], apdev, sae_pwe="0",
1444                                    ft_rsnxe_used=True)
1445        dev[0].set("sae_pwe", "2")
1446        next = run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678",
1447                         sae=True, return_after_initial=True)
1448        if "OK" not in dev[0].request("ROAM " + next):
1449            raise Exception("ROAM command failed")
1450        # The STA is expected to discard Reassociation Response frame due to
1451        # RSNXE Used mismatch. This will result in returning back to the old AP.
1452        ev = dev[0].wait_disconnected()
1453        if next not in ev:
1454            raise Exception("Unexpected disconnection BSSID: " + ev)
1455        if "reason=13 locally_generated=1" not in ev:
1456            raise Exception("Unexpected disconnection reason: " + ev)
1457        ev = dev[0].wait_connected()
1458        if next in ev:
1459            raise Exception("Roaming succeeded unexpectedly")
1460
1461        hapd0.set("ft_rsnxe_used", "0")
1462        hapd1.set("ft_rsnxe_used", "0")
1463        dev[0].roam(next);
1464    finally:
1465        dev[0].set("sae_pwe", "0")
1466
1467def test_ap_ft_sae_pw_id(dev, apdev):
1468    """FT-SAE with Password Identifier"""
1469    check_sae_capab(dev[0])
1470    ssid = "test-ft"
1471
1472    params = ft_params1(ssid=ssid)
1473    params["ieee80211w"] = "2"
1474    params['wpa_key_mgmt'] = "FT-SAE"
1475    params['sae_password'] = 'secret|id=pwid'
1476    hapd0 = hostapd.add_ap(apdev[0], params)
1477    params = ft_params2(ssid=ssid)
1478    params["ieee80211w"] = "2"
1479    params['wpa_key_mgmt'] = "FT-SAE"
1480    params['sae_password'] = 'secret|id=pwid'
1481    hapd = hostapd.add_ap(apdev[1], params)
1482
1483    dev[0].request("SET sae_groups ")
1484    run_roams(dev[0], apdev, hapd0, hapd, ssid, passphrase=None, sae=True,
1485              sae_password="secret", sae_password_id="pwid")
1486
1487def test_ap_ft_sae_with_both_akms(dev, apdev):
1488    """SAE + FT-SAE configuration"""
1489    check_sae_capab(dev[0])
1490    ssid = "test-ft"
1491    passphrase = "12345678"
1492
1493    params = ft_params1(ssid=ssid, passphrase=passphrase)
1494    params['wpa_key_mgmt'] = "FT-SAE SAE"
1495    hapd0 = hostapd.add_ap(apdev[0], params)
1496    params = ft_params2(ssid=ssid, passphrase=passphrase)
1497    params['wpa_key_mgmt'] = "FT-SAE SAE"
1498    hapd = hostapd.add_ap(apdev[1], params)
1499    key_mgmt = hapd.get_config()['key_mgmt']
1500    if key_mgmt.split(' ')[0] != "FT-SAE":
1501        raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
1502
1503    dev[0].request("SET sae_groups ")
1504    run_roams(dev[0], apdev, hapd0, hapd, ssid, passphrase, sae=True,
1505              sae_and_psk=True)
1506
1507def test_ap_ft_sae_pmksa_caching(dev, apdev):
1508    """WPA2-FT-SAE AP and PMKSA caching for initial mobility domain association"""
1509    check_sae_capab(dev[0])
1510    ssid = "test-ft"
1511    passphrase = "12345678"
1512
1513    params = ft_params1(ssid=ssid, passphrase=passphrase)
1514    params['wpa_key_mgmt'] = "FT-SAE"
1515    hapd0 = hostapd.add_ap(apdev[0], params)
1516    params = ft_params2(ssid=ssid, passphrase=passphrase)
1517    params['wpa_key_mgmt'] = "FT-SAE"
1518    hapd = hostapd.add_ap(apdev[1], params)
1519    key_mgmt = hapd.get_config()['key_mgmt']
1520    if key_mgmt.split(' ')[0] != "FT-SAE":
1521        raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
1522
1523    dev[0].request("SET sae_groups ")
1524    run_roams(dev[0], apdev, hapd0, hapd, ssid, passphrase, sae=True,
1525              pmksa_caching=True)
1526
1527def test_ap_ft_sae_pmksa_caching_pwe(dev, apdev):
1528    """WPA2-FT-SAE AP and PMKSA caching for initial mobility domain association (STA PWE both)"""
1529    check_sae_capab(dev[0])
1530    ssid = "test-ft"
1531    passphrase = "12345678"
1532
1533    params = ft_params1(ssid=ssid, passphrase=passphrase)
1534    params['wpa_key_mgmt'] = "FT-SAE"
1535    hapd0 = hostapd.add_ap(apdev[0], params)
1536    params = ft_params2(ssid=ssid, passphrase=passphrase)
1537    params['wpa_key_mgmt'] = "FT-SAE"
1538    hapd = hostapd.add_ap(apdev[1], params)
1539    key_mgmt = hapd.get_config()['key_mgmt']
1540    if key_mgmt.split(' ')[0] != "FT-SAE":
1541        raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
1542
1543    try:
1544        dev[0].request("SET sae_groups ")
1545        dev[0].set("sae_pwe", "2")
1546        run_roams(dev[0], apdev, hapd0, hapd, ssid, passphrase, sae=True,
1547                  pmksa_caching=True)
1548    finally:
1549        dev[0].set("sae_groups", "")
1550        dev[0].set("sae_pwe", "0")
1551
1552def test_ap_ft_sae_pmksa_caching_h2e(dev, apdev):
1553    """WPA2-FT-SAE AP and PMKSA caching for initial mobility domain association (H2E)"""
1554    run_ap_ft_sae_pmksa_caching_h2e(dev, apdev)
1555
1556def test_ap_ft_sae_pmksa_caching_h2e_prepend_pmkid(dev, apdev):
1557    """FT-SAE and PMKSA caching for initial mobility domain association (H2E, prepend PMKID)"""
1558    try:
1559        dev[0].set("ft_prepend_pmkid", "1")
1560        run_ap_ft_sae_pmksa_caching_h2e(dev, apdev)
1561    finally:
1562        dev[0].set("ft_prepend_pmkid", "0")
1563
1564def run_ap_ft_sae_pmksa_caching_h2e(dev, apdev):
1565    check_sae_capab(dev[0])
1566    ssid = "test-ft"
1567    passphrase = "12345678"
1568
1569    params = ft_params1(ssid=ssid, passphrase=passphrase)
1570    params['wpa_key_mgmt'] = "FT-SAE"
1571    params['sae_pwe'] = "1"
1572    hapd0 = hostapd.add_ap(apdev[0], params)
1573    params = ft_params2(ssid=ssid, passphrase=passphrase)
1574    params['wpa_key_mgmt'] = "FT-SAE"
1575    params['sae_pwe'] = "1"
1576    hapd = hostapd.add_ap(apdev[1], params)
1577    key_mgmt = hapd.get_config()['key_mgmt']
1578    if key_mgmt.split(' ')[0] != "FT-SAE":
1579        raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
1580
1581    try:
1582        dev[0].request("SET sae_groups ")
1583        dev[0].set("sae_pwe", "1")
1584        run_roams(dev[0], apdev, hapd0, hapd, ssid, passphrase, sae=True,
1585                  pmksa_caching=True)
1586    finally:
1587        dev[0].set("sae_groups", "")
1588        dev[0].set("sae_pwe", "0")
1589
1590def test_ap_ft_sae_ext_key_19(dev, apdev):
1591    """WPA2-FT-SAE-EXT-KEY AP (group 19)"""
1592    hapd0, hapd1 = start_ft_sae(dev[0], apdev, ext_key=True,
1593                                sae_groups="19")
1594    dev[0].set("sae_groups", "19")
1595    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1596              sae_ext_key=True)
1597    dev[0].set("sae_groups", "")
1598
1599def test_ap_ft_sae_ext_key_20(dev, apdev):
1600    """WPA2-FT-SAE-EXT-KEY AP (group 20)"""
1601    hapd0, hapd1 = start_ft_sae(dev[0], apdev, ext_key=True,
1602                                sae_groups="20")
1603    dev[0].set("sae_groups", "20")
1604    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1605              sae_ext_key=True)
1606    dev[0].set("sae_groups", "")
1607
1608def test_ap_ft_sae_ext_key_21(dev, apdev):
1609    """WPA2-FT-SAE-EXT-KEY AP (group 21)"""
1610    hapd0, hapd1 = start_ft_sae(dev[0], apdev, ext_key=True,
1611                                sae_groups="21")
1612    dev[0].set("sae_groups", "21")
1613    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1614              sae_ext_key=True)
1615    dev[0].set("sae_groups", "")
1616
1617def test_ap_ft_sae_ext_key_19_over_ds(dev, apdev):
1618    """WPA2-FT-SAE-EXT-KEY AP over DS (group 19)"""
1619    hapd0, hapd1 = start_ft_sae(dev[0], apdev, ext_key=True,
1620                                sae_groups="19")
1621    dev[0].set("sae_groups", "19")
1622    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1623              sae_ext_key=True, over_ds=True)
1624    dev[0].set("sae_groups", "")
1625
1626def test_ap_ft_sae_ext_key_20_over_ds(dev, apdev):
1627    """WPA2-FT-SAE-EXT-KEY AP over DS (group 20)"""
1628    hapd0, hapd1 = start_ft_sae(dev[0], apdev, ext_key=True,
1629                                sae_groups="20")
1630    dev[0].set("sae_groups", "20")
1631    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1632              sae_ext_key=True, over_ds=True)
1633    dev[0].set("sae_groups", "")
1634
1635def test_ap_ft_sae_ext_key_21_over_ds(dev, apdev):
1636    """WPA2-FT-SAE-EXT-KEY AP over DS (group 21)"""
1637    hapd0, hapd1 = start_ft_sae(dev[0], apdev, ext_key=True,
1638                                sae_groups="21")
1639    dev[0].set("sae_groups", "21")
1640    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True,
1641              sae_ext_key=True, over_ds=True)
1642    dev[0].set("sae_groups", "")
1643
1644def generic_ap_ft_eap(dev, apdev, vlan=False, cui=False, over_ds=False,
1645                      discovery=False, roams=1, wpa_ptk_rekey=0,
1646                      only_one_way=False):
1647    ssid = "test-ft"
1648    passphrase = "12345678"
1649    if vlan:
1650        identity = "gpsk-vlan1"
1651        conndev = "brvlan1"
1652    elif cui:
1653        identity = "gpsk-cui"
1654        conndev = False
1655    else:
1656        identity = "gpsk user"
1657        conndev = False
1658
1659    radius = hostapd.radius_params()
1660    params = ft_params1(ssid=ssid, passphrase=passphrase, discovery=discovery)
1661    params['wpa_key_mgmt'] = "FT-EAP"
1662    params["ieee8021x"] = "1"
1663    if vlan:
1664        params["dynamic_vlan"] = "1"
1665    params = dict(list(radius.items()) + list(params.items()))
1666    hapd = hostapd.add_ap(apdev[0], params)
1667    key_mgmt = hapd.get_config()['key_mgmt']
1668    if key_mgmt.split(' ')[0] != "FT-EAP":
1669        raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
1670    params = ft_params2(ssid=ssid, passphrase=passphrase, discovery=discovery)
1671    params['wpa_key_mgmt'] = "FT-EAP"
1672    params["ieee8021x"] = "1"
1673    if vlan:
1674        params["dynamic_vlan"] = "1"
1675    if wpa_ptk_rekey:
1676        params["wpa_ptk_rekey"] = str(wpa_ptk_rekey)
1677    params = dict(list(radius.items()) + list(params.items()))
1678    hapd1 = hostapd.add_ap(apdev[1], params)
1679
1680    dev[0].flush_scan_cache()
1681    run_roams(dev[0], apdev, hapd, hapd1, ssid, passphrase, eap=True,
1682              over_ds=over_ds, roams=roams, eap_identity=identity,
1683              conndev=conndev, only_one_way=only_one_way)
1684    if "[WPA2-FT/EAP-CCMP]" not in dev[0].request("SCAN_RESULTS"):
1685        raise Exception("Scan results missing RSN element info")
1686    check_mib(dev[0], [("dot11RSNAAuthenticationSuiteRequested", "00-0f-ac-3"),
1687                       ("dot11RSNAAuthenticationSuiteSelected", "00-0f-ac-3")])
1688    if only_one_way:
1689        return
1690
1691    # Verify EAPOL reauthentication after FT protocol
1692    if dev[0].get_status_field('bssid') == apdev[0]['bssid']:
1693        ap = hapd
1694    else:
1695        ap = hapd1
1696    ap.request("EAPOL_REAUTH " + dev[0].own_addr())
1697    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
1698    if ev is None:
1699        raise Exception("EAP authentication did not start")
1700    ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=5)
1701    if ev is None:
1702        raise Exception("EAP authentication did not succeed")
1703    time.sleep(0.1)
1704    if conndev:
1705        hwsim_utils.test_connectivity_iface(dev[0], ap, conndev)
1706    else:
1707        hwsim_utils.test_connectivity(dev[0], ap)
1708
1709def test_ap_ft_eap(dev, apdev):
1710    """WPA2-EAP-FT AP"""
1711    generic_ap_ft_eap(dev, apdev)
1712
1713def test_ap_ft_eap_cui(dev, apdev):
1714    """WPA2-EAP-FT AP with CUI"""
1715    generic_ap_ft_eap(dev, apdev, vlan=False, cui=True)
1716
1717def test_ap_ft_eap_vlan(dev, apdev):
1718    """WPA2-EAP-FT AP with VLAN"""
1719    generic_ap_ft_eap(dev, apdev, vlan=True)
1720
1721def test_ap_ft_eap_vlan_multi(dev, apdev):
1722    """WPA2-EAP-FT AP with VLAN"""
1723    generic_ap_ft_eap(dev, apdev, vlan=True, roams=50)
1724
1725def test_ap_ft_eap_over_ds(dev, apdev):
1726    """WPA2-EAP-FT AP using over-the-DS"""
1727    generic_ap_ft_eap(dev, apdev, over_ds=True)
1728
1729def test_ap_ft_eap_dis(dev, apdev):
1730    """WPA2-EAP-FT AP with AP discovery"""
1731    generic_ap_ft_eap(dev, apdev, discovery=True)
1732
1733def test_ap_ft_eap_dis_over_ds(dev, apdev):
1734    """WPA2-EAP-FT AP with AP discovery and over-the-DS"""
1735    generic_ap_ft_eap(dev, apdev, over_ds=True, discovery=True)
1736
1737def test_ap_ft_eap_vlan(dev, apdev):
1738    """WPA2-EAP-FT AP with VLAN"""
1739    generic_ap_ft_eap(dev, apdev, vlan=True)
1740
1741def test_ap_ft_eap_vlan_multi(dev, apdev):
1742    """WPA2-EAP-FT AP with VLAN"""
1743    generic_ap_ft_eap(dev, apdev, vlan=True, roams=50)
1744
1745def test_ap_ft_eap_vlan_over_ds(dev, apdev):
1746    """WPA2-EAP-FT AP with VLAN + over_ds"""
1747    generic_ap_ft_eap(dev, apdev, vlan=True, over_ds=True)
1748
1749def test_ap_ft_eap_vlan_over_ds_multi(dev, apdev):
1750    """WPA2-EAP-FT AP with VLAN + over_ds"""
1751    generic_ap_ft_eap(dev, apdev, vlan=True, over_ds=True, roams=50)
1752
1753def generic_ap_ft_eap_pull(dev, apdev, vlan=False):
1754    """WPA2-EAP-FT AP (pull PMK)"""
1755    ssid = "test-ft"
1756    passphrase = "12345678"
1757    if vlan:
1758        identity = "gpsk-vlan1"
1759        conndev = "brvlan1"
1760    else:
1761        identity = "gpsk user"
1762        conndev = False
1763
1764    radius = hostapd.radius_params()
1765    params = ft_params1(ssid=ssid, passphrase=passphrase)
1766    params['wpa_key_mgmt'] = "FT-EAP"
1767    params["ieee8021x"] = "1"
1768    params["pmk_r1_push"] = "0"
1769    if vlan:
1770        params["dynamic_vlan"] = "1"
1771    params = dict(list(radius.items()) + list(params.items()))
1772    hapd = hostapd.add_ap(apdev[0], params)
1773    key_mgmt = hapd.get_config()['key_mgmt']
1774    if key_mgmt.split(' ')[0] != "FT-EAP":
1775        raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
1776    params = ft_params2(ssid=ssid, passphrase=passphrase)
1777    params['wpa_key_mgmt'] = "FT-EAP"
1778    params["ieee8021x"] = "1"
1779    params["pmk_r1_push"] = "0"
1780    if vlan:
1781        params["dynamic_vlan"] = "1"
1782    params = dict(list(radius.items()) + list(params.items()))
1783    hapd1 = hostapd.add_ap(apdev[1], params)
1784
1785    run_roams(dev[0], apdev, hapd, hapd1, ssid, passphrase, eap=True,
1786              eap_identity=identity, conndev=conndev)
1787
1788def test_ap_ft_eap_pull(dev, apdev):
1789    """WPA2-EAP-FT AP (pull PMK)"""
1790    generic_ap_ft_eap_pull(dev, apdev)
1791
1792def test_ap_ft_eap_pull_vlan(dev, apdev):
1793    """WPA2-EAP-FT AP (pull PMK) - with VLAN"""
1794    generic_ap_ft_eap_pull(dev, apdev, vlan=True)
1795
1796def test_ap_ft_eap_pull_wildcard(dev, apdev):
1797    """WPA2-EAP-FT AP (pull PMK) - wildcard R0KH/R1KH"""
1798    ssid = "test-ft"
1799    passphrase = "12345678"
1800
1801    radius = hostapd.radius_params()
1802    params = ft_params1(ssid=ssid, passphrase=passphrase, discovery=True)
1803    params['wpa_key_mgmt'] = "WPA-EAP FT-EAP"
1804    params["ieee8021x"] = "1"
1805    params["pmk_r1_push"] = "0"
1806    params["r0kh"] = "ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
1807    params["r1kh"] = "00:00:00:00:00:00 00:00:00:00:00:00 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
1808    params["ft_psk_generate_local"] = "1"
1809    params["eap_server"] = "0"
1810    params["rkh_pos_timeout"] = "100"
1811    params["rkh_neg_timeout"] = "50"
1812    params["rkh_pull_timeout"] = "1234"
1813    params["rkh_pull_retries"] = "10"
1814    params = dict(list(radius.items()) + list(params.items()))
1815    hapd = hostapd.add_ap(apdev[0], params)
1816    params = ft_params2(ssid=ssid, passphrase=passphrase, discovery=True)
1817    params['wpa_key_mgmt'] = "WPA-EAP FT-EAP"
1818    params["ieee8021x"] = "1"
1819    params["pmk_r1_push"] = "0"
1820    params["r0kh"] = "ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
1821    params["r1kh"] = "00:00:00:00:00:00 00:00:00:00:00:00 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
1822    params["ft_psk_generate_local"] = "1"
1823    params["eap_server"] = "0"
1824    params = dict(list(radius.items()) + list(params.items()))
1825    hapd1 = hostapd.add_ap(apdev[1], params)
1826
1827    run_roams(dev[0], apdev, hapd, hapd1, ssid, passphrase, eap=True)
1828
1829def test_ap_ft_eap_pull_wildcard_multi_bss(dev, apdev, params):
1830    """WPA2-EAP-FT AP (pull PMK) - wildcard R0KH/R1KH with multiple BSSs"""
1831    bssconf = os.path.join(params['logdir'],
1832                           'ap_ft_eap_pull_wildcard_multi_bss.bss.conf')
1833    ssid = "test-ft"
1834    passphrase = "12345678"
1835    radius = hostapd.radius_params()
1836
1837    params = ft_params1(ssid=ssid, passphrase=passphrase, discovery=True)
1838    params['wpa_key_mgmt'] = "WPA-EAP FT-EAP"
1839    params["ieee8021x"] = "1"
1840    params["pmk_r1_push"] = "0"
1841    params["r0kh"] = "ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
1842    params["r1kh"] = "00:00:00:00:00:00 00:00:00:00:00:00 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
1843    params["eap_server"] = "0"
1844    params = dict(list(radius.items()) + list(params.items()))
1845    hapd = hostapd.add_ap(apdev[0], params)
1846    ifname2 = apdev[0]['ifname'] + "-2"
1847    bssid2 = "02:00:00:00:03:01"
1848    params['nas_identifier'] = "nas1b.w1.fi"
1849    params['r1_key_holder'] = "000102030415"
1850    with open(bssconf, 'w') as f:
1851        f.write("driver=nl80211\n")
1852        f.write("hw_mode=g\n")
1853        f.write("channel=1\n")
1854        f.write("ieee80211n=1\n")
1855        f.write("interface=%s\n" % ifname2)
1856        f.write("bssid=%s\n" % bssid2)
1857        f.write("ctrl_interface=/var/run/hostapd\n")
1858
1859        fields = ["ssid", "wpa_passphrase", "nas_identifier", "wpa_key_mgmt",
1860                  "wpa", "rsn_pairwise", "auth_server_addr"]
1861        for name in fields:
1862            f.write("%s=%s\n" % (name, params[name]))
1863        for name, val in params.items():
1864            if name in fields:
1865                continue
1866            f.write("%s=%s\n" % (name, val))
1867    hapd2 = hostapd.add_bss(apdev[0], ifname2, bssconf)
1868
1869    params = ft_params2(ssid=ssid, passphrase=passphrase, discovery=True)
1870    params['wpa_key_mgmt'] = "WPA-EAP FT-EAP"
1871    params["ieee8021x"] = "1"
1872    params["pmk_r1_push"] = "0"
1873    params["r0kh"] = "ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
1874    params["r1kh"] = "00:00:00:00:00:00 00:00:00:00:00:00 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
1875    params["eap_server"] = "0"
1876    params = dict(list(radius.items()) + list(params.items()))
1877    hapd1 = hostapd.add_ap(apdev[1], params)
1878
1879    # The first iteration of the roaming test will use wildcard R0KH discovery
1880    # and RRB sequence number synchronization while the second iteration shows
1881    # the clean RRB exchange where those extra steps are not needed.
1882    for i in range(2):
1883        hapd.note("Test iteration %d" % i)
1884        dev[0].note("Test iteration %d" % i)
1885
1886        id = dev[0].connect(ssid, key_mgmt="FT-EAP", eap="GPSK",
1887                            identity="gpsk user",
1888                            password="abcdefghijklmnop0123456789abcdef",
1889                            bssid=bssid2,
1890                            scan_freq="2412")
1891        res = dev[0].get_status_field("bssid")
1892        if res != bssid2:
1893            raise Exception("Unexpected BSSID after initial connection: " + res)
1894
1895        dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
1896        dev[0].set_network(id, "bssid", "00:00:00:00:00:00")
1897        dev[0].roam(apdev[1]['bssid'])
1898        res = dev[0].get_status_field("bssid")
1899        if res != apdev[1]['bssid']:
1900            raise Exception("Unexpected BSSID after first roam: " + res)
1901
1902        dev[0].scan_for_bss(apdev[0]['bssid'], freq="2412")
1903        dev[0].roam(apdev[0]['bssid'])
1904        res = dev[0].get_status_field("bssid")
1905        if res != apdev[0]['bssid']:
1906            raise Exception("Unexpected BSSID after second roam: " + res)
1907
1908        dev[0].request("REMOVE_NETWORK all")
1909        dev[0].wait_disconnected()
1910        dev[0].dump_monitor()
1911        hapd.dump_monitor()
1912        hapd2.dump_monitor()
1913
1914@remote_compatible
1915def test_ap_ft_mismatching_rrb_key_push(dev, apdev):
1916    """WPA2-PSK-FT AP over DS with mismatching RRB key (push)"""
1917    ssid = "test-ft"
1918    passphrase = "12345678"
1919
1920    params = ft_params1(ssid=ssid, passphrase=passphrase)
1921    params["ieee80211w"] = "2"
1922    hapd0 = hostapd.add_ap(apdev[0], params)
1923    params = ft_params2_incorrect_rrb_key(ssid=ssid, passphrase=passphrase)
1924    params["ieee80211w"] = "2"
1925    hapd1 = hostapd.add_ap(apdev[1], params)
1926
1927    dev[0].flush_scan_cache()
1928    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
1929              fail_test=True)
1930
1931@remote_compatible
1932def test_ap_ft_mismatching_rrb_key_pull(dev, apdev):
1933    """WPA2-PSK-FT AP over DS with mismatching RRB key (pull)"""
1934    ssid = "test-ft"
1935    passphrase = "12345678"
1936
1937    params = ft_params1(ssid=ssid, passphrase=passphrase)
1938    params["pmk_r1_push"] = "0"
1939    hapd0 = hostapd.add_ap(apdev[0], params)
1940    params = ft_params2_incorrect_rrb_key(ssid=ssid, passphrase=passphrase)
1941    params["pmk_r1_push"] = "0"
1942    hapd1 = hostapd.add_ap(apdev[1], params)
1943
1944    dev[0].flush_scan_cache()
1945    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
1946              fail_test=True)
1947
1948@remote_compatible
1949def test_ap_ft_mismatching_r0kh_id_pull(dev, apdev):
1950    """WPA2-PSK-FT AP over DS with mismatching R0KH-ID (pull)"""
1951    ssid = "test-ft"
1952    passphrase = "12345678"
1953
1954    params = ft_params1(ssid=ssid, passphrase=passphrase)
1955    params["pmk_r1_push"] = "0"
1956    params["nas_identifier"] = "nas0.w1.fi"
1957    hostapd.add_ap(apdev[0], params)
1958    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
1959                   scan_freq="2412")
1960
1961    params = ft_params2(ssid=ssid, passphrase=passphrase)
1962    params["pmk_r1_push"] = "0"
1963    hostapd.add_ap(apdev[1], params)
1964
1965    dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
1966    dev[0].roam_over_ds(apdev[1]['bssid'], fail_test=True)
1967
1968@remote_compatible
1969def test_ap_ft_mismatching_rrb_r0kh_push(dev, apdev):
1970    """WPA2-PSK-FT AP over DS with mismatching R0KH key (push)"""
1971    ssid = "test-ft"
1972    passphrase = "12345678"
1973
1974    params = ft_params1(ssid=ssid, passphrase=passphrase)
1975    params["ieee80211w"] = "2"
1976    hapd0 = hostapd.add_ap(apdev[0], params)
1977    params = ft_params2_r0kh_mismatch(ssid=ssid, passphrase=passphrase)
1978    params["ieee80211w"] = "2"
1979    hapd1 = hostapd.add_ap(apdev[1], params)
1980
1981    dev[0].flush_scan_cache()
1982    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
1983              fail_test=True)
1984
1985@remote_compatible
1986def test_ap_ft_mismatching_rrb_r0kh_pull(dev, apdev):
1987    """WPA2-PSK-FT AP over DS with mismatching R0KH key (pull)"""
1988    ssid = "test-ft"
1989    passphrase = "12345678"
1990
1991    params = ft_params1_r0kh_mismatch(ssid=ssid, passphrase=passphrase)
1992    params["pmk_r1_push"] = "0"
1993    hapd0 = hostapd.add_ap(apdev[0], params)
1994    params = ft_params2(ssid=ssid, passphrase=passphrase)
1995    params["pmk_r1_push"] = "0"
1996    hapd1 = hostapd.add_ap(apdev[1], params)
1997
1998    dev[0].flush_scan_cache()
1999    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
2000              fail_test=True)
2001
2002def test_ap_ft_mismatching_rrb_key_push_eap(dev, apdev):
2003    """WPA2-EAP-FT AP over DS with mismatching RRB key (push)"""
2004    ssid = "test-ft"
2005    passphrase = "12345678"
2006
2007    radius = hostapd.radius_params()
2008    params = ft_params1(ssid=ssid, passphrase=passphrase)
2009    params["ieee80211w"] = "2"
2010    params['wpa_key_mgmt'] = "FT-EAP"
2011    params["ieee8021x"] = "1"
2012    params = dict(list(radius.items()) + list(params.items()))
2013    hapd0 = hostapd.add_ap(apdev[0], params)
2014    params = ft_params2_incorrect_rrb_key(ssid=ssid, passphrase=passphrase)
2015    params["ieee80211w"] = "2"
2016    params['wpa_key_mgmt'] = "FT-EAP"
2017    params["ieee8021x"] = "1"
2018    params = dict(list(radius.items()) + list(params.items()))
2019    hapd1 = hostapd.add_ap(apdev[1], params)
2020
2021    dev[0].flush_scan_cache()
2022    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
2023              fail_test=True, eap=True)
2024
2025def test_ap_ft_mismatching_rrb_key_pull_eap(dev, apdev):
2026    """WPA2-EAP-FT AP over DS with mismatching RRB key (pull)"""
2027    ssid = "test-ft"
2028    passphrase = "12345678"
2029
2030    radius = hostapd.radius_params()
2031    params = ft_params1(ssid=ssid, passphrase=passphrase)
2032    params["pmk_r1_push"] = "0"
2033    params['wpa_key_mgmt'] = "FT-EAP"
2034    params["ieee8021x"] = "1"
2035    params = dict(list(radius.items()) + list(params.items()))
2036    hapd0 = hostapd.add_ap(apdev[0], params)
2037    params = ft_params2_incorrect_rrb_key(ssid=ssid, passphrase=passphrase)
2038    params["pmk_r1_push"] = "0"
2039    params['wpa_key_mgmt'] = "FT-EAP"
2040    params["ieee8021x"] = "1"
2041    params = dict(list(radius.items()) + list(params.items()))
2042    hapd1 = hostapd.add_ap(apdev[1], params)
2043
2044    dev[0].flush_scan_cache()
2045    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
2046              fail_test=True, eap=True)
2047
2048def test_ap_ft_mismatching_r0kh_id_pull_eap(dev, apdev):
2049    """WPA2-EAP-FT AP over DS with mismatching R0KH-ID (pull)"""
2050    ssid = "test-ft"
2051    passphrase = "12345678"
2052
2053    radius = hostapd.radius_params()
2054    params = ft_params1(ssid=ssid, passphrase=passphrase)
2055    params["pmk_r1_push"] = "0"
2056    params["nas_identifier"] = "nas0.w1.fi"
2057    params['wpa_key_mgmt'] = "FT-EAP"
2058    params["ieee8021x"] = "1"
2059    params = dict(list(radius.items()) + list(params.items()))
2060    hostapd.add_ap(apdev[0], params)
2061    dev[0].connect(ssid, key_mgmt="FT-EAP", proto="WPA2", ieee80211w="1",
2062                   eap="GPSK", identity="gpsk user",
2063                   password="abcdefghijklmnop0123456789abcdef",
2064                   scan_freq="2412")
2065
2066    params = ft_params2(ssid=ssid, passphrase=passphrase)
2067    params["pmk_r1_push"] = "0"
2068    params['wpa_key_mgmt'] = "FT-EAP"
2069    params["ieee8021x"] = "1"
2070    params = dict(list(radius.items()) + list(params.items()))
2071    hostapd.add_ap(apdev[1], params)
2072
2073    dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
2074    dev[0].roam_over_ds(apdev[1]['bssid'], fail_test=True)
2075
2076def test_ap_ft_mismatching_rrb_r0kh_push_eap(dev, apdev):
2077    """WPA2-EAP-FT AP over DS with mismatching R0KH key (push)"""
2078    ssid = "test-ft"
2079    passphrase = "12345678"
2080
2081    radius = hostapd.radius_params()
2082    params = ft_params1(ssid=ssid, passphrase=passphrase)
2083    params["ieee80211w"] = "2"
2084    params['wpa_key_mgmt'] = "FT-EAP"
2085    params["ieee8021x"] = "1"
2086    params = dict(list(radius.items()) + list(params.items()))
2087    hapd0 = hostapd.add_ap(apdev[0], params)
2088    params = ft_params2_r0kh_mismatch(ssid=ssid, passphrase=passphrase)
2089    params["ieee80211w"] = "2"
2090    params['wpa_key_mgmt'] = "FT-EAP"
2091    params["ieee8021x"] = "1"
2092    params = dict(list(radius.items()) + list(params.items()))
2093    hapd1 = hostapd.add_ap(apdev[1], params)
2094
2095    dev[0].flush_scan_cache()
2096    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
2097              fail_test=True, eap=True)
2098
2099def test_ap_ft_mismatching_rrb_r0kh_pull_eap(dev, apdev):
2100    """WPA2-EAP-FT AP over DS with mismatching R0KH key (pull)"""
2101    ssid = "test-ft"
2102    passphrase = "12345678"
2103
2104    radius = hostapd.radius_params()
2105    params = ft_params1_r0kh_mismatch(ssid=ssid, passphrase=passphrase)
2106    params["pmk_r1_push"] = "0"
2107    params['wpa_key_mgmt'] = "FT-EAP"
2108    params["ieee8021x"] = "1"
2109    params = dict(list(radius.items()) + list(params.items()))
2110    hapd0 = hostapd.add_ap(apdev[0], params)
2111    params = ft_params2(ssid=ssid, passphrase=passphrase)
2112    params["pmk_r1_push"] = "0"
2113    params['wpa_key_mgmt'] = "FT-EAP"
2114    params["ieee8021x"] = "1"
2115    params = dict(list(radius.items()) + list(params.items()))
2116    hapd1 = hostapd.add_ap(apdev[1], params)
2117
2118    dev[0].flush_scan_cache()
2119    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
2120              fail_test=True, eap=True)
2121
2122def test_ap_ft_gtk_rekey(dev, apdev):
2123    """WPA2-PSK-FT AP and GTK rekey"""
2124    ssid = "test-ft"
2125    passphrase = "12345678"
2126
2127    params = ft_params1(ssid=ssid, passphrase=passphrase)
2128    params['wpa_group_rekey'] = '1'
2129    hapd = hostapd.add_ap(apdev[0], params)
2130
2131    dev[0].flush_scan_cache()
2132    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2133                   ieee80211w="1", scan_freq="2412")
2134
2135    ev = dev[0].wait_event(["RSN: Group rekeying completed"], timeout=2)
2136    if ev is None:
2137        raise Exception("GTK rekey timed out after initial association")
2138    hwsim_utils.test_connectivity(dev[0], hapd)
2139
2140    params = ft_params2(ssid=ssid, passphrase=passphrase)
2141    params['wpa_group_rekey'] = '1'
2142    hapd1 = hostapd.add_ap(apdev[1], params)
2143
2144    dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
2145    dev[0].roam(apdev[1]['bssid'])
2146    if dev[0].get_status_field('bssid') != apdev[1]['bssid']:
2147        raise Exception("Did not connect to correct AP")
2148    hwsim_utils.test_connectivity(dev[0], hapd1)
2149
2150    ev = dev[0].wait_event(["RSN: Group rekeying completed"], timeout=2)
2151    if ev is None:
2152        raise Exception("GTK rekey timed out after FT protocol")
2153    hwsim_utils.test_connectivity(dev[0], hapd1)
2154
2155def test_ft_psk_key_lifetime_in_memory(dev, apdev, params):
2156    """WPA2-PSK-FT and key lifetime in memory"""
2157    ssid = "test-ft"
2158    passphrase = "04c2726b4b8d5f1b4db9c07aa4d9e9d8f765cb5d25ec817e6cc4fcdd5255db0"
2159    psk = '93c90846ff67af9037ed83fb72b63dbeddaa81d47f926c20909b5886f1d9358d'
2160    pmk = binascii.unhexlify(psk)
2161    p = ft_params1(ssid=ssid, passphrase=passphrase)
2162    hapd0 = hostapd.add_ap(apdev[0], p)
2163    p = ft_params2(ssid=ssid, passphrase=passphrase)
2164    hapd1 = hostapd.add_ap(apdev[1], p)
2165
2166    pid = find_wpas_process(dev[0])
2167
2168    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2169                   scan_freq="2412")
2170    # The decrypted copy of GTK is freed only after the CTRL-EVENT-CONNECTED
2171    # event has been delivered, so verify that wpa_supplicant has returned to
2172    # eloop before reading process memory.
2173    time.sleep(1)
2174    dev[0].ping()
2175
2176    buf = read_process_memory(pid, pmk)
2177
2178    dev[0].request("DISCONNECT")
2179    dev[0].wait_disconnected()
2180
2181    dev[0].relog()
2182    pmkr0 = None
2183    pmkr1 = None
2184    ptk = None
2185    gtk = None
2186    with open(os.path.join(params['logdir'], 'log0'), 'r') as f:
2187        for l in f.readlines():
2188            if "FT: PMK-R0 - hexdump" in l:
2189                val = l.strip().split(':')[3].replace(' ', '')
2190                pmkr0 = binascii.unhexlify(val)
2191            if "FT: PMK-R1 - hexdump" in l:
2192                val = l.strip().split(':')[3].replace(' ', '')
2193                pmkr1 = binascii.unhexlify(val)
2194            if "FT: KCK - hexdump" in l:
2195                val = l.strip().split(':')[3].replace(' ', '')
2196                kck = binascii.unhexlify(val)
2197            if "FT: KEK - hexdump" in l:
2198                val = l.strip().split(':')[3].replace(' ', '')
2199                kek = binascii.unhexlify(val)
2200            if "FT: TK - hexdump" in l:
2201                val = l.strip().split(':')[3].replace(' ', '')
2202                tk = binascii.unhexlify(val)
2203            if "WPA: Group Key - hexdump" in l:
2204                val = l.strip().split(':')[3].replace(' ', '')
2205                gtk = binascii.unhexlify(val)
2206    if not pmkr0 or not pmkr1 or not kck or not kek or not tk or not gtk:
2207        raise Exception("Could not find keys from debug log")
2208    if len(gtk) != 16:
2209        raise Exception("Unexpected GTK length")
2210
2211    logger.info("Checking keys in memory while associated")
2212    get_key_locations(buf, pmk, "PMK")
2213    get_key_locations(buf, pmkr0, "PMK-R0")
2214    get_key_locations(buf, pmkr1, "PMK-R1")
2215    if pmk not in buf:
2216        raise HwsimSkip("PMK not found while associated")
2217    if pmkr0 not in buf:
2218        raise HwsimSkip("PMK-R0 not found while associated")
2219    if pmkr1 not in buf:
2220        raise HwsimSkip("PMK-R1 not found while associated")
2221    if kck not in buf:
2222        raise Exception("KCK not found while associated")
2223    if kek not in buf:
2224        raise Exception("KEK not found while associated")
2225    #if tk in buf:
2226    #    raise Exception("TK found from memory")
2227
2228    logger.info("Checking keys in memory after disassociation")
2229    buf = read_process_memory(pid, pmk)
2230    get_key_locations(buf, pmk, "PMK")
2231    get_key_locations(buf, pmkr0, "PMK-R0")
2232    get_key_locations(buf, pmkr1, "PMK-R1")
2233
2234    # Note: PMK/PSK is still present in network configuration
2235
2236    fname = os.path.join(params['logdir'],
2237                         'ft_psk_key_lifetime_in_memory.memctx-')
2238    verify_not_present(buf, pmkr0, fname, "PMK-R0")
2239    verify_not_present(buf, pmkr1, fname, "PMK-R1")
2240    verify_not_present(buf, kck, fname, "KCK")
2241    verify_not_present(buf, kek, fname, "KEK")
2242    verify_not_present(buf, tk, fname, "TK")
2243    if gtk in buf:
2244        get_key_locations(buf, gtk, "GTK")
2245    verify_not_present(buf, gtk, fname, "GTK")
2246
2247    dev[0].request("REMOVE_NETWORK all")
2248
2249    logger.info("Checking keys in memory after network profile removal")
2250    buf = read_process_memory(pid, pmk)
2251    get_key_locations(buf, pmk, "PMK")
2252    get_key_locations(buf, pmkr0, "PMK-R0")
2253    get_key_locations(buf, pmkr1, "PMK-R1")
2254
2255    verify_not_present(buf, pmk, fname, "PMK")
2256    verify_not_present(buf, pmkr0, fname, "PMK-R0")
2257    verify_not_present(buf, pmkr1, fname, "PMK-R1")
2258    verify_not_present(buf, kck, fname, "KCK")
2259    verify_not_present(buf, kek, fname, "KEK")
2260    verify_not_present(buf, tk, fname, "TK")
2261    verify_not_present(buf, gtk, fname, "GTK")
2262
2263@remote_compatible
2264def test_ap_ft_invalid_resp(dev, apdev):
2265    """WPA2-PSK-FT AP and invalid response IEs"""
2266    ssid = "test-ft"
2267    passphrase = "12345678"
2268
2269    params = ft_params1(ssid=ssid, passphrase=passphrase)
2270    hapd0 = hostapd.add_ap(apdev[0], params)
2271    dev[0].flush_scan_cache()
2272    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2273                   scan_freq="2412")
2274
2275    params = ft_params2(ssid=ssid, passphrase=passphrase)
2276    hapd1 = hostapd.add_ap(apdev[1], params)
2277
2278    tests = [
2279        # Various IEs for test coverage. The last one is FTIE with invalid
2280        # R1KH-ID subelement.
2281        "020002000000" + "3800" + "38051122334455" + "3754000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010100",
2282        # FTIE with invalid R0KH-ID subelement (len=0).
2283        "020002000000" + "3754000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010300",
2284        # FTIE with invalid R0KH-ID subelement (len=49).
2285        "020002000000" + "378500010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001033101020304050607080910111213141516171819202122232425262728293031323334353637383940414243444546474849",
2286        # Invalid RSNE.
2287        "020002000000" + "3000",
2288        # Required IEs missing from protected IE count.
2289        "020002000000" + "3603a1b201" + "375200010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001" + "3900",
2290        # RIC missing from protected IE count.
2291        "020002000000" + "3603a1b201" + "375200020203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001" + "3900",
2292        # Protected IE missing.
2293        "020002000000" + "3603a1b201" + "375200ff0203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001" + "3900" + "0000"]
2294    for t in tests:
2295        dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
2296        hapd1.set("ext_mgmt_frame_handling", "1")
2297        hapd1.dump_monitor()
2298        if "OK" not in dev[0].request("ROAM " + apdev[1]['bssid']):
2299            raise Exception("ROAM failed")
2300        auth = None
2301        for i in range(20):
2302            msg = hapd1.mgmt_rx()
2303            if msg['subtype'] == 11:
2304                auth = msg
2305                break
2306        if not auth:
2307            raise Exception("Authentication frame not seen")
2308
2309        resp = {}
2310        resp['fc'] = auth['fc']
2311        resp['da'] = auth['sa']
2312        resp['sa'] = auth['da']
2313        resp['bssid'] = auth['bssid']
2314        resp['payload'] = binascii.unhexlify(t)
2315        hapd1.mgmt_tx(resp)
2316        hapd1.set("ext_mgmt_frame_handling", "0")
2317        dev[0].wait_disconnected()
2318
2319        dev[0].request("RECONNECT")
2320        dev[0].wait_connected()
2321
2322def test_ap_ft_gcmp_256(dev, apdev):
2323    """WPA2-PSK-FT AP with GCMP-256 cipher"""
2324    if "GCMP-256" not in dev[0].get_capability("pairwise"):
2325        raise HwsimSkip("Cipher GCMP-256 not supported")
2326    ssid = "test-ft"
2327    passphrase = "12345678"
2328
2329    params = ft_params1(ssid=ssid, passphrase=passphrase)
2330    params['rsn_pairwise'] = "GCMP-256"
2331    hapd0 = hostapd.add_ap(apdev[0], params)
2332    params = ft_params2(ssid=ssid, passphrase=passphrase)
2333    params['rsn_pairwise'] = "GCMP-256"
2334    hapd1 = hostapd.add_ap(apdev[1], params)
2335
2336    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase,
2337              pairwise_cipher="GCMP-256", group_cipher="GCMP-256")
2338
2339def setup_ap_ft_oom(dev, apdev):
2340    skip_with_fips(dev[0])
2341    ssid = "test-ft"
2342    passphrase = "12345678"
2343
2344    params = ft_params1(ssid=ssid, passphrase=passphrase)
2345    hapd0 = hostapd.add_ap(apdev[0], params)
2346    params = ft_params2(ssid=ssid, passphrase=passphrase)
2347    hapd1 = hostapd.add_ap(apdev[1], params)
2348
2349    dev[0].flush_scan_cache()
2350    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2351                   scan_freq="2412")
2352    if dev[0].get_status_field('bssid') == apdev[0]['bssid']:
2353        dst = apdev[1]['bssid']
2354    else:
2355        dst = apdev[0]['bssid']
2356
2357    dev[0].scan_for_bss(dst, freq="2412")
2358
2359    return dst
2360
2361def test_ap_ft_oom(dev, apdev):
2362    """WPA2-PSK-FT and OOM"""
2363    dst = setup_ap_ft_oom(dev, apdev)
2364    with alloc_fail(dev[0], 1, "wpa_ft_gen_req_ies"):
2365        dev[0].roam(dst, check_bssid=False, fail_test=True)
2366
2367def test_ap_ft_oom2(dev, apdev):
2368    """WPA2-PSK-FT and OOM (2)"""
2369    dst = setup_ap_ft_oom(dev, apdev)
2370    with fail_test(dev[0], 1, "wpa_ft_mic"):
2371        dev[0].roam(dst, fail_test=True, assoc_reject_ok=True)
2372
2373def test_ap_ft_oom3(dev, apdev):
2374    """WPA2-PSK-FT and OOM (3)"""
2375    dst = setup_ap_ft_oom(dev, apdev)
2376    with fail_test(dev[0], 1, "os_get_random;wpa_ft_prepare_auth_request"):
2377        dev[0].roam(dst)
2378
2379def test_ap_ft_oom4(dev, apdev):
2380    """WPA2-PSK-FT and OOM (4)"""
2381    ssid = "test-ft"
2382    passphrase = "12345678"
2383    dst = setup_ap_ft_oom(dev, apdev)
2384    dev[0].request("REMOVE_NETWORK all")
2385    with alloc_fail(dev[0], 1, "=sme_update_ft_ies"):
2386        dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2387                       scan_freq="2412")
2388
2389def test_ap_ft_ap_oom(dev, apdev):
2390    """WPA2-PSK-FT and AP OOM"""
2391    ssid = "test-ft"
2392    passphrase = "12345678"
2393
2394    params = ft_params1(ssid=ssid, passphrase=passphrase)
2395    hapd0 = hostapd.add_ap(apdev[0], params)
2396    bssid0 = hapd0.own_addr()
2397
2398    dev[0].flush_scan_cache()
2399    dev[0].scan_for_bss(bssid0, freq="2412")
2400    with alloc_fail(hapd0, 1, "wpa_ft_store_pmk_r0"):
2401        dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2402                       scan_freq="2412")
2403
2404    params = ft_params2(ssid=ssid, passphrase=passphrase)
2405    hapd1 = hostapd.add_ap(apdev[1], params)
2406    bssid1 = hapd1.own_addr()
2407    dev[0].scan_for_bss(bssid1, freq="2412")
2408    # This roam will fail due to missing PMK-R0 (OOM prevented storing it)
2409    dev[0].roam(bssid1, check_bssid=False)
2410
2411def test_ap_ft_ap_oom2(dev, apdev):
2412    """WPA2-PSK-FT and AP OOM 2"""
2413    ssid = "test-ft"
2414    passphrase = "12345678"
2415
2416    params = ft_params1(ssid=ssid, passphrase=passphrase)
2417    hapd0 = hostapd.add_ap(apdev[0], params)
2418    bssid0 = hapd0.own_addr()
2419
2420    dev[0].flush_scan_cache()
2421    dev[0].scan_for_bss(bssid0, freq="2412")
2422    with alloc_fail(hapd0, 1, "wpa_ft_store_pmk_r1"):
2423        dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2424                       scan_freq="2412")
2425
2426    params = ft_params2(ssid=ssid, passphrase=passphrase)
2427    hapd1 = hostapd.add_ap(apdev[1], params)
2428    bssid1 = hapd1.own_addr()
2429    dev[0].scan_for_bss(bssid1, freq="2412")
2430    dev[0].roam(bssid1)
2431    if dev[0].get_status_field('bssid') != bssid1:
2432        raise Exception("Did not roam to AP1")
2433    # This roam will fail due to missing PMK-R1 (OOM prevented storing it)
2434    dev[0].roam(bssid0)
2435
2436def test_ap_ft_ap_oom3(dev, apdev):
2437    """WPA2-PSK-FT and AP OOM 3"""
2438    ssid = "test-ft"
2439    passphrase = "12345678"
2440
2441    params = ft_params1(ssid=ssid, passphrase=passphrase)
2442    hapd0 = hostapd.add_ap(apdev[0], params)
2443    bssid0 = hapd0.own_addr()
2444
2445    dev[0].flush_scan_cache()
2446    dev[0].scan_for_bss(bssid0, freq="2412")
2447    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2448                   scan_freq="2412")
2449
2450    params = ft_params2(ssid=ssid, passphrase=passphrase)
2451    hapd1 = hostapd.add_ap(apdev[1], params)
2452    bssid1 = hapd1.own_addr()
2453    dev[0].scan_for_bss(bssid1, freq="2412")
2454    with alloc_fail(hapd1, 1, "wpa_ft_pull_pmk_r1"):
2455        # This will fail due to not being able to send out PMK-R1 pull request
2456        dev[0].roam(bssid1, check_bssid=False)
2457
2458    with fail_test(hapd1, 2, "os_get_random;wpa_ft_pull_pmk_r1"):
2459        # This will fail due to not being able to send out PMK-R1 pull request
2460        dev[0].roam(bssid1, check_bssid=False)
2461
2462    with fail_test(hapd1, 2, "aes_siv_encrypt;wpa_ft_pull_pmk_r1"):
2463        # This will fail due to not being able to send out PMK-R1 pull request
2464        dev[0].roam(bssid1, check_bssid=False)
2465
2466def test_ap_ft_ap_oom3b(dev, apdev):
2467    """WPA2-PSK-FT and AP OOM 3b"""
2468    ssid = "test-ft"
2469    passphrase = "12345678"
2470
2471    params = ft_params1(ssid=ssid, passphrase=passphrase)
2472    hapd0 = hostapd.add_ap(apdev[0], params)
2473    bssid0 = hapd0.own_addr()
2474
2475    dev[0].scan_for_bss(bssid0, freq="2412")
2476    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2477                   scan_freq="2412")
2478
2479    params = ft_params2(ssid=ssid, passphrase=passphrase)
2480    hapd1 = hostapd.add_ap(apdev[1], params)
2481    bssid1 = hapd1.own_addr()
2482    dev[0].scan_for_bss(bssid1, freq="2412")
2483    with fail_test(hapd1, 1, "os_get_random;wpa_ft_pull_pmk_r1"):
2484        # This will fail due to not being able to send out PMK-R1 pull request
2485        dev[0].roam(bssid1)
2486
2487def test_ap_ft_ap_oom4(dev, apdev):
2488    """WPA2-PSK-FT and AP OOM 4"""
2489    ssid = "test-ft"
2490    passphrase = "12345678"
2491
2492    params = ft_params1(ssid=ssid, passphrase=passphrase)
2493    hapd0 = hostapd.add_ap(apdev[0], params)
2494    bssid0 = hapd0.own_addr()
2495
2496    dev[0].flush_scan_cache()
2497    dev[0].scan_for_bss(bssid0, freq="2412")
2498    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2499                   scan_freq="2412")
2500
2501    params = ft_params2(ssid=ssid, passphrase=passphrase)
2502    hapd1 = hostapd.add_ap(apdev[1], params)
2503    bssid1 = hapd1.own_addr()
2504    dev[0].scan_for_bss(bssid1, freq="2412")
2505    with alloc_fail(hapd1, 1, "wpa_ft_gtk_subelem"):
2506        dev[0].roam(bssid1)
2507        if dev[0].get_status_field('bssid') != bssid1:
2508            raise Exception("Did not roam to AP1")
2509
2510    with fail_test(hapd0, 1, "i802_get_seqnum;wpa_ft_gtk_subelem"):
2511        dev[0].roam(bssid0)
2512        if dev[0].get_status_field('bssid') != bssid0:
2513            raise Exception("Did not roam to AP0")
2514
2515    with fail_test(hapd0, 1, "aes_wrap;wpa_ft_gtk_subelem"):
2516        dev[0].roam(bssid1)
2517        if dev[0].get_status_field('bssid') != bssid1:
2518            raise Exception("Did not roam to AP1")
2519
2520def test_ap_ft_ap_oom5(dev, apdev):
2521    """WPA2-PSK-FT and AP OOM 5"""
2522    ssid = "test-ft"
2523    passphrase = "12345678"
2524
2525    params = ft_params1(ssid=ssid, passphrase=passphrase)
2526    hapd0 = hostapd.add_ap(apdev[0], params)
2527    bssid0 = hapd0.own_addr()
2528
2529    dev[0].flush_scan_cache()
2530    dev[0].scan_for_bss(bssid0, freq="2412")
2531    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2532                   scan_freq="2412")
2533
2534    params = ft_params2(ssid=ssid, passphrase=passphrase)
2535    hapd1 = hostapd.add_ap(apdev[1], params)
2536    bssid1 = hapd1.own_addr()
2537    dev[0].scan_for_bss(bssid1, freq="2412")
2538    with alloc_fail(hapd1, 1, "=wpa_ft_process_auth_req"):
2539        # This will fail to roam
2540        dev[0].roam(bssid1, check_bssid=False)
2541
2542    with fail_test(hapd1, 1, "os_get_random;wpa_ft_process_auth_req"):
2543        # This will fail to roam
2544        dev[0].roam(bssid1, check_bssid=False)
2545
2546    with fail_test(hapd1, 1, "sha256_prf_bits;wpa_pmk_r1_to_ptk;wpa_ft_process_auth_req"):
2547        # This will fail to roam
2548        dev[0].roam(bssid1, check_bssid=False)
2549
2550    with fail_test(hapd1, 3, "wpa_pmk_r1_to_ptk;wpa_ft_process_auth_req"):
2551        # This will fail to roam
2552        dev[0].roam(bssid1, check_bssid=False)
2553
2554    with fail_test(hapd1, 1, "wpa_derive_pmk_r1_name;wpa_ft_process_auth_req"):
2555        # This will fail to roam
2556        dev[0].roam(bssid1, check_bssid=False)
2557
2558def test_ap_ft_ap_oom6(dev, apdev):
2559    """WPA2-PSK-FT and AP OOM 6"""
2560    ssid = "test-ft"
2561    passphrase = "12345678"
2562
2563    params = ft_params1(ssid=ssid, passphrase=passphrase)
2564    hapd0 = hostapd.add_ap(apdev[0], params)
2565    bssid0 = hapd0.own_addr()
2566
2567    dev[0].scan_for_bss(bssid0, freq="2412")
2568    with fail_test(hapd0, 1, "wpa_derive_pmk_r0;wpa_auth_derive_ptk_ft"):
2569        dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2570                       scan_freq="2412")
2571    dev[0].request("REMOVE_NETWORK all")
2572    dev[0].wait_disconnected()
2573    with fail_test(hapd0, 1, "wpa_derive_pmk_r1;wpa_auth_derive_ptk_ft"):
2574        dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2575                       scan_freq="2412")
2576    dev[0].request("REMOVE_NETWORK all")
2577    dev[0].wait_disconnected()
2578    with fail_test(hapd0, 1, "wpa_pmk_r1_to_ptk;wpa_auth_derive_ptk_ft"):
2579        dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2580                       scan_freq="2412")
2581
2582def test_ap_ft_ap_oom7a(dev, apdev):
2583    """WPA2-PSK-FT and AP OOM 7a"""
2584    ssid = "test-ft"
2585    passphrase = "12345678"
2586
2587    params = ft_params1(ssid=ssid, passphrase=passphrase)
2588    params["ieee80211w"] = "2"
2589    hapd0 = hostapd.add_ap(apdev[0], params)
2590    bssid0 = hapd0.own_addr()
2591
2592    dev[0].flush_scan_cache()
2593    dev[0].scan_for_bss(bssid0, freq="2412")
2594    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2595                   ieee80211w="2", scan_freq="2412")
2596
2597    params = ft_params2(ssid=ssid, passphrase=passphrase)
2598    params["ieee80211w"] = "2"
2599    hapd1 = hostapd.add_ap(apdev[1], params)
2600    bssid1 = hapd1.own_addr()
2601    dev[0].scan_for_bss(bssid1, freq="2412")
2602    with alloc_fail(hapd1, 1, "wpa_ft_igtk_subelem"):
2603        # This will fail to roam
2604        dev[0].roam(bssid1)
2605
2606def test_ap_ft_ap_oom7b(dev, apdev):
2607    """WPA2-PSK-FT and AP OOM 7b"""
2608    ssid = "test-ft"
2609    passphrase = "12345678"
2610
2611    params = ft_params1(ssid=ssid, passphrase=passphrase)
2612    params["ieee80211w"] = "2"
2613    hapd0 = hostapd.add_ap(apdev[0], params)
2614    bssid0 = hapd0.own_addr()
2615
2616    dev[0].flush_scan_cache()
2617    dev[0].scan_for_bss(bssid0, freq="2412")
2618    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2619                   ieee80211w="2", scan_freq="2412")
2620
2621    params = ft_params2(ssid=ssid, passphrase=passphrase)
2622    params["ieee80211w"] = "2"
2623    hapd1 = hostapd.add_ap(apdev[1], params)
2624    bssid1 = hapd1.own_addr()
2625    dev[0].scan_for_bss(bssid1, freq="2412")
2626    with fail_test(hapd1, 1, "aes_wrap;wpa_ft_igtk_subelem"):
2627        # This will fail to roam
2628        dev[0].roam(bssid1)
2629
2630def test_ap_ft_ap_oom7c(dev, apdev):
2631    """WPA2-PSK-FT and AP OOM 7c"""
2632    ssid = "test-ft"
2633    passphrase = "12345678"
2634
2635    params = ft_params1(ssid=ssid, passphrase=passphrase)
2636    params["ieee80211w"] = "2"
2637    hapd0 = hostapd.add_ap(apdev[0], params)
2638    bssid0 = hapd0.own_addr()
2639
2640    dev[0].flush_scan_cache()
2641    dev[0].scan_for_bss(bssid0, freq="2412")
2642    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2643                   ieee80211w="2", scan_freq="2412")
2644
2645    params = ft_params2(ssid=ssid, passphrase=passphrase)
2646    params["ieee80211w"] = "2"
2647    hapd1 = hostapd.add_ap(apdev[1], params)
2648    bssid1 = hapd1.own_addr()
2649    dev[0].scan_for_bss(bssid1, freq="2412")
2650    with alloc_fail(hapd1, 1, "=wpa_sm_write_assoc_resp_ies"):
2651        # This will fail to roam
2652        dev[0].roam(bssid1)
2653
2654def test_ap_ft_ap_oom7d(dev, apdev):
2655    """WPA2-PSK-FT and AP OOM 7d"""
2656    ssid = "test-ft"
2657    passphrase = "12345678"
2658
2659    params = ft_params1(ssid=ssid, passphrase=passphrase)
2660    params["ieee80211w"] = "2"
2661    hapd0 = hostapd.add_ap(apdev[0], params)
2662    bssid0 = hapd0.own_addr()
2663
2664    dev[0].flush_scan_cache()
2665    dev[0].scan_for_bss(bssid0, freq="2412")
2666    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2667                   ieee80211w="2", scan_freq="2412")
2668
2669    params = ft_params2(ssid=ssid, passphrase=passphrase)
2670    params["ieee80211w"] = "2"
2671    hapd1 = hostapd.add_ap(apdev[1], params)
2672    bssid1 = hapd1.own_addr()
2673    dev[0].scan_for_bss(bssid1, freq="2412")
2674    with fail_test(hapd1, 1, "wpa_ft_mic;wpa_sm_write_assoc_resp_ies"):
2675        # This will fail to roam
2676        dev[0].roam(bssid1)
2677
2678def test_ap_ft_ap_oom8(dev, apdev):
2679    """WPA2-PSK-FT and AP OOM 8"""
2680    ssid = "test-ft"
2681    passphrase = "12345678"
2682
2683    params = ft_params1(ssid=ssid, passphrase=passphrase)
2684    params['ft_psk_generate_local'] = "1"
2685    hapd0 = hostapd.add_ap(apdev[0], params)
2686    bssid0 = hapd0.own_addr()
2687
2688    dev[0].flush_scan_cache()
2689    dev[0].scan_for_bss(bssid0, freq="2412")
2690    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2691                   scan_freq="2412")
2692
2693    params = ft_params2(ssid=ssid, passphrase=passphrase)
2694    params['ft_psk_generate_local'] = "1"
2695    hapd1 = hostapd.add_ap(apdev[1], params)
2696    bssid1 = hapd1.own_addr()
2697    dev[0].scan_for_bss(bssid1, freq="2412")
2698    with fail_test(hapd1, 1, "wpa_derive_pmk_r0;wpa_ft_psk_pmk_r1"):
2699        # This will fail to roam
2700        dev[0].roam(bssid1, check_bssid=False)
2701    with fail_test(hapd1, 1, "wpa_derive_pmk_r1;wpa_ft_psk_pmk_r1"):
2702        # This will fail to roam
2703        dev[0].roam(bssid1, check_bssid=False)
2704
2705def test_ap_ft_ap_oom9(dev, apdev):
2706    """WPA2-PSK-FT and AP OOM 9"""
2707    ssid = "test-ft"
2708    passphrase = "12345678"
2709
2710    params = ft_params1(ssid=ssid, passphrase=passphrase)
2711    hapd0 = hostapd.add_ap(apdev[0], params)
2712    bssid0 = hapd0.own_addr()
2713
2714    dev[0].scan_for_bss(bssid0, freq="2412")
2715    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2716                   scan_freq="2412")
2717
2718    params = ft_params2(ssid=ssid, passphrase=passphrase)
2719    hapd1 = hostapd.add_ap(apdev[1], params)
2720    bssid1 = hapd1.own_addr()
2721    dev[0].scan_for_bss(bssid1, freq="2412")
2722
2723    with alloc_fail(hapd0, 1, "wpa_ft_action_rx"):
2724        # This will fail to roam
2725        if "OK" not in dev[0].request("FT_DS " + bssid1):
2726            raise Exception("FT_DS failed")
2727        wait_fail_trigger(hapd0, "GET_ALLOC_FAIL")
2728
2729    with alloc_fail(hapd1, 1, "wpa_ft_rrb_rx_request"):
2730        # This will fail to roam
2731        if "OK" not in dev[0].request("FT_DS " + bssid1):
2732            raise Exception("FT_DS failed")
2733        wait_fail_trigger(hapd1, "GET_ALLOC_FAIL")
2734
2735    with alloc_fail(hapd1, 1, "wpa_ft_send_rrb_auth_resp"):
2736        # This will fail to roam
2737        if "OK" not in dev[0].request("FT_DS " + bssid1):
2738            raise Exception("FT_DS failed")
2739        wait_fail_trigger(hapd1, "GET_ALLOC_FAIL")
2740
2741def test_ap_ft_ap_oom10(dev, apdev):
2742    """WPA2-PSK-FT and AP OOM 10"""
2743    ssid = "test-ft"
2744    passphrase = "12345678"
2745
2746    params = ft_params1(ssid=ssid, passphrase=passphrase)
2747    hapd0 = hostapd.add_ap(apdev[0], params)
2748    bssid0 = hapd0.own_addr()
2749
2750    dev[0].scan_for_bss(bssid0, freq="2412")
2751    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2752                   scan_freq="2412")
2753
2754    params = ft_params2(ssid=ssid, passphrase=passphrase)
2755    hapd1 = hostapd.add_ap(apdev[1], params)
2756    bssid1 = hapd1.own_addr()
2757    dev[0].scan_for_bss(bssid1, freq="2412")
2758
2759    with fail_test(hapd0, 1, "aes_siv_decrypt;wpa_ft_rrb_rx_pull"):
2760        # This will fail to roam
2761        if "OK" not in dev[0].request("FT_DS " + bssid1):
2762            raise Exception("FT_DS failed")
2763        wait_fail_trigger(hapd0, "GET_FAIL")
2764
2765    with fail_test(hapd0, 1, "wpa_derive_pmk_r1;wpa_ft_rrb_rx_pull"):
2766        # This will fail to roam
2767        if "OK" not in dev[0].request("FT_DS " + bssid1):
2768            raise Exception("FT_DS failed")
2769        wait_fail_trigger(hapd0, "GET_FAIL")
2770
2771    with fail_test(hapd0, 1, "aes_siv_encrypt;wpa_ft_rrb_rx_pull"):
2772        # This will fail to roam
2773        if "OK" not in dev[0].request("FT_DS " + bssid1):
2774            raise Exception("FT_DS failed")
2775        wait_fail_trigger(hapd0, "GET_FAIL")
2776
2777    with fail_test(hapd1, 1, "aes_siv_decrypt;wpa_ft_rrb_rx_resp"):
2778        # This will fail to roam
2779        if "OK" not in dev[0].request("FT_DS " + bssid1):
2780            raise Exception("FT_DS failed")
2781        wait_fail_trigger(hapd1, "GET_FAIL")
2782
2783def test_ap_ft_ap_oom11(dev, apdev):
2784    """WPA2-PSK-FT and AP OOM 11"""
2785    ssid = "test-ft"
2786    passphrase = "12345678"
2787
2788    params = ft_params1(ssid=ssid, passphrase=passphrase)
2789    hapd0 = hostapd.add_ap(apdev[0], params)
2790    bssid0 = hapd0.own_addr()
2791
2792    dev[0].scan_for_bss(bssid0, freq="2412")
2793    with fail_test(hapd0, 1, "wpa_derive_pmk_r1;wpa_ft_generate_pmk_r1"):
2794        dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2795                       scan_freq="2412")
2796        wait_fail_trigger(hapd0, "GET_FAIL")
2797
2798    dev[1].scan_for_bss(bssid0, freq="2412")
2799    with fail_test(hapd0, 1, "aes_siv_encrypt;wpa_ft_generate_pmk_r1"):
2800        dev[1].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2801                       scan_freq="2412")
2802        wait_fail_trigger(hapd0, "GET_FAIL")
2803
2804def test_ap_ft_over_ds_proto_ap(dev, apdev):
2805    """WPA2-PSK-FT AP over DS protocol testing for AP processing"""
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    bssid0 = hapd0.own_addr()
2812    _bssid0 = bssid0.replace(':', '')
2813    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2814                   scan_freq="2412")
2815    addr = dev[0].own_addr()
2816    _addr = addr.replace(':', '')
2817
2818    params = ft_params2(ssid=ssid, passphrase=passphrase)
2819    hapd1 = hostapd.add_ap(apdev[1], params)
2820    bssid1 = hapd1.own_addr()
2821    _bssid1 = bssid1.replace(':', '')
2822
2823    hapd0.set("ext_mgmt_frame_handling", "1")
2824    hdr = "d0003a01" + _bssid0 + _addr + _bssid0 + "1000"
2825    valid = "0601" + _addr + _bssid1
2826    tests = ["0601",
2827             "0601" + _addr,
2828             "0601" + _addr + _bssid0,
2829             "0601" + _addr + "ffffffffffff",
2830             "0601" + _bssid0 + _bssid0,
2831             valid,
2832             valid + "01",
2833             valid + "3700",
2834             valid + "3600",
2835             valid + "3603ffffff",
2836             valid + "3603a1b2ff",
2837             valid + "3603a1b2ff" + "3700",
2838             valid + "3603a1b2ff" + "37520000" + 16*"00" + 32*"00" + 32*"00",
2839             valid + "3603a1b2ff" + "37520001" + 16*"00" + 32*"00" + 32*"00",
2840             valid + "3603a1b2ff" + "37550000" + 16*"00" + 32*"00" + 32*"00" + "0301aa",
2841             valid + "3603a1b2ff" + "37550000" + 16*"00" + 32*"00" + 32*"00" + "0301aa" + "3000",
2842             valid + "3603a1b2ff" + "37550000" + 16*"00" + 32*"00" + 32*"00" + "0301aa" + "30260100000fac040100000fac040100000facff00000100a225368fe0983b5828a37a0acb37f253",
2843             valid + "3603a1b2ff" + "37550000" + 16*"00" + 32*"00" + 32*"00" + "0301aa" + "30260100000fac040100000fac030100000fac0400000100a225368fe0983b5828a37a0acb37f253",
2844             valid + "3603a1b2ff" + "37550000" + 16*"00" + 32*"00" + 32*"00" + "0301aa" + "30260100000fac040100000fac040100000fac0400000100a225368fe0983b5828a37a0acb37f253",
2845             valid + "0001"]
2846    for t in tests:
2847        hapd0.dump_monitor()
2848        if "OK" not in hapd0.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + t):
2849            raise Exception("MGMT_RX_PROCESS failed")
2850
2851    hapd0.set("ext_mgmt_frame_handling", "0")
2852
2853def test_ap_ft_over_ds_proto(dev, apdev):
2854    """WPA2-PSK-FT AP over DS protocol testing"""
2855    ssid = "test-ft"
2856    passphrase = "12345678"
2857
2858    params = ft_params1(ssid=ssid, passphrase=passphrase)
2859    hapd0 = hostapd.add_ap(apdev[0], params)
2860    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2861                   scan_freq="2412")
2862
2863    # FT Action Response while no FT-over-DS in progress
2864    msg = {}
2865    msg['fc'] = 13 << 4
2866    msg['da'] = dev[0].own_addr()
2867    msg['sa'] = apdev[0]['bssid']
2868    msg['bssid'] = apdev[0]['bssid']
2869    msg['payload'] = binascii.unhexlify("06020200000000000200000004000000")
2870    hapd0.mgmt_tx(msg)
2871
2872    params = ft_params2(ssid=ssid, passphrase=passphrase)
2873    hapd1 = hostapd.add_ap(apdev[1], params)
2874    dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
2875    hapd0.set("ext_mgmt_frame_handling", "1")
2876    hapd0.dump_monitor()
2877    dev[0].request("FT_DS " + apdev[1]['bssid'])
2878    for i in range(0, 10):
2879        req = hapd0.mgmt_rx()
2880        if req is None:
2881            raise Exception("MGMT RX wait timed out")
2882        if req['subtype'] == 13:
2883            break
2884        req = None
2885    if not req:
2886        raise Exception("FT Action frame not received")
2887
2888    # FT Action Response for unexpected Target AP
2889    msg['payload'] = binascii.unhexlify("0602020000000000" + "f20000000400" + "0000")
2890    hapd0.mgmt_tx(msg)
2891
2892    # FT Action Response without MDIE
2893    msg['payload'] = binascii.unhexlify("0602020000000000" + "020000000400" + "0000")
2894    hapd0.mgmt_tx(msg)
2895
2896    # FT Action Response without FTIE
2897    msg['payload'] = binascii.unhexlify("0602020000000000" + "020000000400" + "0000" + "3603a1b201")
2898    hapd0.mgmt_tx(msg)
2899
2900    # FT Action Response with FTIE SNonce mismatch
2901    msg['payload'] = binascii.unhexlify("0602020000000000" + "020000000400" + "0000" + "3603a1b201" + "3766000000000000000000000000000000000000c4e67ac1999bebd00ff4ae4d5dcaf87896bb060b469f7c78d49623fb395c3455ffffff6b693fe6f8d8c5dfac0a22344750775bd09437f98b238c9f87b97f790c0106000102030406030a6e6173312e77312e6669")
2902    hapd0.mgmt_tx(msg)
2903
2904@remote_compatible
2905def test_ap_ft_rrb(dev, apdev):
2906    """WPA2-PSK-FT RRB protocol testing"""
2907    ssid = "test-ft"
2908    passphrase = "12345678"
2909
2910    params = ft_params1(ssid=ssid, passphrase=passphrase)
2911    hapd0 = hostapd.add_ap(apdev[0], params)
2912
2913    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2914                   scan_freq="2412")
2915
2916    _dst_ll = binascii.unhexlify(apdev[0]['bssid'].replace(':', ''))
2917    _src_ll = binascii.unhexlify(dev[0].own_addr().replace(':', ''))
2918    proto = b'\x89\x0d'
2919    ehdr = _dst_ll + _src_ll + proto
2920
2921    # Too short RRB frame
2922    pkt = ehdr + b'\x01'
2923    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2924        raise Exception("DATA_TEST_FRAME failed")
2925
2926    # RRB discarded frame wikth unrecognized type
2927    pkt = ehdr + b'\x02' + b'\x02' + b'\x01\x00' + _src_ll
2928    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2929        raise Exception("DATA_TEST_FRAME failed")
2930
2931    # RRB frame too short for action frame
2932    pkt = ehdr + b'\x01' + b'\x02' + b'\x01\x00' + _src_ll
2933    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2934        raise Exception("DATA_TEST_FRAME failed")
2935
2936    # Too short RRB frame (not enough room for Action Frame body)
2937    pkt = ehdr + b'\x01' + b'\x02' + b'\x00\x00' + _src_ll
2938    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2939        raise Exception("DATA_TEST_FRAME failed")
2940
2941    # Unexpected Action frame category
2942    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'
2943    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2944        raise Exception("DATA_TEST_FRAME failed")
2945
2946    # Unexpected Action in RRB Request
2947    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'
2948    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2949        raise Exception("DATA_TEST_FRAME failed")
2950
2951    # Target AP address in RRB Request does not match with own address
2952    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'
2953    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2954        raise Exception("DATA_TEST_FRAME failed")
2955
2956    # Not enough room for status code in RRB Response
2957    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'
2958    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2959        raise Exception("DATA_TEST_FRAME failed")
2960
2961    # RRB discarded frame with unknown packet_type
2962    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'
2963    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2964        raise Exception("DATA_TEST_FRAME failed")
2965
2966    # RRB Response with non-zero status code; no STA match
2967    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'
2968    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2969        raise Exception("DATA_TEST_FRAME failed")
2970
2971    # RRB Response with zero status code and extra data; STA match
2972    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'
2973    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2974        raise Exception("DATA_TEST_FRAME failed")
2975
2976    # Too short PMK-R1 pull
2977    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'
2978    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2979        raise Exception("DATA_TEST_FRAME failed")
2980
2981    # Too short PMK-R1 resp
2982    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'
2983    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2984        raise Exception("DATA_TEST_FRAME failed")
2985
2986    # Too short PMK-R1 push
2987    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'
2988    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2989        raise Exception("DATA_TEST_FRAME failed")
2990
2991    # No matching R0KH address found for PMK-R0 pull response
2992    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'
2993    if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt).decode()):
2994        raise Exception("DATA_TEST_FRAME failed")
2995
2996@remote_compatible
2997def test_rsn_ie_proto_ft_psk_sta(dev, apdev):
2998    """RSN element protocol testing for FT-PSK + PMF cases on STA side"""
2999    bssid = apdev[0]['bssid']
3000    ssid = "test-ft"
3001    passphrase = "12345678"
3002
3003    params = ft_params1(ssid=ssid, passphrase=passphrase)
3004    params["ieee80211w"] = "1"
3005    # This is the RSN element used normally by hostapd
3006    params['own_ie_override'] = '30140100000fac040100000fac040100000fac048c00' + '3603a1b201'
3007    hapd = hostapd.add_ap(apdev[0], params)
3008    id = dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
3009                        ieee80211w="1", scan_freq="2412",
3010                        pairwise="CCMP", group="CCMP")
3011
3012    tests = [('PMKIDCount field included',
3013              '30160100000fac040100000fac040100000fac048c000000' + '3603a1b201'),
3014             ('Extra IE before RSNE',
3015              'dd0400000000' + '30140100000fac040100000fac040100000fac048c00' + '3603a1b201'),
3016             ('PMKIDCount and Group Management Cipher suite fields included',
3017              '301a0100000fac040100000fac040100000fac048c000000000fac06' + '3603a1b201'),
3018             ('Extra octet after defined fields (future extensibility)',
3019              '301b0100000fac040100000fac040100000fac048c000000000fac0600' + '3603a1b201'),
3020             ('No RSN Capabilities field (PMF disabled in practice)',
3021              '30120100000fac040100000fac040100000fac04' + '3603a1b201')]
3022    for txt, ie in tests:
3023        dev[0].request("DISCONNECT")
3024        dev[0].wait_disconnected()
3025        logger.info(txt)
3026        hapd.disable()
3027        hapd.set('own_ie_override', ie)
3028        hapd.enable()
3029        dev[0].request("BSS_FLUSH 0")
3030        dev[0].scan_for_bss(bssid, 2412, force_scan=True, only_new=True)
3031        dev[0].select_network(id, freq=2412)
3032        dev[0].wait_connected()
3033
3034    dev[0].request("DISCONNECT")
3035    dev[0].wait_disconnected()
3036
3037    logger.info('Invalid RSNE causing internal hostapd error')
3038    hapd.disable()
3039    hapd.set('own_ie_override', '30130100000fac040100000fac040100000fac048c' + '3603a1b201')
3040    hapd.enable()
3041    dev[0].request("BSS_FLUSH 0")
3042    dev[0].scan_for_bss(bssid, 2412, force_scan=True, only_new=True)
3043    dev[0].select_network(id, freq=2412)
3044    # hostapd fails to generate EAPOL-Key msg 3/4, so this connection cannot
3045    # complete.
3046    ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
3047    if ev is not None:
3048        raise Exception("Unexpected connection")
3049    dev[0].request("DISCONNECT")
3050
3051def start_ft(apdev, wpa_ptk_rekey=None):
3052    ssid = "test-ft"
3053    passphrase = "12345678"
3054
3055    params = ft_params1(ssid=ssid, passphrase=passphrase)
3056    if wpa_ptk_rekey:
3057        params['wpa_ptk_rekey'] = str(wpa_ptk_rekey)
3058    hapd0 = hostapd.add_ap(apdev[0], params)
3059    params = ft_params2(ssid=ssid, passphrase=passphrase)
3060    if wpa_ptk_rekey:
3061        params['wpa_ptk_rekey'] = str(wpa_ptk_rekey)
3062    hapd1 = hostapd.add_ap(apdev[1], params)
3063
3064    return hapd0, hapd1
3065
3066def check_ptk_rekey(dev, hapd0=None, hapd1=None):
3067    ev = dev.wait_event(["CTRL-EVENT-DISCONNECTED",
3068                         "WPA: Key negotiation completed"], timeout=5)
3069    if ev is None:
3070        raise Exception("No event received after roam")
3071    if "CTRL-EVENT-DISCONNECTED" in ev:
3072        raise Exception("Unexpected disconnection after roam")
3073
3074    if not hapd0 or not hapd1:
3075        return
3076    if dev.get_status_field('bssid') == hapd0.own_addr():
3077        hapd = hapd0
3078    else:
3079        hapd = hapd1
3080    time.sleep(0.1)
3081    hwsim_utils.test_connectivity(dev, hapd)
3082
3083def test_ap_ft_ptk_rekey(dev, apdev):
3084    """WPA2-PSK-FT PTK rekeying triggered by station after roam"""
3085    hapd0, hapd1 = start_ft(apdev)
3086    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", ptk_rekey="1")
3087    check_ptk_rekey(dev[0], hapd0, hapd1)
3088
3089def test_ap_ft_ptk_rekey2(dev, apdev):
3090    """WPA2-PSK-FT PTK rekeying triggered by station after one roam"""
3091    hapd0, hapd1 = start_ft(apdev)
3092    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", ptk_rekey="1",
3093              only_one_way=True)
3094    check_ptk_rekey(dev[0], hapd0, hapd1)
3095
3096def test_ap_ft_ptk_rekey_ap(dev, apdev):
3097    """WPA2-PSK-FT PTK rekeying triggered by AP after roam"""
3098    hapd0, hapd1 = start_ft(apdev, wpa_ptk_rekey=2)
3099    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678")
3100    check_ptk_rekey(dev[0], hapd0, hapd1)
3101
3102def test_ap_ft_ptk_rekey_ap2(dev, apdev):
3103    """WPA2-PSK-FT PTK rekeying triggered by AP after one roam"""
3104    hapd0, hapd1 = start_ft(apdev, wpa_ptk_rekey=2)
3105    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678",
3106              only_one_way=True)
3107    check_ptk_rekey(dev[0], hapd0, hapd1)
3108
3109def test_ap_ft_eap_ptk_rekey_ap(dev, apdev):
3110    """WPA2-EAP-FT PTK rekeying triggered by AP"""
3111    generic_ap_ft_eap(dev, apdev, only_one_way=True, wpa_ptk_rekey=2)
3112    check_ptk_rekey(dev[0])
3113
3114def test_ap_ft_internal_rrb_check(dev, apdev):
3115    """RRB internal delivery only to WPA enabled BSS"""
3116    ssid = "test-ft"
3117    passphrase = "12345678"
3118
3119    radius = hostapd.radius_params()
3120    params = ft_params1(ssid=ssid, passphrase=passphrase)
3121    params['wpa_key_mgmt'] = "FT-EAP"
3122    params["ieee8021x"] = "1"
3123    params = dict(list(radius.items()) + list(params.items()))
3124    hapd = hostapd.add_ap(apdev[0], params)
3125    key_mgmt = hapd.get_config()['key_mgmt']
3126    if key_mgmt.split(' ')[0] != "FT-EAP":
3127        raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
3128
3129    hapd1 = hostapd.add_ap(apdev[1], {"ssid": ssid})
3130
3131    # Connect to WPA enabled AP
3132    dev[0].connect(ssid, key_mgmt="FT-EAP", proto="WPA2", ieee80211w="1",
3133                   eap="GPSK", identity="gpsk user",
3134                   password="abcdefghijklmnop0123456789abcdef",
3135                   scan_freq="2412")
3136
3137    # Try over_ds roaming to non-WPA-enabled AP.
3138    # If hostapd does not check hapd->wpa_auth internally, it will crash now.
3139    dev[0].roam_over_ds(apdev[1]['bssid'], fail_test=True, force=True)
3140
3141def test_ap_ft_extra_ie(dev, apdev):
3142    """WPA2-PSK-FT AP with WPA2-PSK enabled and unexpected MDE"""
3143    ssid = "test-ft"
3144    passphrase = "12345678"
3145
3146    params = ft_params1(ssid=ssid, passphrase=passphrase)
3147    params["wpa_key_mgmt"] = "WPA-PSK FT-PSK"
3148    hapd0 = hostapd.add_ap(apdev[0], params)
3149    dev[1].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
3150                   scan_freq="2412")
3151    dev[2].connect(ssid, psk=passphrase, key_mgmt="WPA-PSK", proto="WPA2",
3152                   scan_freq="2412")
3153    try:
3154        # Add Mobility Domain element to test AP validation code.
3155        dev[0].request("VENDOR_ELEM_ADD 13 3603a1b201")
3156        dev[0].connect(ssid, psk=passphrase, key_mgmt="WPA-PSK", proto="WPA2",
3157                       scan_freq="2412", wait_connect=False)
3158        ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
3159                                "CTRL-EVENT-ASSOC-REJECT"], timeout=10)
3160        if ev is None:
3161            raise Exception("No connection result")
3162        if "CTRL-EVENT-CONNECTED" in ev:
3163            raise Exception("Non-FT association accepted with MDE")
3164        if "status_code=43" not in ev:
3165            raise Exception("Unexpected status code: " + ev)
3166        dev[0].request("DISCONNECT")
3167    finally:
3168        dev[0].request("VENDOR_ELEM_REMOVE 13 *")
3169
3170def test_ap_ft_ric(dev, apdev):
3171    """WPA2-PSK-FT AP and RIC"""
3172    ssid = "test-ft"
3173    passphrase = "12345678"
3174
3175    params = ft_params1(ssid=ssid, passphrase=passphrase)
3176    hapd0 = hostapd.add_ap(apdev[0], params)
3177    params = ft_params2(ssid=ssid, passphrase=passphrase)
3178    hapd1 = hostapd.add_ap(apdev[1], params)
3179
3180    dev[0].set("ric_ies", "")
3181    dev[0].set("ric_ies", '""')
3182    if "FAIL" not in dev[0].request("SET ric_ies q"):
3183        raise Exception("Invalid ric_ies value accepted")
3184
3185    tests = ["3900",
3186             "3900ff04eeeeeeee",
3187             "390400000000",
3188             "390400000000" + "390400000000",
3189             "390400000000" + "dd050050f20202",
3190             "390400000000" + "dd3d0050f2020201" + 55*"00",
3191             "390400000000" + "dd3d0050f2020201aa300010270000000000000000000000000000000000000000000000000000ffffff7f00000000000000000000000040420f00ffff0000",
3192             "390401010000" + "dd3d0050f2020201aa3000dc050000000000000000000000000000000000000000000000000000dc050000000000000000000000000000808d5b0028230000"]
3193    for t in tests:
3194        dev[0].set("ric_ies", t)
3195        run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase,
3196                  test_connectivity=False)
3197        dev[0].request("REMOVE_NETWORK all")
3198        dev[0].wait_disconnected()
3199        dev[0].dump_monitor()
3200
3201def ie_hex(ies, id):
3202    return binascii.hexlify(struct.pack('BB', id, len(ies[id])) + ies[id]).decode()
3203
3204def test_ap_ft_reassoc_proto(dev, apdev):
3205    """WPA2-PSK-FT AP Reassociation Request frame parsing"""
3206    ssid = "test-ft"
3207    passphrase = "12345678"
3208
3209    params = ft_params1(ssid=ssid, passphrase=passphrase)
3210    hapd0 = hostapd.add_ap(apdev[0], params)
3211    params = ft_params2(ssid=ssid, passphrase=passphrase)
3212    hapd1 = hostapd.add_ap(apdev[1], params)
3213
3214    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
3215                   ieee80211w="1", scan_freq="2412")
3216    if dev[0].get_status_field('bssid') == hapd0.own_addr():
3217        hapd1ap = hapd0
3218        hapd2ap = hapd1
3219    else:
3220        hapd1ap = hapd1
3221        hapd2ap = hapd0
3222
3223    dev[0].scan_for_bss(hapd2ap.own_addr(), freq="2412")
3224    hapd2ap.set("ext_mgmt_frame_handling", "1")
3225    dev[0].request("ROAM " + hapd2ap.own_addr())
3226
3227    while True:
3228        req = hapd2ap.mgmt_rx()
3229        hapd2ap.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
3230        if req['subtype'] == 11:
3231            break
3232
3233    while True:
3234        req = hapd2ap.mgmt_rx()
3235        if req['subtype'] == 2:
3236            break
3237        hapd2ap.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
3238
3239    # IEEE 802.11 header + fixed fields before IEs
3240    hdr = binascii.hexlify(req['frame'][0:34]).decode()
3241    ies = parse_ie(binascii.hexlify(req['frame'][34:]))
3242    # First elements: SSID, Supported Rates, Extended Supported Rates
3243    ies1 = ie_hex(ies, 0) + ie_hex(ies, 1) + ie_hex(ies, 50)
3244
3245    rsne = ie_hex(ies, 48)
3246    mde = ie_hex(ies, 54)
3247    fte = ie_hex(ies, 55)
3248    tests = []
3249    # RSN: Trying to use FT, but MDIE not included
3250    tests += [rsne]
3251    # RSN: Attempted to use unknown MDIE
3252    tests += [rsne + "3603000000"]
3253    # Invalid RSN pairwise cipher
3254    tests += ["30260100000fac040100000fac030100000fac040000010029208a42cd25c85aa571567dce10dae3"]
3255    # FT: No PMKID in RSNIE
3256    tests += ["30160100000fac040100000fac040100000fac0400000000" + ie_hex(ies, 54)]
3257    # FT: Invalid FTIE
3258    tests += [rsne + mde]
3259    # FT: RIC IE(s) in the frame, but not included in protected IE count
3260    # FT: Failed to parse FT IEs
3261    tests += [rsne + mde + fte + "3900"]
3262    # FT: SNonce mismatch in FTIE
3263    tests += [rsne + mde + "37520000" + 16*"00" + 32*"00" + 32*"00"]
3264    # FT: ANonce mismatch in FTIE
3265    tests += [rsne + mde + fte[0:40] + 32*"00" + fte[104:]]
3266    # FT: No R0KH-ID subelem in FTIE
3267    tests += [rsne + mde + "3752" + fte[4:168]]
3268    # FT: R0KH-ID in FTIE did not match with the current R0KH-ID
3269    tests += [rsne + mde + "3755" + fte[4:168] + "0301ff"]
3270    # FT: No R1KH-ID subelem in FTIE
3271    tests += [rsne + mde + "375e" + fte[4:168] + "030a" + binascii.hexlify(b"nas1.w1.fi").decode()]
3272    # FT: Unknown R1KH-ID used in ReassocReq
3273    tests += [rsne + mde + "3766" + fte[4:168] + "030a" + binascii.hexlify(b"nas1.w1.fi").decode() + "0106000000000000"]
3274    # FT: PMKID in Reassoc Req did not match with the PMKR1Name derived from auth request
3275    tests += [rsne[:-32] + 16*"00" + mde + fte]
3276    # Invalid MIC in FTIE
3277    tests += [rsne + mde + fte[0:8] + 16*"00" + fte[40:]]
3278    for t in tests:
3279        hapd2ap.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + ies1 + t)
3280
3281    # Do not leave dev[0] in state where it is waiting for
3282    # NL80211_CMD_ASSOCIATE to complete since that might deliver
3283    # an ASSOC_TIMED_OUT event to the next test case.
3284    dev[0].request("DISCONNECT")
3285    time.sleep(0.2)
3286
3287def test_ap_ft_reassoc_local_fail(dev, apdev):
3288    """WPA2-PSK-FT AP Reassociation Request frame and local failure"""
3289    ssid = "test-ft"
3290    passphrase = "12345678"
3291
3292    params = ft_params1(ssid=ssid, passphrase=passphrase)
3293    hapd0 = hostapd.add_ap(apdev[0], params)
3294    params = ft_params2(ssid=ssid, passphrase=passphrase)
3295    hapd1 = hostapd.add_ap(apdev[1], params)
3296
3297    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
3298                   ieee80211w="1", scan_freq="2412")
3299    if dev[0].get_status_field('bssid') == hapd0.own_addr():
3300        hapd1ap = hapd0
3301        hapd2ap = hapd1
3302    else:
3303        hapd1ap = hapd1
3304        hapd2ap = hapd0
3305
3306    dev[0].scan_for_bss(hapd2ap.own_addr(), freq="2412")
3307    # FT: Failed to calculate MIC
3308    with fail_test(hapd2ap, 1, "wpa_ft_validate_reassoc"):
3309        dev[0].request("ROAM " + hapd2ap.own_addr())
3310        ev = dev[0].wait_event(["CTRL-EVENT-ASSOC-REJECT"], timeout=10)
3311        dev[0].request("DISCONNECT")
3312        if ev is None:
3313            raise Exception("Association reject not seen")
3314
3315def test_ap_ft_reassoc_replay(dev, apdev, params):
3316    """WPA2-PSK-FT AP and replayed Reassociation Request frame"""
3317    capfile = os.path.join(params['logdir'], "hwsim0.pcapng")
3318    ssid = "test-ft"
3319    passphrase = "12345678"
3320
3321    params = ft_params1(ssid=ssid, passphrase=passphrase)
3322    hapd0 = hostapd.add_ap(apdev[0], params)
3323    params = ft_params2(ssid=ssid, passphrase=passphrase)
3324    hapd1 = hostapd.add_ap(apdev[1], params)
3325
3326    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
3327                   scan_freq="2412")
3328    if dev[0].get_status_field('bssid') == hapd0.own_addr():
3329        hapd1ap = hapd0
3330        hapd2ap = hapd1
3331    else:
3332        hapd1ap = hapd1
3333        hapd2ap = hapd0
3334
3335    dev[0].scan_for_bss(hapd2ap.own_addr(), freq="2412")
3336    hapd2ap.set("ext_mgmt_frame_handling", "1")
3337    dev[0].dump_monitor()
3338    if "OK" not in dev[0].request("ROAM " + hapd2ap.own_addr()):
3339        raise Exception("ROAM failed")
3340
3341    reassocreq = None
3342    count = 0
3343    while count < 100:
3344        req = hapd2ap.mgmt_rx()
3345        count += 1
3346        hapd2ap.dump_monitor()
3347        hapd2ap.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
3348        if req['subtype'] == 2:
3349            reassocreq = req
3350            ev = hapd2ap.wait_event(["MGMT-TX-STATUS"], timeout=5)
3351            if ev is None:
3352                raise Exception("No TX status seen")
3353            cmd = "MGMT_TX_STATUS_PROCESS %s" % (" ".join(ev.split(' ')[1:4]))
3354            if "OK" not in hapd2ap.request(cmd):
3355                raise Exception("MGMT_TX_STATUS_PROCESS failed")
3356            break
3357    hapd2ap.set("ext_mgmt_frame_handling", "0")
3358    if reassocreq is None:
3359        raise Exception("No Reassociation Request frame seen")
3360    dev[0].wait_connected()
3361    dev[0].dump_monitor()
3362    hapd2ap.dump_monitor()
3363
3364    hwsim_utils.test_connectivity(dev[0], hapd2ap)
3365
3366    logger.info("Replay the last Reassociation Request frame")
3367    hapd2ap.dump_monitor()
3368    hapd2ap.set("ext_mgmt_frame_handling", "1")
3369    hapd2ap.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
3370    ev = hapd2ap.wait_event(["MGMT-TX-STATUS"], timeout=5)
3371    if ev is None:
3372        raise Exception("No TX status seen")
3373    cmd = "MGMT_TX_STATUS_PROCESS %s" % (" ".join(ev.split(' ')[1:4]))
3374    if "OK" not in hapd2ap.request(cmd):
3375        raise Exception("MGMT_TX_STATUS_PROCESS failed")
3376    hapd2ap.set("ext_mgmt_frame_handling", "0")
3377
3378    try:
3379        hwsim_utils.test_connectivity(dev[0], hapd2ap)
3380        ok = True
3381    except:
3382        ok = False
3383
3384    ap = hapd2ap.own_addr()
3385    sta = dev[0].own_addr()
3386    filt = "wlan.fc.type == 2 && " + \
3387           "wlan.da == " + sta + " && " + \
3388           "wlan.sa == " + ap + " && " + \
3389           "wlan.fc.protected == 1"
3390    fields = ["wlan.ccmp.extiv"]
3391    res = run_tshark(capfile, filt, fields)
3392    vals = res.splitlines()
3393    logger.info("CCMP PN: " + str(vals))
3394    if len(vals) < 2:
3395        raise Exception("Could not find all CCMP protected frames from capture")
3396    if len(set(vals)) < len(vals):
3397        raise Exception("Duplicate CCMP PN used")
3398
3399    if not ok:
3400        raise Exception("The second hwsim connectivity test failed")
3401
3402def test_ap_ft_psk_file(dev, apdev):
3403    """WPA2-PSK-FT AP with PSK from a file"""
3404    ssid = "test-ft"
3405    passphrase = "12345678"
3406
3407    params = ft_params1a(ssid=ssid, passphrase=passphrase)
3408    params['wpa_psk_file'] = 'hostapd.wpa_psk'
3409    hapd = hostapd.add_ap(apdev[0], params)
3410
3411    dev[1].connect(ssid, psk="very secret",
3412                   key_mgmt="FT-PSK", proto="WPA2", ieee80211w="1",
3413                   scan_freq="2412", wait_connect=False)
3414    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
3415                   ieee80211w="1", scan_freq="2412")
3416    dev[0].request("REMOVE_NETWORK all")
3417    dev[0].wait_disconnected()
3418    dev[0].connect(ssid, psk="very secret", key_mgmt="FT-PSK", proto="WPA2",
3419                   ieee80211w="1", scan_freq="2412")
3420    dev[0].request("REMOVE_NETWORK all")
3421    dev[0].wait_disconnected()
3422    dev[0].connect(ssid, psk="secret passphrase",
3423                   key_mgmt="FT-PSK", proto="WPA2", ieee80211w="1",
3424                   scan_freq="2412")
3425    dev[2].connect(ssid, psk="another passphrase for all STAs",
3426                   key_mgmt="FT-PSK", proto="WPA2", ieee80211w="1",
3427                   scan_freq="2412")
3428    ev = dev[1].wait_event(["WPA: 4-Way Handshake failed"], timeout=10)
3429    if ev is None:
3430        raise Exception("Timed out while waiting for failure report")
3431    dev[1].request("REMOVE_NETWORK all")
3432
3433def test_ap_ft_eap_ap_config_change(dev, apdev):
3434    """WPA2-EAP-FT AP changing from 802.1X-only to FT-only"""
3435    ssid = "test-ft"
3436    passphrase = "12345678"
3437    bssid = apdev[0]['bssid']
3438
3439    radius = hostapd.radius_params()
3440    params = ft_params1(ssid=ssid, passphrase=passphrase, discovery=True)
3441    params['wpa_key_mgmt'] = "WPA-EAP"
3442    params["ieee8021x"] = "1"
3443    params["pmk_r1_push"] = "0"
3444    params["r0kh"] = "ff:ff:ff:ff:ff:ff * 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
3445    params["r1kh"] = "00:00:00:00:00:00 00:00:00:00:00:00 00112233445566778899aabbccddeeff00112233445566778899aabbccddeeff"
3446    params["eap_server"] = "0"
3447    params = dict(list(radius.items()) + list(params.items()))
3448    hapd = hostapd.add_ap(apdev[0], params)
3449
3450    dev[0].connect(ssid, key_mgmt="FT-EAP WPA-EAP", proto="WPA2",
3451                   eap="GPSK", identity="gpsk user",
3452                   password="abcdefghijklmnop0123456789abcdef",
3453                   scan_freq="2412")
3454    dev[0].request("DISCONNECT")
3455    dev[0].wait_disconnected()
3456    dev[0].dump_monitor()
3457
3458    hapd.disable()
3459    hapd.set('wpa_key_mgmt', "FT-EAP")
3460    hapd.enable()
3461
3462    dev[0].request("BSS_FLUSH 0")
3463    dev[0].scan_for_bss(bssid, 2412, force_scan=True, only_new=True)
3464
3465    dev[0].request("RECONNECT")
3466    dev[0].wait_connected()
3467
3468def test_ap_ft_eap_sha384(dev, apdev):
3469    """WPA2-EAP-FT with SHA384"""
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    conf = hapd0.request("GET_CONFIG")
3481    if "key_mgmt=FT-EAP-SHA384" not in conf.splitlines():
3482        logger.info("GET_CONFIG:\n" + conf)
3483        raise Exception("GET_CONFIG did not report correct key_mgmt")
3484    params = ft_params2(ssid=ssid, passphrase=passphrase)
3485    params["ieee80211w"] = "2"
3486    params['wpa_key_mgmt'] = "FT-EAP-SHA384"
3487    params["ieee8021x"] = "1"
3488    params = dict(list(radius.items()) + list(params.items()))
3489    hapd1 = hostapd.add_ap(apdev[1], params)
3490
3491    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, eap=True,
3492              sha384=True)
3493
3494def test_ap_ft_eap_sha384_reassoc(dev, apdev):
3495    """WPA2-EAP-FT with SHA384 using REASSOCIATE"""
3496    check_suite_b_192_capa(dev)
3497    ssid = "test-ft"
3498    passphrase = "12345678"
3499
3500    radius = hostapd.radius_params()
3501    params = ft_params1(ssid=ssid, passphrase=passphrase)
3502    params["ieee80211w"] = "2"
3503    params['wpa_key_mgmt'] = "WPA-EAP-SUITE-B-192 FT-EAP-SHA384"
3504    params["ieee8021x"] = "1"
3505    params = dict(list(radius.items()) + list(params.items()))
3506    hapd0 = hostapd.add_ap(apdev[0], params)
3507    params = ft_params2(ssid=ssid, passphrase=passphrase)
3508    params["ieee80211w"] = "2"
3509    params['wpa_key_mgmt'] = "WPA-EAP-SUITE-B-192 FT-EAP-SHA384"
3510    params["ieee8021x"] = "1"
3511    params = dict(list(radius.items()) + list(params.items()))
3512    hapd1 = hostapd.add_ap(apdev[1], params)
3513
3514    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, eap=True,
3515              sha384=True, also_non_ft=True, roam_with_reassoc=True)
3516
3517def test_ap_ft_eap_sha384_over_ds(dev, apdev):
3518    """WPA2-EAP-FT with SHA384 over DS"""
3519    ssid = "test-ft"
3520    passphrase = "12345678"
3521
3522    radius = hostapd.radius_params()
3523    params = ft_params1(ssid=ssid, passphrase=passphrase)
3524    params["ieee80211w"] = "2"
3525    params['wpa_key_mgmt'] = "FT-EAP-SHA384"
3526    params["ieee8021x"] = "1"
3527    params = dict(list(radius.items()) + list(params.items()))
3528    hapd0 = hostapd.add_ap(apdev[0], params)
3529    params = ft_params2(ssid=ssid, passphrase=passphrase)
3530    params["ieee80211w"] = "2"
3531    params['wpa_key_mgmt'] = "FT-EAP-SHA384"
3532    params["ieee8021x"] = "1"
3533    params = dict(list(radius.items()) + list(params.items()))
3534    hapd1 = hostapd.add_ap(apdev[1], params)
3535
3536    dev[0].flush_scan_cache()
3537    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
3538              eap=True, sha384=True)
3539
3540def test_ap_ft_roam_rrm(dev, apdev):
3541    """WPA2-PSK-FT AP and radio measurement request"""
3542    ssid = "test-ft"
3543    passphrase = "12345678"
3544
3545    params = ft_params1(ssid=ssid, passphrase=passphrase)
3546    params["rrm_beacon_report"] = "1"
3547    hapd0 = hostapd.add_ap(apdev[0], params)
3548    bssid0 = hapd0.own_addr()
3549
3550    addr = dev[0].own_addr()
3551    dev[0].flush_scan_cache()
3552    dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
3553                   scan_freq="2412")
3554    hapd0.wait_sta()
3555    check_beacon_req(hapd0, addr, 1)
3556
3557    params = ft_params2(ssid=ssid, passphrase=passphrase)
3558    params["rrm_beacon_report"] = "1"
3559    hapd1 = hostapd.add_ap(apdev[1], params)
3560    bssid1 = hapd1.own_addr()
3561
3562    dev[0].scan_for_bss(bssid1, freq=2412)
3563    dev[0].roam(bssid1)
3564    hapd1.wait_sta()
3565    check_beacon_req(hapd1, addr, 2)
3566
3567    dev[0].scan_for_bss(bssid0, freq=2412)
3568    dev[0].roam(bssid0)
3569    hapd0.wait_sta()
3570    check_beacon_req(hapd0, addr, 3)
3571
3572def test_ap_ft_pmksa_caching(dev, apdev):
3573    """FT-EAP and PMKSA caching for initial mobility domain association"""
3574    ssid = "test-ft"
3575    identity = "gpsk user"
3576
3577    radius = hostapd.radius_params()
3578    params = ft_params1(ssid=ssid)
3579    params['wpa_key_mgmt'] = "FT-EAP"
3580    params["ieee8021x"] = "1"
3581    params["mobility_domain"] = "c3d4"
3582    params = dict(list(radius.items()) + list(params.items()))
3583    hapd = hostapd.add_ap(apdev[0], params)
3584
3585    params = ft_params2(ssid=ssid)
3586    params['wpa_key_mgmt'] = "FT-EAP"
3587    params["ieee8021x"] = "1"
3588    params["mobility_domain"] = "c3d4"
3589    params = dict(list(radius.items()) + list(params.items()))
3590    hapd1 = hostapd.add_ap(apdev[1], params)
3591
3592    run_roams(dev[0], apdev, hapd, hapd1, ssid, None, eap=True,
3593              eap_identity=identity, pmksa_caching=True)
3594
3595def test_ap_ft_pmksa_caching_sha384(dev, apdev):
3596    """FT-EAP-SHA384 and PMKSA caching for initial mobility domain association"""
3597    ssid = "test-ft"
3598    identity = "gpsk user"
3599
3600    radius = hostapd.radius_params()
3601    params = ft_params1(ssid=ssid)
3602    params['wpa_key_mgmt'] = "FT-EAP-SHA384"
3603    params["ieee8021x"] = "1"
3604    params["mobility_domain"] = "c3d4"
3605    params = dict(list(radius.items()) + list(params.items()))
3606    hapd = hostapd.add_ap(apdev[0], params)
3607
3608    params = ft_params2(ssid=ssid)
3609    params['wpa_key_mgmt'] = "FT-EAP-SHA384"
3610    params["ieee8021x"] = "1"
3611    params["mobility_domain"] = "c3d4"
3612    params = dict(list(radius.items()) + list(params.items()))
3613    hapd1 = hostapd.add_ap(apdev[1], params)
3614
3615    run_roams(dev[0], apdev, hapd, hapd1, ssid, None, eap=True,
3616              eap_identity=identity, pmksa_caching=True, sha384=True)
3617
3618def test_ap_ft_r1_key_expiration(dev, apdev):
3619    """WPA2-PSK-FT and PMK-R1 expiration"""
3620    ssid = "test-ft"
3621    passphrase = "12345678"
3622
3623    params = ft_params1(ssid=ssid, passphrase=passphrase)
3624    params['r1_max_key_lifetime'] = "2"
3625    hapd0 = hostapd.add_ap(apdev[0], params)
3626    params = ft_params2(ssid=ssid, passphrase=passphrase)
3627    params['r1_max_key_lifetime'] = "2"
3628    hapd1 = hostapd.add_ap(apdev[1], params)
3629
3630    # This succeeds, but results in having to run another PMK-R1 pull before the
3631    # second AP can complete FT protocol.
3632    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, wait_before_roam=4)
3633
3634def test_ap_ft_r0_key_expiration(dev, apdev):
3635    """WPA2-PSK-FT and PMK-R0 expiration"""
3636    ssid = "test-ft"
3637    passphrase = "12345678"
3638
3639    params = ft_params1(ssid=ssid, passphrase=passphrase)
3640    params.pop('r0_key_lifetime', None)
3641    params['ft_r0_key_lifetime'] = "2"
3642    hapd0 = hostapd.add_ap(apdev[0], params)
3643    params = ft_params2(ssid=ssid, passphrase=passphrase)
3644    params.pop('r0_key_lifetime', None)
3645    params['ft_r0_key_lifetime'] = "2"
3646    hapd1 = hostapd.add_ap(apdev[1], params)
3647
3648    bssid2 = run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase,
3649                       return_after_initial=True)
3650    time.sleep(4)
3651    dev[0].scan_for_bss(bssid2, freq="2412")
3652    if "OK" not in dev[0].request("ROAM " + bssid2):
3653        raise Exception("ROAM failed")
3654    ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
3655                            "CTRL-EVENT-AUTH-REJECT",
3656                            "CTRL-EVENT-ASSOC-REJECT"], timeout=5)
3657    dev[0].request("DISCONNECT")
3658    if ev is None or "CTRL-EVENT-AUTH-REJECT" not in ev:
3659        raise Exception("FT protocol failure not reported")
3660    if "status_code=53" not in ev:
3661        raise Exception("Unexpected status in FT protocol failure: " + ev)
3662
3663    # Generate a new PMK-R0
3664    dev[0].dump_monitor()
3665    dev[0].request("RECONNECT")
3666    dev[0].wait_connected()
3667
3668def test_ap_ft_no_full_ap_client_state(dev, apdev):
3669    """WPA2-PSK-FT AP with full_ap_client_state=0"""
3670    run_ap_ft_skip_prune_assoc(dev, apdev, False, False)
3671
3672def test_ap_ft_skip_prune_assoc(dev, apdev):
3673    """WPA2-PSK-FT AP with skip_prune_assoc"""
3674    run_ap_ft_skip_prune_assoc(dev, apdev, True, True)
3675
3676def test_ap_ft_skip_prune_assoc2(dev, apdev):
3677    """WPA2-PSK-FT AP with skip_prune_assoc (disable full_ap_client_state)"""
3678    run_ap_ft_skip_prune_assoc(dev, apdev, True, False, test_connectivity=False)
3679
3680def test_ap_ft_skip_prune_assoc_pmf(dev, apdev):
3681    """WPA2-PSK-FT/PMF AP with skip_prune_assoc"""
3682    run_ap_ft_skip_prune_assoc(dev, apdev, True, True, pmf=True)
3683
3684def test_ap_ft_skip_prune_assoc_pmf_over_ds(dev, apdev):
3685    """WPA2-PSK-FT/PMF AP with skip_prune_assoc (over DS)"""
3686    dev[0].flush_scan_cache()
3687    run_ap_ft_skip_prune_assoc(dev, apdev, True, True, pmf=True, over_ds=True)
3688
3689def run_ap_ft_skip_prune_assoc(dev, apdev, skip_prune_assoc,
3690                               full_ap_client_state, test_connectivity=True,
3691                               pmf=False, over_ds=False):
3692    ssid = "test-ft"
3693    passphrase = "12345678"
3694
3695    params = ft_params1(ssid=ssid, passphrase=passphrase)
3696    if skip_prune_assoc:
3697        params['skip_prune_assoc'] = '1'
3698    if not full_ap_client_state:
3699        params['driver_params'] = "full_ap_client_state=0"
3700    if pmf:
3701        params["ieee80211w"] = "2"
3702    hapd0 = hostapd.add_ap(apdev[0], params)
3703    params = ft_params2(ssid=ssid, passphrase=passphrase)
3704    if skip_prune_assoc:
3705        params['skip_prune_assoc'] = '1'
3706    if not full_ap_client_state:
3707        params['driver_params'] = "full_ap_client_state=0"
3708    if pmf:
3709        params["ieee80211w"] = "2"
3710    hapd1 = hostapd.add_ap(apdev[1], params)
3711
3712    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase,
3713              ieee80211w="2" if pmf else "0",
3714              over_ds=over_ds, test_connectivity=test_connectivity)
3715
3716def test_ap_ft_sae_skip_prune_assoc(dev, apdev):
3717    """WPA2-PSK-FT-SAE AP with skip_prune_assoc"""
3718    hapd0, hapd1 = start_ft_sae(dev[0], apdev, skip_prune_assoc=True)
3719    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678", sae=True)
3720
3721def test_ap_ft_diff_mobility_domain(dev, apdev):
3722    """WPA2-PSK-FT AP and different mobility domain"""
3723    ssid = "test-ft"
3724    passphrase = "12345678"
3725
3726    params = ft_params1(ssid=ssid, passphrase=passphrase)
3727    hapd0 = hostapd.add_ap(apdev[0], params)
3728    params = ft_params2(ssid=ssid, passphrase=passphrase,
3729                        mobility_domain="c3d4")
3730    hapd1 = hostapd.add_ap(apdev[1], params)
3731
3732    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase)
3733
3734def test_ap_ft_diff_mobility_domain_over_ds(dev, apdev):
3735    """WPA2-PSK-FT AP and different mobility domain (over DS)"""
3736    ssid = "test-ft"
3737    passphrase = "12345678"
3738
3739    params = ft_params1(ssid=ssid, passphrase=passphrase)
3740    hapd0 = hostapd.add_ap(apdev[0], params)
3741    params = ft_params2(ssid=ssid, passphrase=passphrase,
3742                        mobility_domain="c3d4")
3743    hapd1 = hostapd.add_ap(apdev[1], params)
3744
3745    dev[0].connect(ssid, proto="WPA2", key_mgmt="FT-PSK", psk=passphrase,
3746                   scan_freq="2412")
3747    if dev[0].get_status_field('bssid') == apdev[0]['bssid']:
3748        dst = apdev[1]['bssid']
3749    else:
3750        dst = apdev[0]['bssid']
3751    dev[0].scan_for_bss(dst, freq="2412")
3752    if "FAIL" not in dev[0].request("FT_DS " + dst):
3753        raise Exception("FT_DS to another mobility domain accepted")
3754
3755def test_ap_ft_eap_dynamic_rxkhs(dev, apdev):
3756    """FT with dynamic RxKHs configuration"""
3757    fd1, fn1 = tempfile.mkstemp()
3758    fd2, fn2 = tempfile.mkstemp()
3759    try:
3760        f1 = os.fdopen(fd1, 'w')
3761        f2 = os.fdopen(fd2, 'w')
3762        run_ap_ft_eap_dynamic_rxkhs(dev, apdev, f1, fn1, f2, fn2)
3763    finally:
3764        os.unlink(fn1)
3765        os.unlink(fn2)
3766
3767def run_ap_ft_eap_dynamic_rxkhs(dev, apdev, f1, fn1, f2, fn2):
3768    ssid = "test-ft"
3769    passphrase = "12345678"
3770
3771    bssid0 = apdev[0]['bssid']
3772    bssid1 = apdev[1]['bssid']
3773
3774    radius = hostapd.radius_params()
3775
3776    f1.write('r0kh=' + bssid1 + ' nas2.w1.fi 300102030405060708090a0b0c0d0e0f300102030405060708090a0b0c0d0e0f\n')
3777    f1.write('r1kh=' + bssid1 + ' 00:01:02:03:04:06 200102030405060708090a0b0c0d0e0f200102030405060708090a0b0c0d0e0f\n')
3778    f1.close()
3779
3780    params = ft_params1a(rsn=True, ssid=ssid, passphrase=passphrase)
3781    params["ieee80211w"] = "2"
3782    params['wpa_key_mgmt'] = "FT-EAP"
3783    params["ieee8021x"] = "1"
3784    params["rxkh_file"] = fn1
3785    params = dict(list(radius.items()) + list(params.items()))
3786    hapd0 = hostapd.add_ap(apdev[0], params)
3787
3788    if len(hapd0.request("GET_RXKHS").splitlines()) != 2:
3789        raise Exception("Unexpected number of RxKHs (AP0)")
3790
3791    params = ft_params2a(rsn=True, ssid=ssid, passphrase=passphrase)
3792    params["ieee80211w"] = "2"
3793    params['wpa_key_mgmt'] = "FT-EAP"
3794    params["ieee8021x"] = "1"
3795    params["rxkh_file"] = fn2
3796    params = dict(list(radius.items()) + list(params.items()))
3797    hapd1 = hostapd.add_ap(apdev[1], params)
3798
3799    if len(hapd1.request("GET_RXKHS").splitlines()) != 0:
3800        raise Exception("Unexpected number of RxKHs (AP1a)")
3801
3802    bssid = run_roams(dev[1], apdev, hapd0, hapd1, ssid, passphrase, eap=True,
3803                      return_after_initial=True)
3804    # This roam attempt fails since the APs did not yet have matching RxKH
3805    # configuration.
3806    dev[1].roam(bssid, check_bssid=False)
3807
3808    f2.write('r0kh=' + bssid0 + ' nas1.w1.fi 200102030405060708090a0b0c0d0e0f200102030405060708090a0b0c0d0e0f\n')
3809    f2.write('r1kh=' + bssid0 + ' 00:01:02:03:04:05 300102030405060708090a0b0c0d0e0f300102030405060708090a0b0c0d0e0f\n')
3810    f2.close()
3811    if "OK" not in hapd1.request("RELOAD_RXKHS"):
3812        raise Exception("Failed to reload RxKHs")
3813
3814    if len(hapd1.request("GET_RXKHS").splitlines()) != 2:
3815        raise Exception("Unexpected number of RxKHs (AP1b)")
3816
3817    run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, eap=True)
3818
3819def test_ap_ft_ssid_verified(dev, apdev):
3820    """WPA2-PSK-FT and ssid_verified=1 indication"""
3821    hapd0, hapd1 = start_ft(apdev)
3822    run_roams(dev[0], apdev, hapd0, hapd1, "test-ft", "12345678",
3823              check_ssid=True)
3824