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