1# Test cases for FILS
2# Copyright (c) 2015-2017, Qualcomm Atheros, Inc.
3#
4# This software may be distributed under the terms of the BSD license.
5# See README for more details.
6
7import binascii
8import hashlib
9import logging
10logger = logging.getLogger()
11import os
12import socket
13import struct
14import time
15
16import hostapd
17from tshark import run_tshark
18from wpasupplicant import WpaSupplicant
19import hwsim_utils
20from utils import *
21from test_erp import start_erp_as
22from test_ap_hs20 import ip_checksum
23
24def test_fils_sk_full_auth(dev, apdev, params):
25    """FILS SK full authentication"""
26    check_fils_capa(dev[0])
27    check_erp_capa(dev[0])
28
29    start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
30
31    bssid = apdev[0]['bssid']
32    params = hostapd.wpa2_eap_params(ssid="fils")
33    params['wpa_key_mgmt'] = "FILS-SHA256"
34    params['auth_server_port'] = "18128"
35    params['erp_send_reauth_start'] = '1'
36    params['erp_domain'] = 'example.com'
37    params['fils_realm'] = 'example.com'
38    params['wpa_group_rekey'] = '1'
39    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
40
41    dev[0].flush_scan_cache()
42    dev[0].scan_for_bss(bssid, freq=2412)
43    bss = dev[0].get_bss(bssid)
44    logger.debug("BSS: " + str(bss))
45    if "[FILS]" not in bss['flags']:
46        raise Exception("[FILS] flag not indicated")
47    if "[WPA2-FILS-SHA256-CCMP]" not in bss['flags']:
48        raise Exception("[WPA2-FILS-SHA256-CCMP] flag not indicated")
49
50    res = dev[0].request("SCAN_RESULTS")
51    logger.debug("SCAN_RESULTS: " + res)
52    if "[FILS]" not in res:
53        raise Exception("[FILS] flag not indicated")
54    if "[WPA2-FILS-SHA256-CCMP]" not in res:
55        raise Exception("[WPA2-FILS-SHA256-CCMP] flag not indicated")
56
57    dev[0].request("ERP_FLUSH")
58    dev[0].connect("fils", key_mgmt="FILS-SHA256",
59                   eap="PSK", identity="psk.user@example.com",
60                   password_hex="0123456789abcdef0123456789abcdef",
61                   erp="1", scan_freq="2412")
62    hwsim_utils.test_connectivity(dev[0], hapd)
63
64    ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=2)
65    if ev is None:
66        raise Exception("GTK rekey timed out")
67    hwsim_utils.test_connectivity(dev[0], hapd)
68
69    conf = hapd.get_config()
70    if conf['key_mgmt'] != 'FILS-SHA256':
71        raise Exception("Unexpected config key_mgmt: " + conf['key_mgmt'])
72
73def test_fils_sk_sha384_full_auth(dev, apdev, params):
74    """FILS SK full authentication (SHA384)"""
75    check_fils_capa(dev[0])
76    check_erp_capa(dev[0])
77
78    start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
79
80    bssid = apdev[0]['bssid']
81    params = hostapd.wpa2_eap_params(ssid="fils")
82    params['wpa_key_mgmt'] = "FILS-SHA384"
83    params['auth_server_port'] = "18128"
84    params['erp_send_reauth_start'] = '1'
85    params['erp_domain'] = 'example.com'
86    params['fils_realm'] = 'example.com'
87    params['wpa_group_rekey'] = '1'
88    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
89
90    dev[0].flush_scan_cache()
91    dev[0].scan_for_bss(bssid, freq=2412)
92    bss = dev[0].get_bss(bssid)
93    logger.debug("BSS: " + str(bss))
94    if "[FILS]" not in bss['flags']:
95        raise Exception("[FILS] flag not indicated")
96    if "[WPA2-FILS-SHA384-CCMP]" not in bss['flags']:
97        raise Exception("[WPA2-FILS-SHA384-CCMP] flag not indicated")
98
99    res = dev[0].request("SCAN_RESULTS")
100    logger.debug("SCAN_RESULTS: " + res)
101    if "[FILS]" not in res:
102        raise Exception("[FILS] flag not indicated")
103    if "[WPA2-FILS-SHA384-CCMP]" not in res:
104        raise Exception("[WPA2-FILS-SHA384-CCMP] flag not indicated")
105
106    dev[0].request("ERP_FLUSH")
107    dev[0].connect("fils", key_mgmt="FILS-SHA384",
108                   eap="PSK", identity="psk.user@example.com",
109                   password_hex="0123456789abcdef0123456789abcdef",
110                   erp="1", scan_freq="2412")
111    hwsim_utils.test_connectivity(dev[0], hapd)
112
113    ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=2)
114    if ev is None:
115        raise Exception("GTK rekey timed out")
116    hwsim_utils.test_connectivity(dev[0], hapd)
117
118    conf = hapd.get_config()
119    if conf['key_mgmt'] != 'FILS-SHA384':
120        raise Exception("Unexpected config key_mgmt: " + conf['key_mgmt'])
121
122def test_fils_sk_pmksa_caching(dev, apdev, params):
123    """FILS SK and PMKSA caching"""
124    check_fils_capa(dev[0])
125    check_erp_capa(dev[0])
126
127    start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
128
129    bssid = apdev[0]['bssid']
130    params = hostapd.wpa2_eap_params(ssid="fils")
131    params['wpa_key_mgmt'] = "FILS-SHA256"
132    params['auth_server_port'] = "18128"
133    params['erp_domain'] = 'example.com'
134    params['fils_realm'] = 'example.com'
135    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
136
137    dev[0].scan_for_bss(bssid, freq=2412)
138    dev[0].request("ERP_FLUSH")
139    id = dev[0].connect("fils", key_mgmt="FILS-SHA256",
140                        eap="PSK", identity="psk.user@example.com",
141                        password_hex="0123456789abcdef0123456789abcdef",
142                        erp="1", scan_freq="2412")
143    pmksa = dev[0].get_pmksa(bssid)
144    if pmksa is None:
145        raise Exception("No PMKSA cache entry created")
146
147    dev[0].request("DISCONNECT")
148    dev[0].wait_disconnected()
149
150    dev[0].dump_monitor()
151    dev[0].select_network(id, freq=2412)
152    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
153                            "CTRL-EVENT-CONNECTED"], timeout=10)
154    if ev is None:
155        raise Exception("Connection using PMKSA caching timed out")
156    if "CTRL-EVENT-EAP-STARTED" in ev:
157        raise Exception("Unexpected EAP exchange")
158    hwsim_utils.test_connectivity(dev[0], hapd)
159    pmksa2 = dev[0].get_pmksa(bssid)
160    if pmksa2 is None:
161        raise Exception("No PMKSA cache entry found")
162    if pmksa['pmkid'] != pmksa2['pmkid']:
163        raise Exception("Unexpected PMKID change")
164
165    # Verify EAPOL reauthentication after FILS authentication
166    hapd.request("EAPOL_REAUTH " + dev[0].own_addr())
167    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
168    if ev is None:
169        raise Exception("EAP authentication did not start")
170    ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=5)
171    if ev is None:
172        raise Exception("EAP authentication did not succeed")
173    time.sleep(0.1)
174    hwsim_utils.test_connectivity(dev[0], hapd)
175
176def test_fils_sk_pmksa_caching_ocv(dev, apdev, params):
177    """FILS SK and PMKSA caching with OCV"""
178    check_fils_capa(dev[0])
179    check_erp_capa(dev[0])
180
181    start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
182
183    bssid = apdev[0]['bssid']
184    params = hostapd.wpa2_eap_params(ssid="fils")
185    params['wpa_key_mgmt'] = "FILS-SHA256"
186    params['auth_server_port'] = "18128"
187    params['erp_domain'] = 'example.com'
188    params['fils_realm'] = 'example.com'
189    params['ieee80211w'] = '1'
190    params['ocv'] = '1'
191    try:
192        hapd = hostapd.add_ap(apdev[0]['ifname'], params)
193    except Exception as e:
194        if "Failed to set hostapd parameter ocv" in str(e):
195            raise HwsimSkip("OCV not supported")
196        raise
197
198    dev[0].scan_for_bss(bssid, freq=2412)
199    dev[0].request("ERP_FLUSH")
200    id = dev[0].connect("fils", key_mgmt="FILS-SHA256",
201                        eap="PSK", identity="psk.user@example.com",
202                        password_hex="0123456789abcdef0123456789abcdef",
203                        erp="1", scan_freq="2412", ieee80211w="1", ocv="1")
204    pmksa = dev[0].get_pmksa(bssid)
205    if pmksa is None:
206        raise Exception("No PMKSA cache entry created")
207
208    dev[0].request("DISCONNECT")
209    dev[0].wait_disconnected()
210
211    dev[0].dump_monitor()
212    dev[0].select_network(id, freq=2412)
213    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
214                            "CTRL-EVENT-CONNECTED"], timeout=10)
215    if ev is None:
216        raise Exception("Connection using PMKSA caching timed out")
217    if "CTRL-EVENT-EAP-STARTED" in ev:
218        raise Exception("Unexpected EAP exchange")
219    hwsim_utils.test_connectivity(dev[0], hapd)
220    pmksa2 = dev[0].get_pmksa(bssid)
221    if pmksa2 is None:
222        raise Exception("No PMKSA cache entry found")
223    if pmksa['pmkid'] != pmksa2['pmkid']:
224        raise Exception("Unexpected PMKID change")
225
226    # Verify EAPOL reauthentication after FILS authentication
227    hapd.request("EAPOL_REAUTH " + dev[0].own_addr())
228    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
229    if ev is None:
230        raise Exception("EAP authentication did not start")
231    ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=5)
232    if ev is None:
233        raise Exception("EAP authentication did not succeed")
234    time.sleep(0.1)
235    hwsim_utils.test_connectivity(dev[0], hapd)
236
237def test_fils_sk_pmksa_caching_and_cache_id(dev, apdev):
238    """FILS SK and PMKSA caching with Cache Identifier"""
239    check_fils_capa(dev[0])
240    check_erp_capa(dev[0])
241
242    bssid = apdev[0]['bssid']
243    params = hostapd.wpa2_eap_params(ssid="fils")
244    params['wpa_key_mgmt'] = "FILS-SHA256"
245    params['auth_server_port'] = "18128"
246    params['erp_domain'] = 'example.com'
247    params['fils_realm'] = 'example.com'
248    params['fils_cache_id'] = "abcd"
249    params["radius_server_clients"] = "auth_serv/radius_clients.conf"
250    params["radius_server_auth_port"] = '18128'
251    params["eap_server"] = "1"
252    params["eap_user_file"] = "auth_serv/eap_user.conf"
253    params["ca_cert"] = "auth_serv/ca.pem"
254    params["server_cert"] = "auth_serv/server.pem"
255    params["private_key"] = "auth_serv/server.key"
256    params["eap_sim_db"] = "unix:/tmp/hlr_auc_gw.sock"
257    params["dh_file"] = "auth_serv/dh.conf"
258    params["pac_opaque_encr_key"] = "000102030405060708090a0b0c0d0e0f"
259    params["eap_fast_a_id"] = "101112131415161718191a1b1c1d1e1f"
260    params["eap_fast_a_id_info"] = "test server"
261    params["eap_server_erp"] = "1"
262    params["erp_domain"] = "example.com"
263    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
264
265    dev[0].scan_for_bss(bssid, freq=2412)
266    dev[0].request("ERP_FLUSH")
267    id = dev[0].connect("fils", key_mgmt="FILS-SHA256",
268                        eap="PSK", identity="psk.user@example.com",
269                        password_hex="0123456789abcdef0123456789abcdef",
270                        erp="1", scan_freq="2412")
271    res = dev[0].request("PMKSA")
272    if "FILS Cache Identifier" not in res:
273        raise Exception("PMKSA list does not include FILS Cache Identifier")
274    pmksa = dev[0].get_pmksa(bssid)
275    if pmksa is None:
276        raise Exception("No PMKSA cache entry created")
277    if "cache_id" not in pmksa:
278        raise Exception("No FILS Cache Identifier listed")
279    if pmksa["cache_id"] != "abcd":
280        raise Exception("The configured FILS Cache Identifier not seen in PMKSA")
281
282    bssid2 = apdev[1]['bssid']
283    params = hostapd.wpa2_eap_params(ssid="fils")
284    params['wpa_key_mgmt'] = "FILS-SHA256"
285    params['auth_server_port'] = "18128"
286    params['erp_domain'] = 'example.com'
287    params['fils_realm'] = 'example.com'
288    params['fils_cache_id'] = "abcd"
289    hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
290
291    dev[0].scan_for_bss(bssid2, freq=2412)
292
293    dev[0].dump_monitor()
294    if "OK" not in dev[0].request("ROAM " + bssid2):
295        raise Exception("ROAM failed")
296
297    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
298                            "CTRL-EVENT-CONNECTED"], timeout=10)
299    if ev is None:
300        raise Exception("Connection using PMKSA caching timed out")
301    if "CTRL-EVENT-EAP-STARTED" in ev:
302        raise Exception("Unexpected EAP exchange")
303    if bssid2 not in ev:
304        raise Exception("Failed to connect to the second AP")
305
306    hwsim_utils.test_connectivity(dev[0], hapd2)
307    pmksa2 = dev[0].get_pmksa(bssid2)
308    if pmksa2:
309        raise Exception("Unexpected extra PMKSA cache added")
310    pmksa2 = dev[0].get_pmksa(bssid)
311    if not pmksa2:
312        raise Exception("Original PMKSA cache entry removed")
313    if pmksa['pmkid'] != pmksa2['pmkid']:
314        raise Exception("Unexpected PMKID change")
315
316def test_fils_sk_pmksa_caching_ctrl_ext(dev, apdev, params):
317    """FILS SK and PMKSA caching with Cache Identifier and external management"""
318    check_fils_capa(dev[0])
319    check_erp_capa(dev[0])
320
321    hapd_as = start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
322
323    bssid = apdev[0]['bssid']
324    params = hostapd.wpa2_eap_params(ssid="fils")
325    params['wpa_key_mgmt'] = "FILS-SHA384"
326    params['auth_server_port'] = "18128"
327    params['erp_send_reauth_start'] = '1'
328    params['erp_domain'] = 'example.com'
329    params['fils_realm'] = 'example.com'
330    params['fils_cache_id'] = "ffee"
331    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
332
333    dev[0].scan_for_bss(bssid, freq=2412)
334    dev[0].request("ERP_FLUSH")
335    id = dev[0].connect("fils", key_mgmt="FILS-SHA384",
336                        eap="PSK", identity="psk.user@example.com",
337                        password_hex="0123456789abcdef0123456789abcdef",
338                        erp="1", scan_freq="2412")
339
340    res1 = dev[0].request("PMKSA_GET %d" % id)
341    logger.info("PMKSA_GET: " + res1)
342    if "UNKNOWN COMMAND" in res1:
343        raise HwsimSkip("PMKSA_GET not supported in the build")
344    if bssid not in res1:
345        raise Exception("PMKSA cache entry missing")
346    if "ffee" not in res1:
347        raise Exception("FILS Cache Identifier not seen in PMKSA cache entry")
348
349    dev[0].request("DISCONNECT")
350    dev[0].wait_disconnected()
351    hapd_as.disable()
352
353    dev[0].scan_for_bss(bssid, freq=2412)
354    dev[0].request("PMKSA_FLUSH")
355    dev[0].request("ERP_FLUSH")
356    for entry in res1.splitlines():
357        if "OK" not in dev[0].request("PMKSA_ADD %d %s" % (id, entry)):
358            raise Exception("Failed to add PMKSA entry")
359
360    bssid2 = apdev[1]['bssid']
361    params = hostapd.wpa2_eap_params(ssid="fils")
362    params['wpa_key_mgmt'] = "FILS-SHA384"
363    params['auth_server_port'] = "18128"
364    params['erp_send_reauth_start'] = '1'
365    params['erp_domain'] = 'example.com'
366    params['fils_realm'] = 'example.com'
367    params['fils_cache_id'] = "ffee"
368    hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
369
370    dev[0].scan_for_bss(bssid2, freq=2412)
371    dev[0].set_network(id, "bssid", bssid2)
372    dev[0].select_network(id, freq=2412)
373    ev = dev[0].wait_connected()
374    if bssid2 not in ev:
375        raise Exception("Unexpected BSS selected")
376
377def test_fils_sk_erp(dev, apdev, params):
378    """FILS SK using ERP"""
379    run_fils_sk_erp(dev, apdev, "FILS-SHA256", params)
380
381def test_fils_sk_erp_sha384(dev, apdev, params):
382    """FILS SK using ERP and SHA384"""
383    run_fils_sk_erp(dev, apdev, "FILS-SHA384", params)
384
385def run_fils_sk_erp(dev, apdev, key_mgmt, params):
386    check_fils_capa(dev[0])
387    check_erp_capa(dev[0])
388
389    start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
390
391    bssid = apdev[0]['bssid']
392    params = hostapd.wpa2_eap_params(ssid="fils")
393    params['wpa_key_mgmt'] = key_mgmt
394    params['auth_server_port'] = "18128"
395    params['erp_domain'] = 'example.com'
396    params['fils_realm'] = 'example.com'
397    params['disable_pmksa_caching'] = '1'
398    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
399
400    dev[0].scan_for_bss(bssid, freq=2412)
401    dev[0].request("ERP_FLUSH")
402    id = dev[0].connect("fils", key_mgmt=key_mgmt,
403                        eap="PSK", identity="psk.user@example.com",
404                        password_hex="0123456789abcdef0123456789abcdef",
405                        erp="1", scan_freq="2412")
406
407    dev[0].request("DISCONNECT")
408    dev[0].wait_disconnected()
409
410    dev[0].dump_monitor()
411    dev[0].select_network(id, freq=2412)
412    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
413                            "EVENT-ASSOC-REJECT",
414                            "CTRL-EVENT-CONNECTED"], timeout=10)
415    if ev is None:
416        raise Exception("Connection using FILS/ERP timed out")
417    if "CTRL-EVENT-EAP-STARTED" in ev:
418        raise Exception("Unexpected EAP exchange")
419    if "EVENT-ASSOC-REJECT" in ev:
420        raise Exception("Association failed")
421    hwsim_utils.test_connectivity(dev[0], hapd)
422
423def test_fils_sk_erp_followed_by_pmksa_caching(dev, apdev, params):
424    """FILS SK ERP following by PMKSA caching"""
425    check_fils_capa(dev[0])
426    check_erp_capa(dev[0])
427
428    start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
429
430    bssid = apdev[0]['bssid']
431    params = hostapd.wpa2_eap_params(ssid="fils")
432    params['wpa_key_mgmt'] = "FILS-SHA256"
433    params['auth_server_port'] = "18128"
434    params['erp_domain'] = 'example.com'
435    params['fils_realm'] = 'example.com'
436    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
437
438    dev[0].scan_for_bss(bssid, freq=2412)
439    dev[0].request("ERP_FLUSH")
440    id = dev[0].connect("fils", key_mgmt="FILS-SHA256",
441                        eap="PSK", identity="psk.user@example.com",
442                        password_hex="0123456789abcdef0123456789abcdef",
443                        erp="1", scan_freq="2412")
444
445    dev[0].request("DISCONNECT")
446    dev[0].wait_disconnected()
447
448    # Force the second connection to use ERP by deleting the PMKSA entry.
449    dev[0].request("PMKSA_FLUSH")
450
451    dev[0].dump_monitor()
452    dev[0].select_network(id, freq=2412)
453    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
454                            "EVENT-ASSOC-REJECT",
455                            "CTRL-EVENT-CONNECTED"], timeout=10)
456    if ev is None:
457        raise Exception("Connection using FILS/ERP timed out")
458    if "CTRL-EVENT-EAP-STARTED" in ev:
459        raise Exception("Unexpected EAP exchange")
460    if "EVENT-ASSOC-REJECT" in ev:
461        raise Exception("Association failed")
462    hwsim_utils.test_connectivity(dev[0], hapd)
463
464    pmksa = dev[0].get_pmksa(bssid)
465    if pmksa is None:
466        raise Exception("No PMKSA cache entry created")
467
468    dev[0].request("DISCONNECT")
469    dev[0].wait_disconnected()
470
471    # The third connection is expected to use PMKSA caching for FILS
472    # authentication.
473    dev[0].dump_monitor()
474    dev[0].select_network(id, freq=2412)
475    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
476                            "EVENT-ASSOC-REJECT",
477                            "CTRL-EVENT-CONNECTED"], timeout=10)
478    if ev is None:
479        raise Exception("Connection using PMKSA caching timed out")
480    if "CTRL-EVENT-EAP-STARTED" in ev:
481        raise Exception("Unexpected EAP exchange")
482    if "EVENT-ASSOC-REJECT" in ev:
483        raise Exception("Association failed")
484    hwsim_utils.test_connectivity(dev[0], hapd)
485
486    pmksa2 = dev[0].get_pmksa(bssid)
487    if pmksa2 is None:
488        raise Exception("No PMKSA cache entry found")
489    if pmksa['pmkid'] != pmksa2['pmkid']:
490        raise Exception("Unexpected PMKID change")
491
492def test_fils_sk_erp_another_ssid(dev, apdev, params):
493    """FILS SK using ERP and roam to another SSID"""
494    check_fils_capa(dev[0])
495    check_erp_capa(dev[0])
496
497    start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
498
499    bssid = apdev[0]['bssid']
500    params = hostapd.wpa2_eap_params(ssid="fils")
501    params['wpa_key_mgmt'] = "FILS-SHA256"
502    params['auth_server_port'] = "18128"
503    params['erp_domain'] = 'example.com'
504    params['fils_realm'] = 'example.com'
505    params['disable_pmksa_caching'] = '1'
506    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
507
508    dev[0].scan_for_bss(bssid, freq=2412)
509    dev[0].request("ERP_FLUSH")
510    id = dev[0].connect("fils", key_mgmt="FILS-SHA256",
511                        eap="PSK", identity="psk.user@example.com",
512                        password_hex="0123456789abcdef0123456789abcdef",
513                        erp="1", scan_freq="2412")
514
515    dev[0].request("DISCONNECT")
516    dev[0].wait_disconnected()
517    hapd.disable()
518    dev[0].flush_scan_cache()
519    if "FAIL" in dev[0].request("PMKSA_FLUSH"):
520        raise Exception("PMKSA_FLUSH failed")
521
522    params = hostapd.wpa2_eap_params(ssid="fils2")
523    params['wpa_key_mgmt'] = "FILS-SHA256"
524    params['auth_server_port'] = "18128"
525    params['erp_domain'] = 'example.com'
526    params['fils_realm'] = 'example.com'
527    params['disable_pmksa_caching'] = '1'
528    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
529
530    dev[0].scan_for_bss(bssid, freq=2412)
531    dev[0].dump_monitor()
532    id = dev[0].connect("fils2", key_mgmt="FILS-SHA256",
533                        eap="PSK", identity="psk.user@example.com",
534                        password_hex="0123456789abcdef0123456789abcdef",
535                        erp="1", scan_freq="2412", wait_connect=False)
536
537    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
538                            "EVENT-ASSOC-REJECT",
539                            "CTRL-EVENT-CONNECTED"], timeout=10)
540    if ev is None:
541        raise Exception("Connection using FILS/ERP timed out")
542    if "CTRL-EVENT-EAP-STARTED" in ev:
543        raise Exception("Unexpected EAP exchange")
544    if "EVENT-ASSOC-REJECT" in ev:
545        raise Exception("Association failed")
546    hwsim_utils.test_connectivity(dev[0], hapd)
547
548def test_fils_sk_multiple_realms(dev, apdev, params):
549    """FILS SK and multiple realms"""
550    check_fils_capa(dev[0])
551    check_erp_capa(dev[0])
552
553    start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
554
555    bssid = apdev[0]['bssid']
556    params = hostapd.wpa2_eap_params(ssid="fils")
557    params['wpa_key_mgmt'] = "FILS-SHA256"
558    params['auth_server_port'] = "18128"
559    params['erp_domain'] = 'example.com'
560    fils_realms = ['r1.example.org', 'r2.EXAMPLE.org', 'r3.example.org',
561                   'r4.example.org', 'r5.example.org', 'r6.example.org',
562                   'r7.example.org', 'r8.example.org',
563                   'example.com',
564                   'r9.example.org', 'r10.example.org', 'r11.example.org',
565                   'r12.example.org', 'r13.example.org', 'r14.example.org',
566                   'r15.example.org', 'r16.example.org']
567    params['fils_realm'] = fils_realms
568    params['fils_cache_id'] = "1234"
569    params['hessid'] = bssid
570    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
571
572    dev[0].flush_scan_cache()
573    dev[0].scan_for_bss(bssid, freq=2412)
574
575    if "OK" not in dev[0].request("ANQP_GET " + bssid + " 275"):
576        raise Exception("ANQP_GET command failed")
577    ev = dev[0].wait_event(["GAS-QUERY-DONE"], timeout=10)
578    if ev is None:
579        raise Exception("GAS query timed out")
580    bss = dev[0].get_bss(bssid)
581
582    if 'fils_info' not in bss:
583        raise Exception("FILS Indication element information missing")
584    if bss['fils_info'] != '02b8':
585        raise Exception("Unexpected FILS Information: " + bss['fils_info'])
586
587    if 'fils_cache_id' not in bss:
588        raise Exception("FILS Cache Identifier missing")
589    if bss['fils_cache_id'] != '1234':
590        raise Exception("Unexpected FILS Cache Identifier: " + bss['fils_cache_id'])
591
592    if 'fils_realms' not in bss:
593        raise Exception("FILS Realm Identifiers missing")
594    expected = ''
595    count = 0
596    for realm in fils_realms:
597        hash = hashlib.sha256(realm.lower().encode()).digest()
598        expected += binascii.hexlify(hash[0:2]).decode()
599        count += 1
600        if count == 7:
601            break
602    if bss['fils_realms'] != expected:
603        raise Exception("Unexpected FILS Realm Identifiers: " + bss['fils_realms'])
604
605    if 'anqp_fils_realm_info' not in bss:
606        raise Exception("FILS Realm Information ANQP-element not seen")
607    info = bss['anqp_fils_realm_info']
608    expected = ''
609    for realm in fils_realms:
610        hash = hashlib.sha256(realm.lower().encode()).digest()
611        expected += binascii.hexlify(hash[0:2]).decode()
612    if info != expected:
613        raise Exception("Unexpected FILS Realm Info ANQP-element: " + info)
614
615    dev[0].request("ERP_FLUSH")
616    id = dev[0].connect("fils", key_mgmt="FILS-SHA256",
617                        eap="PSK", identity="psk.user@example.com",
618                        password_hex="0123456789abcdef0123456789abcdef",
619                        erp="1", scan_freq="2412")
620
621    dev[0].request("DISCONNECT")
622    dev[0].wait_disconnected()
623
624    dev[0].dump_monitor()
625    dev[0].select_network(id, freq=2412)
626    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
627                            "EVENT-ASSOC-REJECT",
628                            "CTRL-EVENT-CONNECTED"], timeout=10)
629    if ev is None:
630        raise Exception("Connection using FILS/ERP timed out")
631    if "CTRL-EVENT-EAP-STARTED" in ev:
632        raise Exception("Unexpected EAP exchange")
633    if "EVENT-ASSOC-REJECT" in ev:
634        raise Exception("Association failed")
635    hwsim_utils.test_connectivity(dev[0], hapd)
636
637# DHCP message op codes
638BOOTREQUEST = 1
639BOOTREPLY = 2
640
641OPT_PAD = 0
642OPT_DHCP_MESSAGE_TYPE = 53
643OPT_RAPID_COMMIT = 80
644OPT_END = 255
645
646DHCPDISCOVER = 1
647DHCPOFFER = 2
648DHCPREQUEST = 3
649DHCPDECLINE = 4
650DHCPACK = 5
651DHCPNAK = 6
652DHCPRELEASE = 7
653DHCPINFORM = 8
654
655def build_dhcp(req, dhcp_msg, chaddr, giaddr="0.0.0.0",
656               ip_src="0.0.0.0", ip_dst="255.255.255.255",
657               rapid_commit=True, override_op=None, magic_override=None,
658               opt_end=True, extra_op=None):
659    proto = b'\x08\x00' # IPv4
660    _ip_src = socket.inet_pton(socket.AF_INET, ip_src)
661    _ip_dst = socket.inet_pton(socket.AF_INET, ip_dst)
662
663    _ciaddr = b'\x00\x00\x00\x00'
664    _yiaddr = b'\x00\x00\x00\x00'
665    _siaddr = b'\x00\x00\x00\x00'
666    _giaddr = socket.inet_pton(socket.AF_INET, giaddr)
667    _chaddr = binascii.unhexlify(chaddr.replace(':', '')) + 10 * b'\x00'
668    htype = 1 # Hardware address type; 1 = Ethernet
669    hlen = 6 # Hardware address length
670    hops = 0
671    xid = 123456
672    secs = 0
673    flags = 0
674    if req:
675        op = BOOTREQUEST
676        src_port = 68
677        dst_port = 67
678    else:
679        op = BOOTREPLY
680        src_port = 67
681        dst_port = 68
682    if override_op is not None:
683        op = override_op
684    payload = struct.pack('>BBBBLHH', op, htype, hlen, hops, xid, secs, flags)
685    sname = 64*b'\x00'
686    file = 128*b'\x00'
687    payload += _ciaddr + _yiaddr + _siaddr + _giaddr + _chaddr + sname + file
688    # magic - DHCP
689    if magic_override is not None:
690        payload += magic_override
691    else:
692        payload += b'\x63\x82\x53\x63'
693    # Option: DHCP Message Type
694    if dhcp_msg is not None:
695        payload += struct.pack('BBB', OPT_DHCP_MESSAGE_TYPE, 1, dhcp_msg)
696    if rapid_commit:
697        # Option: Rapid Commit
698        payload += struct.pack('BB', OPT_RAPID_COMMIT, 0)
699    if extra_op:
700        payload += extra_op
701    # End Option
702    if opt_end:
703        payload += struct.pack('B', OPT_END)
704
705    udp = struct.pack('>HHHH', src_port, dst_port,
706                      8 + len(payload), 0) + payload
707
708    tot_len = 20 + len(udp)
709    start = struct.pack('>BBHHBBBB', 0x45, 0, tot_len, 0, 0, 0, 128, 17)
710    ipv4 = start + b'\x00\x00' + _ip_src + _ip_dst
711    csum = ip_checksum(ipv4)
712    ipv4 = start + csum + _ip_src + _ip_dst
713
714    return proto + ipv4 + udp
715
716def fils_hlp_config(fils_hlp_wait_time=10000):
717    params = hostapd.wpa2_eap_params(ssid="fils")
718    params['wpa_key_mgmt'] = "FILS-SHA256"
719    params['auth_server_port'] = "18128"
720    params['erp_domain'] = 'example.com'
721    params['fils_realm'] = 'example.com'
722    params['disable_pmksa_caching'] = '1'
723    params['own_ip_addr'] = '127.0.0.3'
724    params['dhcp_server'] = '127.0.0.2'
725    params['fils_hlp_wait_time'] = str(fils_hlp_wait_time)
726    return params
727
728def test_fils_sk_hlp(dev, apdev, params):
729    """FILS SK HLP (rapid commit server)"""
730    run_fils_sk_hlp(dev, apdev, True, params)
731
732def test_fils_sk_hlp_no_rapid_commit(dev, apdev, params):
733    """FILS SK HLP (no rapid commit server)"""
734    run_fils_sk_hlp(dev, apdev, False, params)
735
736def run_fils_sk_hlp(dev, apdev, rapid_commit_server, params):
737    check_fils_capa(dev[0])
738    check_erp_capa(dev[0])
739
740    start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
741
742    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
743    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
744    sock.settimeout(5)
745    sock.bind(("127.0.0.2", 67))
746
747    bssid = apdev[0]['bssid']
748    params = fils_hlp_config()
749    params['fils_hlp_wait_time'] = '10000'
750    if not rapid_commit_server:
751        params['dhcp_rapid_commit_proxy'] = '1'
752    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
753
754    dev[0].scan_for_bss(bssid, freq=2412)
755    dev[0].request("ERP_FLUSH")
756    if "OK" not in dev[0].request("FILS_HLP_REQ_FLUSH"):
757        raise Exception("Failed to flush pending FILS HLP requests")
758    tests = ["",
759             "q",
760             "ff:ff:ff:ff:ff:ff",
761             "ff:ff:ff:ff:ff:ff q"]
762    for t in tests:
763        if "FAIL" not in dev[0].request("FILS_HLP_REQ_ADD " + t):
764            raise Exception("Invalid FILS_HLP_REQ_ADD accepted: " + t)
765    dhcpdisc = build_dhcp(req=True, dhcp_msg=DHCPDISCOVER,
766                          chaddr=dev[0].own_addr())
767    tests = ["ff:ff:ff:ff:ff:ff aabb",
768             "ff:ff:ff:ff:ff:ff " + 255*'cc',
769             hapd.own_addr() + " ddee010203040506070809",
770             "ff:ff:ff:ff:ff:ff " + binascii.hexlify(dhcpdisc).decode()]
771    for t in tests:
772        if "OK" not in dev[0].request("FILS_HLP_REQ_ADD " + t):
773            raise Exception("FILS_HLP_REQ_ADD failed: " + t)
774    id = dev[0].connect("fils", key_mgmt="FILS-SHA256",
775                        eap="PSK", identity="psk.user@example.com",
776                        password_hex="0123456789abcdef0123456789abcdef",
777                        erp="1", scan_freq="2412")
778
779    dev[0].request("DISCONNECT")
780    dev[0].wait_disconnected()
781
782    dev[0].dump_monitor()
783    dev[0].select_network(id, freq=2412)
784
785    (msg, addr) = sock.recvfrom(1000)
786    logger.debug("Received DHCP message from %s" % str(addr))
787    if rapid_commit_server:
788        # TODO: Proper rapid commit response
789        dhcpdisc = build_dhcp(req=False, dhcp_msg=DHCPACK,
790                              chaddr=dev[0].own_addr(), giaddr="127.0.0.3")
791        sock.sendto(dhcpdisc[2+20+8:], addr)
792    else:
793        dhcpdisc = build_dhcp(req=False, dhcp_msg=DHCPOFFER, rapid_commit=False,
794                              chaddr=dev[0].own_addr(), giaddr="127.0.0.3")
795        sock.sendto(dhcpdisc[2+20+8:], addr)
796        (msg, addr) = sock.recvfrom(1000)
797        logger.debug("Received DHCP message from %s" % str(addr))
798        dhcpdisc = build_dhcp(req=False, dhcp_msg=DHCPACK, rapid_commit=False,
799                              chaddr=dev[0].own_addr(), giaddr="127.0.0.3")
800        sock.sendto(dhcpdisc[2+20+8:], addr)
801    ev = dev[0].wait_event(["FILS-HLP-RX"], timeout=10)
802    if ev is None:
803        raise Exception("FILS HLP response not reported")
804    vals = ev.split(' ')
805    frame = binascii.unhexlify(vals[3].split('=')[1])
806    proto, = struct.unpack('>H', frame[0:2])
807    if proto != 0x0800:
808        raise Exception("Unexpected ethertype in HLP response: %d" % proto)
809    frame = frame[2:]
810    ip = frame[0:20]
811    if ip_checksum(ip) != b'\x00\x00':
812        raise Exception("IP header checksum mismatch in HLP response")
813    frame = frame[20:]
814    udp = frame[0:8]
815    frame = frame[8:]
816    sport, dport, ulen, ucheck = struct.unpack('>HHHH', udp)
817    if sport != 67 or dport != 68:
818        raise Exception("Unexpected UDP port in HLP response")
819    dhcp = frame[0:28]
820    frame = frame[28:]
821    op, htype, hlen, hops, xid, secs, flags, ciaddr, yiaddr, siaddr, giaddr = struct.unpack('>4BL2H4L', dhcp)
822    chaddr = frame[0:16]
823    frame = frame[16:]
824    sname = frame[0:64]
825    frame = frame[64:]
826    file = frame[0:128]
827    frame = frame[128:]
828    options = frame
829    if options[0:4] != b'\x63\x82\x53\x63':
830        raise Exception("No DHCP magic seen in HLP response")
831    options = options[4:]
832    # TODO: fully parse and validate DHCPACK options
833    if struct.pack('BBB', OPT_DHCP_MESSAGE_TYPE, 1, DHCPACK) not in options:
834        raise Exception("DHCPACK not in HLP response")
835
836    dev[0].wait_connected()
837
838    dev[0].request("FILS_HLP_REQ_FLUSH")
839
840def test_fils_sk_hlp_timeout(dev, apdev, params):
841    """FILS SK HLP (rapid commit server timeout)"""
842    check_fils_capa(dev[0])
843    check_erp_capa(dev[0])
844
845    start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
846
847    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
848    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
849    sock.settimeout(5)
850    sock.bind(("127.0.0.2", 67))
851
852    bssid = apdev[0]['bssid']
853    params = fils_hlp_config(fils_hlp_wait_time=30)
854    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
855
856    dev[0].scan_for_bss(bssid, freq=2412)
857    dev[0].request("ERP_FLUSH")
858    if "OK" not in dev[0].request("FILS_HLP_REQ_FLUSH"):
859        raise Exception("Failed to flush pending FILS HLP requests")
860    dhcpdisc = build_dhcp(req=True, dhcp_msg=DHCPDISCOVER,
861                          chaddr=dev[0].own_addr())
862    if "OK" not in dev[0].request("FILS_HLP_REQ_ADD " + "ff:ff:ff:ff:ff:ff " + binascii.hexlify(dhcpdisc).decode()):
863        raise Exception("FILS_HLP_REQ_ADD failed")
864    id = dev[0].connect("fils", key_mgmt="FILS-SHA256",
865                        eap="PSK", identity="psk.user@example.com",
866                        password_hex="0123456789abcdef0123456789abcdef",
867                        erp="1", scan_freq="2412")
868
869    dev[0].request("DISCONNECT")
870    dev[0].wait_disconnected()
871
872    dev[0].dump_monitor()
873    dev[0].select_network(id, freq=2412)
874
875    (msg, addr) = sock.recvfrom(1000)
876    logger.debug("Received DHCP message from %s" % str(addr))
877    # Wait for HLP wait timeout to hit
878    # FILS: HLP response timeout - continue with association response
879    dev[0].wait_connected()
880
881    dev[0].request("FILS_HLP_REQ_FLUSH")
882
883def test_fils_sk_hlp_oom(dev, apdev, params):
884    """FILS SK HLP and hostapd OOM"""
885    check_fils_capa(dev[0])
886    check_erp_capa(dev[0])
887
888    start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
889
890    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
891    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
892    sock.settimeout(5)
893    sock.bind(("127.0.0.2", 67))
894
895    bssid = apdev[0]['bssid']
896    params = fils_hlp_config(fils_hlp_wait_time=500)
897    params['dhcp_rapid_commit_proxy'] = '1'
898    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
899
900    dev[0].scan_for_bss(bssid, freq=2412)
901    dev[0].request("ERP_FLUSH")
902    if "OK" not in dev[0].request("FILS_HLP_REQ_FLUSH"):
903        raise Exception("Failed to flush pending FILS HLP requests")
904    dhcpdisc = build_dhcp(req=True, dhcp_msg=DHCPDISCOVER,
905                          chaddr=dev[0].own_addr())
906    if "OK" not in dev[0].request("FILS_HLP_REQ_ADD " + "ff:ff:ff:ff:ff:ff " + binascii.hexlify(dhcpdisc).decode()):
907        raise Exception("FILS_HLP_REQ_ADD failed")
908    id = dev[0].connect("fils", key_mgmt="FILS-SHA256",
909                        eap="PSK", identity="psk.user@example.com",
910                        password_hex="0123456789abcdef0123456789abcdef",
911                        erp="1", scan_freq="2412")
912
913    dev[0].request("DISCONNECT")
914    dev[0].wait_disconnected()
915
916    dev[0].dump_monitor()
917    with alloc_fail(hapd, 1, "fils_process_hlp"):
918        dev[0].select_network(id, freq=2412)
919        dev[0].wait_connected()
920    dev[0].request("DISCONNECT")
921    dev[0].wait_disconnected()
922
923    dev[0].dump_monitor()
924    with alloc_fail(hapd, 1, "fils_process_hlp_dhcp"):
925        dev[0].select_network(id, freq=2412)
926        dev[0].wait_connected()
927    dev[0].request("DISCONNECT")
928    dev[0].wait_disconnected()
929
930    dev[0].dump_monitor()
931    with alloc_fail(hapd, 1, "wpabuf_alloc;fils_process_hlp_dhcp"):
932        dev[0].select_network(id, freq=2412)
933        dev[0].wait_connected()
934    dev[0].request("DISCONNECT")
935    dev[0].wait_disconnected()
936
937    dev[0].dump_monitor()
938    with alloc_fail(hapd, 1, "wpabuf_alloc;fils_dhcp_handler"):
939        dev[0].select_network(id, freq=2412)
940        (msg, addr) = sock.recvfrom(1000)
941        logger.debug("Received DHCP message from %s" % str(addr))
942        dhcpdisc = build_dhcp(req=False, dhcp_msg=DHCPACK,
943                              chaddr=dev[0].own_addr(), giaddr="127.0.0.3")
944        sock.sendto(dhcpdisc[2+20+8:], addr)
945        dev[0].wait_connected()
946    dev[0].request("DISCONNECT")
947    dev[0].wait_disconnected()
948
949    dev[0].dump_monitor()
950    with alloc_fail(hapd, 1, "wpabuf_resize;fils_dhcp_handler"):
951        dev[0].select_network(id, freq=2412)
952        (msg, addr) = sock.recvfrom(1000)
953        logger.debug("Received DHCP message from %s" % str(addr))
954        dhcpdisc = build_dhcp(req=False, dhcp_msg=DHCPACK,
955                              chaddr=dev[0].own_addr(), giaddr="127.0.0.3")
956        sock.sendto(dhcpdisc[2+20+8:], addr)
957        dev[0].wait_connected()
958    dev[0].request("DISCONNECT")
959    dev[0].wait_disconnected()
960
961    dev[0].dump_monitor()
962    dev[0].select_network(id, freq=2412)
963    (msg, addr) = sock.recvfrom(1000)
964    logger.debug("Received DHCP message from %s" % str(addr))
965    dhcpoffer = build_dhcp(req=False, dhcp_msg=DHCPOFFER, rapid_commit=False,
966                           chaddr=dev[0].own_addr(), giaddr="127.0.0.3")
967    with alloc_fail(hapd, 1, "wpabuf_resize;fils_dhcp_request"):
968        sock.sendto(dhcpoffer[2+20+8:], addr)
969        dev[0].wait_connected()
970        dev[0].request("DISCONNECT")
971        dev[0].wait_disconnected()
972
973    dev[0].request("FILS_HLP_REQ_FLUSH")
974
975def test_fils_sk_hlp_req_parsing(dev, apdev, params):
976    """FILS SK HLP request parsing"""
977    check_fils_capa(dev[0])
978    check_erp_capa(dev[0])
979
980    start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
981
982    bssid = apdev[0]['bssid']
983    params = fils_hlp_config(fils_hlp_wait_time=30)
984    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
985
986    dev[0].scan_for_bss(bssid, freq=2412)
987    dev[0].request("ERP_FLUSH")
988    if "OK" not in dev[0].request("FILS_HLP_REQ_FLUSH"):
989        raise Exception("Failed to flush pending FILS HLP requests")
990
991    tot_len = 20 + 1
992    start = struct.pack('>BBHHBBBB', 0x45, 0, tot_len, 0, 0, 0, 128, 17)
993    _ip_src = b'\x00\x00\x00\x00'
994    _ip_dst = b'\x00\x00\x00\x00'
995    ipv4 = start + b'\x00\x00' + _ip_src + _ip_dst
996    csum = ip_checksum(ipv4)
997    ipv4_overflow = start + csum + _ip_src + _ip_dst
998
999    tot_len = 20
1000    start = struct.pack('>BBHHBBBB', 0x45, 0, tot_len, 0, 0, 0, 128, 123)
1001    ipv4 = start + b'\x00\x00' + _ip_src + _ip_dst
1002    csum = ip_checksum(ipv4)
1003    ipv4_unknown_proto = start + csum + _ip_src + _ip_dst
1004
1005    tot_len = 20
1006    start = struct.pack('>BBHHBBBB', 0x45, 0, tot_len, 0, 0, 0, 128, 17)
1007    ipv4 = start + b'\x00\x00' + _ip_src + _ip_dst
1008    csum = ip_checksum(ipv4)
1009    ipv4_missing_udp_hdr = start + csum + _ip_src + _ip_dst
1010
1011    src_port = 68
1012    dst_port = 67
1013    udp = struct.pack('>HHHH', src_port, dst_port, 8 + 1, 0)
1014    tot_len = 20 + len(udp)
1015    start = struct.pack('>BBHHBBBB', 0x45, 0, tot_len, 0, 0, 0, 128, 17)
1016    ipv4 = start + b'\x00\x00' + _ip_src + _ip_dst
1017    csum = ip_checksum(ipv4)
1018    udp_overflow = start + csum + _ip_src + _ip_dst + udp
1019
1020    udp = struct.pack('>HHHH', src_port, dst_port, 7, 0)
1021    tot_len = 20 + len(udp)
1022    start = struct.pack('>BBHHBBBB', 0x45, 0, tot_len, 0, 0, 0, 128, 17)
1023    ipv4 = start + b'\x00\x00' + _ip_src + _ip_dst
1024    csum = ip_checksum(ipv4)
1025    udp_underflow = start + csum + _ip_src + _ip_dst + udp
1026
1027    src_port = 123
1028    dst_port = 456
1029    udp = struct.pack('>HHHH', src_port, dst_port, 8, 0)
1030    tot_len = 20 + len(udp)
1031    start = struct.pack('>BBHHBBBB', 0x45, 0, tot_len, 0, 0, 0, 128, 17)
1032    ipv4 = start + b'\x00\x00' + _ip_src + _ip_dst
1033    csum = ip_checksum(ipv4)
1034    udp_unknown_port = start + csum + _ip_src + _ip_dst + udp
1035
1036    src_port = 68
1037    dst_port = 67
1038    udp = struct.pack('>HHHH', src_port, dst_port, 8, 0)
1039    tot_len = 20 + len(udp)
1040    start = struct.pack('>BBHHBBBB', 0x45, 0, tot_len, 0, 0, 0, 128, 17)
1041    ipv4 = start + b'\x00\x00' + _ip_src + _ip_dst
1042    csum = ip_checksum(ipv4)
1043    dhcp_missing_data = start + csum + _ip_src + _ip_dst + udp
1044
1045    dhcp_not_req = build_dhcp(req=True, dhcp_msg=DHCPDISCOVER,
1046                              chaddr=dev[0].own_addr(), override_op=BOOTREPLY)
1047    dhcp_no_magic = build_dhcp(req=True, dhcp_msg=None,
1048                               chaddr=dev[0].own_addr(), magic_override=b'',
1049                               rapid_commit=False, opt_end=False)
1050    dhcp_unknown_magic = build_dhcp(req=True, dhcp_msg=DHCPDISCOVER,
1051                                    chaddr=dev[0].own_addr(),
1052                                    magic_override=b'\x00\x00\x00\x00')
1053    dhcp_opts = build_dhcp(req=True, dhcp_msg=DHCPNAK,
1054                           chaddr=dev[0].own_addr(),
1055                           extra_op=b'\x00\x11', opt_end=False)
1056    dhcp_opts2 = build_dhcp(req=True, dhcp_msg=DHCPNAK,
1057                            chaddr=dev[0].own_addr(),
1058                            extra_op=b'\x11\x01', opt_end=False)
1059    dhcp_valid = build_dhcp(req=True, dhcp_msg=DHCPDISCOVER,
1060                            chaddr=dev[0].own_addr())
1061
1062    tests = ["ff",
1063             "0800",
1064             "0800" + 20*"00",
1065             "0800" + binascii.hexlify(ipv4_overflow).decode(),
1066             "0800" + binascii.hexlify(ipv4_unknown_proto).decode(),
1067             "0800" + binascii.hexlify(ipv4_missing_udp_hdr).decode(),
1068             "0800" + binascii.hexlify(udp_overflow).decode(),
1069             "0800" + binascii.hexlify(udp_underflow).decode(),
1070             "0800" + binascii.hexlify(udp_unknown_port).decode(),
1071             "0800" + binascii.hexlify(dhcp_missing_data).decode(),
1072             binascii.hexlify(dhcp_not_req).decode(),
1073             binascii.hexlify(dhcp_no_magic).decode(),
1074             binascii.hexlify(dhcp_unknown_magic).decode()]
1075    for t in tests:
1076        if "OK" not in dev[0].request("FILS_HLP_REQ_ADD ff:ff:ff:ff:ff:ff " + t):
1077            raise Exception("FILS_HLP_REQ_ADD failed: " + t)
1078    id = dev[0].connect("fils", key_mgmt="FILS-SHA256",
1079                        eap="PSK", identity="psk.user@example.com",
1080                        password_hex="0123456789abcdef0123456789abcdef",
1081                        erp="1", scan_freq="2412")
1082
1083    dev[0].request("DISCONNECT")
1084    dev[0].wait_disconnected()
1085
1086    dev[0].dump_monitor()
1087    dev[0].select_network(id, freq=2412)
1088    dev[0].wait_connected()
1089    dev[0].request("DISCONNECT")
1090    dev[0].wait_disconnected()
1091
1092    dev[0].request("FILS_HLP_REQ_FLUSH")
1093    tests = [binascii.hexlify(dhcp_opts).decode(),
1094             binascii.hexlify(dhcp_opts2).decode()]
1095    for t in tests:
1096        if "OK" not in dev[0].request("FILS_HLP_REQ_ADD ff:ff:ff:ff:ff:ff " + t):
1097            raise Exception("FILS_HLP_REQ_ADD failed: " + t)
1098
1099    dev[0].dump_monitor()
1100    dev[0].select_network(id, freq=2412)
1101    dev[0].wait_connected()
1102    dev[0].request("DISCONNECT")
1103    dev[0].wait_disconnected()
1104
1105    dev[0].request("FILS_HLP_REQ_FLUSH")
1106    if "OK" not in dev[0].request("FILS_HLP_REQ_ADD ff:ff:ff:ff:ff:ff " + binascii.hexlify(dhcp_valid).decode()):
1107        raise Exception("FILS_HLP_REQ_ADD failed")
1108    hapd.set("own_ip_addr", "0.0.0.0")
1109    dev[0].select_network(id, freq=2412)
1110    dev[0].wait_connected()
1111    dev[0].request("DISCONNECT")
1112    dev[0].wait_disconnected()
1113
1114    hapd.set("dhcp_server", "0.0.0.0")
1115    dev[0].select_network(id, freq=2412)
1116    dev[0].wait_connected()
1117    dev[0].request("DISCONNECT")
1118    dev[0].wait_disconnected()
1119
1120    # FILS: Failed to bind DHCP socket: Address already in use
1121    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
1122    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
1123    sock.settimeout(5)
1124    sock.bind(("127.0.0.2", 67))
1125    hapd.set("own_ip_addr", "127.0.0.2")
1126    hapd.set("dhcp_server", "127.0.0.2")
1127    dev[0].select_network(id, freq=2412)
1128    dev[0].wait_connected()
1129    dev[0].request("DISCONNECT")
1130    dev[0].wait_disconnected()
1131
1132    # FILS: DHCP sendto failed: Invalid argument
1133    hapd.set("own_ip_addr", "127.0.0.3")
1134    hapd.set("dhcp_server", "127.0.0.2")
1135    hapd.set("dhcp_relay_port", "0")
1136    hapd.set("dhcp_server_port", "0")
1137    dev[0].select_network(id, freq=2412)
1138    dev[0].wait_connected()
1139    dev[0].request("DISCONNECT")
1140    dev[0].wait_disconnected()
1141
1142    dev[0].request("FILS_HLP_REQ_FLUSH")
1143
1144def test_fils_sk_hlp_dhcp_parsing(dev, apdev, params):
1145    """FILS SK HLP and DHCP response parsing"""
1146    check_fils_capa(dev[0])
1147    check_erp_capa(dev[0])
1148
1149    start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
1150
1151    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
1152    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
1153    sock.settimeout(5)
1154    sock.bind(("127.0.0.2", 67))
1155
1156    bssid = apdev[0]['bssid']
1157    params = fils_hlp_config(fils_hlp_wait_time=30)
1158    params['dhcp_rapid_commit_proxy'] = '1'
1159    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1160
1161    dev[0].scan_for_bss(bssid, freq=2412)
1162    dev[0].request("ERP_FLUSH")
1163    if "OK" not in dev[0].request("FILS_HLP_REQ_FLUSH"):
1164        raise Exception("Failed to flush pending FILS HLP requests")
1165    dhcpdisc = build_dhcp(req=True, dhcp_msg=DHCPDISCOVER,
1166                          chaddr=dev[0].own_addr())
1167    if "OK" not in dev[0].request("FILS_HLP_REQ_ADD " + "ff:ff:ff:ff:ff:ff " + binascii.hexlify(dhcpdisc).decode()):
1168        raise Exception("FILS_HLP_REQ_ADD failed")
1169    id = dev[0].connect("fils", key_mgmt="FILS-SHA256",
1170                        eap="PSK", identity="psk.user@example.com",
1171                        password_hex="0123456789abcdef0123456789abcdef",
1172                        erp="1", scan_freq="2412")
1173
1174    dev[0].request("DISCONNECT")
1175    dev[0].wait_disconnected()
1176
1177    dev[0].dump_monitor()
1178    with alloc_fail(hapd, 1, "fils_process_hlp"):
1179        dev[0].select_network(id, freq=2412)
1180        dev[0].wait_connected()
1181    dev[0].request("DISCONNECT")
1182    dev[0].wait_disconnected()
1183
1184    dev[0].dump_monitor()
1185    dev[0].select_network(id, freq=2412)
1186    (msg, addr) = sock.recvfrom(1000)
1187    logger.debug("Received DHCP message from %s" % str(addr))
1188    dhcpdisc = build_dhcp(req=False, dhcp_msg=DHCPACK,
1189                          chaddr=dev[0].own_addr(), giaddr="127.0.0.3")
1190    #sock.sendto(dhcpdisc[2+20+8:], addr)
1191    chaddr = binascii.unhexlify(dev[0].own_addr().replace(':', '')) + 10*b'\x00'
1192    tests = [b"\x00",
1193             b"\x02" + 500 * b"\x00",
1194             b"\x02\x00\x00\x00" + 20*b"\x00" + b"\x7f\x00\x00\x03" + 500*b"\x00",
1195             b"\x02\x00\x00\x00" + 20*b"\x00" + b"\x7f\x00\x00\x03" + 16*b"\x00" + 64*b"\x00" + 128*b"\x00" + b"\x63\x82\x53\x63",
1196             b"\x02\x00\x00\x00" + 20*b"\x00" + b"\x7f\x00\x00\x03" + 16*b"\x00" + 64*b"\x00" + 128*b"\x00" + b"\x63\x82\x53\x63" + b"\x00\x11",
1197             b"\x02\x00\x00\x00" + 20*b"\x00" + b"\x7f\x00\x00\x03" + 16*b"\x00" + 64*b"\x00" + 128*b"\x00" + b"\x63\x82\x53\x63" + b"\x11\x01",
1198             b"\x02\x00\x00\x00" + 20*b"\x00" + b"\x7f\x00\x00\x03" + chaddr + 64*b"\x00" + 128*b"\x00" + b"\x63\x82\x53\x63" + b"\x35\x00\xff",
1199             b"\x02\x00\x00\x00" + 20*b"\x00" + b"\x7f\x00\x00\x03" + chaddr + 64*b"\x00" + 128*b"\x00" + b"\x63\x82\x53\x63" + b"\x35\x01\x00\xff",
1200             1501 * b"\x00"]
1201    for t in tests:
1202        sock.sendto(t, addr)
1203    dev[0].wait_connected()
1204    dev[0].request("DISCONNECT")
1205    dev[0].wait_disconnected()
1206
1207    # FILS: DHCP sendto failed: Invalid argument for second DHCP TX in proxy
1208    dev[0].dump_monitor()
1209    dev[0].select_network(id, freq=2412)
1210    (msg, addr) = sock.recvfrom(1000)
1211    logger.debug("Received DHCP message from %s" % str(addr))
1212    hapd.set("dhcp_server_port", "0")
1213    dhcpoffer = build_dhcp(req=False, dhcp_msg=DHCPOFFER, rapid_commit=False,
1214                           chaddr=dev[0].own_addr(), giaddr="127.0.0.3")
1215    sock.sendto(dhcpoffer[2+20+8:], addr)
1216    dev[0].wait_connected()
1217    dev[0].request("DISCONNECT")
1218    dev[0].wait_disconnected()
1219    hapd.set("dhcp_server_port", "67")
1220
1221    # Options in DHCPOFFER
1222    dev[0].dump_monitor()
1223    dev[0].select_network(id, freq=2412)
1224    (msg, addr) = sock.recvfrom(1000)
1225    logger.debug("Received DHCP message from %s" % str(addr))
1226    dhcpoffer = build_dhcp(req=False, dhcp_msg=DHCPOFFER, rapid_commit=False,
1227                           chaddr=dev[0].own_addr(), giaddr="127.0.0.3",
1228                           extra_op=b"\x00\x11", opt_end=False)
1229    sock.sendto(dhcpoffer[2+20+8:], addr)
1230    (msg, addr) = sock.recvfrom(1000)
1231    logger.debug("Received DHCP message from %s" % str(addr))
1232    dev[0].wait_connected()
1233    dev[0].request("DISCONNECT")
1234    dev[0].wait_disconnected()
1235
1236    # Options in DHCPOFFER (2)
1237    dev[0].dump_monitor()
1238    dev[0].select_network(id, freq=2412)
1239    (msg, addr) = sock.recvfrom(1000)
1240    logger.debug("Received DHCP message from %s" % str(addr))
1241    dhcpoffer = build_dhcp(req=False, dhcp_msg=DHCPOFFER, rapid_commit=False,
1242                           chaddr=dev[0].own_addr(), giaddr="127.0.0.3",
1243                           extra_op=b"\x11\x01", opt_end=False)
1244    sock.sendto(dhcpoffer[2+20+8:], addr)
1245    (msg, addr) = sock.recvfrom(1000)
1246    logger.debug("Received DHCP message from %s" % str(addr))
1247    dev[0].wait_connected()
1248    dev[0].request("DISCONNECT")
1249    dev[0].wait_disconnected()
1250
1251    # Server ID in DHCPOFFER
1252    dev[0].dump_monitor()
1253    dev[0].select_network(id, freq=2412)
1254    (msg, addr) = sock.recvfrom(1000)
1255    logger.debug("Received DHCP message from %s" % str(addr))
1256    dhcpoffer = build_dhcp(req=False, dhcp_msg=DHCPOFFER, rapid_commit=False,
1257                           chaddr=dev[0].own_addr(), giaddr="127.0.0.3",
1258                           extra_op=b"\x36\x01\x30")
1259    sock.sendto(dhcpoffer[2+20+8:], addr)
1260    (msg, addr) = sock.recvfrom(1000)
1261    logger.debug("Received DHCP message from %s" % str(addr))
1262    dev[0].wait_connected()
1263    dev[0].request("DISCONNECT")
1264    dev[0].wait_disconnected()
1265
1266    # FILS: Could not update DHCPDISCOVER
1267    dev[0].request("FILS_HLP_REQ_FLUSH")
1268    dhcpdisc = build_dhcp(req=True, dhcp_msg=DHCPDISCOVER,
1269                          chaddr=dev[0].own_addr(),
1270                          extra_op=b"\x00\x11", opt_end=False)
1271    if "OK" not in dev[0].request("FILS_HLP_REQ_ADD " + "ff:ff:ff:ff:ff:ff " + binascii.hexlify(dhcpdisc).decode()):
1272        raise Exception("FILS_HLP_REQ_ADD failed")
1273    dev[0].dump_monitor()
1274    dev[0].select_network(id, freq=2412)
1275    (msg, addr) = sock.recvfrom(1000)
1276    logger.debug("Received DHCP message from %s" % str(addr))
1277    dhcpoffer = build_dhcp(req=False, dhcp_msg=DHCPOFFER, rapid_commit=False,
1278                           chaddr=dev[0].own_addr(), giaddr="127.0.0.3",
1279                           extra_op=b"\x36\x01\x30")
1280    sock.sendto(dhcpoffer[2+20+8:], addr)
1281    dev[0].wait_connected()
1282    dev[0].request("DISCONNECT")
1283    dev[0].wait_disconnected()
1284
1285    # FILS: Could not update DHCPDISCOVER (2)
1286    dev[0].request("FILS_HLP_REQ_FLUSH")
1287    dhcpdisc = build_dhcp(req=True, dhcp_msg=DHCPDISCOVER,
1288                          chaddr=dev[0].own_addr(),
1289                          extra_op=b"\x11\x01", opt_end=False)
1290    if "OK" not in dev[0].request("FILS_HLP_REQ_ADD " + "ff:ff:ff:ff:ff:ff " + binascii.hexlify(dhcpdisc).decode()):
1291        raise Exception("FILS_HLP_REQ_ADD failed")
1292    dev[0].dump_monitor()
1293    dev[0].select_network(id, freq=2412)
1294    (msg, addr) = sock.recvfrom(1000)
1295    logger.debug("Received DHCP message from %s" % str(addr))
1296    dhcpoffer = build_dhcp(req=False, dhcp_msg=DHCPOFFER, rapid_commit=False,
1297                           chaddr=dev[0].own_addr(), giaddr="127.0.0.3",
1298                           extra_op=b"\x36\x01\x30")
1299    sock.sendto(dhcpoffer[2+20+8:], addr)
1300    dev[0].wait_connected()
1301    dev[0].request("DISCONNECT")
1302    dev[0].wait_disconnected()
1303
1304    dev[0].request("FILS_HLP_REQ_FLUSH")
1305
1306def test_fils_sk_erp_and_reauth(dev, apdev, params):
1307    """FILS SK using ERP and AP going away"""
1308    check_fils_capa(dev[0])
1309    check_erp_capa(dev[0])
1310
1311    start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
1312
1313    bssid = apdev[0]['bssid']
1314    params = hostapd.wpa2_eap_params(ssid="fils")
1315    params['wpa_key_mgmt'] = "FILS-SHA256"
1316    params['auth_server_port'] = "18128"
1317    params['erp_domain'] = 'example.com'
1318    params['fils_realm'] = 'example.com'
1319    params['disable_pmksa_caching'] = '1'
1320    params['broadcast_deauth'] = '0'
1321    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1322
1323    dev[0].scan_for_bss(bssid, freq=2412)
1324    dev[0].request("ERP_FLUSH")
1325    id = dev[0].connect("fils", key_mgmt="FILS-SHA256",
1326                        eap="PSK", identity="psk.user@example.com",
1327                        password_hex="0123456789abcdef0123456789abcdef",
1328                        erp="1", scan_freq="2412")
1329
1330    hapd.disable()
1331    dev[0].wait_disconnected()
1332    dev[0].dump_monitor()
1333    hapd.enable()
1334
1335    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
1336                            "EVENT-ASSOC-REJECT",
1337                            "CTRL-EVENT-CONNECTED"], timeout=10)
1338    if ev is None:
1339        raise Exception("Reconnection using FILS/ERP timed out")
1340    if "CTRL-EVENT-EAP-STARTED" in ev:
1341        raise Exception("Unexpected EAP exchange")
1342    if "EVENT-ASSOC-REJECT" in ev:
1343        raise Exception("Association failed")
1344
1345def test_fils_sk_erp_sim(dev, apdev, params):
1346    """FILS SK using ERP with SIM"""
1347    check_fils_capa(dev[0])
1348    check_erp_capa(dev[0])
1349
1350    realm = 'wlan.mnc001.mcc232.3gppnetwork.org'
1351    start_erp_as(erp_domain=realm,
1352                 msk_dump=os.path.join(params['logdir'], "msk.lst"))
1353
1354    bssid = apdev[0]['bssid']
1355    params = hostapd.wpa2_eap_params(ssid="fils")
1356    params['wpa_key_mgmt'] = "FILS-SHA256"
1357    params['auth_server_port'] = "18128"
1358    params['fils_realm'] = realm
1359    params['disable_pmksa_caching'] = '1'
1360    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1361
1362    dev[0].scan_for_bss(bssid, freq=2412)
1363    dev[0].request("ERP_FLUSH")
1364    id = dev[0].connect("fils", key_mgmt="FILS-SHA256",
1365                        eap="SIM", identity="1232010000000000@" + realm,
1366                        password="90dca4eda45b53cf0f12d7c9c3bc6a89:cb9cccc4b9258e6dca4760379fb82581",
1367                        erp="1", scan_freq="2412")
1368
1369    hapd.disable()
1370    dev[0].wait_disconnected()
1371    dev[0].dump_monitor()
1372    hapd.enable()
1373
1374    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
1375                            "EVENT-ASSOC-REJECT",
1376                            "CTRL-EVENT-CONNECTED"], timeout=10)
1377    if ev is None:
1378        raise Exception("Reconnection using FILS/ERP timed out")
1379    if "CTRL-EVENT-EAP-STARTED" in ev:
1380        raise Exception("Unexpected EAP exchange")
1381    if "EVENT-ASSOC-REJECT" in ev:
1382        raise Exception("Association failed")
1383
1384def test_fils_sk_pfs_19(dev, apdev, params):
1385    """FILS SK with PFS (DH group 19)"""
1386    run_fils_sk_pfs(dev, apdev, "19", params)
1387
1388def test_fils_sk_pfs_20(dev, apdev, params):
1389    """FILS SK with PFS (DH group 20)"""
1390    run_fils_sk_pfs(dev, apdev, "20", params)
1391
1392def test_fils_sk_pfs_21(dev, apdev, params):
1393    """FILS SK with PFS (DH group 21)"""
1394    run_fils_sk_pfs(dev, apdev, "21", params)
1395
1396def test_fils_sk_pfs_25(dev, apdev, params):
1397    """FILS SK with PFS (DH group 25)"""
1398    run_fils_sk_pfs(dev, apdev, "25", params)
1399
1400def test_fils_sk_pfs_26(dev, apdev, params):
1401    """FILS SK with PFS (DH group 26)"""
1402    run_fils_sk_pfs(dev, apdev, "26", params)
1403
1404def test_fils_sk_pfs_27(dev, apdev, params):
1405    """FILS SK with PFS (DH group 27)"""
1406    run_fils_sk_pfs(dev, apdev, "27", params)
1407
1408def test_fils_sk_pfs_28(dev, apdev, params):
1409    """FILS SK with PFS (DH group 28)"""
1410    run_fils_sk_pfs(dev, apdev, "28", params)
1411
1412def test_fils_sk_pfs_29(dev, apdev, params):
1413    """FILS SK with PFS (DH group 29)"""
1414    run_fils_sk_pfs(dev, apdev, "29", params)
1415
1416def test_fils_sk_pfs_30(dev, apdev, params):
1417    """FILS SK with PFS (DH group 30)"""
1418    run_fils_sk_pfs(dev, apdev, "30", params)
1419
1420def run_fils_sk_pfs(dev, apdev, group, params):
1421    check_fils_sk_pfs_capa(dev[0])
1422    check_erp_capa(dev[0])
1423
1424    tls = dev[0].request("GET tls_library")
1425    if int(group) in [25]:
1426        if not (tls.startswith("OpenSSL") and ("build=OpenSSL 1.0.2" in tls or "build=OpenSSL 1.1" in tls or "build=OpenSSL 3.0" in tls) and ("run=OpenSSL 1.0.2" in tls or "run=OpenSSL 1.1" in tls or "run=OpenSSL 3.0" in tls)):
1427            raise HwsimSkip("EC group not supported")
1428    if int(group) in [27, 28, 29, 30]:
1429        if not (tls.startswith("OpenSSL") and ("build=OpenSSL 1.0.2" in tls or "build=OpenSSL 1.1" in tls or "build=OpenSSL 3.0" in tls) and ("run=OpenSSL 1.0.2" in tls or "run=OpenSSL 1.1" in tls or "run=OpenSSL 3.0" in tls)):
1430            raise HwsimSkip("Brainpool EC group not supported")
1431
1432    start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
1433
1434    bssid = apdev[0]['bssid']
1435    params = hostapd.wpa2_eap_params(ssid="fils")
1436    params['wpa_key_mgmt'] = "FILS-SHA256"
1437    params['auth_server_port'] = "18128"
1438    params['erp_domain'] = 'example.com'
1439    params['fils_realm'] = 'example.com'
1440    params['disable_pmksa_caching'] = '1'
1441    params['fils_dh_group'] = group
1442    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1443
1444    dev[0].scan_for_bss(bssid, freq=2412)
1445    dev[0].request("ERP_FLUSH")
1446    id = dev[0].connect("fils", key_mgmt="FILS-SHA256",
1447                        eap="PSK", identity="psk.user@example.com",
1448                        password_hex="0123456789abcdef0123456789abcdef",
1449                        erp="1", fils_dh_group=group, scan_freq="2412")
1450
1451    dev[0].request("DISCONNECT")
1452    dev[0].wait_disconnected()
1453
1454    dev[0].dump_monitor()
1455    dev[0].select_network(id, freq=2412)
1456    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
1457                            "EVENT-ASSOC-REJECT",
1458                            "CTRL-EVENT-CONNECTED"], timeout=10)
1459    if ev is None:
1460        raise Exception("Connection using FILS/ERP timed out")
1461    if "CTRL-EVENT-EAP-STARTED" in ev:
1462        raise Exception("Unexpected EAP exchange")
1463    if "EVENT-ASSOC-REJECT" in ev:
1464        raise Exception("Association failed")
1465    hwsim_utils.test_connectivity(dev[0], hapd)
1466
1467def test_fils_sk_pfs_group_mismatch(dev, apdev, params):
1468    """FILS SK PFS DH group mismatch"""
1469    check_fils_sk_pfs_capa(dev[0])
1470    check_erp_capa(dev[0])
1471
1472    start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
1473
1474    bssid = apdev[0]['bssid']
1475    params = hostapd.wpa2_eap_params(ssid="fils")
1476    params['wpa_key_mgmt'] = "FILS-SHA256"
1477    params['auth_server_port'] = "18128"
1478    params['erp_domain'] = 'example.com'
1479    params['fils_realm'] = 'example.com'
1480    params['disable_pmksa_caching'] = '1'
1481    params['fils_dh_group'] = "20"
1482    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1483
1484    dev[0].scan_for_bss(bssid, freq=2412)
1485    dev[0].request("ERP_FLUSH")
1486    id = dev[0].connect("fils", key_mgmt="FILS-SHA256",
1487                        eap="PSK", identity="psk.user@example.com",
1488                        password_hex="0123456789abcdef0123456789abcdef",
1489                        erp="1", fils_dh_group="19", scan_freq="2412")
1490
1491    dev[0].request("DISCONNECT")
1492    dev[0].wait_disconnected()
1493
1494    dev[0].dump_monitor()
1495    dev[0].select_network(id, freq=2412)
1496    ev = dev[0].wait_event(["CTRL-EVENT-AUTH-REJECT"], timeout=10)
1497    dev[0].request("DISCONNECT")
1498    if ev is None:
1499        raise Exception("Authentication rejection not seen")
1500    if "auth_type=5 auth_transaction=2 status_code=77" not in ev:
1501        raise Exception("Unexpected auth reject value: " + ev)
1502
1503def test_fils_sk_pfs_pmksa_caching(dev, apdev, params):
1504    """FILS SK with PFS and PMKSA caching"""
1505    check_fils_sk_pfs_capa(dev[0])
1506    check_erp_capa(dev[0])
1507
1508    start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
1509
1510    bssid = apdev[0]['bssid']
1511    params = hostapd.wpa2_eap_params(ssid="fils")
1512    params['wpa_key_mgmt'] = "FILS-SHA256"
1513    params['auth_server_port'] = "18128"
1514    params['erp_domain'] = 'example.com'
1515    params['fils_realm'] = 'example.com'
1516    params['fils_dh_group'] = "19"
1517    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1518
1519    dev[0].scan_for_bss(bssid, freq=2412)
1520    dev[0].request("ERP_FLUSH")
1521    id = dev[0].connect("fils", key_mgmt="FILS-SHA256",
1522                        eap="PSK", identity="psk.user@example.com",
1523                        password_hex="0123456789abcdef0123456789abcdef",
1524                        erp="1", fils_dh_group="19", scan_freq="2412")
1525    pmksa = dev[0].get_pmksa(bssid)
1526    if pmksa is None:
1527        raise Exception("No PMKSA cache entry created")
1528
1529    dev[0].request("DISCONNECT")
1530    dev[0].wait_disconnected()
1531
1532    # FILS authentication with PMKSA caching and PFS
1533    dev[0].dump_monitor()
1534    dev[0].select_network(id, freq=2412)
1535    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
1536                            "CTRL-EVENT-CONNECTED"], timeout=10)
1537    if ev is None:
1538        raise Exception("Connection using PMKSA caching timed out")
1539    if "CTRL-EVENT-EAP-STARTED" in ev:
1540        raise Exception("Unexpected EAP exchange")
1541    hwsim_utils.test_connectivity(dev[0], hapd)
1542    pmksa2 = dev[0].get_pmksa(bssid)
1543    if pmksa2 is None:
1544        raise Exception("No PMKSA cache entry found")
1545    if pmksa['pmkid'] != pmksa2['pmkid']:
1546        raise Exception("Unexpected PMKID change")
1547
1548    # Verify EAPOL reauthentication after FILS authentication
1549    hapd.request("EAPOL_REAUTH " + dev[0].own_addr())
1550    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
1551    if ev is None:
1552        raise Exception("EAP authentication did not start")
1553    ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=5)
1554    if ev is None:
1555        raise Exception("EAP authentication did not succeed")
1556    time.sleep(0.1)
1557    hwsim_utils.test_connectivity(dev[0], hapd)
1558
1559    dev[0].request("DISCONNECT")
1560    dev[0].wait_disconnected()
1561
1562    # FILS authentication with ERP and PFS
1563    dev[0].request("PMKSA_FLUSH")
1564    dev[0].dump_monitor()
1565    dev[0].select_network(id, freq=2412)
1566    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
1567                            "CTRL-EVENT-EAP-SUCCESS",
1568                            "CTRL-EVENT-CONNECTED"], timeout=10)
1569    if ev is None:
1570        raise Exception("Connection using ERP and PFS timed out")
1571    if "CTRL-EVENT-EAP-STARTED" in ev:
1572        raise Exception("Unexpected EAP exchange")
1573    if "CTRL-EVENT-EAP-SUCCESS" not in ev:
1574        raise Exception("ERP success not reported")
1575    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
1576                            "SME: Trying to authenticate",
1577                            "CTRL-EVENT-CONNECTED"], timeout=10)
1578    if ev is None:
1579        raise Exception("Connection using ERP and PFS timed out")
1580    if "CTRL-EVENT-EAP-STARTED" in ev:
1581        raise Exception("Unexpected EAP exchange")
1582    if "SME: Trying to authenticate" in ev:
1583        raise Exception("Unexpected extra authentication round with ERP and PFS")
1584    hwsim_utils.test_connectivity(dev[0], hapd)
1585    pmksa3 = dev[0].get_pmksa(bssid)
1586    if pmksa3 is None:
1587        raise Exception("No PMKSA cache entry found")
1588    if pmksa2['pmkid'] == pmksa3['pmkid']:
1589        raise Exception("PMKID did not change")
1590
1591    dev[0].request("DISCONNECT")
1592    dev[0].wait_disconnected()
1593
1594    # FILS authentication with PMKSA caching and PFS
1595    dev[0].dump_monitor()
1596    dev[0].select_network(id, freq=2412)
1597    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
1598                            "CTRL-EVENT-CONNECTED"], timeout=10)
1599    if ev is None:
1600        raise Exception("Connection using PMKSA caching timed out")
1601    if "CTRL-EVENT-EAP-STARTED" in ev:
1602        raise Exception("Unexpected EAP exchange")
1603    hwsim_utils.test_connectivity(dev[0], hapd)
1604    pmksa4 = dev[0].get_pmksa(bssid)
1605    if pmksa4 is None:
1606        raise Exception("No PMKSA cache entry found")
1607    if pmksa3['pmkid'] != pmksa4['pmkid']:
1608        raise Exception("Unexpected PMKID change (2)")
1609
1610def test_fils_sk_auth_mismatch(dev, apdev, params):
1611    """FILS SK authentication type mismatch (PFS not supported)"""
1612    check_fils_sk_pfs_capa(dev[0])
1613    check_erp_capa(dev[0])
1614
1615    start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
1616
1617    bssid = apdev[0]['bssid']
1618    params = hostapd.wpa2_eap_params(ssid="fils")
1619    params['wpa_key_mgmt'] = "FILS-SHA256"
1620    params['auth_server_port'] = "18128"
1621    params['erp_domain'] = 'example.com'
1622    params['fils_realm'] = 'example.com'
1623    params['disable_pmksa_caching'] = '1'
1624    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1625
1626    dev[0].scan_for_bss(bssid, freq=2412)
1627    dev[0].request("ERP_FLUSH")
1628    id = dev[0].connect("fils", key_mgmt="FILS-SHA256",
1629                        eap="PSK", identity="psk.user@example.com",
1630                        password_hex="0123456789abcdef0123456789abcdef",
1631                        erp="1", fils_dh_group="19", scan_freq="2412")
1632
1633    dev[0].request("DISCONNECT")
1634    dev[0].wait_disconnected()
1635
1636    hapd.dump_monitor()
1637    dev[0].dump_monitor()
1638    dev[0].select_network(id, freq=2412)
1639    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
1640                            "EVENT-ASSOC-REJECT",
1641                            "CTRL-EVENT-CONNECTED"], timeout=10)
1642    if ev is None:
1643        raise Exception("Connection using FILS/ERP timed out")
1644    if "CTRL-EVENT-EAP-STARTED" not in ev:
1645        raise Exception("No EAP exchange seen")
1646    dev[0].wait_connected()
1647    hapd.wait_sta()
1648    hwsim_utils.test_connectivity(dev[0], hapd)
1649
1650def setup_fils_rekey(dev, apdev, params, wpa_ptk_rekey=0, wpa_group_rekey=0,
1651                     pmksa_caching=True, ext_key_id=False):
1652    check_fils_capa(dev[0])
1653    check_erp_capa(dev[0])
1654
1655    start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
1656
1657    bssid = apdev[0]['bssid']
1658    params = hostapd.wpa2_eap_params(ssid="fils")
1659    params['wpa_key_mgmt'] = "FILS-SHA256"
1660    params['auth_server_port'] = "18128"
1661    params['erp_domain'] = 'example.com'
1662    params['fils_realm'] = 'example.com'
1663    if wpa_ptk_rekey:
1664        params['wpa_ptk_rekey'] = str(wpa_ptk_rekey)
1665    if wpa_group_rekey:
1666        params['wpa_group_rekey'] = str(wpa_group_rekey)
1667    if not pmksa_caching:
1668            params['disable_pmksa_caching'] = '1'
1669    if ext_key_id:
1670        params['extended_key_id'] = '1'
1671    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1672
1673    dev[0].scan_for_bss(bssid, freq=2412)
1674    dev[0].request("ERP_FLUSH")
1675    id = dev[0].connect("fils", key_mgmt="FILS-SHA256",
1676                        eap="PSK", identity="psk.user@example.com",
1677                        password_hex="0123456789abcdef0123456789abcdef",
1678                        erp="1", scan_freq="2412")
1679
1680    dev[0].request("DISCONNECT")
1681    dev[0].wait_disconnected()
1682
1683    dev[0].dump_monitor()
1684    dev[0].select_network(id, freq=2412)
1685    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
1686                            "CTRL-EVENT-CONNECTED"], timeout=10)
1687    if ev is None:
1688        raise Exception("Connection using ERP or PMKSA caching timed out")
1689    if "CTRL-EVENT-EAP-STARTED" in ev:
1690        raise Exception("Unexpected EAP exchange")
1691    dev[0].dump_monitor()
1692
1693    hwsim_utils.test_connectivity(dev[0], hapd)
1694    return hapd
1695
1696def test_fils_auth_gtk_rekey(dev, apdev, params):
1697    """GTK rekeying after FILS authentication"""
1698    hapd = setup_fils_rekey(dev, apdev, params, wpa_group_rekey=1)
1699    ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=2)
1700    if ev is None:
1701        raise Exception("GTK rekey timed out")
1702    hwsim_utils.test_connectivity(dev[0], hapd)
1703
1704    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=5)
1705    if ev is not None:
1706        raise Exception("Rekeying failed - disconnected")
1707    hwsim_utils.test_connectivity(dev[0], hapd)
1708
1709def test_fils_auth_ptk_rekey_ap(dev, apdev, params):
1710    """PTK rekeying after FILS authentication triggered by AP"""
1711    hapd = setup_fils_rekey(dev, apdev, params, wpa_ptk_rekey=2)
1712    ev = dev[0].wait_event(["WPA: Key negotiation completed"], timeout=3)
1713    if ev is None:
1714        raise Exception("PTK rekey timed out")
1715    hwsim_utils.test_connectivity(dev[0], hapd)
1716
1717    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1)
1718    if ev is not None:
1719        raise Exception("Rekeying failed - disconnected")
1720    hwsim_utils.test_connectivity(dev[0], hapd)
1721
1722def test_fils_auth_ptk_rekey_ap_erp(dev, apdev, params):
1723    """PTK rekeying after FILS authentication triggered by AP (ERP)"""
1724    hapd = setup_fils_rekey(dev, apdev, params, wpa_ptk_rekey=2,
1725                            pmksa_caching=False)
1726    ev = dev[0].wait_event(["WPA: Key negotiation completed"], timeout=3)
1727    if ev is None:
1728        raise Exception("PTK rekey timed out")
1729    hwsim_utils.test_connectivity(dev[0], hapd)
1730
1731    ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1)
1732    if ev is not None:
1733        raise Exception("Rekeying failed - disconnected")
1734    hwsim_utils.test_connectivity(dev[0], hapd)
1735
1736def test_fils_and_ft(dev, apdev, params):
1737    """FILS SK using ERP and FT initial mobility domain association"""
1738    check_fils_capa(dev[0])
1739    check_erp_capa(dev[0])
1740
1741    er = start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
1742
1743    bssid = apdev[0]['bssid']
1744    params = hostapd.wpa2_eap_params(ssid="fils")
1745    params['wpa_key_mgmt'] = "FILS-SHA256"
1746    params['auth_server_port'] = "18128"
1747    params['erp_domain'] = 'example.com'
1748    params['fils_realm'] = 'example.com'
1749    params['disable_pmksa_caching'] = '1'
1750    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1751
1752    dev[0].scan_for_bss(bssid, freq=2412)
1753    dev[0].request("ERP_FLUSH")
1754    id = dev[0].connect("fils", key_mgmt="FILS-SHA256",
1755                        eap="PSK", identity="psk.user@example.com",
1756                        password_hex="0123456789abcdef0123456789abcdef",
1757                        erp="1", scan_freq="2412")
1758
1759    dev[0].request("DISCONNECT")
1760    dev[0].wait_disconnected()
1761    hapd.disable()
1762    dev[0].flush_scan_cache()
1763    if "FAIL" in dev[0].request("PMKSA_FLUSH"):
1764        raise Exception("PMKSA_FLUSH failed")
1765
1766    params = hostapd.wpa2_eap_params(ssid="fils-ft")
1767    params['wpa_key_mgmt'] = "FILS-SHA256 FT-FILS-SHA256 FT-EAP"
1768    params['auth_server_port'] = "18128"
1769    params['erp_domain'] = 'example.com'
1770    params['fils_realm'] = 'example.com'
1771    params['disable_pmksa_caching'] = '1'
1772    params["mobility_domain"] = "a1b2"
1773    params["r0_key_lifetime"] = "10000"
1774    params["pmk_r1_push"] = "1"
1775    params["reassociation_deadline"] = "1000"
1776    params['nas_identifier'] = "nas1.w1.fi"
1777    params['r1_key_holder'] = "000102030405"
1778    params['r0kh'] = ["02:00:00:00:04:00 nas2.w1.fi 300102030405060708090a0b0c0d0e0f"]
1779    params['r1kh'] = "02:00:00:00:04:00 00:01:02:03:04:06 200102030405060708090a0b0c0d0e0f"
1780    params['ieee80211w'] = "1"
1781    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1782
1783    dev[0].scan_for_bss(bssid, freq=2412)
1784    dev[0].dump_monitor()
1785    id = dev[0].connect("fils-ft", key_mgmt="FILS-SHA256 FT-FILS-SHA256 FT-EAP",
1786                        ieee80211w="1",
1787                        eap="PSK", identity="psk.user@example.com",
1788                        password_hex="0123456789abcdef0123456789abcdef",
1789                        erp="1", scan_freq="2412", wait_connect=False)
1790
1791    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
1792                            "CTRL-EVENT-AUTH-REJECT",
1793                            "EVENT-ASSOC-REJECT",
1794                            "CTRL-EVENT-CONNECTED"], timeout=10)
1795    if ev is None:
1796        raise Exception("Connection using FILS/ERP timed out")
1797    if "CTRL-EVENT-EAP-STARTED" in ev:
1798        raise Exception("Unexpected EAP exchange")
1799    if "CTRL-EVENT-AUTH-REJECT" in ev:
1800        raise Exception("Authentication failed")
1801    if "EVENT-ASSOC-REJECT" in ev:
1802        raise Exception("Association failed")
1803    hwsim_utils.test_connectivity(dev[0], hapd)
1804
1805    er.disable()
1806
1807    # FIX: FT-FILS-SHA256 does not currently work for FT protocol due to not
1808    # fully defined FT Reassociation Request/Response frame MIC use in FTE.
1809    # FT-EAP can be used to work around that in this test case to confirm the
1810    # FT key hierarchy was properly formed in the previous step.
1811    #params['wpa_key_mgmt'] = "FILS-SHA256 FT-FILS-SHA256"
1812    params['wpa_key_mgmt'] = "FT-EAP"
1813    params['nas_identifier'] = "nas2.w1.fi"
1814    params['r1_key_holder'] = "000102030406"
1815    params['r0kh'] = ["02:00:00:00:03:00 nas1.w1.fi 200102030405060708090a0b0c0d0e0f"]
1816    params['r1kh'] = "02:00:00:00:03:00 00:01:02:03:04:05 300102030405060708090a0b0c0d0e0f"
1817    hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
1818
1819    dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412", force_scan=True)
1820    # FIX: Cannot use FT-over-DS without the FTE MIC issue addressed
1821    #dev[0].roam_over_ds(apdev[1]['bssid'])
1822    dev[0].roam(apdev[1]['bssid'])
1823
1824def test_fils_and_ft_over_air(dev, apdev, params):
1825    """FILS SK using ERP and FT-over-air (SHA256)"""
1826    run_fils_and_ft_over_air(dev, apdev, params, "FT-FILS-SHA256")
1827
1828def test_fils_and_ft_over_air_sha384(dev, apdev, params):
1829    """FILS SK using ERP and FT-over-air (SHA384)"""
1830    run_fils_and_ft_over_air(dev, apdev, params, "FT-FILS-SHA384")
1831
1832def run_fils_and_ft_over_air(dev, apdev, params, key_mgmt):
1833    hapd, hapd2 = run_fils_and_ft_setup(dev, apdev, params, key_mgmt)
1834    conf = hapd.request("GET_CONFIG")
1835    if "key_mgmt=" + key_mgmt not in conf.splitlines():
1836        logger.info("GET_CONFIG:\n" + conf)
1837        raise Exception("GET_CONFIG did not report correct key_mgmt")
1838
1839    logger.info("FT protocol using FT key hierarchy established during FILS authentication")
1840    dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412", force_scan=True)
1841    hapd.request("NOTE FT protocol to AP2 using FT keys established during FILS FILS authentication")
1842    dev[0].roam(apdev[1]['bssid'])
1843    hwsim_utils.test_connectivity(dev[0], hapd2)
1844
1845    logger.info("FT protocol using the previously established FT key hierarchy from FILS authentication")
1846    hapd.request("NOTE FT protocol back to AP1 using FT keys established during FILS FILS authentication")
1847    dev[0].roam(apdev[0]['bssid'])
1848    hwsim_utils.test_connectivity(dev[0], hapd)
1849
1850    hapd.request("NOTE FT protocol back to AP2 using FT keys established during FILS FILS authentication")
1851    dev[0].roam(apdev[1]['bssid'])
1852    hwsim_utils.test_connectivity(dev[0], hapd2)
1853
1854    hapd.request("NOTE FT protocol back to AP1 using FT keys established during FILS FILS authentication (2)")
1855    dev[0].roam(apdev[0]['bssid'])
1856    hwsim_utils.test_connectivity(dev[0], hapd)
1857
1858def test_fils_and_ft_over_ds(dev, apdev, params):
1859    """FILS SK using ERP and FT-over-DS (SHA256)"""
1860    run_fils_and_ft_over_ds(dev, apdev, params, "FT-FILS-SHA256")
1861
1862def test_fils_and_ft_over_ds_sha384(dev, apdev, params):
1863    """FILS SK using ERP and FT-over-DS (SHA384)"""
1864    run_fils_and_ft_over_ds(dev, apdev, params, "FT-FILS-SHA384")
1865
1866def run_fils_and_ft_over_ds(dev, apdev, params, key_mgmt):
1867    hapd, hapd2 = run_fils_and_ft_setup(dev, apdev, params, key_mgmt)
1868
1869    logger.info("FT protocol using FT key hierarchy established during FILS authentication")
1870    dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412", force_scan=True)
1871    hapd.request("NOTE FT protocol to AP2 using FT keys established during FILS FILS authentication")
1872    dev[0].roam_over_ds(apdev[1]['bssid'])
1873
1874    logger.info("FT protocol using the previously established FT key hierarchy from FILS authentication")
1875    hapd.request("NOTE FT protocol back to AP1 using FT keys established during FILS FILS authentication")
1876    dev[0].roam_over_ds(apdev[0]['bssid'])
1877
1878    hapd.request("NOTE FT protocol back to AP2 using FT keys established during FILS FILS authentication")
1879    dev[0].roam_over_ds(apdev[1]['bssid'])
1880
1881    hapd.request("NOTE FT protocol back to AP1 using FT keys established during FILS FILS authentication (2)")
1882    dev[0].roam_over_ds(apdev[0]['bssid'])
1883
1884def run_fils_and_ft_setup(dev, apdev, params, key_mgmt):
1885    check_fils_capa(dev[0])
1886    check_erp_capa(dev[0])
1887
1888    er = start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
1889
1890    logger.info("Set up ERP key hierarchy without FILS/FT authentication")
1891    bssid = apdev[0]['bssid']
1892    params = hostapd.wpa2_eap_params(ssid="fils")
1893    params['wpa_key_mgmt'] = key_mgmt
1894    params['auth_server_port'] = "18128"
1895    params['erp_domain'] = 'example.com'
1896    params['fils_realm'] = 'example.com'
1897    params['disable_pmksa_caching'] = '1'
1898    params['ieee80211w'] = "2"
1899    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1900
1901    dev[0].scan_for_bss(bssid, freq=2412)
1902    dev[0].request("ERP_FLUSH")
1903    hapd.request("NOTE Initial association to establish ERP keys")
1904    id = dev[0].connect("fils", key_mgmt=key_mgmt, ieee80211w="2",
1905                        eap="PSK", identity="psk.user@example.com",
1906                        password_hex="0123456789abcdef0123456789abcdef",
1907                        erp="1", scan_freq="2412")
1908    hapd.wait_sta()
1909    hwsim_utils.test_connectivity(dev[0], hapd)
1910
1911    dev[0].request("DISCONNECT")
1912    dev[0].wait_disconnected()
1913    hapd.disable()
1914    dev[0].flush_scan_cache()
1915    if "FAIL" in dev[0].request("PMKSA_FLUSH"):
1916        raise Exception("PMKSA_FLUSH failed")
1917
1918    logger.info("Initial mobility domain association using FILS authentication")
1919    params = hostapd.wpa2_eap_params(ssid="fils-ft")
1920    params['wpa_key_mgmt'] = key_mgmt
1921    params['auth_server_port'] = "18128"
1922    params['erp_domain'] = 'example.com'
1923    params['fils_realm'] = 'example.com'
1924    params['disable_pmksa_caching'] = '1'
1925    params["mobility_domain"] = "a1b2"
1926    params["r0_key_lifetime"] = "10000"
1927    params["pmk_r1_push"] = "1"
1928    params["reassociation_deadline"] = "1000"
1929    params['nas_identifier'] = "nas1.w1.fi"
1930    params['r1_key_holder'] = "000102030405"
1931    params['r0kh'] = ["02:00:00:00:03:00 nas1.w1.fi 100102030405060708090a0b0c0d0e0f100102030405060708090a0b0c0d0e0f",
1932                      "02:00:00:00:04:00 nas2.w1.fi 300102030405060708090a0b0c0d0e0f"]
1933    params['r1kh'] = "02:00:00:00:04:00 00:01:02:03:04:06 200102030405060708090a0b0c0d0e0f"
1934    params['ieee80211w'] = "2"
1935    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1936
1937    dev[0].scan_for_bss(bssid, freq=2412)
1938    dev[0].dump_monitor()
1939    hapd.request("NOTE Initial FT mobility domain association using FILS authentication")
1940    dev[0].set_network_quoted(id, "ssid", "fils-ft")
1941    dev[0].select_network(id, freq=2412)
1942
1943    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
1944                            "CTRL-EVENT-AUTH-REJECT",
1945                            "EVENT-ASSOC-REJECT",
1946                            "CTRL-EVENT-CONNECTED"], timeout=10)
1947    if ev is None:
1948        raise Exception("Connection using FILS/ERP timed out")
1949    if "CTRL-EVENT-EAP-STARTED" in ev:
1950        raise Exception("Unexpected EAP exchange")
1951    if "CTRL-EVENT-AUTH-REJECT" in ev:
1952        raise Exception("Authentication failed")
1953    if "EVENT-ASSOC-REJECT" in ev:
1954        raise Exception("Association failed")
1955    hapd.wait_sta()
1956    hwsim_utils.test_connectivity(dev[0], hapd)
1957
1958    er.disable()
1959
1960    params['wpa_key_mgmt'] = key_mgmt
1961    params['nas_identifier'] = "nas2.w1.fi"
1962    params['r1_key_holder'] = "000102030406"
1963    params['r0kh'] = ["02:00:00:00:03:00 nas1.w1.fi 200102030405060708090a0b0c0d0e0f",
1964                      "02:00:00:00:04:00 nas2.w1.fi 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"]
1965    params['r1kh'] = "02:00:00:00:03:00 00:01:02:03:04:05 300102030405060708090a0b0c0d0e0f"
1966    hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
1967
1968    return hapd, hapd2
1969
1970def test_fils_assoc_replay(dev, apdev, params):
1971    """FILS AP and replayed Association Request frame"""
1972    capfile = os.path.join(params['logdir'], "hwsim0.pcapng")
1973    check_fils_capa(dev[0])
1974    check_erp_capa(dev[0])
1975
1976    start_erp_as()
1977
1978    bssid = apdev[0]['bssid']
1979    params = hostapd.wpa2_eap_params(ssid="fils")
1980    params['wpa_key_mgmt'] = "FILS-SHA256"
1981    params['auth_server_port'] = "18128"
1982    params['erp_domain'] = 'example.com'
1983    params['fils_realm'] = 'example.com'
1984    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
1985
1986    dev[0].scan_for_bss(bssid, freq=2412)
1987    dev[0].request("ERP_FLUSH")
1988    id = dev[0].connect("fils", key_mgmt="FILS-SHA256",
1989                        eap="PSK", identity="psk.user@example.com",
1990                        password_hex="0123456789abcdef0123456789abcdef",
1991                        erp="1", scan_freq="2412")
1992
1993    dev[0].request("DISCONNECT")
1994    dev[0].wait_disconnected()
1995
1996    hapd.set("ext_mgmt_frame_handling", "1")
1997    dev[0].dump_monitor()
1998    dev[0].select_network(id, freq=2412)
1999
2000    assocreq = None
2001    count = 0
2002    while count < 100:
2003        req = hapd.mgmt_rx()
2004        count += 1
2005        hapd.dump_monitor()
2006        hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
2007        if req['subtype'] == 0:
2008            assocreq = req
2009            ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5)
2010            if ev is None:
2011                raise Exception("No TX status seen")
2012            cmd = "MGMT_TX_STATUS_PROCESS %s" % (" ".join(ev.split(' ')[1:4]))
2013            if "OK" not in hapd.request(cmd):
2014                raise Exception("MGMT_TX_STATUS_PROCESS failed")
2015            break
2016    hapd.set("ext_mgmt_frame_handling", "0")
2017    if assocreq is None:
2018        raise Exception("No Association Request frame seen")
2019    dev[0].wait_connected()
2020    dev[0].dump_monitor()
2021    hapd.dump_monitor()
2022
2023    hwsim_utils.test_connectivity(dev[0], hapd)
2024
2025    logger.info("Replay the last Association Request frame")
2026    hapd.dump_monitor()
2027    hapd.set("ext_mgmt_frame_handling", "1")
2028    hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
2029    ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5)
2030    if ev is None:
2031        raise Exception("No TX status seen")
2032    cmd = "MGMT_TX_STATUS_PROCESS %s" % (" ".join(ev.split(' ')[1:4]))
2033    if "OK" not in hapd.request(cmd):
2034        raise Exception("MGMT_TX_STATUS_PROCESS failed")
2035    hapd.set("ext_mgmt_frame_handling", "0")
2036
2037    try:
2038        hwsim_utils.test_connectivity(dev[0], hapd)
2039        ok = True
2040    except:
2041        ok = False
2042
2043    ap = hapd.own_addr()
2044    sta = dev[0].own_addr()
2045    filt = "wlan.fc.type == 2 && " + \
2046           "wlan.da == " + sta + " && " + \
2047           "wlan.sa == " + ap + " && wlan.ccmp.extiv"
2048    fields = ["wlan.ccmp.extiv"]
2049    res = run_tshark(capfile, filt, fields)
2050    vals = res.splitlines()
2051    logger.info("CCMP PN: " + str(vals))
2052    if len(vals) < 2:
2053        raise Exception("Could not find all CCMP protected frames from capture")
2054    if len(set(vals)) < len(vals):
2055        raise Exception("Duplicate CCMP PN used")
2056
2057    if not ok:
2058        raise Exception("The second hwsim connectivity test failed")
2059
2060def test_fils_sk_erp_server_flush(dev, apdev, params):
2061    """FILS SK ERP and ERP flush on server, but not on peer"""
2062    check_fils_capa(dev[0])
2063    check_erp_capa(dev[0])
2064
2065    hapd_as = start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
2066
2067    bssid = apdev[0]['bssid']
2068    params = hostapd.wpa2_eap_params(ssid="fils")
2069    params['wpa_key_mgmt'] = "FILS-SHA256"
2070    params['auth_server_port'] = "18128"
2071    params['erp_domain'] = 'example.com'
2072    params['fils_realm'] = 'example.com'
2073    params['disable_pmksa_caching'] = '1'
2074    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
2075
2076    dev[0].scan_for_bss(bssid, freq=2412)
2077    dev[0].request("ERP_FLUSH")
2078    id = dev[0].connect("fils", key_mgmt="FILS-SHA256",
2079                        eap="PSK", identity="psk.user@example.com",
2080                        password_hex="0123456789abcdef0123456789abcdef",
2081                        erp="1", scan_freq="2412")
2082
2083    dev[0].request("DISCONNECT")
2084    dev[0].wait_disconnected()
2085
2086    dev[0].dump_monitor()
2087    dev[0].select_network(id, freq=2412)
2088    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
2089                            "EVENT-ASSOC-REJECT",
2090                            "CTRL-EVENT-CONNECTED"], timeout=10)
2091    if ev is None:
2092        raise Exception("Connection using FILS/ERP timed out")
2093    if "CTRL-EVENT-EAP-STARTED" in ev:
2094        raise Exception("Unexpected EAP exchange")
2095    if "EVENT-ASSOC-REJECT" in ev:
2096        raise Exception("Association failed")
2097
2098    dev[0].request("DISCONNECT")
2099    dev[0].wait_disconnected()
2100
2101    hapd_as.request("ERP_FLUSH")
2102    dev[0].dump_monitor()
2103    dev[0].select_network(id, freq=2412)
2104    ev = dev[0].wait_event(["CTRL-EVENT-AUTH-REJECT"], timeout=10)
2105    if ev is None:
2106        raise Exception("No authentication rejection seen after ERP flush on server")
2107
2108    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
2109                            "CTRL-EVENT-AUTH-REJECT",
2110                            "EVENT-ASSOC-REJECT",
2111                            "CTRL-EVENT-CONNECTED"], timeout=10)
2112    if ev is None:
2113        raise Exception("Connection attempt using FILS/ERP timed out")
2114    if "CTRL-EVENT-AUTH-REJECT" in ev:
2115        raise Exception("Failed to recover from ERP flush on server")
2116    if "EVENT-ASSOC-REJECT" in ev:
2117        raise Exception("Association failed")
2118    if "CTRL-EVENT-EAP-STARTED" not in ev:
2119        raise Exception("New EAP exchange not seen")
2120    dev[0].wait_connected(error="Connection timeout after ERP flush")
2121
2122    dev[0].request("DISCONNECT")
2123    dev[0].wait_disconnected()
2124    dev[0].dump_monitor()
2125    dev[0].select_network(id, freq=2412)
2126    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
2127                            "CTRL-EVENT-AUTH-REJECT",
2128                            "EVENT-ASSOC-REJECT",
2129                            "CTRL-EVENT-CONNECTED"], timeout=10)
2130    if ev is None:
2131        raise Exception("Connection attempt using FILS with new ERP keys timed out")
2132    if "CTRL-EVENT-AUTH-REJECT" in ev:
2133        raise Exception("Authentication failed with new ERP keys")
2134    if "EVENT-ASSOC-REJECT" in ev:
2135        raise Exception("Association failed with new ERP keys")
2136    if "CTRL-EVENT-EAP-STARTED" in ev:
2137        raise Exception("Unexpected EAP exchange")
2138
2139def test_fils_sk_erp_radius_ext(dev, apdev, params):
2140    """FILS SK using ERP and external RADIUS server"""
2141    as_hapd = hostapd.Hostapd("as")
2142    try:
2143        as_hapd.disable()
2144        as_hapd.set("eap_server_erp", "1")
2145        as_hapd.set("erp_domain", "erp.example.com")
2146        as_hapd.enable()
2147        run_fils_sk_erp_radius_ext(dev, apdev, params)
2148    finally:
2149        as_hapd.disable()
2150        as_hapd.set("eap_server_erp", "0")
2151        as_hapd.set("erp_domain", "")
2152        as_hapd.enable()
2153
2154def run_fils_sk_erp_radius_ext(dev, apdev, params):
2155    check_fils_capa(dev[0])
2156    check_erp_capa(dev[0])
2157
2158    bssid = apdev[0]['bssid']
2159    params = hostapd.wpa2_eap_params(ssid="fils")
2160    params['wpa_key_mgmt'] = "FILS-SHA256"
2161    params['erp_domain'] = 'erp.example.com'
2162    params['fils_realm'] = 'erp.example.com'
2163    params['disable_pmksa_caching'] = '1'
2164    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
2165
2166    dev[0].scan_for_bss(bssid, freq=2412)
2167    dev[0].request("ERP_FLUSH")
2168    id = dev[0].connect("fils", key_mgmt="FILS-SHA256",
2169                        eap="PWD", identity="pwd@erp.example.com",
2170                        password="secret password",
2171                        erp="1", scan_freq="2412")
2172
2173    dev[0].request("DISCONNECT")
2174    dev[0].wait_disconnected()
2175
2176    dev[0].dump_monitor()
2177    dev[0].select_network(id, freq=2412)
2178    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
2179                            "EVENT-ASSOC-REJECT",
2180                            "CTRL-EVENT-CONNECTED"], timeout=10)
2181    if ev is None:
2182        raise Exception("Connection using FILS/ERP timed out")
2183    if "CTRL-EVENT-EAP-STARTED" in ev:
2184        raise Exception("Unexpected EAP exchange")
2185    if "EVENT-ASSOC-REJECT" in ev:
2186        raise Exception("Association failed")
2187    hwsim_utils.test_connectivity(dev[0], hapd)
2188
2189def test_fils_sk_erp_radius_roam(dev, apdev):
2190    """FILS SK/ERP and roaming with different AKM"""
2191    as_hapd = hostapd.Hostapd("as")
2192    try:
2193        as_hapd.disable()
2194        as_hapd.set("eap_server_erp", "1")
2195        as_hapd.set("erp_domain", "example.com")
2196        as_hapd.enable()
2197        run_fils_sk_erp_radius_roam(dev, apdev)
2198    finally:
2199        as_hapd.disable()
2200        as_hapd.set("eap_server_erp", "0")
2201        as_hapd.set("erp_domain", "")
2202        as_hapd.enable()
2203
2204def run_fils_sk_erp_radius_roam(dev, apdev):
2205    check_fils_capa(dev[0])
2206    check_erp_capa(dev[0])
2207
2208    bssid = apdev[0]['bssid']
2209    params = hostapd.wpa2_eap_params(ssid="fils")
2210    params['wpa_key_mgmt'] = "FILS-SHA256"
2211    params['erp_domain'] = 'example.com'
2212    params['fils_realm'] = 'example.com'
2213    params['disable_pmksa_caching'] = '1'
2214    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
2215
2216    dev[0].scan_for_bss(bssid, freq=2412)
2217    dev[0].request("ERP_FLUSH")
2218    id = dev[0].connect("fils", key_mgmt="FILS-SHA256 FILS-SHA384",
2219                        eap="PWD", identity="erp-pwd@example.com",
2220                        password="secret password",
2221                        erp="1", scan_freq="2412")
2222
2223    bssid2 = apdev[1]['bssid']
2224    params = hostapd.wpa2_eap_params(ssid="fils")
2225    params['wpa_key_mgmt'] = "FILS-SHA384"
2226    params['erp_domain'] = 'example.com'
2227    params['fils_realm'] = 'example.com'
2228    params['disable_pmksa_caching'] = '1'
2229    hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
2230
2231    dev[0].scan_for_bss(bssid2, freq=2412)
2232
2233    dev[0].dump_monitor()
2234    if "OK" not in dev[0].request("ROAM " + bssid2):
2235        raise Exception("ROAM failed")
2236
2237    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
2238                            "CTRL-EVENT-CONNECTED"], timeout=10)
2239    if ev is None:
2240        raise Exception("Connection using PMKSA caching timed out")
2241    if "CTRL-EVENT-EAP-STARTED" in ev:
2242        raise Exception("Unexpected EAP exchange")
2243    if bssid2 not in ev:
2244        raise Exception("Failed to connect to the second AP")
2245
2246    hapd2.wait_sta()
2247    hwsim_utils.test_connectivity(dev[0], hapd2)
2248
2249def test_fils_sk_erp_roam_diff_akm(dev, apdev, params):
2250    """FILS SK using ERP and SHA256/SHA384 change in roam"""
2251    check_fils_capa(dev[0])
2252    check_erp_capa(dev[0])
2253
2254    start_erp_as()
2255
2256    bssid = apdev[0]['bssid']
2257    params = hostapd.wpa2_eap_params(ssid="fils")
2258    params['wpa_key_mgmt'] = "FILS-SHA256"
2259    params['auth_server_port'] = "18128"
2260    params['erp_domain'] = 'example.com'
2261    params['fils_realm'] = 'example.com'
2262    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
2263
2264    dev[0].scan_for_bss(bssid, freq=2412)
2265    dev[0].request("ERP_FLUSH")
2266    id = dev[0].connect("fils", key_mgmt="FILS-SHA256 FILS-SHA384",
2267                        eap="PSK", identity="psk.user@example.com",
2268                        password_hex="0123456789abcdef0123456789abcdef",
2269                        erp="1", scan_freq="2412")
2270    dev[0].request("DISCONNECT")
2271    dev[0].wait_disconnected()
2272    dev[0].request("RECONNECT")
2273    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
2274                            "CTRL-EVENT-CONNECTED"], timeout=10)
2275    if ev is None:
2276        raise Exception("Connection using FILS timed out")
2277    if "CTRL-EVENT-EAP-STARTED" in ev:
2278        raise Exception("Unexpected EAP exchange")
2279
2280    bssid2 = apdev[1]['bssid']
2281    params = hostapd.wpa2_eap_params(ssid="fils")
2282    params['wpa_key_mgmt'] = "FILS-SHA256 FILS-SHA384"
2283    params['auth_server_port'] = "18128"
2284    params['erp_domain'] = 'example.com'
2285    params['fils_realm'] = 'example.com'
2286    hapd2 = hostapd.add_ap(apdev[1]['ifname'], params)
2287
2288    dev[0].scan_for_bss(bssid2, freq=2412)
2289
2290    dev[0].dump_monitor()
2291    if "OK" not in dev[0].request("ROAM " + bssid2):
2292        raise Exception("ROAM failed")
2293
2294    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
2295                            "CTRL-EVENT-CONNECTED"], timeout=10)
2296    if ev is None:
2297        raise Exception("Roaming using FILS timed out")
2298    if "CTRL-EVENT-EAP-STARTED" in ev:
2299        raise Exception("Unexpected EAP exchange")
2300    if bssid2 not in ev:
2301        raise Exception("Failed to connect to the second AP")
2302
2303    hwsim_utils.test_connectivity(dev[0], hapd2)
2304
2305def test_fils_auth_ptk_rekey_ap_ext_key_id(dev, apdev, params):
2306    """PTK rekeying after FILS authentication triggered by AP (Ext Key ID)"""
2307    check_ext_key_id_capa(dev[0])
2308    try:
2309        dev[0].set("extended_key_id", "1")
2310        hapd = setup_fils_rekey(dev, apdev, params, wpa_ptk_rekey=2,
2311                                ext_key_id=True)
2312        check_ext_key_id_capa(hapd)
2313        idx = int(dev[0].request("GET last_tk_key_idx"))
2314        if idx != 0:
2315            raise Exception("Unexpected Key ID before TK rekey: %d" % idx)
2316        ev = dev[0].wait_event(["WPA: Key negotiation completed"], timeout=3)
2317        if ev is None:
2318            raise Exception("PTK rekey timed out")
2319        idx = int(dev[0].request("GET last_tk_key_idx"))
2320        if idx != 1:
2321            raise Exception("Unexpected Key ID after TK rekey: %d" % idx)
2322        hwsim_utils.test_connectivity(dev[0], hapd)
2323
2324        ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], timeout=1)
2325        if ev is not None:
2326            raise Exception("Rekeying failed - disconnected")
2327        hwsim_utils.test_connectivity(dev[0], hapd)
2328    finally:
2329        dev[0].set("extended_key_id", "0")
2330
2331def test_fils_discovery_frame(dev, apdev, params):
2332    """FILS Discovery frame generation"""
2333    check_fils_capa(dev[0])
2334    check_erp_capa(dev[0])
2335
2336    start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
2337
2338    bssid = apdev[0]['bssid']
2339    params = hostapd.wpa2_eap_params(ssid="fils")
2340    params['wpa_key_mgmt'] = "FILS-SHA256"
2341    params['auth_server_port'] = "18128"
2342    params['erp_send_reauth_start'] = '1'
2343    params['erp_domain'] = 'example.com'
2344    params['fils_realm'] = 'example.com'
2345    params['wpa_group_rekey'] = '1'
2346    params['fils_discovery_min_interval'] = '20'
2347    params['fils_discovery_max_interval'] = '20'
2348    hapd = hostapd.add_ap(apdev[0]['ifname'], params, no_enable=True)
2349
2350    if "OK" not in hapd.request("ENABLE"):
2351        raise HwsimSkip("FILS Discovery frame transmission not supported")
2352
2353    ev = hapd.wait_event(["AP-ENABLED", "AP-DISABLED"], timeout=5)
2354    if ev is None:
2355        raise Exception("AP startup timed out")
2356    if "AP-ENABLED" not in ev:
2357        raise Exception("AP startup failed")
2358
2359    dev[0].request("ERP_FLUSH")
2360    dev[0].connect("fils", key_mgmt="FILS-SHA256",
2361                   eap="PSK", identity="psk.user@example.com",
2362                   password_hex="0123456789abcdef0123456789abcdef",
2363                   erp="1", scan_freq="2412")
2364
2365def test_fils_offload_to_driver(dev, apdev, params):
2366    """FILS offload to driver"""
2367    check_fils_capa(dev[0])
2368    check_erp_capa(dev[0])
2369    run_fils_offload_to_driver(dev[0], apdev, params)
2370
2371def test_fils_offload_to_driver2(dev, apdev, params):
2372    """FILS offload to driver"""
2373    wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
2374    wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
2375    run_fils_offload_to_driver(wpas, apdev, params)
2376
2377def run_fils_offload_to_driver(dev, apdev, params):
2378    start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
2379
2380    bssid = apdev[0]['bssid']
2381    params = hostapd.wpa2_eap_params(ssid="fils")
2382    params['wpa_key_mgmt'] = "FILS-SHA256"
2383    params['auth_server_port'] = "18128"
2384    params['erp_send_reauth_start'] = '1'
2385    params['erp_domain'] = 'example.com'
2386    params['fils_realm'] = 'example.com'
2387    params['disable_pmksa_caching'] = '1'
2388    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
2389
2390    dev.request("ERP_FLUSH")
2391    id = dev.connect("fils", key_mgmt="FILS-SHA256",
2392                     eap="PSK", identity="psk.user@example.com",
2393                     password_hex="0123456789abcdef0123456789abcdef",
2394                     erp="1", scan_freq="2412")
2395
2396    p = "freq=2412 authorized=1 fils_erp_next_seq_num=4"
2397    if "OK" not in dev.request("DRIVER_EVENT ASSOC " + p):
2398        raise Exception("DRIVER_EVENT ASSOC did not succeed")
2399    dev.wait_connected()
2400
2401    dev.request("DISCONNECT")
2402    dev.wait_disconnected()
2403    dev.dump_monitor()
2404
2405    dev.select_network(id, freq=2412)
2406    dev.wait_connected()
2407    dev.dump_monitor()
2408
2409    # This does not really work properly with SME-in-wpa_supplicant case
2410    p = "freq=2412 authorized=1 fils_erp_next_seq_num=4"
2411    if "OK" not in dev.request("DRIVER_EVENT ASSOC " + p):
2412        raise Exception("DRIVER_EVENT ASSOC did not succeed")
2413
2414    dev.wait_connected()
2415
2416def test_fils_sk_okc(dev, apdev, params):
2417    """FILS SK and opportunistic key caching"""
2418    check_fils_capa(dev[0])
2419    check_erp_capa(dev[0])
2420
2421    start_erp_as(msk_dump=os.path.join(params['logdir'], "msk.lst"))
2422
2423    bssid = apdev[0]['bssid']
2424    params = hostapd.wpa2_eap_params(ssid="fils")
2425    params['wpa_key_mgmt'] = "FILS-SHA256"
2426    params['okc'] = '1'
2427    params['auth_server_port'] = "18128"
2428    params['erp_domain'] = 'example.com'
2429    params['fils_realm'] = 'example.com'
2430    hapd = hostapd.add_ap(apdev[0]['ifname'], params)
2431
2432    dev[0].scan_for_bss(bssid, freq=2412)
2433    dev[0].request("ERP_FLUSH")
2434    id = dev[0].connect("fils", key_mgmt="FILS-SHA256",
2435                        eap="PSK", identity="psk.user@example.com",
2436                        password_hex="0123456789abcdef0123456789abcdef",
2437                        erp="1", okc=True, scan_freq="2412")
2438    pmksa = dev[0].get_pmksa(bssid)
2439    if pmksa is None:
2440        raise Exception("No PMKSA cache entry created")
2441    hapd.wait_sta()
2442
2443    hapd2 = hostapd.add_ap(apdev[1], params)
2444    bssid2 = hapd2.own_addr()
2445
2446    dev[0].scan_for_bss(bssid2, freq=2412)
2447    if "OK" not in dev[0].request("ROAM " + bssid2):
2448        raise Exception("ROAM failed")
2449    ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED",
2450                            "CTRL-EVENT-CONNECTED"], timeout=10)
2451    if ev is None:
2452        raise Exception("Connection using OKC/PMKSA caching timed out")
2453    if "CTRL-EVENT-EAP-STARTED" in ev:
2454        raise Exception("Unexpected EAP exchange")
2455    hapd2.wait_sta()
2456    hwsim_utils.test_connectivity(dev[0], hapd2)
2457    pmksa2 = dev[0].get_pmksa(bssid2)
2458    if pmksa2 is None:
2459        raise Exception("No PMKSA cache entry found")
2460    if 'opportunistic' not in pmksa2 or pmksa2['opportunistic'] != '1':
2461        raise Exception("OKC not indicated in PMKSA entry")
2462    if pmksa['pmkid'] != pmksa2['pmkid']:
2463        raise Exception("Unexpected PMKID change")
2464