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