1# Protected management frames tests
2# Copyright (c) 2013-2024, Jouni Malinen <j@w1.fi>
3#
4# This software may be distributed under the terms of the BSD license.
5# See README for more details.
6
7from remotehost import remote_compatible
8import binascii
9import os
10import time
11import logging
12logger = logging.getLogger()
13
14import hwsim_utils
15import hostapd
16from utils import *
17from wlantest import Wlantest
18from wpasupplicant import WpaSupplicant
19from test_eap_proto import rx_msg, tx_msg, proxy_msg
20
21@remote_compatible
22def test_ap_pmf_required(dev, apdev):
23    """WPA2-PSK AP with PMF required"""
24    ssid = "test-pmf-required"
25    params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
26    params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
27    params["ieee80211w"] = "2"
28    hapd = hostapd.add_ap(apdev[0], params)
29    Wlantest.setup(hapd)
30    wt = Wlantest()
31    wt.flush()
32    wt.add_passphrase("12345678")
33    key_mgmt = hapd.get_config()['key_mgmt']
34    if key_mgmt.split(' ')[0] != "WPA-PSK-SHA256":
35        raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
36    dev[0].connect(ssid, psk="12345678", ieee80211w="1",
37                   key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
38                   scan_freq="2412")
39    if "[WPA2-PSK-SHA256-CCMP]" not in dev[0].request("SCAN_RESULTS"):
40        raise Exception("Scan results missing RSN element info")
41    hwsim_utils.test_connectivity(dev[0], hapd)
42    dev[1].connect(ssid, psk="12345678", ieee80211w="2",
43                   key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
44                   scan_freq="2412")
45    hwsim_utils.test_connectivity(dev[1], hapd)
46    if "OK" not in hapd.request("SA_QUERY " + dev[0].own_addr()):
47        raise Exception("SA_QUERY failed")
48    if "OK" not in hapd.request("SA_QUERY " + dev[1].own_addr()):
49        raise Exception("SA_QUERY failed")
50    if "FAIL" not in hapd.request("SA_QUERY foo"):
51        raise Exception("Invalid SA_QUERY accepted")
52    wt.require_ap_pmf_mandatory(apdev[0]['bssid'])
53    wt.require_sta_pmf(apdev[0]['bssid'], dev[0].p2p_interface_addr())
54    wt.require_sta_pmf_mandatory(apdev[0]['bssid'], dev[1].p2p_interface_addr())
55    time.sleep(0.1)
56    if wt.get_sta_counter("valid_saqueryresp_tx", apdev[0]['bssid'],
57                          dev[0].p2p_interface_addr()) < 1:
58        raise Exception("STA did not reply to SA Query")
59    if wt.get_sta_counter("valid_saqueryresp_tx", apdev[0]['bssid'],
60                          dev[1].p2p_interface_addr()) < 1:
61        raise Exception("STA did not reply to SA Query")
62
63def start_ocv_ap(apdev):
64    ssid = "test-pmf-required"
65    params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
66    params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
67    params["ieee80211w"] = "2"
68    params["ocv"] = "1"
69    try:
70        hapd = hostapd.add_ap(apdev, params)
71    except Exception as e:
72        if "Failed to set hostapd parameter ocv" in str(e):
73            raise HwsimSkip("OCV not supported")
74        raise
75
76    Wlantest.setup(hapd)
77    wt = Wlantest()
78    wt.flush()
79    wt.add_passphrase("12345678")
80
81    return hapd, ssid, wt
82
83@remote_compatible
84def test_ocv_sa_query(dev, apdev):
85    """Test SA Query with OCV"""
86    hapd, ssid, wt = start_ocv_ap(apdev[0])
87    dev[0].connect(ssid, psk="12345678", ieee80211w="1", ocv="1",
88                   key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
89                   scan_freq="2412")
90    hapd.wait_sta() # wait so we can actually request SA_QUERY
91    # Test that client can handle SA Query with OCI element
92    if "OK" not in hapd.request("SA_QUERY " + dev[0].own_addr()):
93        raise Exception("SA_QUERY failed")
94    ev = hapd.wait_event(["OCV-FAILURE"], timeout=0.1)
95    if ev:
96        raise Exception("Unexpected OCV failure reported")
97    if wt.get_sta_counter("valid_saqueryresp_tx", apdev[0]['bssid'],
98                          dev[0].own_addr()) < 1:
99        raise Exception("STA did not reply to SA Query")
100
101    # Test that AP can handle SA Query with OCI element
102    if "OK" not in dev[0].request("UNPROT_DEAUTH"):
103        raise Exception("Triggering SA Query from the STA failed")
104    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=3)
105    if ev is not None:
106        raise Exception("SA Query from the STA failed")
107
108@remote_compatible
109def test_ocv_sa_query_csa(dev, apdev):
110    """Test SA Query with OCV after channel switch"""
111    hapd, ssid, wt = start_ocv_ap(apdev[0])
112    dev[0].connect(ssid, psk="12345678", ieee80211w="1", ocv="1",
113                   key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
114                   scan_freq="2412")
115
116    hapd.request("CHAN_SWITCH 5 2437 ht")
117    time.sleep(1)
118    if wt.get_sta_counter("valid_saqueryreq_tx", apdev[0]['bssid'],
119                          dev[0].own_addr()) < 1:
120        raise Exception("STA did not start SA Query after channel switch")
121
122    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=16)
123    if ev is not None:
124        raise Exception("Unexpected disconnection")
125
126def test_ocv_sa_query_csa_no_resp(dev, apdev):
127    """Test SA Query with OCV after channel switch getting no response"""
128    hapd, ssid, wt = start_ocv_ap(apdev[0])
129    dev[0].connect(ssid, psk="12345678", ieee80211w="1", ocv="1",
130                   key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
131                   scan_freq="2412")
132
133    hapd.set("ext_mgmt_frame_handling", "1")
134    hapd.request("CHAN_SWITCH 5 2437 ht")
135    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=5)
136    if ev is None:
137        raise Exception("Disconnection after CSA not reported")
138    if "locally_generated=1" not in ev:
139        raise Exception("Unexpectedly disconnected by AP: " + ev)
140
141def test_ocv_sa_query_csa_missing(dev, apdev):
142    """Test SA Query with OCV missing after channel switch"""
143    hapd, ssid, wt = start_ocv_ap(apdev[0])
144    dev[0].connect(ssid, psk="12345678", ieee80211w="1", ocv="1",
145                   key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
146                   scan_freq="2412")
147    hapd.wait_sta() # wait so kernel won't drop deauth frame (MFP)
148    hapd.set("ext_mgmt_frame_handling", "1")
149    dev[0].request("DISCONNECT")
150    dev[0].wait_disconnected()
151    ev = hapd.wait_event(['MGMT-RX'], timeout=5)
152    if ev is None:
153        raise Exception("Deauthentication frame RX not reported")
154    hapd.set("ext_mgmt_frame_handling", "0")
155    hapd.request("CHAN_SWITCH 5 2437 ht")
156    ev = hapd.wait_event(["AP-STA-DISCONNECTED"], timeout=20)
157    if ev is None:
158        raise Exception("No disconnection event received from hostapd")
159
160@remote_compatible
161def test_ap_pmf_optional(dev, apdev):
162    """WPA2-PSK AP with PMF optional"""
163    ssid = "test-pmf-optional"
164    params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
165    params["wpa_key_mgmt"] = "WPA-PSK"
166    params["ieee80211w"] = "1"
167    hapd = hostapd.add_ap(apdev[0], params)
168    Wlantest.setup(hapd)
169    wt = Wlantest()
170    wt.flush()
171    wt.add_passphrase("12345678")
172    dev[0].connect(ssid, psk="12345678", ieee80211w="1",
173                   key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
174                   scan_freq="2412")
175    hwsim_utils.test_connectivity(dev[0], hapd)
176    dev[1].connect(ssid, psk="12345678", ieee80211w="2",
177                   key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
178                   scan_freq="2412")
179    hwsim_utils.test_connectivity(dev[1], hapd)
180    wt.require_ap_pmf_optional(apdev[0]['bssid'])
181    wt.require_sta_pmf(apdev[0]['bssid'], dev[0].p2p_interface_addr())
182    wt.require_sta_pmf_mandatory(apdev[0]['bssid'], dev[1].p2p_interface_addr())
183
184@remote_compatible
185def test_ap_pmf_optional_2akm(dev, apdev):
186    """WPA2-PSK AP with PMF optional (2 AKMs)"""
187    ssid = "test-pmf-optional-2akm"
188    params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
189    params["wpa_key_mgmt"] = "WPA-PSK WPA-PSK-SHA256"
190    params["ieee80211w"] = "1"
191    hapd = hostapd.add_ap(apdev[0], params)
192    Wlantest.setup(hapd)
193    wt = Wlantest()
194    wt.flush()
195    wt.add_passphrase("12345678")
196    dev[0].connect(ssid, psk="12345678", ieee80211w="1",
197                   key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
198                   scan_freq="2412")
199    hwsim_utils.test_connectivity(dev[0], hapd)
200    dev[1].connect(ssid, psk="12345678", ieee80211w="2",
201                   key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
202                   scan_freq="2412")
203    hwsim_utils.test_connectivity(dev[1], hapd)
204    wt.require_ap_pmf_optional(apdev[0]['bssid'])
205    wt.require_sta_pmf(apdev[0]['bssid'], dev[0].p2p_interface_addr())
206    wt.require_sta_key_mgmt(apdev[0]['bssid'], dev[0].p2p_interface_addr(),
207                            "PSK-SHA256")
208    wt.require_sta_pmf_mandatory(apdev[0]['bssid'], dev[1].p2p_interface_addr())
209    wt.require_sta_key_mgmt(apdev[0]['bssid'], dev[1].p2p_interface_addr(),
210                            "PSK-SHA256")
211
212@remote_compatible
213def test_ap_pmf_negative(dev, apdev):
214    """WPA2-PSK AP without PMF (negative test)"""
215    ssid = "test-pmf-negative"
216    params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
217    hapd = hostapd.add_ap(apdev[0], params)
218    Wlantest.setup(hapd)
219    wt = Wlantest()
220    wt.flush()
221    wt.add_passphrase("12345678")
222    dev[0].connect(ssid, psk="12345678", ieee80211w="1",
223                   key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
224                   scan_freq="2412")
225    hwsim_utils.test_connectivity(dev[0], hapd)
226    try:
227        dev[1].connect(ssid, psk="12345678", ieee80211w="2",
228                       key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
229                       scan_freq="2412")
230        hwsim_utils.test_connectivity(dev[1], hapd)
231        raise Exception("PMF required STA connected to no PMF AP")
232    except Exception as e:
233        logger.debug("Ignore expected exception: " + str(e))
234    wt.require_ap_no_pmf(apdev[0]['bssid'])
235
236@remote_compatible
237def test_ap_pmf_assoc_comeback(dev, apdev):
238    """WPA2-PSK AP with PMF association comeback"""
239    run_ap_pmf_assoc_comeback(dev, apdev)
240
241def test_ap_pmf_assoc_comeback_10000tu(dev, apdev):
242    """WPA2-PSK AP with PMF association comeback (10000 TUs)"""
243    run_ap_pmf_assoc_comeback(dev, apdev, comeback=10000)
244
245def run_ap_pmf_assoc_comeback(dev, apdev, comeback=None):
246    ssid = "assoc-comeback"
247    params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
248    params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
249    params["ieee80211w"] = "2"
250    if comeback is not None:
251        params["assoc_sa_query_max_timeout"] = str(comeback)
252    hapd = hostapd.add_ap(apdev[0], params)
253    Wlantest.setup(hapd)
254    wt = Wlantest()
255    wt.flush()
256    wt.add_passphrase("12345678")
257    dev[0].connect(ssid, psk="12345678", ieee80211w="1",
258                   key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
259                   scan_freq="2412")
260    hapd.wait_sta(wait_4way_hs=True)
261    hapd.set("ext_mgmt_frame_handling", "1")
262    dev[0].request("DISCONNECT")
263    dev[0].wait_disconnected(timeout=10)
264    ev = hapd.wait_event(["MGMT-RX"], timeout=1)
265    if ev is None:
266        raise Exception("Deauthentication frame RX not reported")
267    hapd.set("ext_mgmt_frame_handling", "0")
268    dev[0].request("REASSOCIATE")
269    dev[0].wait_connected(timeout=20, error="Timeout on re-connection")
270    hapd.wait_4way_hs()
271    if wt.get_sta_counter("assocresp_comeback", apdev[0]['bssid'],
272                          dev[0].p2p_interface_addr()) < 1:
273        raise Exception("AP did not use association comeback request")
274
275def test_ap_pmf_assoc_comeback_in_wpas(dev, apdev):
276    """WPA2-PSK AP with PMF association comeback in wpa_supplicant"""
277    ssid = "assoc-comeback"
278    params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
279    params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
280    params["ieee80211w"] = "2"
281    params["test_assoc_comeback_type"] = "255"
282    hapd = hostapd.add_ap(apdev[0], params)
283
284    dev[0].set("test_assoc_comeback_type", "255")
285    dev[0].connect(ssid, psk="12345678", ieee80211w="1",
286                   key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
287                   scan_freq="2412")
288    hapd.wait_sta(wait_4way_hs=True)
289    hapd.set("ext_mgmt_frame_handling", "1")
290    dev[0].request("DISCONNECT")
291    dev[0].wait_disconnected(timeout=10)
292    ev = hapd.wait_event(["MGMT-RX"], timeout=1)
293    if ev is None:
294        raise Exception("Deauthentication frame RX not reported")
295    hapd.set("ext_mgmt_frame_handling", "0")
296    dev[0].request("REASSOCIATE")
297    ev = dev[0].wait_event(["CTRL-EVENT-ASSOC-REJECT"], timeout=10)
298    if ev is None or "status_code=30" not in ev:
299        raise Exception("Association comeback not requested")
300    ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
301                            "CTRL-EVENT-ASSOC-REJECT"], timeout=10)
302    if ev is None:
303        raise Exception("Association not reported")
304    if "CTRL-EVENT-ASSOC-REJECT" in ev:
305        raise Exception("Unexpected association rejection: " + ev)
306    hapd.wait_4way_hs()
307
308    hapd.set("ext_mgmt_frame_handling", "1")
309    dev[0].request("DISCONNECT")
310    dev[0].wait_disconnected(timeout=10)
311    ev = hapd.wait_event(["MGMT-RX"], timeout=1)
312    if ev is None:
313        raise Exception("Deauthentication frame RX not reported")
314    hapd.set("ext_mgmt_frame_handling", "0")
315    dev[0].set("test_assoc_comeback_type", "254")
316    dev[0].request("REASSOCIATE")
317    ev = dev[0].wait_event(["CTRL-EVENT-ASSOC-REJECT"], timeout=10)
318    if ev is None or "status_code=30" not in ev:
319        raise Exception("Association comeback not requested")
320    ev = dev[0].wait_event(["SME: Temporary assoc reject: missing association comeback time",
321                            "CTRL-EVENT-CONNECTED",
322                            "CTRL-EVENT-ASSOC-REJECT"], timeout=10)
323    if ev is None:
324        raise Exception("Association not reported")
325    if "SME: Temporary assoc reject: missing association comeback time" not in ev:
326        raise Exception("Unexpected result: " + ev)
327    dev[0].wait_connected(timeout=20, error="Timeout on re-connection with misbehaving AP")
328    hapd.wait_4way_hs()
329
330@remote_compatible
331def test_ap_pmf_assoc_comeback2(dev, apdev):
332    """WPA2-PSK AP with PMF association comeback (using DROP_SA)"""
333    ssid = "assoc-comeback"
334    params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
335    params["wpa_key_mgmt"] = "WPA-PSK"
336    params["ieee80211w"] = "1"
337    hapd = hostapd.add_ap(apdev[0], params)
338    Wlantest.setup(hapd)
339    wt = Wlantest()
340    wt.flush()
341    wt.add_passphrase("12345678")
342    dev[0].connect(ssid, psk="12345678", ieee80211w="2",
343                   key_mgmt="WPA-PSK", proto="WPA2", scan_freq="2412")
344    if "OK" not in dev[0].request("DROP_SA"):
345        raise Exception("DROP_SA failed")
346    dev[0].request("REASSOCIATE")
347    dev[0].wait_connected(timeout=10, error="Timeout on re-connection")
348    if wt.get_sta_counter("reassocresp_comeback", apdev[0]['bssid'],
349                          dev[0].p2p_interface_addr()) < 1:
350        raise Exception("AP did not use reassociation comeback request")
351
352@remote_compatible
353def test_ap_pmf_assoc_comeback3(dev, apdev):
354    """WPA2-PSK AP with PMF association comeback (using radio_disabled)"""
355    drv_flags = dev[0].get_driver_status_field("capa.flags")
356    if int(drv_flags, 0) & 0x20 == 0:
357        raise HwsimSkip("Driver does not support radio_disabled")
358    ssid = "assoc-comeback"
359    params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
360    params["wpa_key_mgmt"] = "WPA-PSK"
361    params["ieee80211w"] = "1"
362    hapd = hostapd.add_ap(apdev[0], params)
363    Wlantest.setup(hapd)
364    wt = Wlantest()
365    wt.flush()
366    wt.add_passphrase("12345678")
367    dev[0].connect(ssid, psk="12345678", ieee80211w="2",
368                   key_mgmt="WPA-PSK", proto="WPA2", scan_freq="2412")
369    dev[0].set("radio_disabled", "1")
370    dev[0].set("radio_disabled", "0")
371    dev[0].request("REASSOCIATE")
372    dev[0].wait_connected(timeout=10, error="Timeout on re-connection")
373    if wt.get_sta_counter("assocresp_comeback", apdev[0]['bssid'],
374                          dev[0].own_addr()) < 1:
375        raise Exception("AP did not use reassociation comeback request")
376
377@remote_compatible
378def test_ap_pmf_assoc_comeback_wps(dev, apdev):
379    """WPA2-PSK AP with PMF association comeback (WPS)"""
380    ssid = "assoc-comeback"
381    appin = "12345670"
382    params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
383    params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
384    params["ieee80211w"] = "2"
385    params["eap_server"] = "1"
386    params["wps_state"] = "2"
387    params["ap_pin"] = appin
388    hapd = hostapd.add_ap(apdev[0], params)
389    Wlantest.setup(hapd)
390    wt = Wlantest()
391    wt.flush()
392    wt.add_passphrase("12345678")
393    dev[0].connect(ssid, psk="12345678", ieee80211w="1",
394                   key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
395                   scan_freq="2412")
396    hapd.wait_sta(wait_4way_hs=True)
397    hapd.set("ext_mgmt_frame_handling", "1")
398    dev[0].request("DISCONNECT")
399    dev[0].wait_disconnected(timeout=10)
400    ev = hapd.wait_event(["MGMT-RX"], timeout=1)
401    if ev is None:
402        raise Exception("Deauthentication frame RX not reported")
403    hapd.set("ext_mgmt_frame_handling", "0")
404    dev[0].wps_reg(apdev[0]['bssid'], appin)
405    hapd.wait_4way_hs()
406    if wt.get_sta_counter("assocresp_comeback", apdev[0]['bssid'],
407                          dev[0].p2p_interface_addr()) < 1:
408        raise Exception("AP did not use association comeback request")
409
410def test_ap_pmf_ap_dropping_sa(dev, apdev):
411    """WPA2-PSK PMF AP dropping SA"""
412    ssid = "pmf"
413    params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
414    params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
415    params["ieee80211w"] = "2"
416    hapd = hostapd.add_ap(apdev[0], params)
417    bssid = hapd.own_addr()
418    Wlantest.setup(hapd)
419    wt = Wlantest()
420    wt.flush()
421    wt.add_passphrase("12345678")
422    dev[0].connect(ssid, psk="12345678", ieee80211w="2",
423                   key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
424    addr0 = dev[0].own_addr()
425    dev[0].dump_monitor()
426    hapd.wait_sta()
427    # Drop SA and association at the AP locally without notifying the STA. This
428    # results in the STA getting unprotected Deauthentication frames when trying
429    # to transmit the next Class 3 frame.
430    if "OK" not in hapd.request("DEAUTHENTICATE " + addr0 + " tx=0"):
431        raise Exception("DEAUTHENTICATE command failed")
432    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1)
433    if ev is not None:
434        raise Exception("Unexpected disconnection event after DEAUTHENTICATE tx=0: " + ev)
435    dev[0].request("DATA_TEST_CONFIG 1")
436    dev[0].request("DATA_TEST_TX " + bssid + " " + addr0)
437    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=5)
438    dev[0].request("DATA_TEST_CONFIG 0")
439    if ev is None or "locally_generated=1" not in ev:
440        raise Exception("Locally generated disconnection not reported")
441
442def test_ap_pmf_valid_broadcast_deauth(dev, apdev):
443    """WPA2-PSK PMF AP sending valid broadcast deauth without dropping SA"""
444    run_ap_pmf_valid(dev, apdev, False, True)
445
446def test_ap_pmf_valid_broadcast_disassoc(dev, apdev):
447    """WPA2-PSK PMF AP sending valid broadcast disassoc without dropping SA"""
448    run_ap_pmf_valid(dev, apdev, True, True)
449
450def test_ap_pmf_valid_unicast_deauth(dev, apdev):
451    """WPA2-PSK PMF AP sending valid unicast deauth without dropping SA"""
452    run_ap_pmf_valid(dev, apdev, False, False)
453
454def test_ap_pmf_valid_unicast_disassoc(dev, apdev):
455    """WPA2-PSK PMF AP sending valid unicast disassoc without dropping SA"""
456    run_ap_pmf_valid(dev, apdev, True, False)
457
458def run_ap_pmf_valid(dev, apdev, disassociate, broadcast):
459    ssid = "pmf"
460    params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
461    params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
462    params["ieee80211w"] = "2"
463    hapd = hostapd.add_ap(apdev[0], params)
464    bssid = hapd.own_addr()
465    Wlantest.setup(hapd)
466    wt = Wlantest()
467    wt.flush()
468    wt.add_passphrase("12345678")
469    dev[0].connect(ssid, psk="12345678", ieee80211w="2",
470                   key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
471    addr0 = dev[0].own_addr()
472    dev[0].dump_monitor()
473    hapd.wait_sta()
474    cmd = "DISASSOCIATE " if disassociate else "DEAUTHENTICATE "
475    cmd += "ff:ff:ff:ff:ff:ff" if broadcast else addr0
476    cmd += " test=1"
477    if "OK" not in hapd.request(cmd):
478        raise Exception("hostapd command failed")
479    sta = hapd.get_sta(addr0)
480    if not sta:
481        raise Exception("STA entry lost")
482    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=5)
483    if ev is None:
484        raise Exception("Disconnection not reported")
485    if "locally_generated=1" in ev:
486        raise Exception("Unexpected locally generated disconnection")
487
488    # Wait for SA Query procedure to fail and association comeback to succeed
489    dev[0].wait_connected()
490
491def start_wpas_ap(ssid):
492    wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
493    wpas.interface_add("wlan5", drv_params="use_monitor=1")
494    id = wpas.add_network()
495    wpas.set_network(id, "mode", "2")
496    wpas.set_network_quoted(id, "ssid", ssid)
497    wpas.set_network(id, "proto", "WPA2")
498    wpas.set_network(id, "key_mgmt", "WPA-PSK-SHA256")
499    wpas.set_network(id, "ieee80211w", "2")
500    wpas.set_network_quoted(id, "psk", "12345678")
501    wpas.set_network(id, "pairwise", "CCMP")
502    wpas.set_network(id, "group", "CCMP")
503    wpas.set_network(id, "frequency", "2412")
504    wpas.set_network(id, "scan_freq", "2412")
505    wpas.connect_network(id)
506    wpas.dump_monitor()
507    return wpas
508
509def test_ap_pmf_sta_sa_query(dev, apdev):
510    """WPA2-PSK AP with station using SA Query"""
511    ssid = "assoc-comeback"
512    addr = dev[0].own_addr()
513
514    wpas = start_wpas_ap(ssid)
515    bssid = wpas.own_addr()
516
517    Wlantest.setup(wpas)
518    wt = Wlantest()
519    wt.flush()
520    wt.add_passphrase("12345678")
521
522    dev[0].connect(ssid, psk="12345678", ieee80211w="1",
523                   key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
524                   scan_freq="2412")
525    wpas.dump_monitor()
526    wpas.request("DEAUTHENTICATE " + addr + " test=0")
527    wpas.dump_monitor()
528    wpas.request("DISASSOCIATE " + addr + " test=0")
529    wpas.dump_monitor()
530    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1)
531    if ev is not None:
532        raise Exception("Unexpected disconnection")
533
534    wpas.request("DEAUTHENTICATE " + addr + " reason=6 test=0")
535    wpas.dump_monitor()
536    wpas.request("DISASSOCIATE " + addr + " reason=7 test=0")
537    wpas.dump_monitor()
538    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1)
539    if ev is not None:
540        raise Exception("Unexpected disconnection")
541    if wt.get_sta_counter("valid_saqueryreq_tx", bssid, addr) < 1:
542        raise Exception("STA did not send SA Query")
543    if wt.get_sta_counter("valid_saqueryresp_rx", bssid, addr) < 1:
544        raise Exception("AP did not reply to SA Query")
545    wpas.dump_monitor()
546
547def test_ap_pmf_sta_sa_query_no_response(dev, apdev):
548    """WPA2-PSK AP with station using SA Query and getting no response"""
549    ssid = "assoc-comeback"
550    addr = dev[0].own_addr()
551
552    wpas = start_wpas_ap(ssid)
553    bssid = wpas.own_addr()
554
555    dev[0].connect(ssid, psk="12345678", ieee80211w="1",
556                   key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
557                   scan_freq="2412")
558    wpas.dump_monitor()
559    wpas.request("DEAUTHENTICATE " + addr + " test=0")
560    wpas.dump_monitor()
561    wpas.request("DISASSOCIATE " + addr + " test=0")
562    wpas.dump_monitor()
563    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1)
564    if ev is not None:
565        raise Exception("Unexpected disconnection")
566
567    wpas.request("SET ext_mgmt_frame_handling 1")
568    wpas.request("DEAUTHENTICATE " + addr + " reason=6 test=0")
569    wpas.dump_monitor()
570    wpas.request("DISASSOCIATE " + addr + " reason=7 test=0")
571    wpas.dump_monitor()
572    dev[0].wait_disconnected()
573    wpas.dump_monitor()
574    wpas.request("SET ext_mgmt_frame_handling 0")
575    dev[0].wait_connected()
576    wpas.dump_monitor()
577
578def test_ap_pmf_sta_unprot_deauth_burst(dev, apdev):
579    """WPA2-PSK AP with station receiving burst of unprotected Deauthentication frames"""
580    ssid = "deauth-attack"
581    addr = dev[0].own_addr()
582
583    wpas = start_wpas_ap(ssid)
584    bssid = wpas.own_addr()
585
586    Wlantest.setup(wpas)
587    wt = Wlantest()
588    wt.flush()
589    wt.add_passphrase("12345678")
590
591    dev[0].connect(ssid, psk="12345678", ieee80211w="1",
592                   key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
593                   scan_freq="2412")
594
595    for i in range(0, 10):
596        wpas.request("DEAUTHENTICATE " + addr + " reason=6 test=0")
597        wpas.request("DISASSOCIATE " + addr + " reason=7 test=0")
598    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1)
599    if ev is not None:
600        raise Exception("Unexpected disconnection")
601    num_req = wt.get_sta_counter("valid_saqueryreq_tx", bssid, addr)
602    num_resp = wt.get_sta_counter("valid_saqueryresp_rx", bssid, addr)
603    if num_req < 1:
604        raise Exception("STA did not send SA Query")
605    if num_resp < 1:
606        raise Exception("AP did not reply to SA Query")
607    if num_req > 1:
608        raise Exception("STA initiated too many SA Query procedures (%d)" % num_req)
609
610    time.sleep(10)
611    for i in range(0, 5):
612        wpas.request("DEAUTHENTICATE " + addr + " reason=6 test=0")
613        wpas.request("DISASSOCIATE " + addr + " reason=7 test=0")
614    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1)
615    if ev is not None:
616        raise Exception("Unexpected disconnection")
617    num_req = wt.get_sta_counter("valid_saqueryreq_tx", bssid, addr)
618    num_resp = wt.get_sta_counter("valid_saqueryresp_rx", bssid, addr)
619    if num_req != 2 or num_resp != 2:
620        raise Exception("Unexpected number of SA Query procedures (req=%d resp=%d)" % (num_req, num_resp))
621
622def test_ap_pmf_sta_sa_query_oom(dev, apdev):
623    """WPA2-PSK AP with station using SA Query (OOM)"""
624    ssid = "assoc-comeback"
625    addr = dev[0].own_addr()
626    wpas = start_wpas_ap(ssid)
627    dev[0].connect(ssid, psk="12345678", ieee80211w="1",
628                   key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
629                   scan_freq="2412")
630    with alloc_fail(dev[0], 1, "=sme_sa_query_timer"):
631        wpas.request("DEAUTHENTICATE " + addr + " reason=6 test=0")
632        wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
633    dev[0].request("DISCONNECT")
634    wpas.request("DISCONNECT")
635    dev[0].wait_disconnected()
636
637def test_ap_pmf_sta_sa_query_local_failure(dev, apdev):
638    """WPA2-PSK AP with station using SA Query (local failure)"""
639    ssid = "assoc-comeback"
640    addr = dev[0].own_addr()
641    wpas = start_wpas_ap(ssid)
642    dev[0].connect(ssid, psk="12345678", ieee80211w="1",
643                   key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
644                   scan_freq="2412")
645    with fail_test(dev[0], 1, "os_get_random;sme_sa_query_timer"):
646        wpas.request("DEAUTHENTICATE " + addr + " reason=6 test=0")
647        wait_fail_trigger(dev[0], "GET_FAIL")
648    dev[0].request("DISCONNECT")
649    wpas.request("DISCONNECT")
650    dev[0].wait_disconnected()
651
652def test_ap_pmf_sta_sa_query_hostapd(dev, apdev):
653    """WPA2-PSK AP with station using SA Query (hostapd)"""
654    ssid = "assoc-comeback"
655    passphrase = "12345678"
656    addr = dev[0].own_addr()
657
658    params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase,
659                                 wpa_key_mgmt="WPA-PSK-SHA256",
660                                 ieee80211w="2")
661    hapd = hostapd.add_ap(apdev[0], params)
662    bssid = hapd.own_addr()
663
664    Wlantest.setup(hapd)
665    wt = Wlantest()
666    wt.flush()
667    wt.add_passphrase("12345678")
668
669    dev[0].connect(ssid, psk=passphrase, ieee80211w="2",
670                   key_mgmt="WPA-PSK-SHA256", proto="WPA2",
671                   scan_freq="2412")
672    hapd.wait_sta()
673    if "OK" not in hapd.request("DEAUTHENTICATE " + addr + " test=0") or \
674       "OK" not in hapd.request("DISASSOCIATE " + addr + " test=0"):
675        raise Exception("Failed to send unprotected disconnection messages")
676    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1)
677    if ev is not None:
678        raise Exception("Unexpected disconnection")
679
680    if "OK" not in hapd.request("DEAUTHENTICATE " + addr + " reason=6 test=0") or \
681       "OK" not in hapd.request("DISASSOCIATE " + addr + " reason=7 test=0"):
682        raise Exception("Failed to send unprotected disconnection messages (2)")
683    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1)
684    if ev is not None:
685        raise Exception("Unexpected disconnection")
686    if wt.get_sta_counter("valid_saqueryreq_tx", bssid, addr) < 1:
687        raise Exception("STA did not send SA Query")
688    if wt.get_sta_counter("valid_saqueryresp_rx", bssid, addr) < 1:
689        raise Exception("AP did not reply to SA Query")
690
691def test_ap_pmf_sta_sa_query_no_response_hostapd(dev, apdev):
692    """WPA2-PSK AP with station using SA Query and getting no response (hostapd)"""
693    ssid = "assoc-comeback"
694    passphrase = "12345678"
695    addr = dev[0].own_addr()
696
697    params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase,
698                                 wpa_key_mgmt="WPA-PSK-SHA256",
699                                 ieee80211w="2")
700    hapd = hostapd.add_ap(apdev[0], params)
701    bssid = hapd.own_addr()
702
703    Wlantest.setup(hapd)
704    wt = Wlantest()
705    wt.flush()
706    wt.add_passphrase("12345678")
707
708    dev[0].connect(ssid, psk=passphrase, ieee80211w="2",
709                   key_mgmt="WPA-PSK-SHA256", proto="WPA2",
710                   scan_freq="2412")
711    hapd.wait_sta()
712    hapd.set("ext_mgmt_frame_handling", "1")
713    if "OK" not in hapd.request("DEAUTHENTICATE " + addr + " reason=6 test=0") or \
714       "OK" not in hapd.request("DISASSOCIATE " + addr + " reason=7 test=0"):
715        raise Exception("Failed to send unprotected disconnection messages")
716    dev[0].wait_disconnected()
717    hapd.set("ext_mgmt_frame_handling", "0")
718    if wt.get_sta_counter("valid_saqueryreq_tx", bssid, addr) < 1:
719        raise Exception("STA did not send SA Query")
720    if wt.get_sta_counter("valid_saqueryresp_rx", bssid, addr) > 0:
721        raise Exception("AP replied to SA Query")
722    dev[0].wait_connected()
723
724def test_ap_pmf_sta_unprot_deauth_burst_hostapd(dev, apdev):
725    """WPA2-PSK AP with station receiving burst of unprotected Deauthentication frames (hostapd)"""
726    ssid = "deauth-attack"
727    passphrase = "12345678"
728    addr = dev[0].own_addr()
729
730    params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase,
731                                 wpa_key_mgmt="WPA-PSK-SHA256",
732                                 ieee80211w="2")
733    hapd = hostapd.add_ap(apdev[0], params)
734    bssid = hapd.own_addr()
735
736    Wlantest.setup(hapd)
737    wt = Wlantest()
738    wt.flush()
739    wt.add_passphrase("12345678")
740
741    dev[0].connect(ssid, psk=passphrase, ieee80211w="2",
742                   key_mgmt="WPA-PSK-SHA256", proto="WPA2",
743                   scan_freq="2412")
744    hapd.wait_sta()
745    for i in range(10):
746        if "OK" not in hapd.request("DEAUTHENTICATE " + addr + " reason=6 test=0") or \
747           "OK" not in hapd.request("DISASSOCIATE " + addr + " reason=7 test=0"):
748            raise Exception("Failed to send unprotected disconnection messages")
749    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1)
750    if ev is not None:
751        raise Exception("Unexpected disconnection")
752    num_req = wt.get_sta_counter("valid_saqueryreq_tx", bssid, addr)
753    num_resp = wt.get_sta_counter("valid_saqueryresp_rx", bssid, addr)
754    if num_req < 1:
755        raise Exception("STA did not send SA Query")
756    if num_resp < 1:
757        raise Exception("AP did not reply to SA Query")
758    if num_req > 1:
759        raise Exception("STA initiated too many SA Query procedures (%d)" % num_req)
760
761    time.sleep(10)
762    for i in range(5):
763        if "OK" not in hapd.request("DEAUTHENTICATE " + addr + " reason=6 test=0") or \
764           "OK" not in hapd.request("DISASSOCIATE " + addr + " reason=7 test=0"):
765            raise Exception("Failed to send unprotected disconnection messages")
766    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1)
767    if ev is not None:
768        raise Exception("Unexpected disconnection")
769    num_req = wt.get_sta_counter("valid_saqueryreq_tx", bssid, addr)
770    num_resp = wt.get_sta_counter("valid_saqueryresp_rx", bssid, addr)
771    if num_req != 2 or num_resp != 2:
772        raise Exception("Unexpected number of SA Query procedures (req=%d resp=%d)" % (num_req, num_resp))
773
774def test_ap_pmf_required_eap(dev, apdev):
775    """WPA2-EAP AP with PMF required"""
776    ssid = "test-pmf-required-eap"
777    params = hostapd.wpa2_eap_params(ssid=ssid)
778    params["wpa_key_mgmt"] = "WPA-EAP-SHA256"
779    params["ieee80211w"] = "2"
780    hapd = hostapd.add_ap(apdev[0], params)
781    key_mgmt = hapd.get_config()['key_mgmt']
782    if key_mgmt.split(' ')[0] != "WPA-EAP-SHA256":
783        raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
784    dev[0].connect("test-pmf-required-eap", key_mgmt="WPA-EAP-SHA256",
785                   ieee80211w="2", eap="PSK", identity="psk.user@example.com",
786                   password_hex="0123456789abcdef0123456789abcdef",
787                   scan_freq="2412")
788    dev[1].connect("test-pmf-required-eap", key_mgmt="WPA-EAP WPA-EAP-SHA256",
789                   ieee80211w="1", eap="PSK", identity="psk.user@example.com",
790                   password_hex="0123456789abcdef0123456789abcdef",
791                   scan_freq="2412")
792
793def test_ap_pmf_optional_eap(dev, apdev):
794    """WPA2EAP AP with PMF optional"""
795    params = hostapd.wpa2_eap_params(ssid="test-wpa2-eap")
796    params["ieee80211w"] = "1"
797    hapd = hostapd.add_ap(apdev[0], params)
798    dev[0].connect("test-wpa2-eap", key_mgmt="WPA-EAP", eap="TTLS",
799                   identity="pap user", anonymous_identity="ttls",
800                   password="password",
801                   ca_cert="auth_serv/ca.pem", phase2="auth=PAP",
802                   ieee80211w="1", scan_freq="2412")
803    dev[1].connect("test-wpa2-eap", key_mgmt="WPA-EAP WPA-EAP-SHA256",
804                   eap="TTLS", identity="pap user", anonymous_identity="ttls",
805                   password="password",
806                   ca_cert="auth_serv/ca.pem", phase2="auth=PAP",
807                   ieee80211w="2", scan_freq="2412")
808
809@remote_compatible
810def test_ap_pmf_required_sha1(dev, apdev):
811    """WPA2-PSK AP with PMF required with SHA1 AKM"""
812    ssid = "test-pmf-required-sha1"
813    params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
814    params["wpa_key_mgmt"] = "WPA-PSK"
815    params["ieee80211w"] = "2"
816    hapd = hostapd.add_ap(apdev[0], params)
817    Wlantest.setup(hapd)
818    wt = Wlantest()
819    wt.flush()
820    wt.add_passphrase("12345678")
821    key_mgmt = hapd.get_config()['key_mgmt']
822    if key_mgmt.split(' ')[0] != "WPA-PSK":
823        raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
824    dev[0].connect(ssid, psk="12345678", ieee80211w="2",
825                   key_mgmt="WPA-PSK", proto="WPA2", scan_freq="2412")
826    if "[WPA2-PSK-CCMP]" not in dev[0].request("SCAN_RESULTS"):
827        raise Exception("Scan results missing RSN element info")
828    hwsim_utils.test_connectivity(dev[0], hapd)
829
830@remote_compatible
831def test_ap_pmf_toggle(dev, apdev):
832    """WPA2-PSK AP with PMF optional and changing PMF on reassociation"""
833    try:
834        _test_ap_pmf_toggle(dev, apdev)
835    finally:
836        dev[0].request("SET reassoc_same_bss_optim 0")
837
838def _test_ap_pmf_toggle(dev, apdev):
839    ssid = "test-pmf-optional"
840    params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
841    params["wpa_key_mgmt"] = "WPA-PSK"
842    params["ieee80211w"] = "1"
843    params["assoc_sa_query_max_timeout"] = "1"
844    params["assoc_sa_query_retry_timeout"] = "1"
845    hapd = hostapd.add_ap(apdev[0], params)
846    Wlantest.setup(hapd)
847    wt = Wlantest()
848    wt.flush()
849    wt.add_passphrase("12345678")
850    bssid = apdev[0]['bssid']
851    addr = dev[0].own_addr()
852    dev[0].request("SET reassoc_same_bss_optim 1")
853    id = dev[0].connect(ssid, psk="12345678", ieee80211w="1",
854                        key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
855                        scan_freq="2412")
856    wt.require_ap_pmf_optional(bssid)
857    wt.require_sta_pmf(bssid, addr)
858    sta = hapd.get_sta(addr)
859    if '[MFP]' not in sta['flags']:
860        raise Exception("MFP flag not present for STA")
861
862    dev[0].set_network(id, "ieee80211w", "0")
863    dev[0].request("REASSOCIATE")
864    dev[0].wait_connected()
865    wt.require_sta_no_pmf(bssid, addr)
866    sta = hapd.get_sta(addr)
867    if '[MFP]' in sta['flags']:
868        raise Exception("MFP flag unexpectedly present for STA")
869    err, data = hapd.cmd_execute(['iw', 'dev', apdev[0]['ifname'], 'station',
870                                  'get', addr])
871    if "yes" in [l for l in data.splitlines() if "MFP" in l][0]:
872        raise Exception("Kernel STA entry had MFP enabled")
873
874    dev[0].set_network(id, "ieee80211w", "1")
875    dev[0].request("REASSOCIATE")
876    dev[0].wait_connected()
877    wt.require_sta_pmf(bssid, addr)
878    sta = hapd.get_sta(addr)
879    if '[MFP]' not in sta['flags']:
880        raise Exception("MFP flag not present for STA")
881    err, data = hapd.cmd_execute(['iw', 'dev', apdev[0]['ifname'], 'station',
882                                  'get', addr])
883    if "yes" not in [l for l in data.splitlines() if "MFP" in l][0]:
884        raise Exception("Kernel STA entry did not have MFP enabled")
885
886@remote_compatible
887def test_ap_pmf_required_sta_no_pmf(dev, apdev):
888    """WPA2-PSK AP with PMF required and PMF disabled on STA"""
889    ssid = "test-pmf-required"
890    params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
891    params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
892    params["ieee80211w"] = "2"
893    hapd = hostapd.add_ap(apdev[0], params)
894
895    # Disable PMF on the station and try to connect
896    dev[0].connect(ssid, psk="12345678", ieee80211w="0",
897                   key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
898                   scan_freq="2412", wait_connect=False)
899    ev = dev[0].wait_event(["CTRL-EVENT-NETWORK-NOT-FOUND",
900                            "CTRL-EVENT-ASSOC-REJECT"], timeout=2)
901    if ev is None:
902        raise Exception("No connection result")
903    if "CTRL-EVENT-ASSOC-REJECT" in ev:
904        raise Exception("Tried to connect to PMF required AP without PMF enabled")
905    dev[0].request("REMOVE_NETWORK all")
906
907def test_ap_pmf_inject_auth(dev, apdev):
908    """WPA2-PSK AP with PMF and Authentication frame injection"""
909    ssid = "test-pmf"
910    params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
911    params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
912    params["ieee80211w"] = "2"
913    hapd = hostapd.add_ap(apdev[0], params)
914    dev[0].connect(ssid, psk="12345678", ieee80211w="2",
915                   key_mgmt="WPA-PSK-SHA256", proto="WPA2",
916                   scan_freq="2412")
917    hapd.wait_sta()
918    hwsim_utils.test_connectivity(dev[0], hapd)
919
920    bssid = hapd.own_addr().replace(':', '')
921    addr = dev[0].own_addr().replace(':', '')
922
923    # Inject an unprotected Authentication frame claiming to be from the
924    # associated STA, from another STA, from the AP's own address, from all
925    # zeros and all ones addresses, and from a multicast address.
926    hapd.request("SET ext_mgmt_frame_handling 1")
927    failed = False
928    addresses = [ addr, "021122334455", bssid, 6*"00", 6*"ff", 6*"01" ]
929    for a in addresses:
930        auth = "b0003a01" + bssid + a + bssid + '1000000001000000'
931        res = hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=%s" % auth)
932        if "OK" not in res:
933            failed = True
934    hapd.request("SET ext_mgmt_frame_handling 0")
935    if failed:
936        raise Exception("MGMT_RX_PROCESS failed")
937    time.sleep(0.1)
938
939    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.1)
940    if ev:
941        raise Exception("Unexpected disconnection reported on the STA")
942
943    # Verify that original association is still functional.
944    hwsim_utils.test_connectivity(dev[0], hapd)
945
946    # Inject an unprotected Association Request frame (with and without RSNE)
947    # claiming to be from the set of test addresses.
948    hapd.request("SET ext_mgmt_frame_handling 1")
949    for a in addresses:
950        assoc = "00003a01" + bssid + a + bssid + '2000' + '31040500' + '0008746573742d706d66' + '010802040b160c121824' + '301a0100000fac040100000fac040100000fac06c0000000000fac06'
951        res = hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=%s" % assoc)
952        if "OK" not in res:
953            failed = True
954
955        assoc = "00003a01" + bssid + a + bssid + '2000' + '31040500' + '0008746573742d706d66' + '010802040b160c121824' + '3000'
956        res = hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=%s" % assoc)
957        if "OK" not in res:
958            failed = True
959
960        assoc = "00003a01" + bssid + a + bssid + '2000' + '31040500' + '0008746573742d706d66' + '010802040b160c121824'
961        res = hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=%s" % assoc)
962        if "OK" not in res:
963            failed = True
964    hapd.request("SET ext_mgmt_frame_handling 0")
965    if failed:
966        raise Exception("MGMT_RX_PROCESS failed")
967    time.sleep(5)
968
969    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.1)
970    if ev:
971        raise Exception("Unexpected disconnection reported on the STA")
972
973    # Verify that original association is still functional.
974    hwsim_utils.test_connectivity(dev[0], hapd)
975
976def test_ap_pmf_inject_assoc(dev, apdev):
977    """WPA2-PSK with PMF and Association Request frame injection"""
978    run_ap_pmf_inject_assoc(dev, apdev, False)
979
980def test_ap_pmf_inject_assoc_wps(dev, apdev):
981    """WPA2-PSK/WPS with PMF and Association Request frame injection"""
982    run_ap_pmf_inject_assoc(dev, apdev, True)
983
984def inject_assoc_req(hapd, addr, frame):
985    hapd.set("ext_mgmt_frame_handling", "1")
986    res = hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=%s" % frame)
987    if "OK" not in res:
988        raise Exception("MGMT_RX_PROCESS failed")
989    hapd.set("ext_mgmt_frame_handling", "0")
990    sta = hapd.get_sta(addr)
991    if "[MFP]" not in sta['flags']:
992        raise Exception("MFP flag removed")
993    if sta["AKMSuiteSelector"] != '00-0f-ac-6':
994        raise Exception("AKMSuiteSelector value changed")
995
996def run_ap_pmf_inject_assoc(dev, apdev, wps):
997    ssid = "test-pmf"
998    params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
999    params["wpa_key_mgmt"] = "WPA-PSK WPA-PSK-SHA256"
1000    params["ieee80211w"] = "1"
1001    if wps:
1002        params["eap_server"] = "1"
1003        params["wps_state"] = "2"
1004
1005    hapd = hostapd.add_ap(apdev[0], params)
1006    dev[0].connect(ssid, psk="12345678", ieee80211w="2",
1007                   key_mgmt="WPA-PSK-SHA256", proto="WPA2",
1008                   scan_freq="2412")
1009    hapd.wait_sta()
1010    sta = hapd.get_sta(dev[0].own_addr())
1011    if "[MFP]" not in sta['flags']:
1012        raise Exception("MFP flag not reported")
1013    if sta["AKMSuiteSelector"] != '00-0f-ac-6':
1014        raise Exception("Incorrect AKMSuiteSelector value")
1015
1016    bssid = hapd.own_addr().replace(':', '')
1017    addr = dev[0].own_addr().replace(':', '')
1018
1019    # Inject unprotected Association Request frames
1020    assoc1 = "00003a01" + bssid + addr + bssid + '2000' + '31040500' + '0008746573742d706d66' + '010802040b160c121824' + '30140100000fac040100000fac040100000fac020000'
1021    assoc2 = "00003a01" + bssid + addr + bssid + '2000' + '31040500' + '0008746573742d706d66' + '010802040b160c121824' + '30140100000fac040100000fac040100000fac060000'
1022    assoc3 = "00003a01" + bssid + addr + bssid + '2000' + '31040500' + '0008746573742d706d66' + '010802040b160c121824'
1023
1024    inject_assoc_req(hapd, dev[0].own_addr(), assoc1)
1025    time.sleep(0.1)
1026    inject_assoc_req(hapd, dev[0].own_addr(), assoc1)
1027    time.sleep(0.1)
1028    inject_assoc_req(hapd, dev[0].own_addr(), assoc2)
1029    time.sleep(0.1)
1030    inject_assoc_req(hapd, dev[0].own_addr(), assoc3)
1031    time.sleep(0.1)
1032    inject_assoc_req(hapd, dev[0].own_addr(), assoc2)
1033
1034    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=5.1)
1035    if ev:
1036        raise Exception("Unexpected disconnection reported on the STA")
1037    ev = hapd.wait_event(["AP-STA-DISCONNECTED"], timeout=0.1)
1038    if ev:
1039        raise Exception("Unexpected disconnection event received from hostapd")
1040
1041    # Verify that original association is still functional.
1042    hwsim_utils.test_connectivity(dev[0], hapd)
1043
1044def test_ap_pmf_inject_data(dev, apdev):
1045    """WPA2-PSK AP with PMF and Data frame injection"""
1046    try:
1047        run_ap_pmf_inject_data(dev, apdev)
1048    finally:
1049        stop_monitor(apdev[1]["ifname"])
1050
1051def run_ap_pmf_inject_data(dev, apdev):
1052    ssid = "test-pmf"
1053    params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1054    params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
1055    params["ieee80211w"] = "2"
1056    hapd = hostapd.add_ap(apdev[0], params)
1057    dev[0].connect(ssid, psk="12345678", ieee80211w="2",
1058                   key_mgmt="WPA-PSK-SHA256", proto="WPA2",
1059                   scan_freq="2412")
1060    hapd.wait_sta()
1061    hwsim_utils.test_connectivity(dev[0], hapd)
1062
1063    sock = start_monitor(apdev[1]["ifname"])
1064    radiotap = radiotap_build()
1065
1066    bssid = hapd.own_addr().replace(':', '')
1067    addr = dev[0].own_addr().replace(':', '')
1068
1069    # Inject Data frame with A2=broadcast, A2=multicast, A2=BSSID, A2=STA, and
1070    # A2=unknown unicast
1071    addresses = [ 6*"ff", 6*"01", bssid, addr, "020102030405" ]
1072    for a in addresses:
1073        frame = binascii.unhexlify("48010000" + bssid + a + bssid + "0000")
1074        sock.send(radiotap + frame)
1075
1076    time.sleep(0.1)
1077    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.1)
1078    if ev:
1079        raise Exception("Unexpected disconnection reported on the STA")
1080    hwsim_utils.test_connectivity(dev[0], hapd)
1081
1082def test_ap_pmf_inject_msg1(dev, apdev):
1083    """WPA2-PSK AP with PMF and EAPOL-Key msg 1/4 injection"""
1084    try:
1085        run_ap_pmf_inject_msg1(dev, apdev)
1086    finally:
1087        stop_monitor(apdev[1]["ifname"])
1088
1089def test_ap_pmf_inject_msg1_no_pmf(dev, apdev):
1090    """WPA2-PSK AP without PMF and EAPOL-Key msg 1/4 injection"""
1091    try:
1092        run_ap_pmf_inject_msg1(dev, apdev, pmf=False)
1093    finally:
1094        stop_monitor(apdev[1]["ifname"])
1095
1096def run_ap_pmf_inject_msg1(dev, apdev, pmf=True):
1097    ssid = "test-pmf"
1098    params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1099    params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
1100    if pmf:
1101        params["ieee80211w"] = "2"
1102    hapd = hostapd.add_ap(apdev[0], params)
1103    dev[0].connect(ssid, psk="12345678", ieee80211w="2" if pmf else "0",
1104                   key_mgmt="WPA-PSK-SHA256", proto="WPA2",
1105                   scan_freq="2412")
1106    hapd.wait_sta()
1107
1108    sock = start_monitor(apdev[1]["ifname"])
1109    radiotap = radiotap_build()
1110
1111    bssid = hapd.own_addr().replace(':', '')
1112    addr = dev[0].own_addr().replace(':', '')
1113
1114    # Inject unprotected EAPOL-Key msg 1/4 with an invalid KDE
1115    f = "88020000" + addr + bssid + bssid + "0000" + "0700"
1116    f += "aaaa03000000" + "888e"
1117    f += "0203006602008b00100000000000000005bcb714da6f98f817b88948485c26ef052922b795814819f1889ae01e11b486910000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007" + "dd33000fac0400"
1118    frame = binascii.unhexlify(f)
1119    sock.send(radiotap + frame)
1120
1121    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.5)
1122    if ev:
1123        raise Exception("Unexpected disconnection reported on the STA")
1124    hwsim_utils.test_connectivity(dev[0], hapd)
1125    state = dev[0].get_status_field("wpa_state")
1126    if state != "COMPLETED":
1127        raise Exception("Unexpected wpa_state: " + state)
1128
1129def test_ap_pmf_inject_eap(dev, apdev):
1130    """WPA2-EAP AP with PMF and EAP frame injection"""
1131    try:
1132        run_ap_pmf_inject_eap(dev, apdev)
1133    finally:
1134        stop_monitor(apdev[1]["ifname"])
1135
1136def run_ap_pmf_inject_eap(dev, apdev, pmf=True):
1137    ssid = "test-pmf-eap"
1138    params = hostapd.wpa2_eap_params(ssid=ssid)
1139    params["wpa_key_mgmt"] = "WPA-EAP-SHA256"
1140    params["ieee80211w"] = "2"
1141    hapd = hostapd.add_ap(apdev[0], params)
1142    dev[0].connect(ssid, key_mgmt="WPA-EAP-SHA256",
1143                   ieee80211w="2", eap="PSK", identity="psk.user@example.com",
1144                   password_hex="0123456789abcdef0123456789abcdef",
1145                   scan_freq="2412")
1146    hapd.wait_sta()
1147    dev[0].dump_monitor()
1148    hapd.dump_monitor()
1149
1150    sock = start_monitor(apdev[1]["ifname"])
1151    radiotap = radiotap_build()
1152
1153    bssid = hapd.own_addr().replace(':', '')
1154    addr = dev[0].own_addr().replace(':', '')
1155
1156    disconnected = False
1157    eap_start = False
1158    eap_failure = False
1159    ap_disconnected = False
1160
1161    # Inject various unexpected unprotected EAPOL frames to the STA
1162    f = "88020000" + addr + bssid + bssid + "0000" + "0700"
1163    f += "aaaa03000000" + "888e"
1164    tests = []
1165    for i in range(101):
1166        tests += [ "02000005012d000501" ] # EAP-Request/Identity
1167    for i in range(101):
1168        tests += [ "02000022012e00222f00862406a9b45782fee8a62e837457d1367365727665722e77312e6669" ] # EAP-Request/PSK
1169    tests += [ "0200000404780004" ] # EAP-Failure
1170    tests += [ "0200000403780004" ] # EAP-Success
1171    tests += [ "02000006057800060100" ] # EAP-Initiate
1172    tests += [ "0200000406780004" ] # EAP-Finish
1173    tests += [ "0200000400780004" ] # EAP-?
1174    tests += [ "02020000" ] # EAPOL-Logoff
1175    tests += [ "02010000" ] # EAPOL-Start
1176    for t in tests:
1177        dev[0].note("Inject " + t)
1178        frame = binascii.unhexlify(f + t)
1179        sock.send(radiotap + frame)
1180        for i in range(2):
1181            ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED",
1182                                    "CTRL-EVENT-EAP-STARTED",
1183                                    "CTRL-EVENT-EAP-FAILURE"],
1184                                   timeout=0.0001)
1185            if ev is None:
1186                break
1187            if "CTRL-EVENT-DISCONNECTED" in ev:
1188                disconnected = True
1189            if "CTRL-EVENT-EAP-START" in ev:
1190                eap_start = True
1191            if "CTRL-EVENT-EAP-FAILURE" in ev:
1192                eap_failure = True
1193        dev[0].dump_monitor(mon=False)
1194    dev[0].dump_monitor()
1195    ev = hapd.wait_event(["AP-STA-DISCONNECTED"], timeout=0.1)
1196    if ev:
1197        ap_disconnected = True
1198    if disconnected or eap_start or eap_failure or ap_disconnected:
1199        raise Exception("Unexpected event:%s%s%s%s" %
1200                        (" disconnected" if disconnected else "",
1201                         " eap_start" if eap_start else "",
1202                         " eap_failure" if eap_failure else "",
1203                         " ap_disconnected" if ap_disconnected else ""))
1204    hwsim_utils.test_connectivity(dev[0], hapd)
1205    state = dev[0].get_status_field("wpa_state")
1206    if state != "COMPLETED":
1207        raise Exception("Unexpected wpa_state: " + state)
1208
1209    dev[0].dump_monitor()
1210    hapd.dump_monitor()
1211
1212    # Inject various unexpected unprotected EAPOL frames to the AP
1213    f = "88010000" + bssid + addr + bssid + "0000" + "0700"
1214    f += "aaaa03000000" + "888e"
1215    tests = []
1216    tests += [ "02020000" ] # EAPOL-Logoff
1217    for i in range(10):
1218        tests += [ "02010000" ] # EAPOL-Start
1219    for t in tests:
1220        hapd.note("Inject " + t)
1221        frame = binascii.unhexlify(f + t)
1222        sock.send(radiotap + frame)
1223        for i in range(2):
1224            ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED",
1225                                    "CTRL-EVENT-EAP-STARTED",
1226                                    "CTRL-EVENT-EAP-FAILURE"],
1227                                   timeout=0.0001)
1228            if ev is None:
1229                break
1230            if "CTRL-EVENT-DISCONNECTED" in ev:
1231                disconnected = True
1232            if "CTRL-EVENT-EAP-START" in ev:
1233                eap_start = True
1234            if "CTRL-EVENT-EAP-FAILURE" in ev:
1235                eap_failure = True
1236        dev[0].dump_monitor(mon=False)
1237    dev[0].dump_monitor()
1238    ev = hapd.wait_event(["AP-STA-DISCONNECTED"], timeout=0.1)
1239    if ev:
1240        ap_disconnected = True
1241    hapd.dump_monitor()
1242    if disconnected or eap_start or eap_failure or ap_disconnected:
1243        raise Exception("Unexpected event(2):%s%s%s%s" %
1244                        (" disconnected" if disconnected else "",
1245                         " eap_start" if eap_start else "",
1246                         " eap_failure" if eap_failure else "",
1247                         " ap_disconnected" if ap_disconnected else ""))
1248    hwsim_utils.test_connectivity(dev[0], hapd)
1249    state = dev[0].get_status_field("wpa_state")
1250    if state != "COMPLETED":
1251        raise Exception("Unexpected wpa_state(2): " + state)
1252
1253def test_ap_pmf_tkip_reject(dev, apdev):
1254    """Mixed mode BSS and MFP-enabled AP rejecting TKIP"""
1255    skip_without_tkip(dev[0])
1256    params = hostapd.wpa2_params(ssid="test-pmf", passphrase="12345678")
1257    params['wpa'] = '3'
1258    params["ieee80211w"] = "1"
1259    params["wpa_pairwise"] = "TKIP CCMP"
1260    params["rsn_pairwise"] = "TKIP CCMP"
1261    hostapd.add_ap(apdev[0], params)
1262
1263    dev[0].connect("test-pmf", psk="12345678", pairwise="CCMP", ieee80211w="2",
1264                   scan_freq="2412")
1265    dev[0].dump_monitor()
1266
1267    dev[1].connect("test-pmf", psk="12345678", proto="WPA", pairwise="TKIP",
1268                   ieee80211w="0", scan_freq="2412")
1269    dev[1].dump_monitor()
1270
1271    dev[2].connect("test-pmf", psk="12345678", pairwise="TKIP",
1272                   ieee80211w="2", scan_freq="2412", wait_connect=False)
1273    ev = dev[2].wait_event(["CTRL-EVENT-CONNECTED",
1274                            "CTRL-EVENT-ASSOC-REJECT"], timeout=10)
1275    if ev is None:
1276        raise Exception("No connection result reported")
1277    if "CTRL-EVENT-ASSOC-REJECT" not in ev:
1278        raise Exception("MFP + TKIP connection was not rejected")
1279    if "status_code=31" not in ev:
1280        raise Exception("Unexpected status code in rejection: " + ev)
1281    dev[2].request("DISCONNECT")
1282    dev[2].dump_monitor()
1283
1284def test_ap_pmf_sa_query_timeout(dev, apdev):
1285    """SA Query timeout"""
1286    ssid = "test-pmf-required"
1287    params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1288    params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
1289    params["ieee80211w"] = "2"
1290    hapd = hostapd.add_ap(apdev[0], params)
1291    dev[0].connect(ssid, psk="12345678", ieee80211w="2",
1292                   key_mgmt="WPA-PSK-SHA256", proto="WPA2",
1293                   scan_freq="2412")
1294
1295    hapd.set("ext_mgmt_frame_handling", "1")
1296    if "OK" not in dev[0].request("UNPROT_DEAUTH"):
1297        raise Exception("Triggering SA Query from the STA failed")
1298    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=2)
1299    if ev is None:
1300        raise Exception("No disconnection on SA Query timeout seen")
1301    hapd.set("ext_mgmt_frame_handling", "0")
1302    dev[0].wait_connected()
1303    dev[0].dump_monitor()
1304
1305    hapd.set("ext_mgmt_frame_handling", "1")
1306    if "OK" not in dev[0].request("UNPROT_DEAUTH"):
1307        raise Exception("Triggering SA Query from the STA failed")
1308    ev = hapd.mgmt_rx()
1309    hapd.set("ext_mgmt_frame_handling", "0")
1310    dev[0].request("DISCONNECT")
1311    dev[0].wait_disconnected()
1312    dev[0].request("RECONNECT")
1313    dev[0].wait_connected()
1314    hapd.set("ext_mgmt_frame_handling", "1")
1315    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1.5)
1316    if ev is not None:
1317        raise Exception("Unexpected disconnection after reconnection seen")
1318
1319def mac80211_read_key(keydir):
1320    vals = {}
1321    for name in os.listdir(keydir):
1322        try:
1323            with open(os.path.join(keydir, name)) as f:
1324                vals[name] = f.read().strip()
1325        except OSError as e:
1326            pass
1327    return vals
1328
1329def check_mac80211_bigtk(dev, hapd):
1330    sta_key = None
1331    ap_key = None
1332
1333    phy = dev.get_driver_status_field("phyname")
1334    keys = "/sys/kernel/debug/ieee80211/%s/keys" % phy
1335    try:
1336        for key in os.listdir(keys):
1337            keydir = os.path.join(keys, key)
1338            vals = mac80211_read_key(keydir)
1339            keyidx = int(vals['keyidx'])
1340            if keyidx == 6 or keyidx == 7:
1341                sta_key = vals;
1342                break
1343    except OSError as e:
1344        raise HwsimSkip("debugfs not supported in mac80211 (STA)")
1345
1346    phy = hapd.get_driver_status_field("phyname")
1347    keys = "/sys/kernel/debug/ieee80211/%s/keys" % phy
1348    try:
1349        for key in os.listdir(keys):
1350            keydir = os.path.join(keys, key)
1351            vals = mac80211_read_key(keydir)
1352            keyidx = int(vals['keyidx'])
1353            if keyidx == 6 or keyidx == 7:
1354                ap_key = vals;
1355                break
1356    except OSError as e:
1357        raise HwsimSkip("debugfs not supported in mac80211 (AP)")
1358
1359    if not sta_key:
1360        raise Exception("Could not find STA key information from debugfs")
1361    logger.info("STA key: " + str(sta_key))
1362
1363    if not ap_key:
1364        raise Exception("Could not find AP key information from debugfs")
1365    logger.info("AP key: " + str(ap_key))
1366
1367    if sta_key['key'] != ap_key['key']:
1368        raise Exception("AP and STA BIGTK mismatch")
1369
1370    if sta_key['keyidx'] != ap_key['keyidx']:
1371        raise Exception("AP and STA BIGTK keyidx mismatch")
1372
1373    if sta_key['algorithm'] != ap_key['algorithm']:
1374        raise Exception("AP and STA BIGTK algorithm mismatch")
1375
1376    replays = int(sta_key['replays'])
1377    icverrors = int(sta_key['icverrors'])
1378    if replays > 0 or icverrors > 0:
1379        raise Exception("STA reported errors: replays=%d icverrors=%d" % replays, icverrors)
1380
1381    rx_spec = int(sta_key['rx_spec'], base=16)
1382    if rx_spec < 3:
1383        raise Exception("STA did not update BIGTK receive counter sufficiently")
1384
1385    tx_spec = int(ap_key['tx_spec'], base=16)
1386    if tx_spec < 3:
1387        raise Exception("AP did not update BIGTK BIPN sufficiently")
1388
1389def test_ap_pmf_beacon_protection_bip(dev, apdev):
1390    """WPA2-PSK Beacon protection (BIP)"""
1391    run_ap_pmf_beacon_protection(dev, apdev, "AES-128-CMAC")
1392
1393def test_ap_pmf_beacon_protection_bip_cmac_256(dev, apdev):
1394    """WPA2-PSK Beacon protection (BIP-CMAC-256)"""
1395    run_ap_pmf_beacon_protection(dev, apdev, "BIP-CMAC-256")
1396
1397def test_ap_pmf_beacon_protection_bip_gmac_128(dev, apdev):
1398    """WPA2-PSK Beacon protection (BIP-GMAC-128)"""
1399    run_ap_pmf_beacon_protection(dev, apdev, "BIP-GMAC-128")
1400
1401def test_ap_pmf_beacon_protection_bip_gmac_256(dev, apdev):
1402    """WPA2-PSK Beacon protection (BIP-GMAC-256)"""
1403    run_ap_pmf_beacon_protection(dev, apdev, "BIP-GMAC-256")
1404
1405def run_ap_pmf_beacon_protection(dev, apdev, cipher):
1406    ssid = "test-beacon-prot"
1407    params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1408    params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
1409    params["ieee80211w"] = "2"
1410    params["beacon_prot"] = "1"
1411    params["group_mgmt_cipher"] = cipher
1412    try:
1413        hapd = hostapd.add_ap(apdev[0], params)
1414    except Exception as e:
1415        if "Failed to enable hostapd interface" in str(e):
1416            raise HwsimSkip("Beacon protection not supported")
1417        raise
1418
1419    bssid = hapd.own_addr()
1420
1421    Wlantest.setup(hapd)
1422    wt = Wlantest()
1423    wt.flush()
1424    wt.add_passphrase("12345678")
1425
1426    dev[0].flush_scan_cache()
1427
1428    # STA with Beacon protection enabled
1429    dev[0].connect(ssid, psk="12345678", ieee80211w="2", beacon_prot="1",
1430                   key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
1431    if dev[0].get_status_field("bigtk_set") != "1":
1432        raise Exception("bigtk_set=1 not indicated")
1433
1434    # STA with Beacon protection disabled
1435    dev[1].connect(ssid, psk="12345678", ieee80211w="2",
1436                   key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
1437    if dev[1].get_status_field("bigtk_set") == "1":
1438        raise Exception("Unexpected bigtk_set=1 indication")
1439
1440    time.sleep(1)
1441    check_mac80211_bigtk(dev[0], hapd)
1442
1443    valid_bip = wt.get_bss_counter('valid_bip_mmie', bssid)
1444    invalid_bip = wt.get_bss_counter('invalid_bip_mmie', bssid)
1445    missing_bip = wt.get_bss_counter('missing_bip_mmie', bssid)
1446    logger.info("wlantest BIP counters: valid=%d invalid=%d missing=%d" % (valid_bip, invalid_bip, missing_bip))
1447    if valid_bip < 0 or invalid_bip > 0 or missing_bip > 0:
1448        raise Exception("Unexpected wlantest BIP counters: valid=%d invalid=%d missing=%d" % (valid_bip, invalid_bip, missing_bip))
1449
1450    ev = dev[0].wait_event(["CTRL-EVENT-BEACON-LOSS"], timeout=10)
1451    if ev is not None:
1452        raise Exception("Beacon loss detected")
1453
1454    # Verify that the SSID has been successfully verified from a protected
1455    # Beacon frame.
1456    if dev[0].get_status_field("ssid_verified") != "1":
1457        raise Exception("ssid_verified=1 not in STATUS")
1458
1459def test_ap_pmf_beacon_protection_mismatch(dev, apdev):
1460    """WPA2-PSK Beacon protection MIC mismatch"""
1461    run_ap_pmf_beacon_protection_mismatch(dev, apdev, False)
1462
1463def test_ap_pmf_beacon_protection_missing(dev, apdev):
1464    """WPA2-PSK Beacon protection MME missing"""
1465    run_ap_pmf_beacon_protection_mismatch(dev, apdev, True)
1466
1467def run_ap_pmf_beacon_protection_mismatch(dev, apdev, clear):
1468    ssid = "test-beacon-prot"
1469    params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1470    params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
1471    params["ieee80211w"] = "2"
1472    params["beacon_prot"] = "1"
1473    params["group_mgmt_cipher"] = "AES-128-CMAC"
1474    try:
1475        hapd = hostapd.add_ap(apdev[0], params)
1476    except Exception as e:
1477        if "Failed to enable hostapd interface" in str(e):
1478            raise HwsimSkip("Beacon protection not supported")
1479        raise
1480
1481    bssid = hapd.own_addr()
1482
1483    Wlantest.setup(hapd)
1484    wt = Wlantest()
1485    wt.flush()
1486    wt.add_passphrase("12345678")
1487
1488    dev[0].connect(ssid, psk="12345678", ieee80211w="2", beacon_prot="1",
1489                   key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
1490
1491    WPA_ALG_NONE = 0
1492    WPA_ALG_IGTK = 4
1493    KEY_FLAG_DEFAULT = 0x02
1494    KEY_FLAG_TX = 0x08
1495    KEY_FLAG_GROUP = 0x10
1496    KEY_FLAG_GROUP_TX_DEFAULT = KEY_FLAG_GROUP | KEY_FLAG_TX | KEY_FLAG_DEFAULT
1497
1498    addr = "ff:ff:ff:ff:ff:ff"
1499
1500    if clear:
1501        res = hapd.request("SET_KEY %d %s %d %d %s %s %d" % (WPA_ALG_NONE, addr, 6, 1, 6*"00", "", KEY_FLAG_GROUP))
1502    else:
1503        res = hapd.request("SET_KEY %d %s %d %d %s %s %d" % (WPA_ALG_IGTK, addr, 6, 1, 6*"00", 16*"00", KEY_FLAG_GROUP_TX_DEFAULT))
1504    if "OK" not in res:
1505        raise Exception("SET_KEY failed")
1506
1507    ev = dev[0].wait_event(["CTRL-EVENT-UNPROT-BEACON"], timeout=5)
1508    if ev is None:
1509        raise Exception("Unprotected Beacon frame not reported")
1510
1511    ev = dev[0].wait_event(["CTRL-EVENT-BEACON-LOSS"], timeout=5)
1512    if ev is None:
1513        raise Exception("Beacon loss not reported")
1514
1515    ev = hapd.wait_event(["CTRL-EVENT-UNPROT-BEACON"], timeout=5)
1516    if ev is None:
1517        raise Exception("WNM-Notification Request frame not reported")
1518
1519def test_ap_pmf_beacon_protection_reconnect(dev, apdev):
1520    """Beacon protection and reconnection"""
1521    ssid = "test-beacon-prot"
1522    params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1523    params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
1524    params["ieee80211w"] = "2"
1525    params["beacon_prot"] = "1"
1526    params["group_mgmt_cipher"] = "AES-128-CMAC"
1527    try:
1528        hapd = hostapd.add_ap(apdev[0], params)
1529    except Exception as e:
1530        if "Failed to enable hostapd interface" in str(e):
1531            raise HwsimSkip("Beacon protection not supported")
1532        raise
1533
1534    dev[0].connect(ssid, psk="12345678", ieee80211w="2", beacon_prot="1",
1535                   key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
1536    dev[0].request("DISCONNECT")
1537    dev[0].wait_disconnected()
1538    dev[0].request("RECONNECT")
1539    dev[0].wait_connected()
1540    time.sleep(1)
1541    check_mac80211_bigtk(dev[0], hapd)
1542    ev = dev[0].wait_event(["CTRL-EVENT-BEACON-LOSS"], timeout=5)
1543    if ev is not None:
1544        raise Exception("Beacon loss detected")
1545
1546def test_ap_pmf_beacon_protection_unicast(dev, apdev):
1547    """WPA2-PSK Beacon protection (BIP) and unicast Beacon frame"""
1548    try:
1549        run_ap_pmf_beacon_protection_unicast(dev, apdev)
1550    finally:
1551        stop_monitor(apdev[1]["ifname"])
1552
1553def run_ap_pmf_beacon_protection_unicast(dev, apdev):
1554    cipher = "AES-128-CMAC"
1555    ssid = "test-beacon-prot"
1556    params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1557    params["wpa_key_mgmt"] = "WPA-PSK-SHA256"
1558    params["ieee80211w"] = "2"
1559    params["beacon_prot"] = "1"
1560    params["group_mgmt_cipher"] = cipher
1561    try:
1562        hapd = hostapd.add_ap(apdev[0], params)
1563    except Exception as e:
1564        if "Failed to enable hostapd interface" in str(e):
1565            raise HwsimSkip("Beacon protection not supported")
1566        raise
1567
1568    bssid = hapd.own_addr()
1569
1570    Wlantest.setup(hapd)
1571    wt = Wlantest()
1572    wt.flush()
1573    wt.add_passphrase("12345678")
1574
1575    # STA with Beacon protection enabled
1576    dev[0].connect(ssid, psk="12345678", ieee80211w="2", beacon_prot="1",
1577                   key_mgmt="WPA-PSK-SHA256", proto="WPA2", scan_freq="2412")
1578    hapd.wait_sta()
1579
1580    sock = start_monitor(apdev[1]["ifname"])
1581    radiotap = radiotap_build()
1582
1583    bssid = hapd.own_addr().replace(':', '')
1584    addr = dev[0].own_addr().replace(':', '')
1585
1586    h = "80000000" + addr + bssid + bssid + "0000"
1587    h += "c0a0260d27090600"+ "6400" + "1104"
1588    h += "0010746573742d626561636f6e2d70726f74"
1589    h += "010882848b960c121824"
1590    h += "03010"
1591    h += "1050400020000"
1592    h += "2a0104"
1593    h += "32043048606c"
1594    h += "30140100000fac040100000fac040100000fac06cc00"
1595    h += "3b025100"
1596    h += "2d1a0c001bffff000000000000000000000100000000000000000000"
1597    h += "3d1601000000000000000000000000000000000000000000"
1598    h += "7f0b0400000200000040000010"
1599    h += "dd180050f2020101010003a4000027a4000042435e0062322f00"
1600
1601    frame = binascii.unhexlify(h)
1602    h += "4c1006002100000000002b8fab24bcef3bb1" #MME
1603    frame2 = binascii.unhexlify(h)
1604
1605    sock.send(radiotap + frame)
1606    ev = dev[0].wait_event(["CTRL-EVENT-UNPROT-BEACON"], timeout=5)
1607    if ev is None:
1608        raise Exception("Unprotected beacon was not reported")
1609    if hapd.own_addr() not in ev:
1610        raise Exception("Unexpected BSSID in unproted beacon indication")
1611
1612    time.sleep(10.1)
1613    sock.send(radiotap + frame2)
1614    ev = dev[0].wait_event(["CTRL-EVENT-UNPROT-BEACON"], timeout=5)
1615    if ev is None:
1616        raise Exception("Unprotected beacon was not reported")
1617    if hapd.own_addr() not in ev:
1618        raise Exception("Unexpected BSSID in unproted beacon indication")
1619
1620def test_ap_pmf_sta_global_require(dev, apdev):
1621    """WPA2-PSK AP with PMF optional and wpa_supplicant pmf=2"""
1622    ssid = "test-pmf-optional"
1623    params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1624    params["wpa_key_mgmt"] = "WPA-PSK"
1625    params["ieee80211w"] = "1"
1626    hapd = hostapd.add_ap(apdev[0], params)
1627    try:
1628        dev[0].set("pmf", "2")
1629        dev[0].connect(ssid, psk="12345678",
1630                       key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
1631                       scan_freq="2412")
1632        pmf = dev[0].get_status_field("pmf")
1633        if pmf != "1":
1634            raise Exception("Unexpected PMF state: " + str(pmf))
1635    finally:
1636        dev[0].set("pmf", "0")
1637
1638def test_ap_pmf_sta_global_require2(dev, apdev):
1639    """WPA2-PSK AP with PMF optional and wpa_supplicant pmf=2 (2)"""
1640    ssid = "test-pmf-optional"
1641    params = hostapd.wpa2_params(ssid=ssid, passphrase="12345678")
1642    params["wpa_key_mgmt"] = "WPA-PSK"
1643    params["ieee80211w"] = "0"
1644    hapd = hostapd.add_ap(apdev[0], params)
1645    bssid = hapd.own_addr()
1646    try:
1647        dev[0].scan_for_bss(bssid, freq=2412)
1648        dev[0].set("pmf", "2")
1649        dev[0].connect(ssid, psk="12345678",
1650                       key_mgmt="WPA-PSK WPA-PSK-SHA256", proto="WPA2",
1651                       scan_freq="2412", wait_connect=False)
1652        ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
1653                                "CTRL-EVENT-NETWORK-NOT-FOUND"], timeout=10)
1654        if ev is None:
1655            raise Exception("Connection result not reported")
1656        if "CTRL-EVENT-CONNECTED" in ev:
1657            raise Exception("Unexpected connection")
1658    finally:
1659        dev[0].set("pmf", "0")
1660
1661def test_ap_pmf_drop_robust_mgmt_prior_to_keys_installation(dev, apdev):
1662    """Drop non protected Robust Action frames prior to keys installation"""
1663    ssid = "test-pmf-required"
1664    passphrase = '12345678'
1665    params = hostapd.wpa2_params(ssid=ssid, passphrase=passphrase)
1666    params['delay_eapol_tx'] = '1'
1667    params['ieee80211w'] = '2'
1668    params['wpa_pairwise_update_count'] = '5'
1669    hapd = hostapd.add_ap(apdev[0], params, wait_enabled=False)
1670
1671    # Spectrum management with Channel Switch element
1672    msg = {'fc': 0x00d0,
1673           'sa': hapd.own_addr(),
1674           'da': dev[0].own_addr(),
1675           'bssid': hapd.own_addr(),
1676           'payload': binascii.unhexlify('00042503000608')
1677           }
1678
1679    dev[0].connect(ssid, psk=passphrase, scan_freq='2412', ieee80211w='1',
1680                   wait_connect=False)
1681
1682    # wait for the first delay before sending the frame
1683    ev = hapd.wait_event(['DELAY-EAPOL-TX-1'], timeout=10)
1684    if ev is None:
1685        raise Exception("EAPOL is not delayed")
1686
1687    # send the Action frame while connecting (prior to keys installation)
1688    hapd.mgmt_tx(msg)
1689
1690    dev[0].wait_connected(timeout=10, error="Timeout on connection")
1691    hapd.wait_sta()
1692    hwsim_utils.test_connectivity(dev[0], hapd)
1693
1694    # Verify no channel switch event
1695    ev = dev[0].wait_event(['CTRL-EVENT-STARTED-CHANNEL-SWITCH'], timeout=5)
1696    if ev is not None:
1697        raise Exception("Unexpected CSA prior to keys installation")
1698
1699    # Send the frame after keys installation and verify channel switch event
1700    hapd.mgmt_tx(msg)
1701    ev = dev[0].wait_event(['CTRL-EVENT-STARTED-CHANNEL-SWITCH'], timeout=5)
1702    if ev is None:
1703        raise Exception("Expected CSA handling after keys installation")
1704
1705def test_ap_pmf_eapol_logoff(dev, apdev):
1706    """WPA2-EAP AP with PMF required and EAPOL-Logoff"""
1707    ssid = "test-pmf-required-eap"
1708    params = hostapd.wpa2_eap_params(ssid=ssid)
1709    params["wpa_key_mgmt"] = "WPA-EAP-SHA256"
1710    params["ieee80211w"] = "2"
1711    hapd = hostapd.add_ap(apdev[0], params)
1712    hapd.request("SET ext_eapol_frame_io 1")
1713
1714    dev[0].set("ext_eapol_frame_io", "1")
1715    dev[0].connect("test-pmf-required-eap", key_mgmt="WPA-EAP-SHA256",
1716                   ieee80211w="2", eap="PSK", identity="psk.user@example.com",
1717                   password_hex="0123456789abcdef0123456789abcdef",
1718                   scan_freq="2412", wait_connect=False)
1719
1720    # EAP-Request/Identity
1721    proxy_msg(hapd, dev[0])
1722
1723    # EAP-Response/Identity RX
1724    msg = rx_msg(dev[0])
1725    # EAPOL-Logoff TX (inject)
1726    tx_msg(dev[0], hapd, "02020000")
1727    # EAP-Response/Identity TX (proxy previously received)
1728    tx_msg(dev[0], hapd, msg)
1729
1730    # Verify that the 10 ms timeout for deauthenticating STA after EAP-Failure
1731    # is not used in this sequence with the EAPOL-Logoff message before the
1732    # successful authentication.
1733    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=0.03)
1734    if ev:
1735        raise Exception("Unexpected disconnection")
1736
1737    # EAP-Request/Identity
1738    proxy_msg(hapd, dev[0])
1739    # EAP-Response/Identity
1740    proxy_msg(dev[0], hapd)
1741
1742    # EAP-PSK
1743    proxy_msg(hapd, dev[0])
1744    proxy_msg(dev[0], hapd)
1745    proxy_msg(hapd, dev[0])
1746    proxy_msg(dev[0], hapd)
1747    proxy_msg(hapd, dev[0])
1748
1749    # 4-way handshake
1750    proxy_msg(hapd, dev[0])
1751    proxy_msg(dev[0], hapd)
1752    proxy_msg(hapd, dev[0])
1753    proxy_msg(dev[0], hapd)
1754
1755    ev = hapd.wait_event(["EAPOL-4WAY-HS-COMPLETED"], timeout=1)
1756    if ev is None:
1757        raise Exception("4-way handshake did not complete successfully")
1758    dev[0].wait_connected(timeout=0.1)
1759    hapd.wait_sta()
1760
1761    # Verify that the STA gets disconnected when the EAPOL-Logoff message is
1762    # sent after successful authentication.
1763
1764    # EAPOL-Logoff TX (inject)
1765    tx_msg(dev[0], hapd, "02020000")
1766    hapd.request("SET ext_eapol_frame_io 0")
1767    dev[0].set("ext_eapol_frame_io", "0")
1768    ev = dev[0].wait_disconnected(timeout=1)
1769    if "reason=23" not in ev:
1770        raise Exception("Unexpected disconnection reason: " + ev)
1771