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