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