1 # Fast BSS Transition tests
2 # Copyright (c) 2013-2015, Jouni Malinen <j@w1.fi>
4 # This software may be distributed under the terms of the BSD license.
5 # See README for more details.
12 logger = logging.getLogger()
16 from utils import HwsimSkip, alloc_fail, fail_test, skip_with_fips
17 from wlantest import Wlantest
18 from test_ap_psk import check_mib, find_wpas_process, read_process_memory, verify_not_present, get_key_locations
21 params = { "wpa": "2",
22 "wpa_key_mgmt": "FT-PSK",
23 "rsn_pairwise": "CCMP" }
27 params = { "wpa": "3",
28 "wpa_key_mgmt": "WPA-PSK FT-PSK",
29 "wpa_pairwise": "TKIP",
30 "rsn_pairwise": "CCMP" }
33 def ft_params(rsn=True, ssid=None, passphrase=None):
35 params = ft_base_rsn()
37 params = ft_base_mixed()
41 params["wpa_passphrase"] = passphrase
43 params["mobility_domain"] = "a1b2"
44 params["r0_key_lifetime"] = "10000"
45 params["pmk_r1_push"] = "1"
46 params["reassociation_deadline"] = "1000"
49 def ft_params1(rsn=True, ssid=None, passphrase=None):
50 params = ft_params(rsn, ssid, passphrase)
51 params['nas_identifier'] = "nas1.w1.fi"
52 params['r1_key_holder'] = "000102030405"
53 params['r0kh'] = [ "02:00:00:00:03:00 nas1.w1.fi 100102030405060708090a0b0c0d0e0f",
54 "02:00:00:00:04:00 nas2.w1.fi 300102030405060708090a0b0c0d0e0f" ]
55 params['r1kh'] = "02:00:00:00:04:00 00:01:02:03:04:06 200102030405060708090a0b0c0d0e0f"
58 def ft_params2(rsn=True, ssid=None, passphrase=None):
59 params = ft_params(rsn, ssid, passphrase)
60 params['nas_identifier'] = "nas2.w1.fi"
61 params['r1_key_holder'] = "000102030406"
62 params['r0kh'] = [ "02:00:00:00:03:00 nas1.w1.fi 200102030405060708090a0b0c0d0e0f",
63 "02:00:00:00:04:00 nas2.w1.fi 000102030405060708090a0b0c0d0e0f" ]
64 params['r1kh'] = "02:00:00:00:03:00 00:01:02:03:04:05 300102030405060708090a0b0c0d0e0f"
67 def ft_params1_r0kh_mismatch(rsn=True, ssid=None, passphrase=None):
68 params = ft_params(rsn, ssid, passphrase)
69 params['nas_identifier'] = "nas1.w1.fi"
70 params['r1_key_holder'] = "000102030405"
71 params['r0kh'] = [ "02:00:00:00:03:00 nas1.w1.fi 100102030405060708090a0b0c0d0e0f",
72 "12:00:00:00:04:00 nas2.w1.fi 300102030405060708090a0b0c0d0e0f" ]
73 params['r1kh'] = "12:00:00:00:04:00 10:01:02:03:04:06 200102030405060708090a0b0c0d0e0f"
76 def ft_params2_incorrect_rrb_key(rsn=True, ssid=None, passphrase=None):
77 params = ft_params(rsn, ssid, passphrase)
78 params['nas_identifier'] = "nas2.w1.fi"
79 params['r1_key_holder'] = "000102030406"
80 params['r0kh'] = [ "02:00:00:00:03:00 nas1.w1.fi 200102030405060708090a0b0c0d0ef1",
81 "02:00:00:00:04:00 nas2.w1.fi 000102030405060708090a0b0c0d0ef2" ]
82 params['r1kh'] = "02:00:00:00:03:00 00:01:02:03:04:05 300102030405060708090a0b0c0d0ef3"
85 def ft_params2_r0kh_mismatch(rsn=True, ssid=None, passphrase=None):
86 params = ft_params(rsn, ssid, passphrase)
87 params['nas_identifier'] = "nas2.w1.fi"
88 params['r1_key_holder'] = "000102030406"
89 params['r0kh'] = [ "12:00:00:00:03:00 nas1.w1.fi 200102030405060708090a0b0c0d0e0f",
90 "02:00:00:00:04:00 nas2.w1.fi 000102030405060708090a0b0c0d0e0f" ]
91 params['r1kh'] = "12:00:00:00:03:00 10:01:02:03:04:05 300102030405060708090a0b0c0d0e0f"
94 def run_roams(dev, apdev, hapd0, hapd1, ssid, passphrase, over_ds=False,
95 sae=False, eap=False, fail_test=False, roams=1,
96 pairwise_cipher="CCMP", group_cipher="TKIP CCMP"):
97 logger.info("Connect to first AP")
99 dev.connect(ssid, key_mgmt="FT-EAP", proto="WPA2", ieee80211w="1",
100 eap="GPSK", identity="gpsk user",
101 password="abcdefghijklmnop0123456789abcdef",
103 pairwise=pairwise_cipher, group=group_cipher)
109 dev.connect(ssid, psk=passphrase, key_mgmt=key_mgmt, proto="WPA2",
110 ieee80211w="1", scan_freq="2412",
111 pairwise=pairwise_cipher, group=group_cipher)
112 if dev.get_status_field('bssid') == apdev[0]['bssid']:
122 hwsim_utils.test_connectivity(dev, hapd1ap)
124 dev.scan_for_bss(ap2['bssid'], freq="2412")
126 for i in range(0, roams):
127 logger.info("Roam to the second AP")
129 dev.roam_over_ds(ap2['bssid'], fail_test=fail_test)
131 dev.roam(ap2['bssid'], fail_test=fail_test)
134 if dev.get_status_field('bssid') != ap2['bssid']:
135 raise Exception("Did not connect to correct AP")
136 if i == 0 or i == roams - 1:
137 hwsim_utils.test_connectivity(dev, hapd2ap)
139 logger.info("Roam back to the first AP")
141 dev.roam_over_ds(ap1['bssid'])
143 dev.roam(ap1['bssid'])
144 if dev.get_status_field('bssid') != ap1['bssid']:
145 raise Exception("Did not connect to correct AP")
146 if i == 0 or i == roams - 1:
147 hwsim_utils.test_connectivity(dev, hapd1ap)
149 def test_ap_ft(dev, apdev):
152 passphrase="12345678"
154 params = ft_params1(ssid=ssid, passphrase=passphrase)
155 hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
156 params = ft_params2(ssid=ssid, passphrase=passphrase)
157 hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
159 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase)
160 if "[WPA2-FT/PSK-CCMP]" not in dev[0].request("SCAN_RESULTS"):
161 raise Exception("Scan results missing RSN element info")
163 def test_ap_ft_many(dev, apdev):
164 """WPA2-PSK-FT AP multiple times"""
166 passphrase="12345678"
168 params = ft_params1(ssid=ssid, passphrase=passphrase)
169 hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
170 params = ft_params2(ssid=ssid, passphrase=passphrase)
171 hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
173 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, roams=50)
175 def test_ap_ft_mixed(dev, apdev):
176 """WPA2-PSK-FT mixed-mode AP"""
177 ssid = "test-ft-mixed"
178 passphrase="12345678"
180 params = ft_params1(rsn=False, ssid=ssid, passphrase=passphrase)
181 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
182 key_mgmt = hapd.get_config()['key_mgmt']
183 vals = key_mgmt.split(' ')
184 if vals[0] != "WPA-PSK" or vals[1] != "FT-PSK":
185 raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
186 params = ft_params2(rsn=False, ssid=ssid, passphrase=passphrase)
187 hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
189 run_roams(dev[0], apdev, hapd, hapd1, ssid, passphrase)
191 def test_ap_ft_pmf(dev, apdev):
192 """WPA2-PSK-FT AP with PMF"""
194 passphrase="12345678"
196 params = ft_params1(ssid=ssid, passphrase=passphrase)
197 params["ieee80211w"] = "2";
198 hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
199 params = ft_params2(ssid=ssid, passphrase=passphrase)
200 params["ieee80211w"] = "2";
201 hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
203 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase)
205 def test_ap_ft_over_ds(dev, apdev):
206 """WPA2-PSK-FT AP over DS"""
208 passphrase="12345678"
210 params = ft_params1(ssid=ssid, passphrase=passphrase)
211 hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
212 params = ft_params2(ssid=ssid, passphrase=passphrase)
213 hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
215 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True)
216 check_mib(dev[0], [ ("dot11RSNAAuthenticationSuiteRequested", "00-0f-ac-4"),
217 ("dot11RSNAAuthenticationSuiteSelected", "00-0f-ac-4") ])
219 def test_ap_ft_over_ds_many(dev, apdev):
220 """WPA2-PSK-FT AP over DS multiple times"""
222 passphrase="12345678"
224 params = ft_params1(ssid=ssid, passphrase=passphrase)
225 hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
226 params = ft_params2(ssid=ssid, passphrase=passphrase)
227 hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
229 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
232 def test_ap_ft_over_ds_unknown_target(dev, apdev):
235 passphrase="12345678"
237 params = ft_params1(ssid=ssid, passphrase=passphrase)
238 hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
240 dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
242 dev[0].roam_over_ds("02:11:22:33:44:55", fail_test=True)
244 def test_ap_ft_over_ds_unexpected(dev, apdev):
245 """WPA2-PSK-FT AP over DS and unexpected response"""
247 passphrase="12345678"
249 params = ft_params1(ssid=ssid, passphrase=passphrase)
250 hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
251 params = ft_params2(ssid=ssid, passphrase=passphrase)
252 hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
254 dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
256 if dev[0].get_status_field('bssid') == apdev[0]['bssid']:
267 addr = dev[0].own_addr()
268 hapd1ap.set("ext_mgmt_frame_handling", "1")
269 logger.info("Foreign STA address")
273 msg['sa'] = ap1['bssid']
274 msg['bssid'] = ap1['bssid']
275 msg['payload'] = binascii.unhexlify("06021122334455660102030405060000")
278 logger.info("No over-the-DS in progress")
279 msg['payload'] = binascii.unhexlify("0602" + addr.replace(':', '') + "0102030405060000")
282 logger.info("Non-zero status code")
283 msg['payload'] = binascii.unhexlify("0602" + addr.replace(':', '') + "0102030405060100")
286 hapd1ap.dump_monitor()
288 dev[0].scan_for_bss(ap2['bssid'], freq="2412")
289 if "OK" not in dev[0].request("FT_DS " + ap2['bssid']):
290 raise Exception("FT_DS failed")
292 req = hapd1ap.mgmt_rx()
294 logger.info("Foreign Target AP")
295 msg['payload'] = binascii.unhexlify("0602" + addr.replace(':', '') + "0102030405060000")
298 addrs = addr.replace(':', '') + ap2['bssid'].replace(':', '')
300 logger.info("No IEs")
301 msg['payload'] = binascii.unhexlify("0602" + addrs + "0000")
304 logger.info("Invalid IEs (trigger parsing failure)")
305 msg['payload'] = binascii.unhexlify("0602" + addrs + "00003700")
308 logger.info("Too short MDIE")
309 msg['payload'] = binascii.unhexlify("0602" + addrs + "000036021122")
312 logger.info("Mobility domain mismatch")
313 msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603112201")
316 logger.info("No FTIE")
317 msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603a1b201")
320 logger.info("FTIE SNonce mismatch")
321 msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603a1b201375e0000" + "00000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "1000000000000000000000000000000000000000000000000000000000000001" + "030a6e6173322e77312e6669")
324 logger.info("No R0KH-ID subelem in FTIE")
325 snonce = binascii.hexlify(req['payload'][111:111+32])
326 msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603a1b20137520000" + "00000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + snonce)
329 logger.info("No R0KH-ID subelem mismatch in FTIE")
330 snonce = binascii.hexlify(req['payload'][111:111+32])
331 msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603a1b201375e0000" + "00000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + snonce + "030a11223344556677889900")
334 logger.info("No R1KH-ID subelem in FTIE")
335 r0khid = binascii.hexlify(req['payload'][145:145+10])
336 msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603a1b201375e0000" + "00000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + snonce + "030a" + r0khid)
339 logger.info("No RSNE")
340 r0khid = binascii.hexlify(req['payload'][145:145+10])
341 msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603a1b20137660000" + "00000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + snonce + "030a" + r0khid + "0106000102030405")
344 def test_ap_ft_pmf_over_ds(dev, apdev):
345 """WPA2-PSK-FT AP over DS with PMF"""
347 passphrase="12345678"
349 params = ft_params1(ssid=ssid, passphrase=passphrase)
350 params["ieee80211w"] = "2";
351 hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
352 params = ft_params2(ssid=ssid, passphrase=passphrase)
353 params["ieee80211w"] = "2";
354 hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
356 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True)
358 def test_ap_ft_over_ds_pull(dev, apdev):
359 """WPA2-PSK-FT AP over DS (pull PMK)"""
361 passphrase="12345678"
363 params = ft_params1(ssid=ssid, passphrase=passphrase)
364 params["pmk_r1_push"] = "0"
365 hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
366 params = ft_params2(ssid=ssid, passphrase=passphrase)
367 params["pmk_r1_push"] = "0"
368 hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
370 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True)
372 def test_ap_ft_sae(dev, apdev):
373 """WPA2-PSK-FT-SAE AP"""
374 if "SAE" not in dev[0].get_capability("auth_alg"):
375 raise HwsimSkip("SAE not supported")
377 passphrase="12345678"
379 params = ft_params1(ssid=ssid, passphrase=passphrase)
380 params['wpa_key_mgmt'] = "FT-SAE"
381 hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
382 params = ft_params2(ssid=ssid, passphrase=passphrase)
383 params['wpa_key_mgmt'] = "FT-SAE"
384 hapd = hostapd.add_ap(apdev[1]['ifname'], params)
385 key_mgmt = hapd.get_config()['key_mgmt']
386 if key_mgmt.split(' ')[0] != "FT-SAE":
387 raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
389 dev[0].request("SET sae_groups ")
390 run_roams(dev[0], apdev, hapd0, hapd, ssid, passphrase, sae=True)
392 def test_ap_ft_sae_over_ds(dev, apdev):
393 """WPA2-PSK-FT-SAE AP over DS"""
394 if "SAE" not in dev[0].get_capability("auth_alg"):
395 raise HwsimSkip("SAE not supported")
397 passphrase="12345678"
399 params = ft_params1(ssid=ssid, passphrase=passphrase)
400 params['wpa_key_mgmt'] = "FT-SAE"
401 hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
402 params = ft_params2(ssid=ssid, passphrase=passphrase)
403 params['wpa_key_mgmt'] = "FT-SAE"
404 hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
406 dev[0].request("SET sae_groups ")
407 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, sae=True,
410 def test_ap_ft_eap(dev, apdev):
413 passphrase="12345678"
415 radius = hostapd.radius_params()
416 params = ft_params1(ssid=ssid, passphrase=passphrase)
417 params['wpa_key_mgmt'] = "FT-EAP"
418 params["ieee8021x"] = "1"
419 params = dict(radius.items() + params.items())
420 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
421 key_mgmt = hapd.get_config()['key_mgmt']
422 if key_mgmt.split(' ')[0] != "FT-EAP":
423 raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
424 params = ft_params2(ssid=ssid, passphrase=passphrase)
425 params['wpa_key_mgmt'] = "FT-EAP"
426 params["ieee8021x"] = "1"
427 params = dict(radius.items() + params.items())
428 hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
430 run_roams(dev[0], apdev, hapd, hapd1, ssid, passphrase, eap=True)
431 if "[WPA2-FT/EAP-CCMP]" not in dev[0].request("SCAN_RESULTS"):
432 raise Exception("Scan results missing RSN element info")
433 check_mib(dev[0], [ ("dot11RSNAAuthenticationSuiteRequested", "00-0f-ac-3"),
434 ("dot11RSNAAuthenticationSuiteSelected", "00-0f-ac-3") ])
436 def test_ap_ft_eap_pull(dev, apdev):
437 """WPA2-EAP-FT AP (pull PMK)"""
439 passphrase="12345678"
441 radius = hostapd.radius_params()
442 params = ft_params1(ssid=ssid, passphrase=passphrase)
443 params['wpa_key_mgmt'] = "FT-EAP"
444 params["ieee8021x"] = "1"
445 params["pmk_r1_push"] = "0"
446 params = dict(radius.items() + params.items())
447 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
448 key_mgmt = hapd.get_config()['key_mgmt']
449 if key_mgmt.split(' ')[0] != "FT-EAP":
450 raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
451 params = ft_params2(ssid=ssid, passphrase=passphrase)
452 params['wpa_key_mgmt'] = "FT-EAP"
453 params["ieee8021x"] = "1"
454 params["pmk_r1_push"] = "0"
455 params = dict(radius.items() + params.items())
456 hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
458 run_roams(dev[0], apdev, hapd, hapd1, ssid, passphrase, eap=True)
460 def test_ap_ft_mismatching_rrb_key_push(dev, apdev):
461 """WPA2-PSK-FT AP over DS with mismatching RRB key (push)"""
463 passphrase="12345678"
465 params = ft_params1(ssid=ssid, passphrase=passphrase)
466 params["ieee80211w"] = "2";
467 hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
468 params = ft_params2_incorrect_rrb_key(ssid=ssid, passphrase=passphrase)
469 params["ieee80211w"] = "2";
470 hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
472 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
475 def test_ap_ft_mismatching_rrb_key_pull(dev, apdev):
476 """WPA2-PSK-FT AP over DS with mismatching RRB key (pull)"""
478 passphrase="12345678"
480 params = ft_params1(ssid=ssid, passphrase=passphrase)
481 params["pmk_r1_push"] = "0"
482 hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
483 params = ft_params2_incorrect_rrb_key(ssid=ssid, passphrase=passphrase)
484 params["pmk_r1_push"] = "0"
485 hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
487 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
490 def test_ap_ft_mismatching_r0kh_id_pull(dev, apdev):
491 """WPA2-PSK-FT AP over DS with mismatching R0KH-ID (pull)"""
493 passphrase="12345678"
495 params = ft_params1(ssid=ssid, passphrase=passphrase)
496 params["pmk_r1_push"] = "0"
497 params["nas_identifier"] = "nas0.w1.fi"
498 hostapd.add_ap(apdev[0]['ifname'], params)
499 dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
502 params = ft_params2(ssid=ssid, passphrase=passphrase)
503 params["pmk_r1_push"] = "0"
504 hostapd.add_ap(apdev[1]['ifname'], params)
506 dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
507 dev[0].roam_over_ds(apdev[1]['bssid'], fail_test=True)
509 def test_ap_ft_mismatching_rrb_r0kh_push(dev, apdev):
510 """WPA2-PSK-FT AP over DS with mismatching R0KH key (push)"""
512 passphrase="12345678"
514 params = ft_params1(ssid=ssid, passphrase=passphrase)
515 params["ieee80211w"] = "2";
516 hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
517 params = ft_params2_r0kh_mismatch(ssid=ssid, passphrase=passphrase)
518 params["ieee80211w"] = "2";
519 hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
521 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
524 def test_ap_ft_mismatching_rrb_r0kh_pull(dev, apdev):
525 """WPA2-PSK-FT AP over DS with mismatching R0KH key (pull)"""
527 passphrase="12345678"
529 params = ft_params1_r0kh_mismatch(ssid=ssid, passphrase=passphrase)
530 params["pmk_r1_push"] = "0"
531 hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
532 params = ft_params2(ssid=ssid, passphrase=passphrase)
533 params["pmk_r1_push"] = "0"
534 hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
536 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
539 def test_ap_ft_gtk_rekey(dev, apdev):
540 """WPA2-PSK-FT AP and GTK rekey"""
542 passphrase="12345678"
544 params = ft_params1(ssid=ssid, passphrase=passphrase)
545 params['wpa_group_rekey'] = '1'
546 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
548 dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
549 ieee80211w="1", scan_freq="2412")
551 ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=2)
553 raise Exception("GTK rekey timed out after initial association")
554 hwsim_utils.test_connectivity(dev[0], hapd)
556 params = ft_params2(ssid=ssid, passphrase=passphrase)
557 params['wpa_group_rekey'] = '1'
558 hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
560 dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
561 dev[0].roam(apdev[1]['bssid'])
562 if dev[0].get_status_field('bssid') != apdev[1]['bssid']:
563 raise Exception("Did not connect to correct AP")
564 hwsim_utils.test_connectivity(dev[0], hapd1)
566 ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=2)
568 raise Exception("GTK rekey timed out after FT protocol")
569 hwsim_utils.test_connectivity(dev[0], hapd1)
571 def test_ft_psk_key_lifetime_in_memory(dev, apdev, params):
572 """WPA2-PSK-FT and key lifetime in memory"""
574 passphrase="04c2726b4b8d5f1b4db9c07aa4d9e9d8f765cb5d25ec817e6cc4fcdd5255db0"
575 psk = '93c90846ff67af9037ed83fb72b63dbeddaa81d47f926c20909b5886f1d9358d'
576 pmk = binascii.unhexlify(psk)
577 p = ft_params1(ssid=ssid, passphrase=passphrase)
578 hapd0 = hostapd.add_ap(apdev[0]['ifname'], p)
579 p = ft_params2(ssid=ssid, passphrase=passphrase)
580 hapd1 = hostapd.add_ap(apdev[1]['ifname'], p)
582 pid = find_wpas_process(dev[0])
584 dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
588 buf = read_process_memory(pid, pmk)
590 dev[0].request("DISCONNECT")
591 dev[0].wait_disconnected()
598 with open(os.path.join(params['logdir'], 'log0'), 'r') as f:
599 for l in f.readlines():
600 if "FT: PMK-R0 - hexdump" in l:
601 val = l.strip().split(':')[3].replace(' ', '')
602 pmkr0 = binascii.unhexlify(val)
603 if "FT: PMK-R1 - hexdump" in l:
604 val = l.strip().split(':')[3].replace(' ', '')
605 pmkr1 = binascii.unhexlify(val)
606 if "FT: KCK - hexdump" in l:
607 val = l.strip().split(':')[3].replace(' ', '')
608 kck = binascii.unhexlify(val)
609 if "FT: KEK - hexdump" in l:
610 val = l.strip().split(':')[3].replace(' ', '')
611 kek = binascii.unhexlify(val)
612 if "FT: TK - hexdump" in l:
613 val = l.strip().split(':')[3].replace(' ', '')
614 tk = binascii.unhexlify(val)
615 if "WPA: Group Key - hexdump" in l:
616 val = l.strip().split(':')[3].replace(' ', '')
617 gtk = binascii.unhexlify(val)
618 if not pmkr0 or not pmkr1 or not kck or not kek or not tk or not gtk:
619 raise Exception("Could not find keys from debug log")
621 raise Exception("Unexpected GTK length")
623 logger.info("Checking keys in memory while associated")
624 get_key_locations(buf, pmk, "PMK")
625 get_key_locations(buf, pmkr0, "PMK-R0")
626 get_key_locations(buf, pmkr1, "PMK-R1")
628 raise HwsimSkip("PMK not found while associated")
630 raise HwsimSkip("PMK-R0 not found while associated")
632 raise HwsimSkip("PMK-R1 not found while associated")
634 raise Exception("KCK not found while associated")
636 raise Exception("KEK not found while associated")
638 raise Exception("TK found from memory")
640 raise Exception("GTK found from memory")
642 logger.info("Checking keys in memory after disassociation")
643 buf = read_process_memory(pid, pmk)
644 get_key_locations(buf, pmk, "PMK")
645 get_key_locations(buf, pmkr0, "PMK-R0")
646 get_key_locations(buf, pmkr1, "PMK-R1")
648 # Note: PMK/PSK is still present in network configuration
650 fname = os.path.join(params['logdir'],
651 'ft_psk_key_lifetime_in_memory.memctx-')
652 verify_not_present(buf, pmkr0, fname, "PMK-R0")
653 verify_not_present(buf, pmkr1, fname, "PMK-R1")
654 verify_not_present(buf, kck, fname, "KCK")
655 verify_not_present(buf, kek, fname, "KEK")
656 verify_not_present(buf, tk, fname, "TK")
657 verify_not_present(buf, gtk, fname, "GTK")
659 dev[0].request("REMOVE_NETWORK all")
661 logger.info("Checking keys in memory after network profile removal")
662 buf = read_process_memory(pid, pmk)
663 get_key_locations(buf, pmk, "PMK")
664 get_key_locations(buf, pmkr0, "PMK-R0")
665 get_key_locations(buf, pmkr1, "PMK-R1")
667 verify_not_present(buf, pmk, fname, "PMK")
668 verify_not_present(buf, pmkr0, fname, "PMK-R0")
669 verify_not_present(buf, pmkr1, fname, "PMK-R1")
670 verify_not_present(buf, kck, fname, "KCK")
671 verify_not_present(buf, kek, fname, "KEK")
672 verify_not_present(buf, tk, fname, "TK")
673 verify_not_present(buf, gtk, fname, "GTK")
675 def test_ap_ft_invalid_resp(dev, apdev):
676 """WPA2-PSK-FT AP and invalid response IEs"""
678 passphrase="12345678"
680 params = ft_params1(ssid=ssid, passphrase=passphrase)
681 hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
682 dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
685 params = ft_params2(ssid=ssid, passphrase=passphrase)
686 hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
689 # Various IEs for test coverage. The last one is FTIE with invalid
690 # R1KH-ID subelement.
691 "020002000000" + "3800" + "38051122334455" + "3754000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010100",
692 # FTIE with invalid R0KH-ID subelement (len=0).
693 "020002000000" + "3754000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010300",
694 # FTIE with invalid R0KH-ID subelement (len=49).
695 "020002000000" + "378500010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001033101020304050607080910111213141516171819202122232425262728293031323334353637383940414243444546474849",
697 "020002000000" + "3000",
698 # Required IEs missing from protected IE count.
699 "020002000000" + "3603a1b201" + "375200010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001" + "3900",
700 # RIC missing from protected IE count.
701 "020002000000" + "3603a1b201" + "375200020203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001" + "3900",
702 # Protected IE missing.
703 "020002000000" + "3603a1b201" + "375200ff0203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001" + "3900" + "0000" ]
705 dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
706 hapd1.set("ext_mgmt_frame_handling", "1")
708 if "OK" not in dev[0].request("ROAM " + apdev[1]['bssid']):
709 raise Exception("ROAM failed")
712 msg = hapd1.mgmt_rx()
713 if msg['subtype'] == 11:
717 raise Exception("Authentication frame not seen")
720 resp['fc'] = auth['fc']
721 resp['da'] = auth['sa']
722 resp['sa'] = auth['da']
723 resp['bssid'] = auth['bssid']
724 resp['payload'] = binascii.unhexlify(t)
726 hapd1.set("ext_mgmt_frame_handling", "0")
727 dev[0].wait_disconnected()
729 dev[0].request("RECONNECT")
730 dev[0].wait_connected()
732 def test_ap_ft_gcmp_256(dev, apdev):
733 """WPA2-PSK-FT AP with GCMP-256 cipher"""
734 if "GCMP-256" not in dev[0].get_capability("pairwise"):
735 raise HwsimSkip("Cipher GCMP-256 not supported")
737 passphrase="12345678"
739 params = ft_params1(ssid=ssid, passphrase=passphrase)
740 params['rsn_pairwise'] = "GCMP-256"
741 hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
742 params = ft_params2(ssid=ssid, passphrase=passphrase)
743 params['rsn_pairwise'] = "GCMP-256"
744 hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
746 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase,
747 pairwise_cipher="GCMP-256", group_cipher="GCMP-256")
749 def test_ap_ft_oom(dev, apdev):
750 """WPA2-PSK-FT and OOM"""
751 skip_with_fips(dev[0])
753 passphrase="12345678"
755 params = ft_params1(ssid=ssid, passphrase=passphrase)
756 hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
757 params = ft_params2(ssid=ssid, passphrase=passphrase)
758 hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
760 dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
762 if dev[0].get_status_field('bssid') == apdev[0]['bssid']:
763 dst = apdev[1]['bssid']
765 dst = apdev[0]['bssid']
767 dev[0].scan_for_bss(dst, freq="2412")
768 with alloc_fail(dev[0], 1, "wpa_ft_gen_req_ies"):
770 with alloc_fail(dev[0], 1, "wpa_ft_mic"):
771 dev[0].roam(dst, fail_test=True)
772 with fail_test(dev[0], 1, "os_get_random;wpa_ft_prepare_auth_request"):
773 dev[0].roam(dst, fail_test=True)
775 def test_ap_ft_over_ds_proto(dev, apdev):
776 """WPA2-PSK-FT AP over DS protocol testing"""
778 passphrase="12345678"
780 params = ft_params1(ssid=ssid, passphrase=passphrase)
781 hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
782 dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
785 # FT Action Response while no FT-over-DS in progress
788 msg['da'] = dev[0].own_addr()
789 msg['sa'] = apdev[0]['bssid']
790 msg['bssid'] = apdev[0]['bssid']
791 msg['payload'] = binascii.unhexlify("06020200000000000200000004000000")
794 params = ft_params2(ssid=ssid, passphrase=passphrase)
795 hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
796 dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
797 hapd0.set("ext_mgmt_frame_handling", "1")
799 dev[0].request("FT_DS " + apdev[1]['bssid'])
800 for i in range(0, 10):
801 req = hapd0.mgmt_rx()
803 raise Exception("MGMT RX wait timed out")
804 if req['subtype'] == 13:
808 raise Exception("FT Action frame not received")
810 # FT Action Response for unexpected Target AP
811 msg['payload'] = binascii.unhexlify("0602020000000000" + "f20000000400" + "0000")
814 # FT Action Response without MDIE
815 msg['payload'] = binascii.unhexlify("0602020000000000" + "020000000400" + "0000")
818 # FT Action Response without FTIE
819 msg['payload'] = binascii.unhexlify("0602020000000000" + "020000000400" + "0000" + "3603a1b201")
822 # FT Action Response with FTIE SNonce mismatch
823 msg['payload'] = binascii.unhexlify("0602020000000000" + "020000000400" + "0000" + "3603a1b201" + "3766000000000000000000000000000000000000c4e67ac1999bebd00ff4ae4d5dcaf87896bb060b469f7c78d49623fb395c3455ffffff6b693fe6f8d8c5dfac0a22344750775bd09437f98b238c9f87b97f790c0106000102030406030a6e6173312e77312e6669")
826 def test_ap_ft_rrb(dev, apdev):
827 """WPA2-PSK-FT RRB protocol testing"""
829 passphrase="12345678"
831 params = ft_params1(ssid=ssid, passphrase=passphrase)
832 hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
834 dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
837 _dst_ll = binascii.unhexlify(apdev[0]['bssid'].replace(':',''))
838 _src_ll = binascii.unhexlify(dev[0].own_addr().replace(':',''))
840 ehdr = _dst_ll + _src_ll + proto
842 # Too short RRB frame
844 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
845 raise Exception("DATA_TEST_FRAME failed")
847 # RRB discarded frame wikth unrecognized type
848 pkt = ehdr + '\x02' + '\x02' + '\x01\x00' + _src_ll
849 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
850 raise Exception("DATA_TEST_FRAME failed")
852 # RRB frame too short for action frame
853 pkt = ehdr + '\x01' + '\x02' + '\x01\x00' + _src_ll
854 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
855 raise Exception("DATA_TEST_FRAME failed")
857 # Too short RRB frame (not enough room for Action Frame body)
858 pkt = ehdr + '\x01' + '\x02' + '\x00\x00' + _src_ll
859 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
860 raise Exception("DATA_TEST_FRAME failed")
862 # Unexpected Action frame category
863 pkt = ehdr + '\x01' + '\x02' + '\x0e\x00' + _src_ll + '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
864 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
865 raise Exception("DATA_TEST_FRAME failed")
867 # Unexpected Action in RRB Request
868 pkt = ehdr + '\x01' + '\x00' + '\x0e\x00' + _src_ll + '\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
869 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
870 raise Exception("DATA_TEST_FRAME failed")
872 # Target AP address in RRB Request does not match with own address
873 pkt = ehdr + '\x01' + '\x00' + '\x0e\x00' + _src_ll + '\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
874 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
875 raise Exception("DATA_TEST_FRAME failed")
877 # Not enough room for status code in RRB Response
878 pkt = ehdr + '\x01' + '\x01' + '\x0e\x00' + _src_ll + '\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
879 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
880 raise Exception("DATA_TEST_FRAME failed")
882 # RRB discarded frame with unknown packet_type
883 pkt = ehdr + '\x01' + '\x02' + '\x0e\x00' + _src_ll + '\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
884 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
885 raise Exception("DATA_TEST_FRAME failed")
887 # RRB Response with non-zero status code; no STA match
888 pkt = ehdr + '\x01' + '\x01' + '\x10\x00' + _src_ll + '\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + '\xff\xff'
889 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
890 raise Exception("DATA_TEST_FRAME failed")
892 # RRB Response with zero status code and extra data; STA match
893 pkt = ehdr + '\x01' + '\x01' + '\x11\x00' + _src_ll + '\x06\x01' + _src_ll + '\x00\x00\x00\x00\x00\x00' + '\x00\x00' + '\x00'
894 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
895 raise Exception("DATA_TEST_FRAME failed")
897 # Too short PMK-R1 pull
898 pkt = ehdr + '\x01' + '\xc8' + '\x0e\x00' + _src_ll + '\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
899 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
900 raise Exception("DATA_TEST_FRAME failed")
902 # Too short PMK-R1 resp
903 pkt = ehdr + '\x01' + '\xc9' + '\x0e\x00' + _src_ll + '\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
904 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
905 raise Exception("DATA_TEST_FRAME failed")
907 # Too short PMK-R1 push
908 pkt = ehdr + '\x01' + '\xca' + '\x0e\x00' + _src_ll + '\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
909 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
910 raise Exception("DATA_TEST_FRAME failed")
912 # No matching R0KH address found for PMK-R0 pull response
913 pkt = ehdr + '\x01' + '\xc9' + '\x5a\x00' + _src_ll + '\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + 76*'\00'
914 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
915 raise Exception("DATA_TEST_FRAME failed")
917 def test_rsn_ie_proto_ft_psk_sta(dev, apdev):
918 """RSN element protocol testing for FT-PSK + PMF cases on STA side"""
919 bssid = apdev[0]['bssid']
921 passphrase="12345678"
923 params = ft_params1(ssid=ssid, passphrase=passphrase)
924 params["ieee80211w"] = "1";
925 # This is the RSN element used normally by hostapd
926 params['own_ie_override'] = '30140100000fac040100000fac040100000fac048c00' + '3603a1b201'
927 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
928 id = dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
929 ieee80211w="1", scan_freq="2412",
930 pairwise="CCMP", group="CCMP")
932 tests = [ ('PMKIDCount field included',
933 '30160100000fac040100000fac040100000fac048c000000' + '3603a1b201'),
934 ('Extra IE before RSNE',
935 'dd0400000000' + '30140100000fac040100000fac040100000fac048c00' + '3603a1b201'),
936 ('PMKIDCount and Group Management Cipher suite fields included',
937 '301a0100000fac040100000fac040100000fac048c000000000fac06' + '3603a1b201'),
938 ('Extra octet after defined fields (future extensibility)',
939 '301b0100000fac040100000fac040100000fac048c000000000fac0600' + '3603a1b201'),
940 ('No RSN Capabilities field (PMF disabled in practice)',
941 '30120100000fac040100000fac040100000fac04' + '3603a1b201') ]
943 dev[0].request("DISCONNECT")
944 dev[0].wait_disconnected()
947 hapd.set('own_ie_override', ie)
949 dev[0].request("BSS_FLUSH 0")
950 dev[0].scan_for_bss(bssid, 2412, force_scan=True, only_new=True)
951 dev[0].select_network(id, freq=2412)
952 dev[0].wait_connected()
954 dev[0].request("DISCONNECT")
955 dev[0].wait_disconnected()
957 logger.info('Invalid RSNE causing internal hostapd error')
959 hapd.set('own_ie_override', '30130100000fac040100000fac040100000fac048c' + '3603a1b201')
961 dev[0].request("BSS_FLUSH 0")
962 dev[0].scan_for_bss(bssid, 2412, force_scan=True, only_new=True)
963 dev[0].select_network(id, freq=2412)
964 # hostapd fails to generate EAPOL-Key msg 3/4, so this connection cannot
966 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
968 raise Exception("Unexpected connection")
969 dev[0].request("DISCONNECT")
971 logger.info('Unexpected PMKID causing internal hostapd error')
973 hapd.set('own_ie_override', '30260100000fac040100000fac040100000fac048c000100ffffffffffffffffffffffffffffffff' + '3603a1b201')
975 dev[0].request("BSS_FLUSH 0")
976 dev[0].scan_for_bss(bssid, 2412, force_scan=True, only_new=True)
977 dev[0].select_network(id, freq=2412)
978 # hostapd fails to generate EAPOL-Key msg 3/4, so this connection cannot
980 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
982 raise Exception("Unexpected connection")
983 dev[0].request("DISCONNECT")