1# WPA2-Personal OCV tests
2# Copyright (c) 2018, Mathy Vanhoef
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, struct
9import logging, time
10logger = logging.getLogger()
11
12import hostapd
13from wpasupplicant import WpaSupplicant
14import hwsim_utils
15from utils import *
16from test_erp import start_erp_as
17from test_ap_ft import ft_params1, ft_params2
18from test_ap_psk import parse_eapol, build_eapol, pmk_to_ptk, eapol_key_mic, recv_eapol, send_eapol, reply_eapol, build_eapol_key_3_4, aes_wrap, pad_key_data
19
20#TODO: Refuse setting up AP with OCV but without MFP support
21#TODO: Refuse to connect to AP that advertises OCV but not MFP
22
23def make_ocikde(op_class, channel, seg1_idx):
24    WLAN_EID_VENDOR_SPECIFIC = 221
25    RSN_KEY_DATA_OCI = b"\x00\x0f\xac\x0d"
26
27    data = RSN_KEY_DATA_OCI + struct.pack("<BBB", op_class, channel, seg1_idx)
28    ocikde = struct.pack("<BB", WLAN_EID_VENDOR_SPECIFIC, len(data)) + data
29
30    return ocikde
31
32def ocv_setup_ap(apdev, params):
33    ssid = "test-wpa2-ocv"
34    passphrase = "qwertyuiop"
35    params.update(hostapd.wpa2_params(ssid=ssid, passphrase=passphrase))
36    try:
37        hapd = hostapd.add_ap(apdev, params)
38    except Exception as e:
39        if "Failed to set hostapd parameter ocv" in str(e):
40            raise HwsimSkip("OCV not supported")
41        raise
42    return hapd, ssid, passphrase
43
44def build_eapol_key_1_2(kck, key_data, replay_counter=3, key_info=0x1382,
45                        extra_len=0, descr_type=2, key_len=16):
46    msg = {}
47    msg['version'] = 2
48    msg['type'] = 3
49    msg['length'] = 95 + len(key_data) + extra_len
50
51    msg['descr_type'] = descr_type
52    msg['rsn_key_info'] = key_info
53    msg['rsn_key_len'] = key_len
54    msg['rsn_replay_counter'] = struct.pack('>Q', replay_counter)
55    msg['rsn_key_nonce'] = binascii.unhexlify('0000000000000000000000000000000000000000000000000000000000000000')
56    msg['rsn_key_iv'] = binascii.unhexlify('00000000000000000000000000000000')
57    msg['rsn_key_rsc'] = binascii.unhexlify('0000000000000000')
58    msg['rsn_key_id'] = binascii.unhexlify('0000000000000000')
59    msg['rsn_key_data_len'] = len(key_data)
60    msg['rsn_key_data'] = key_data
61    eapol_key_mic(kck, msg)
62    return msg
63
64def build_eapol_key_2_2(kck, key_data, replay_counter=3, key_info=0x0302,
65                        extra_len=0, descr_type=2, key_len=16):
66    return build_eapol_key_1_2(kck, key_data, replay_counter, key_info,
67                               extra_len, descr_type, key_len)
68
69@remote_compatible
70def test_wpa2_ocv(dev, apdev):
71    """OCV on 2.4 GHz"""
72    params = {"channel": "1",
73              "ieee80211w": "2",
74              "ocv": "1"}
75    hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
76    for ocv in range(2):
77        dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv=str(ocv),
78                       ieee80211w="1")
79        dev[0].request("REMOVE_NETWORK all")
80        dev[0].wait_disconnected()
81
82@remote_compatible
83def test_wpa2_ocv_5ghz(dev, apdev):
84    """OCV on 5 GHz"""
85    try:
86        run_wpa2_ocv_5ghz(dev, apdev)
87    finally:
88        set_world_reg(apdev[0], apdev[1], dev[0])
89        dev[0].flush_scan_cache()
90
91def run_wpa2_ocv_5ghz(dev, apdev):
92    params = {"hw_mode": "a",
93              "channel": "40",
94              "ieee80211w": "2",
95              "country_code": "US",
96              "ocv": "1"}
97    hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
98    for ocv in range(2):
99        dev[0].connect(ssid, psk=passphrase, scan_freq="5200", ocv=str(ocv),
100                       ieee80211w="1")
101        dev[0].wait_regdom(country_ie=True)
102        dev[0].request("REMOVE_NETWORK all")
103        dev[0].wait_disconnected()
104
105@remote_compatible
106def test_wpa2_ocv_ht20(dev, apdev):
107    """OCV with HT20 channel"""
108    params = {"channel": "6",
109              "ieee80211n": "1",
110              "ieee80211w": "1",
111              "ocv": "1"}
112    hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
113    for ocv in range(2):
114        dev[0].connect(ssid, psk=passphrase, scan_freq="2437", ocv=str(ocv),
115                       ieee80211w="1", disable_ht="1")
116        dev[1].connect(ssid, psk=passphrase, scan_freq="2437", ocv=str(ocv),
117                       ieee80211w="1")
118        dev[0].request("REMOVE_NETWORK all")
119        dev[1].request("REMOVE_NETWORK all")
120        dev[0].wait_disconnected()
121        dev[1].wait_disconnected()
122
123@remote_compatible
124def test_wpa2_ocv_ht40(dev, apdev):
125    """OCV with HT40 channel"""
126    try:
127        run_wpa2_ocv_ht40(dev, apdev)
128    finally:
129        set_world_reg(apdev[0], apdev[1], dev[0])
130        dev[0].flush_scan_cache()
131        dev[1].flush_scan_cache()
132
133def run_wpa2_ocv_ht40(dev, apdev):
134    for channel, capab, freq, mode in [("6", "[HT40-]", "2437", "g"),
135                                       ("6", "[HT40+]", "2437", "g"),
136                                       ("40", "[HT40-]", "5200", "a"),
137                                       ("36", "[HT40+]", "5180", "a")]:
138        params = {"hw_mode": mode,
139                  "channel": channel,
140                  "country_code": "US",
141                  "ieee80211n": "1",
142                  "ht_capab": capab,
143                  "ieee80211w": "1",
144                  "ocv": "1"}
145        hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
146        dev[0].flush_scan_cache()
147        dev[1].flush_scan_cache()
148        for ocv in range(2):
149            dev[0].connect(ssid, psk=passphrase, scan_freq=freq, ocv=str(ocv),
150                           ieee80211w="1", disable_ht="1")
151            dev[1].connect(ssid, psk=passphrase, scan_freq=freq, ocv=str(ocv),
152                           ieee80211w="1")
153            dev[0].wait_regdom(country_ie=True)
154            dev[0].request("REMOVE_NETWORK all")
155            dev[1].request("REMOVE_NETWORK all")
156            dev[0].wait_disconnected()
157            dev[1].wait_disconnected()
158        hapd.disable()
159
160@remote_compatible
161def test_wpa2_ocv_vht40(dev, apdev):
162    """OCV with VHT40 channel"""
163    try:
164        run_wpa2_ocv_vht40(dev, apdev)
165    finally:
166        set_world_reg(apdev[0], apdev[1], dev[0])
167        dev[0].flush_scan_cache()
168        dev[1].flush_scan_cache()
169        dev[2].flush_scan_cache()
170
171def run_wpa2_ocv_vht40(dev, apdev):
172    for channel, capab, freq in [("40", "[HT40-]", "5200"),
173                                 ("36", "[HT40+]", "5180")]:
174        params = {"hw_mode": "a",
175                  "channel": channel,
176                  "country_code": "US",
177                  "ht_capab": capab,
178                  "ieee80211n": "1",
179                  "ieee80211ac": "1",
180                  "vht_oper_chwidth": "0",
181                  "vht_oper_centr_freq_seg0_idx": "38",
182                  "ieee80211w": "1",
183                  "ocv": "1"}
184        hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
185        dev[0].flush_scan_cache()
186        dev[1].flush_scan_cache()
187        dev[2].flush_scan_cache()
188        for ocv in range(2):
189            dev[0].connect(ssid, psk=passphrase, scan_freq=freq, ocv=str(ocv),
190                           ieee80211w="1", disable_ht="1")
191            dev[1].connect(ssid, psk=passphrase, scan_freq=freq, ocv=str(ocv),
192                           ieee80211w="1", disable_vht="1")
193            dev[2].connect(ssid, psk=passphrase, scan_freq=freq, ocv=str(ocv),
194                           ieee80211w="1")
195            dev[0].wait_regdom(country_ie=True)
196            dev[0].request("REMOVE_NETWORK all")
197            dev[1].request("REMOVE_NETWORK all")
198            dev[2].request("REMOVE_NETWORK all")
199            dev[0].wait_disconnected()
200            dev[1].wait_disconnected()
201            dev[2].wait_disconnected()
202        hapd.disable()
203
204@remote_compatible
205def test_wpa2_ocv_vht80(dev, apdev):
206    """OCV with VHT80 channel"""
207    try:
208        run_wpa2_ocv_vht80(dev, apdev)
209    finally:
210        set_world_reg(apdev[0], apdev[1], dev[0])
211        dev[0].flush_scan_cache()
212        dev[1].flush_scan_cache()
213        dev[2].flush_scan_cache()
214
215def run_wpa2_ocv_vht80(dev, apdev):
216    for channel, capab, freq in [("40", "[HT40-]", "5200"),
217                                 ("36", "[HT40+]", "5180")]:
218        params = {"hw_mode": "a",
219                  "channel": channel,
220                  "country_code": "US",
221                  "ht_capab": capab,
222                  "ieee80211n": "1",
223                  "ieee80211ac": "1",
224                  "vht_oper_chwidth": "1",
225                  "vht_oper_centr_freq_seg0_idx": "42",
226                  "ieee80211w": "1",
227                  "ocv": "1"}
228        hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
229        for ocv in range(2):
230            dev[0].connect(ssid, psk=passphrase, scan_freq=freq, ocv=str(ocv),
231                           ieee80211w="1", disable_ht="1")
232            dev[1].connect(ssid, psk=passphrase, scan_freq=freq, ocv=str(ocv),
233                           ieee80211w="1", disable_vht="1")
234            dev[2].connect(ssid, psk=passphrase, scan_freq=freq, ocv=str(ocv),
235                           ieee80211w="1")
236            dev[0].wait_regdom(country_ie=True)
237            dev[0].request("REMOVE_NETWORK all")
238            dev[1].request("REMOVE_NETWORK all")
239            dev[2].request("REMOVE_NETWORK all")
240            dev[0].wait_disconnected()
241            dev[1].wait_disconnected()
242            dev[2].wait_disconnected()
243        hapd.disable()
244
245@remote_compatible
246def test_wpa2_ocv_vht160(dev, apdev):
247    """OCV with VHT160 channel"""
248    try:
249        run_wpa2_ocv_vht160(dev, apdev)
250    finally:
251        set_world_reg(apdev[0], apdev[1], dev[0])
252        dev[0].flush_scan_cache()
253        dev[1].flush_scan_cache()
254        dev[2].flush_scan_cache()
255
256def run_wpa2_ocv_vht160(dev, apdev):
257    for channel, capab, freq in [("100", "[HT40+]", "5500"),
258                                 ("104", "[HT40-]", "5520")]:
259        params = {"hw_mode": "a",
260                  "channel": channel,
261                  "country_code": "ZA",
262                  "ht_capab": capab,
263                  "vht_capab": "[VHT160]",
264                  "ieee80211n": "1",
265                  "ieee80211ac": "1",
266                  "vht_oper_chwidth": "2",
267                  "vht_oper_centr_freq_seg0_idx": "114",
268                  "ieee80211w": "1",
269                  "ocv": "1"}
270        hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
271        for ocv in range(2):
272            dev[0].connect(ssid, psk=passphrase, scan_freq=freq, ocv=str(ocv),
273                           ieee80211w="1", disable_ht="1")
274            dev[1].connect(ssid, psk=passphrase, scan_freq=freq, ocv=str(ocv),
275                           ieee80211w="1", disable_vht="1")
276            dev[2].connect(ssid, psk=passphrase, scan_freq=freq, ocv=str(ocv),
277                           ieee80211w="1")
278            dev[0].wait_regdom(country_ie=True)
279            dev[0].request("REMOVE_NETWORK all")
280            dev[1].request("REMOVE_NETWORK all")
281            dev[2].request("REMOVE_NETWORK all")
282            dev[0].wait_disconnected()
283            dev[1].wait_disconnected()
284            dev[2].wait_disconnected()
285        hapd.disable()
286
287@remote_compatible
288def test_wpa2_ocv_vht80plus80(dev, apdev):
289    """OCV with VHT80+80 channel"""
290    try:
291        run_wpa2_ocv_vht80plus80(dev, apdev)
292    finally:
293        set_world_reg(apdev[0], apdev[1], dev[0])
294        dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=0.5)
295        dev[0].flush_scan_cache()
296        dev[1].flush_scan_cache()
297        dev[2].flush_scan_cache()
298
299def run_wpa2_ocv_vht80plus80(dev, apdev):
300    for channel, capab, freq in [("36", "[HT40+]", "5180"),
301                                 ("40", "[HT40-]", "5200")]:
302        params = {"hw_mode": "a",
303                  "channel": channel,
304                  "country_code": "US",
305                  "ht_capab": capab,
306                  "vht_capab": "[VHT160-80PLUS80]",
307                  "ieee80211n": "1",
308                  "ieee80211ac": "1",
309                  "vht_oper_chwidth": "3",
310                  "vht_oper_centr_freq_seg0_idx": "42",
311                  "vht_oper_centr_freq_seg1_idx": "155",
312                  "ieee80211w": "1",
313                  "ieee80211d": "1",
314                  "ieee80211h": "1",
315                  "ocv": "1"}
316        hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
317        for ocv in range(2):
318            dev[0].connect(ssid, psk=passphrase, scan_freq=freq, ocv=str(ocv),
319                           ieee80211w="1", disable_ht="1")
320            dev[1].connect(ssid, psk=passphrase, scan_freq=freq, ocv=str(ocv),
321                           ieee80211w="1", disable_vht="1")
322            dev[2].connect(ssid, psk=passphrase, scan_freq=freq, ocv=str(ocv),
323                           ieee80211w="1")
324            dev[0].wait_regdom(country_ie=True)
325            dev[0].request("REMOVE_NETWORK all")
326            dev[1].request("REMOVE_NETWORK all")
327            dev[2].request("REMOVE_NETWORK all")
328            dev[0].wait_disconnected()
329            dev[1].wait_disconnected()
330            dev[2].wait_disconnected()
331        for i in range(3):
332            dev[i].connect(ssid, psk=passphrase, scan_freq=freq, ocv=str(ocv),
333                           ieee80211w="1")
334            if i == 0:
335                dev[i].wait_regdom(country_ie=True)
336        hapd.disable()
337        for i in range(3):
338            dev[i].request("DISCONNECT")
339        for i in range(3):
340            dev[i].disconnect_and_stop_scan()
341
342class APConnection:
343    def init_params(self):
344        # Static parameters
345        self.ssid = "test-wpa2-ocv"
346        self.passphrase = "qwertyuiop"
347        self.psk = "c2c6c255af836bed1b3f2f1ded98e052f5ad618bb554e2836757b55854a0eab7"
348
349        # Dynamic parameters
350        self.hapd = None
351        self.addr = None
352        self.rsne = None
353        self.kck = None
354        self.kek = None
355        self.msg = None
356        self.bssid = None
357        self.anonce = None
358        self.snonce = None
359
360    def __init__(self, apdev, dev, params):
361        self.init_params()
362
363        # By default, OCV is enabled for both the client and AP. The following
364        # parameters can be used to disable OCV for the client or AP.
365        ap_ocv = params.pop("ap_ocv", "1")
366        sta_ocv = params.pop("sta_ocv", "1")
367
368        freq = params.pop("freq")
369        params.update(hostapd.wpa2_params(ssid=self.ssid,
370                                          passphrase=self.passphrase))
371        params["wpa_pairwise_update_count"] = "10"
372        params["ocv"] = ap_ocv
373        try:
374            self.hapd = hostapd.add_ap(apdev, params)
375        except Exception as e:
376            if "Failed to set hostapd parameter ocv" in str(e):
377                raise HwsimSkip("OCV not supported")
378            raise
379        self.hapd.request("SET ext_eapol_frame_io 1")
380        dev.request("SET ext_eapol_frame_io 1")
381
382        self.bssid = apdev['bssid']
383        pmk = binascii.unhexlify("c2c6c255af836bed1b3f2f1ded98e052f5ad618bb554e2836757b55854a0eab7")
384
385        if sta_ocv != "0":
386            self.rsne = binascii.unhexlify("301a0100000fac040100000fac040100000fac0280400000000fac06")
387        else:
388            self.rsne = binascii.unhexlify("301a0100000fac040100000fac040100000fac0280000000000fac06")
389        self.snonce = binascii.unhexlify('1111111111111111111111111111111111111111111111111111111111111111')
390
391        dev.connect(self.ssid, raw_psk=self.psk, scan_freq=freq, ocv=sta_ocv,
392                    ieee80211w="1", wait_connect=False)
393        if "country_code" in params:
394            dev.wait_regdom(country_ie=True)
395        self.addr = dev.p2p_interface_addr()
396
397        # Wait for EAPOL-Key msg 1/4 from hostapd to determine when associated
398        self.msg = recv_eapol(self.hapd)
399        self.anonce = self.msg['rsn_key_nonce']
400        (ptk, self.kck, self.kek) = pmk_to_ptk(pmk, self.addr, self.bssid,
401                                               self.snonce, self.anonce)
402
403    # hapd, addr, rsne, kck, msg, anonce, snonce
404    def test_bad_oci(self, logmsg, op_class, channel, seg1_idx):
405        logger.debug("Bad OCI element: " + logmsg)
406        if op_class is None:
407            ocikde = b''
408        else:
409            ocikde = make_ocikde(op_class, channel, seg1_idx)
410
411        reply_eapol("2/4", self.hapd, self.addr, self.msg, 0x010a, self.snonce,
412                    self.rsne + ocikde, self.kck)
413        self.msg = recv_eapol(self.hapd)
414        if self.anonce != self.msg['rsn_key_nonce'] or self.msg["rsn_key_info"] != 138:
415            raise Exception("Didn't receive retransmitted 1/4")
416
417    def confirm_valid_oci(self, op_class, channel, seg1_idx):
418        logger.debug("Valid OCI element to complete handshake")
419        ocikde = make_ocikde(op_class, channel, seg1_idx)
420
421        reply_eapol("2/4", self.hapd, self.addr, self.msg, 0x010a, self.snonce,
422                    self.rsne + ocikde, self.kck)
423        self.msg = recv_eapol(self.hapd)
424        if self.anonce != self.msg['rsn_key_nonce'] or self.msg["rsn_key_info"] != 5066:
425            raise Exception("Didn't receive 3/4 in response to valid 2/4")
426
427        reply_eapol("4/4", self.hapd, self.addr, self.msg, 0x030a, None, None,
428                    self.kck)
429        self.hapd.wait_sta(timeout=15)
430
431@remote_compatible
432def test_wpa2_ocv_ap_mismatch(dev, apdev):
433    """OCV AP mismatch"""
434    params = {"channel": "1",
435              "ieee80211w": "1",
436              "freq": "2412"}
437    conn = APConnection(apdev[0], dev[0], params)
438    conn.test_bad_oci("element missing", None, 0, 0)
439    conn.test_bad_oci("wrong channel number", 81, 6, 0)
440    conn.test_bad_oci("invalid channel number", 81, 0, 0)
441    conn.test_bad_oci("wrong operating class", 80, 0, 0)
442    conn.test_bad_oci("invalid operating class", 0, 0, 0)
443    conn.confirm_valid_oci(81, 1, 0)
444
445@remote_compatible
446def test_wpa2_ocv_ap_ht_mismatch(dev, apdev):
447    """OCV AP mismatch (HT)"""
448    params = {"channel": "6",
449              "ht_capab": "[HT40-]",
450              "ieee80211w": "1",
451              "freq": "2437"}
452    conn = APConnection(apdev[0], dev[0], params)
453    conn.test_bad_oci("wrong primary channel", 84, 5, 0)
454    conn.test_bad_oci("lower bandwidth than negotiated", 81, 6, 0)
455    conn.test_bad_oci("bad upper/lower channel", 83, 6, 0)
456    conn.confirm_valid_oci(84, 6, 0)
457
458@remote_compatible
459def test_wpa2_ocv_ap_vht80_mismatch(dev, apdev):
460    """OCV AP mismatch (VHT80)"""
461    try:
462        run_wpa2_ocv_ap_vht80_mismatch(dev, apdev)
463    finally:
464        set_world_reg(apdev[0], apdev[1], dev[0])
465        dev[0].flush_scan_cache()
466
467def run_wpa2_ocv_ap_vht80_mismatch(dev, apdev):
468    params = {"hw_mode": "a",
469              "channel": "36",
470              "country_code": "US",
471              "ht_capab": "[HT40+]",
472              "ieee80211w": "1",
473              "ieee80211n": "1",
474              "ieee80211ac": "1",
475              "vht_oper_chwidth": "1",
476              "freq": "5180",
477              "vht_oper_centr_freq_seg0_idx": "42"}
478    conn = APConnection(apdev[0], dev[0], params)
479    conn.test_bad_oci("wrong primary channel", 128, 38, 0)
480    conn.test_bad_oci("wrong primary channel", 128, 32, 0)
481    conn.test_bad_oci("smaller bandwidth than negotiated", 116, 36, 0)
482    conn.test_bad_oci("smaller bandwidth than negotiated", 115, 36, 0)
483    conn.confirm_valid_oci(128, 36, 0)
484
485    dev[0].dump_monitor()
486    dev[0].request("DISCONNECT")
487    dev[0].wait_disconnected()
488
489@remote_compatible
490def test_wpa2_ocv_ap_vht160_mismatch(dev, apdev):
491    """OCV AP mismatch (VHT160)"""
492    try:
493        run_wpa2_ocv_ap_vht160_mismatch(dev, apdev)
494    finally:
495        set_world_reg(apdev[0], apdev[1], dev[0])
496        dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=0.5)
497        dev[0].flush_scan_cache()
498
499def run_wpa2_ocv_ap_vht160_mismatch(dev, apdev):
500    params = {"hw_mode": "a",
501              "channel": "100",
502              "country_code": "ZA",
503              "ht_capab": "[HT40+]",
504              "ieee80211w": "1",
505              "ieee80211n": "1",
506              "ieee80211ac": "1",
507              "vht_oper_chwidth": "2",
508              "freq": "5500",
509              "vht_oper_centr_freq_seg0_idx": "114",
510              "ieee80211d": "1",
511              "ieee80211h": "1"}
512    conn = APConnection(apdev[0], dev[0], params)
513    conn.test_bad_oci("wrong primary channel", 129, 36, 0)
514    conn.test_bad_oci("wrong primary channel", 129, 114, 0)
515    conn.test_bad_oci("smaller bandwidth (20 Mhz) than negotiated", 121, 100, 0)
516    conn.test_bad_oci("smaller bandwidth (40 Mhz) than negotiated", 122, 100, 0)
517    conn.test_bad_oci("smaller bandwidth (80 Mhz) than negotiated", 128, 100, 0)
518    conn.test_bad_oci("using 80+80 channel instead of 160", 130, 100, 155)
519    conn.confirm_valid_oci(129, 100, 0)
520
521    dev[0].dump_monitor()
522    if conn.hapd:
523        conn.hapd.request("DISABLE")
524    dev[0].disconnect_and_stop_scan()
525
526@remote_compatible
527def test_wpa2_ocv_ap_vht80plus80_mismatch(dev, apdev):
528    """OCV AP mismatch (VHT80+80)"""
529    try:
530        run_wpa2_ocv_ap_vht80plus80_mismatch(dev, apdev)
531    finally:
532        set_world_reg(apdev[0], apdev[1], dev[0])
533        dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=0.5)
534        dev[0].flush_scan_cache()
535
536def run_wpa2_ocv_ap_vht80plus80_mismatch(dev, apdev):
537    params = {"hw_mode": "a",
538              "channel": "36",
539              "country_code": "US",
540              "ht_capab": "[HT40+]",
541              "ieee80211w": "1",
542              "ieee80211n": "1",
543              "ieee80211ac": "1",
544              "vht_oper_chwidth": "3",
545              "freq": "5180",
546              "vht_oper_centr_freq_seg0_idx": "42",
547              "ieee80211d": "1",
548              "vht_oper_centr_freq_seg1_idx": "155",
549              "ieee80211h": "1"}
550    conn = APConnection(apdev[0], dev[0], params)
551    conn.test_bad_oci("using 80 MHz operating class", 128, 36, 155)
552    conn.test_bad_oci("wrong frequency segment 1", 130, 36, 138)
553    conn.confirm_valid_oci(130, 36, 155)
554
555    dev[0].dump_monitor()
556    if conn.hapd:
557        conn.hapd.request("DISABLE")
558    dev[0].disconnect_and_stop_scan()
559
560@remote_compatible
561def test_wpa2_ocv_ap_unexpected1(dev, apdev):
562    """OCV and unexpected OCI KDE from station"""
563    params = {"channel": "1",
564              "ieee80211w": "1",
565              "ap_ocv": "0",
566              "sta_ocv": "1",
567              "freq": "2412"}
568    conn = APConnection(apdev[0], dev[0], params)
569    logger.debug("Client will send OCI KDE even if it was not negotiated")
570    conn.confirm_valid_oci(81, 1, 0)
571
572@remote_compatible
573def test_wpa2_ocv_ap_unexpected2(dev, apdev):
574    """OCV and unexpected OCI KDE from station"""
575    params = {"channel": "1",
576              "ieee80211w": "1",
577              "ap_ocv": "1",
578              "sta_ocv": "0",
579              "freq": "2412"}
580    conn = APConnection(apdev[0], dev[0], params)
581    logger.debug("Client will send OCI KDE even if it was not negotiated")
582    conn.confirm_valid_oci(81, 1, 0)
583
584@remote_compatible
585def test_wpa2_ocv_ap_retransmit_msg3(dev, apdev):
586    """Verify that manually retransmitted msg 3/4 contain a correct OCI"""
587    bssid = apdev[0]['bssid']
588    ssid = "test-wpa2-ocv"
589    passphrase = "qwertyuiop"
590    psk = "c2c6c255af836bed1b3f2f1ded98e052f5ad618bb554e2836757b55854a0eab7"
591    params = hostapd.wpa2_params(ssid=ssid)
592    params["wpa_psk"] = psk
593    params["ieee80211w"] = "1"
594    params["ocv"] = "1"
595    params['wpa_disable_eapol_key_retries'] = "1"
596    try:
597        hapd = hostapd.add_ap(apdev[0], params)
598    except Exception as e:
599        if "Failed to set hostapd parameter ocv" in str(e):
600            raise HwsimSkip("OCV not supported")
601        raise
602    hapd.request("SET ext_eapol_frame_io 1")
603    dev[0].request("SET ext_eapol_frame_io 1")
604    dev[0].connect(ssid, psk=passphrase, scan_freq="2412", wait_connect=False,
605                   ocv="1", ieee80211w="1")
606    addr = dev[0].own_addr()
607
608    # EAPOL-Key msg 1/4
609    ev = hapd.wait_event(["EAPOL-TX"], timeout=15)
610    if ev is None:
611        raise Exception("Timeout on EAPOL-TX from hostapd")
612    res = dev[0].request("EAPOL_RX " + bssid + " " + ev.split(' ')[2])
613    if "OK" not in res:
614        raise Exception("EAPOL_RX to wpa_supplicant failed")
615
616    # EAPOL-Key msg 2/4
617    ev = dev[0].wait_event(["EAPOL-TX"], timeout=15)
618    if ev is None:
619        raise Exception("Timeout on EAPOL-TX from wpa_supplicant")
620    res = hapd.request("EAPOL_RX " + addr + " " + ev.split(' ')[2])
621    if "OK" not in res:
622        raise Exception("EAPOL_RX to hostapd failed")
623
624    # EAPOL-Key msg 3/4
625    ev = hapd.wait_event(["EAPOL-TX"], timeout=15)
626    if ev is None:
627        raise Exception("Timeout on EAPOL-TX from hostapd")
628    logger.info("Drop the first EAPOL-Key msg 3/4")
629
630    # Use normal EAPOL TX/RX to handle retries.
631    hapd.request("SET ext_eapol_frame_io 0")
632    dev[0].request("SET ext_eapol_frame_io 0")
633
634    # Manually retransmit EAPOL-Key msg 3/4
635    if "OK" not in hapd.request("RESEND_M3 " + addr):
636        raise Exception("RESEND_M3 failed")
637
638    dev[0].wait_connected()
639    hwsim_utils.test_connectivity(dev[0], hapd)
640
641def test_wpa2_ocv_ap_group_hs(dev, apdev):
642    """OCV group handshake (AP)"""
643    params = {"channel": "1",
644              "ieee80211w": "1",
645              "freq": "2412",
646              "wpa_strict_rekey": "1"}
647    conn = APConnection(apdev[0], dev[0], params)
648    conn.confirm_valid_oci(81, 1, 0)
649
650    conn.hapd.request("SET ext_eapol_frame_io 0")
651    dev[1].connect(conn.ssid, psk=conn.passphrase, scan_freq="2412", ocv="1",
652                   ieee80211w="1")
653    conn.hapd.wait_sta()
654    conn.hapd.request("SET ext_eapol_frame_io 1")
655
656    # Trigger a group key handshake
657    dev[1].request("DISCONNECT")
658    dev[0].dump_monitor()
659
660    # Wait for EAPOL-Key msg 1/2
661    conn.msg = recv_eapol(conn.hapd)
662    if conn.msg["rsn_key_info"] != 4994:
663        raise Exception("Didn't receive 1/2 of group key handshake")
664
665    # Send a EAPOL-Key msg 2/2 with a bad OCI
666    logger.info("Bad OCI element")
667    ocikde = make_ocikde(1, 1, 1)
668    msg = build_eapol_key_2_2(conn.kck, ocikde, replay_counter=3)
669    conn.hapd.dump_monitor()
670    send_eapol(conn.hapd, conn.addr, build_eapol(msg))
671
672    # Wait for retransmitted EAPOL-Key msg 1/2
673    conn.msg = recv_eapol(conn.hapd)
674    if conn.msg["rsn_key_info"] != 4994:
675        raise Exception("Didn't receive 1/2 of group key handshake")
676
677    # Send a EAPOL-Key msg 2/2 with a good OCI
678    logger.info("Good OCI element")
679    ocikde = make_ocikde(81, 1, 0)
680    msg = build_eapol_key_2_2(conn.kck, ocikde, replay_counter=4)
681    conn.hapd.dump_monitor()
682    send_eapol(conn.hapd, conn.addr, build_eapol(msg))
683
684    # Verify that group key handshake has completed
685    ev = conn.hapd.wait_event(["EAPOL-TX"], timeout=1)
686    if ev is not None:
687        eapol = binascii.unhexlify(ev.split(' ')[2])
688        msg = parse_eapol(eapol)
689        if msg["rsn_key_info"] == 4994:
690            raise Exception("AP didn't accept 2/2 of group key handshake")
691
692class STAConnection:
693    def init_params(self):
694        # Static parameters
695        self.ssid = "test-wpa2-ocv"
696        self.passphrase = "qwertyuiop"
697        self.psk = "c2c6c255af836bed1b3f2f1ded98e052f5ad618bb554e2836757b55854a0eab7"
698
699        # Dynamic parameters
700        self.hapd = None
701        self.dev = None
702        self.addr = None
703        self.rsne = None
704        self.kck = None
705        self.kek = None
706        self.msg = None
707        self.bssid = None
708        self.anonce = None
709        self.snonce = None
710        self.gtkie = None
711        self.counter = None
712
713    def __init__(self, apdev, dev, params, sta_params=None):
714        self.init_params()
715        self.dev = dev
716        self.bssid = apdev['bssid']
717
718        freq = params.pop("freq")
719        if sta_params is None:
720            sta_params = dict()
721        if "ocv" not in sta_params:
722            sta_params["ocv"] = "1"
723        if "ieee80211w" not in sta_params:
724            sta_params["ieee80211w"] = "1"
725
726        params.update(hostapd.wpa2_params(ssid=self.ssid,
727                                          passphrase=self.passphrase))
728        params['wpa_pairwise_update_count'] = "10"
729
730        try:
731            self.hapd = hostapd.add_ap(apdev, params)
732        except Exception as e:
733            if "Failed to set hostapd parameter ocv" in str(e):
734                raise HwsimSkip("OCV not supported")
735            raise
736        self.hapd.request("SET ext_eapol_frame_io 1")
737        self.dev.request("SET ext_eapol_frame_io 1")
738        pmk = binascii.unhexlify("c2c6c255af836bed1b3f2f1ded98e052f5ad618bb554e2836757b55854a0eab7")
739
740        self.gtkie = binascii.unhexlify("dd16000fac010100dc11188831bf4aa4a8678d2b41498618")
741        if sta_params["ocv"] != "0":
742            self.rsne = binascii.unhexlify("30140100000fac040100000fac040100000fac028c40")
743        else:
744            self.rsne = binascii.unhexlify("30140100000fac040100000fac040100000fac028c00")
745
746        self.dev.connect(self.ssid, raw_psk=self.psk, scan_freq=freq,
747                         wait_connect=False, **sta_params)
748        if "country_code" in params:
749            self.dev.wait_regdom(country_ie=True)
750        self.addr = dev.p2p_interface_addr()
751
752        # Forward msg 1/4 from AP to STA
753        self.msg = recv_eapol(self.hapd)
754        self.anonce = self.msg['rsn_key_nonce']
755        send_eapol(self.dev, self.bssid, build_eapol(self.msg))
756
757        # Capture msg 2/4 from the STA so we can derive the session keys
758        self.msg = recv_eapol(dev)
759        self.snonce = self.msg['rsn_key_nonce']
760        (ptk, self.kck, self.kek) = pmk_to_ptk(pmk, self.addr, self.bssid,
761                                               self.snonce, self.anonce)
762
763        self.counter = struct.unpack('>Q',
764                                     self.msg['rsn_replay_counter'])[0] + 1
765
766    def test_bad_oci(self, logmsg, op_class, channel, seg1_idx, errmsg):
767        logger.info("Bad OCI element: " + logmsg)
768        if op_class is None:
769            ocikde = b''
770        else:
771            ocikde = make_ocikde(op_class, channel, seg1_idx)
772
773        plain = self.rsne + self.gtkie + ocikde
774        wrapped = aes_wrap(self.kek, pad_key_data(plain))
775        msg = build_eapol_key_3_4(self.anonce, self.kck, wrapped,
776                                  replay_counter=self.counter)
777
778        self.dev.dump_monitor()
779        send_eapol(self.dev, self.bssid, build_eapol(msg))
780        self.counter += 1
781
782        ev = self.dev.wait_event([errmsg], timeout=5)
783        if ev is None:
784            raise Exception("Bad OCI not reported")
785
786    def confirm_valid_oci(self, op_class, channel, seg1_idx):
787        logger.debug("Valid OCI element to complete handshake")
788        ocikde = make_ocikde(op_class, channel, seg1_idx)
789
790        plain = self.rsne + self.gtkie + ocikde
791        wrapped = aes_wrap(self.kek, pad_key_data(plain))
792        msg = build_eapol_key_3_4(self.anonce, self.kck, wrapped,
793                                  replay_counter=self.counter)
794
795        self.dev.dump_monitor()
796        send_eapol(self.dev, self.bssid, build_eapol(msg))
797        self.counter += 1
798
799        self.dev.wait_connected(timeout=1)
800
801@remote_compatible
802def test_wpa2_ocv_mismatch_client(dev, apdev):
803    """OCV client mismatch"""
804    params = {"channel": "1",
805              "ieee80211w": "1",
806              "ocv": "1",
807              "freq": "2412"}
808    conn = STAConnection(apdev[0], dev[0], params)
809    conn.test_bad_oci("element missing", None, 0, 0,
810                      "did not receive mandatory OCI")
811    conn.test_bad_oci("wrong channel number", 81, 6, 0,
812                      "primary channel mismatch")
813    conn.test_bad_oci("invalid channel number", 81, 0, 0,
814                      "unable to interpret received OCI")
815    conn.test_bad_oci("wrong operating class", 80, 0, 0,
816                      "unable to interpret received OCI")
817    conn.test_bad_oci("invalid operating class", 0, 0, 0,
818                      "unable to interpret received OCI")
819    conn.confirm_valid_oci(81, 1, 0)
820
821@remote_compatible
822def test_wpa2_ocv_vht160_mismatch_client(dev, apdev):
823    """OCV client mismatch (VHT160)"""
824    try:
825        run_wpa2_ocv_vht160_mismatch_client(dev, apdev)
826    finally:
827        set_world_reg(apdev[0], apdev[1], dev[0])
828        dev[0].wait_event(["CTRL-EVENT-REGDOM-CHANGE"], timeout=0.5)
829        dev[0].flush_scan_cache()
830
831def run_wpa2_ocv_vht160_mismatch_client(dev, apdev):
832    params = {"hw_mode": "a",
833              "channel": "100",
834              "country_code": "ZA",
835              "ht_capab": "[HT40+]",
836              "ieee80211w": "1",
837              "ieee80211n": "1",
838              "ieee80211ac": "1",
839              "vht_oper_chwidth": "2",
840              "ocv": "1",
841              "vht_oper_centr_freq_seg0_idx": "114",
842              "freq": "5500",
843              "ieee80211d": "1",
844              "ieee80211h": "1"}
845    sta_params = {"disable_vht": "1"}
846    conn = STAConnection(apdev[0], dev[0], params, sta_params)
847    conn.test_bad_oci("smaller bandwidth (20 Mhz) than negotiated",
848                      121, 100, 0, "channel bandwidth mismatch")
849    conn.test_bad_oci("wrong frequency, bandwith, and secondary channel",
850                      123, 104, 0, "primary channel mismatch")
851    conn.test_bad_oci("wrong upper/lower behaviour",
852                      129, 104, 0, "primary channel mismatch")
853    conn.confirm_valid_oci(122, 100, 0)
854
855    dev[0].dump_monitor()
856    if conn.hapd:
857        conn.hapd.request("DISABLE")
858    dev[0].disconnect_and_stop_scan()
859
860def test_wpa2_ocv_sta_group_hs(dev, apdev):
861    """OCV group handshake (STA)"""
862    params = {"channel": "1",
863              "ieee80211w": "1",
864              "ocv": "1",
865              "freq": "2412",
866              "wpa_strict_rekey": "1"}
867    conn = STAConnection(apdev[0], dev[0], params.copy())
868    conn.confirm_valid_oci(81, 1, 0)
869
870    # Send a EAPOL-Key msg 1/2 with a bad OCI
871    logger.info("Bad OCI element")
872    plain = conn.gtkie + make_ocikde(1, 1, 1)
873    wrapped = aes_wrap(conn.kek, pad_key_data(plain))
874    msg = build_eapol_key_1_2(conn.kck, wrapped, replay_counter=3)
875    send_eapol(dev[0], conn.bssid, build_eapol(msg))
876
877    # We shouldn't get a EAPOL-Key message back
878    ev = dev[0].wait_event(["EAPOL-TX"], timeout=1)
879    if ev is not None:
880        raise Exception("Received response to invalid EAPOL-Key 1/2")
881
882    # Reset AP to try with valid OCI
883    conn.hapd.disable()
884    conn = STAConnection(apdev[0], dev[0], params.copy())
885    conn.confirm_valid_oci(81, 1, 0)
886
887    # Send a EAPOL-Key msg 1/2 with a good OCI
888    logger.info("Good OCI element")
889    plain = conn.gtkie + make_ocikde(81, 1, 0)
890    wrapped = aes_wrap(conn.kek, pad_key_data(plain))
891    msg = build_eapol_key_1_2(conn.kck, wrapped, replay_counter=4)
892    send_eapol(dev[0], conn.bssid, build_eapol(msg))
893
894    # Wait for EAPOL-Key msg 2/2
895    conn.msg = recv_eapol(dev[0])
896    if conn.msg["rsn_key_info"] != 0x0302:
897        raise Exception("Didn't receive 2/2 of group key handshake")
898
899def test_wpa2_ocv_auto_enable_pmf(dev, apdev):
900    """OCV on 2.4 GHz with PMF getting enabled automatically"""
901    params = {"channel": "1",
902              "ocv": "1"}
903    hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
904    for ocv in range(2):
905        dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv=str(ocv),
906                       ieee80211w="2")
907        dev[0].request("REMOVE_NETWORK all")
908        dev[0].wait_disconnected()
909
910def test_wpa2_ocv_sta_override_eapol(dev, apdev):
911    """OCV on 2.4 GHz and STA override EAPOL-Key msg 2/4"""
912    params = {"channel": "1",
913              "ieee80211w": "2",
914              "ocv": "1"}
915    hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
916    dev[0].set("oci_freq_override_eapol", "2462")
917    dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1",
918                   ieee80211w="2", wait_connect=False)
919    ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
920                            "CTRL-EVENT-DISCONNECTED"], timeout=15)
921    dev[0].request("DISCONNECT")
922    if ev is None:
923        raise Exception("No connection result reported")
924    if "CTRL-EVENT-CONNECTED" in ev:
925        raise Exception("Unexpected connection")
926    if "reason=15" not in ev:
927        raise Exception("Unexpected disconnection reason: " + ev)
928
929    check_ocv_failure(hapd, "EAPOL-Key msg 2/4", "eapol-key-m2",
930                      dev[0].own_addr())
931
932def test_wpa2_ocv_sta_override_sa_query_req(dev, apdev):
933    """OCV on 2.4 GHz and STA override SA Query Request"""
934    params = {"channel": "1",
935              "ieee80211w": "2",
936              "ocv": "1"}
937    hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
938    dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1",
939                   ieee80211w="2")
940    hapd.wait_sta()
941    dev[0].set("oci_freq_override_saquery_req", "2462")
942    if "OK" not in dev[0].request("UNPROT_DEAUTH"):
943        raise Exception("Triggering SA Query from the STA failed")
944    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=3)
945    if ev is None:
946        raise Exception("Disconnection after failed SA Query not reported")
947    dev[0].set("oci_freq_override_saquery_req", "0")
948    dev[0].wait_connected()
949    if "OK" not in dev[0].request("UNPROT_DEAUTH"):
950        raise Exception("Triggering SA Query from the STA failed")
951    check_ocv_failure(hapd, "SA Query Request", "saqueryreq",
952                      dev[0].own_addr())
953    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=3)
954    if ev is not None:
955        raise Exception("SA Query from the STA failed")
956
957def test_wpa2_ocv_sta_override_sa_query_resp(dev, apdev):
958    """OCV on 2.4 GHz and STA override SA Query Response"""
959    params = {"channel": "1",
960              "ieee80211w": "2",
961              "ocv": "1"}
962    hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
963    dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1",
964                   ieee80211w="2")
965    dev[0].set("oci_freq_override_saquery_resp", "2462")
966    hapd.wait_sta()
967    if "OK" not in hapd.request("SA_QUERY " + dev[0].own_addr()):
968        raise Exception("SA_QUERY failed")
969    check_ocv_failure(hapd, "SA Query Response", "saqueryresp",
970                      dev[0].own_addr())
971
972def check_ocv_failure(dev, frame_txt, frame, addr):
973    ev = dev.wait_event(["OCV-FAILURE"], timeout=3)
974    if ev is None:
975        raise Exception("OCV failure for %s not reported" % frame_txt)
976    if "addr=" + addr not in ev:
977        raise Exception("Unexpected OCV failure addr: " + ev)
978    if "frame=" + frame not in ev:
979        raise Exception("Unexpected OCV failure frame: " + ev)
980    if "error=primary channel mismatch" not in ev:
981        raise Exception("Unexpected OCV failure error: " + ev)
982
983def test_wpa2_ocv_ap_override_eapol_m3(dev, apdev):
984    """OCV on 2.4 GHz and AP override EAPOL-Key msg 3/4"""
985    run_wpa2_ocv_ap_override_eapol_m3(dev, apdev)
986
987def test_wpa2_ocv_ap_override_eapol_m3_post_enable(dev, apdev):
988    """OCV on 2.4 GHz and AP override EAPOL-Key msg 3/4 (post enable)"""
989    run_wpa2_ocv_ap_override_eapol_m3(dev, apdev, True)
990
991def run_wpa2_ocv_ap_override_eapol_m3(dev, apdev, post_enable=False):
992    params = {"channel": "1",
993              "ieee80211w": "2",
994              "ocv": "1"}
995    if not post_enable:
996        params["oci_freq_override_eapol_m3"] = "2462"
997    hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
998    bssid = hapd.own_addr()
999    if post_enable:
1000        hapd.set("oci_freq_override_eapol_m3", "2462")
1001    dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1",
1002                   ieee80211w="2", wait_connect=False)
1003
1004    check_ocv_failure(dev[0], "EAPOL-Key msg 3/4", "eapol-key-m3", bssid)
1005
1006    ev = dev[0].wait_disconnected()
1007    if "reason=15" not in ev:
1008        raise Exception("Unexpected disconnection reason: " + ev)
1009
1010def test_wpa2_ocv_ap_override_eapol_g1(dev, apdev):
1011    """OCV on 2.4 GHz and AP override EAPOL-Key group msg 1/2"""
1012    run_wpa2_ocv_ap_override_eapol_g1(dev, apdev)
1013
1014def test_wpa2_ocv_ap_override_eapol_g1_post_enable(dev, apdev):
1015    """OCV on 2.4 GHz and AP override EAPOL-Key group msg 1/2 (post enable)"""
1016    run_wpa2_ocv_ap_override_eapol_g1(dev, apdev, True)
1017
1018def run_wpa2_ocv_ap_override_eapol_g1(dev, apdev, post_enable=False):
1019    params = {"channel": "1",
1020              "ieee80211w": "2",
1021              "ocv": "1"}
1022    if not post_enable:
1023        params["oci_freq_override_eapol_g1"] = "2462"
1024    hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
1025    bssid = hapd.own_addr()
1026    dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1",
1027                   ieee80211w="2")
1028
1029    if post_enable:
1030        hapd.set("oci_freq_override_eapol_g1", "2462")
1031    if "OK" not in hapd.request("REKEY_GTK"):
1032        raise Exception("REKEY_GTK failed")
1033    check_ocv_failure(dev[0], "EAPOL-Key group msg 1/2", "eapol-key-g1", bssid)
1034
1035def test_wpa2_ocv_ap_override_saquery_req(dev, apdev):
1036    """OCV on 2.4 GHz and AP override SA Query Request"""
1037    params = {"channel": "1",
1038              "ieee80211w": "2",
1039              "ocv": "1",
1040              "oci_freq_override_saquery_req": "2462"}
1041    hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
1042    bssid = hapd.own_addr()
1043    dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1",
1044                   ieee80211w="2")
1045
1046    if "OK" not in hapd.request("SA_QUERY " + dev[0].own_addr()):
1047        raise Exception("SA_QUERY failed")
1048    check_ocv_failure(dev[0], "SA Query Request", "saqueryreq", bssid)
1049
1050def test_wpa2_ocv_ap_override_saquery_resp(dev, apdev):
1051    """OCV on 2.4 GHz and AP override SA Query Response"""
1052    params = {"channel": "1",
1053              "ieee80211w": "2",
1054              "ocv": "1",
1055              "oci_freq_override_saquery_resp": "2462"}
1056    hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
1057    bssid = hapd.own_addr()
1058    dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="1",
1059                   ieee80211w="2")
1060
1061    if "OK" not in dev[0].request("UNPROT_DEAUTH"):
1062        raise Exception("Triggering SA Query from the STA failed")
1063    check_ocv_failure(dev[0], "SA Query Response", "saqueryresp", bssid)
1064
1065def test_wpa2_ocv_ap_override_fils_assoc(dev, apdev, params):
1066    """OCV on 2.4 GHz and AP override FILS association"""
1067    run_wpa2_ocv_ap_override_fils_assoc(dev, apdev, params)
1068
1069def test_wpa2_ocv_ap_override_fils_assoc_post_enable(dev, apdev, params):
1070    """OCV on 2.4 GHz and AP override FILS association (post enable)"""
1071    run_wpa2_ocv_ap_override_fils_assoc(dev, apdev, params, True)
1072
1073def run_wpa2_ocv_ap_override_fils_assoc(dev, apdev, params, post_enable=False):
1074    check_fils_capa(dev[0])
1075    check_erp_capa(dev[0])
1076
1077    start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
1078
1079    bssid = apdev[0]['bssid']
1080    ssid = "test-wpa2-ocv"
1081    params = hostapd.wpa2_eap_params(ssid=ssid)
1082    params['wpa_key_mgmt'] = "FILS-SHA256"
1083    params['auth_server_port'] = "18128"
1084    params['erp_send_reauth_start'] = '1'
1085    params['erp_domain'] = 'example.com'
1086    params['fils_realm'] = 'example.com'
1087    params['wpa_group_rekey'] = '1'
1088    params["ieee80211w"] = "2"
1089    params["ocv"] = "1"
1090    if not post_enable:
1091        params["oci_freq_override_fils_assoc"] = "2462"
1092    try:
1093        hapd = hostapd.add_ap(apdev[0], params)
1094    except Exception as e:
1095        if "Failed to set hostapd parameter ocv" in str(e):
1096            raise HwsimSkip("OCV not supported")
1097        raise
1098    bssid = hapd.own_addr()
1099    if post_enable:
1100        hapd.set("oci_freq_override_fils_assoc", "2462")
1101    dev[0].request("ERP_FLUSH")
1102    id = dev[0].connect(ssid, key_mgmt="FILS-SHA256",
1103                        eap="PSK", identity="psk.user@example.com",
1104                        password_hex="0123456789abcdef0123456789abcdef",
1105                        erp="1", scan_freq="2412", ocv="1", ieee80211w="2")
1106
1107    dev[0].request("DISCONNECT")
1108    dev[0].wait_disconnected()
1109
1110    dev[0].dump_monitor()
1111    dev[0].select_network(id, freq=2412)
1112
1113    check_ocv_failure(dev[0], "FILS Association Response", "fils-assoc", bssid)
1114    dev[0].request("DISCONNECT")
1115
1116def test_wpa2_ocv_ap_override_ft_assoc(dev, apdev):
1117    """OCV on 2.4 GHz and AP override FT reassociation"""
1118    run_wpa2_ocv_ap_override_ft_assoc(dev, apdev)
1119
1120def test_wpa2_ocv_ap_override_ft_assoc_post_enable(dev, apdev):
1121    """OCV on 2.4 GHz and AP override FT reassociation (post enable)"""
1122    run_wpa2_ocv_ap_override_ft_assoc(dev, apdev, True)
1123
1124def run_wpa2_ocv_ap_override_ft_assoc(dev, apdev, post_enable=False):
1125    ssid = "test-wpa2-ocv"
1126    passphrase = "qwertyuiop"
1127    params = ft_params1(ssid=ssid, passphrase=passphrase)
1128    params["ieee80211w"] = "2"
1129    params["ocv"] = "1"
1130    if not post_enable:
1131        params["oci_freq_override_ft_assoc"] = "2462"
1132    try:
1133        hapd0 = hostapd.add_ap(apdev[0], params)
1134    except Exception as e:
1135        if "Failed to set hostapd parameter ocv" in str(e):
1136            raise HwsimSkip("OCV not supported")
1137        raise
1138    params = ft_params2(ssid=ssid, passphrase=passphrase)
1139    params["ieee80211w"] = "2"
1140    params["ocv"] = "1"
1141    if not post_enable:
1142        params["oci_freq_override_ft_assoc"] = "2462"
1143    hapd1 = hostapd.add_ap(apdev[1], params)
1144
1145    if post_enable:
1146        hapd0.set("oci_freq_override_ft_assoc", "2462")
1147        hapd1.set("oci_freq_override_ft_assoc", "2462")
1148
1149    dev[0].connect(ssid, key_mgmt="FT-PSK", psk=passphrase,
1150                   scan_freq="2412", ocv="1", ieee80211w="2")
1151
1152    bssid = dev[0].get_status_field("bssid")
1153    bssid0 = hapd0.own_addr()
1154    bssid1 = hapd1.own_addr()
1155    target = bssid0 if bssid == bssid1 else bssid1
1156
1157    dev[0].scan_for_bss(target, freq="2412")
1158    if "OK" not in dev[0].request("ROAM " + target):
1159        raise Exception("ROAM failed")
1160
1161    check_ocv_failure(dev[0], "FT Reassociation Response", "ft-assoc", target)
1162    dev[0].request("DISCONNECT")
1163
1164@remote_compatible
1165def test_wpa2_ocv_no_pmf(dev, apdev):
1166    """OCV on 2.4 GHz and no PMF on STA"""
1167    params = {"channel": "1",
1168              "ieee80211w": "1",
1169              "ocv": "1"}
1170    hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
1171    ie = "301a0100000fac040100000fac040100000fac0200400000000fac06"
1172    if "OK" not in dev[0].request("TEST_ASSOC_IE " + ie):
1173        raise Exception("Could not set TEST_ASSOC_IE")
1174    dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="0",
1175                   ieee80211w="0", wait_connect=False)
1176    ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", "CTRL-EVENT-ASSOC-REJECT"],
1177                           timeout=10)
1178    dev[0].request("DISCONNECT")
1179    if ev is None:
1180        raise Exception("No connection result seen")
1181    if "CTRL-EVENT-CONNECTED" in ev:
1182        raise Exception("Unexpected connection")
1183    if "status_code=31" not in ev:
1184        raise Exception("Unexpected status code: " + ev)
1185
1186@remote_compatible
1187def test_wpa2_ocv_no_pmf_workaround(dev, apdev):
1188    """OCV on 2.4 GHz and no PMF on STA with workaround"""
1189    params = {"channel": "1",
1190              "ieee80211w": "1",
1191              "ocv": "2"}
1192    hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
1193    ie = "301a0100000fac040100000fac040100000fac0200400000000fac06"
1194    if "OK" not in dev[0].request("TEST_ASSOC_IE " + ie):
1195        raise Exception("Could not set TEST_ASSOC_IE")
1196    dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="0",
1197                   ieee80211w="0")
1198
1199@remote_compatible
1200def test_wpa2_ocv_no_oci(dev, apdev):
1201    """OCV on 2.4 GHz and no OCI from STA"""
1202    params = {"channel": "1",
1203              "ieee80211w": "1",
1204              "ocv": "1"}
1205    hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
1206    ie = "301a0100000fac040100000fac040100000fac0280400000000fac06"
1207    if "OK" not in dev[0].request("TEST_ASSOC_IE " + ie):
1208        raise Exception("Could not set TEST_ASSOC_IE")
1209    dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="0",
1210                   ieee80211w="1", wait_connect=False)
1211    ev = hapd.wait_event(["OCV-FAILURE"], timeout=10)
1212    if ev is None:
1213        raise Exception("No OCV failure reported")
1214    if "frame=eapol-key-m2 error=did not receive mandatory OCI" not in ev:
1215        raise Exception("Unexpected error: " + ev)
1216    ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
1217                            "WPA: 4-Way Handshake failed"], timeout=10)
1218    dev[0].request("DISCONNECT")
1219    if "CTRL-EVENT-CONNECTED" in ev:
1220        raise Exception("Unexpected connection")
1221    if ev is None:
1222        raise Exception("4-way handshake failure not reported")
1223
1224@remote_compatible
1225def test_wpa2_ocv_no_oci_workaround(dev, apdev):
1226    """OCV on 2.4 GHz and no OCI from STA with workaround"""
1227    params = {"channel": "1",
1228              "ieee80211w": "1",
1229              "ocv": "2"}
1230    hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
1231    ie = "301a0100000fac040100000fac040100000fac0280400000000fac06"
1232    if "OK" not in dev[0].request("TEST_ASSOC_IE " + ie):
1233        raise Exception("Could not set TEST_ASSOC_IE")
1234    dev[0].connect(ssid, psk=passphrase, scan_freq="2412", ocv="0",
1235                   ieee80211w="1")
1236
1237def test_wpa2_ocv_without_pmf(dev, apdev):
1238    """OCV without PMF"""
1239    params = {"channel": "6",
1240              "ieee80211n": "1",
1241              "ieee80211w": "1",
1242              "ocv": "1"}
1243    hapd, ssid, passphrase = ocv_setup_ap(apdev[0], params)
1244    hapd.disable()
1245    hapd.set("ieee80211w", "0")
1246    if "FAIL" not in hapd.request("ENABLE"):
1247        raise Exception("OCV without PMF accepted")
1248