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