]> git.ipfire.org Git - thirdparty/hostap.git/blame - tests/hwsim/test_ap_ft.py
tests: Clear scan cache at the end of ap_wps_per_station_psk_failure
[thirdparty/hostap.git] / tests / hwsim / test_ap_ft.py
CommitLineData
cd7f1b9a 1# Fast BSS Transition tests
34d3eaa8 2# Copyright (c) 2013-2015, Jouni Malinen <j@w1.fi>
cd7f1b9a
JM
3#
4# This software may be distributed under the terms of the BSD license.
5# See README for more details.
6
9fd6804d 7from remotehost import remote_compatible
5b3c40a6
JM
8import binascii
9import os
cd7f1b9a 10import time
cd7f1b9a 11import logging
c9aa4308 12logger = logging.getLogger()
cd7f1b9a
JM
13
14import hwsim_utils
15import hostapd
38934ed1 16from utils import HwsimSkip, alloc_fail, fail_test, skip_with_fips
cd7f1b9a 17from wlantest import Wlantest
5b3c40a6 18from test_ap_psk import check_mib, find_wpas_process, read_process_memory, verify_not_present, get_key_locations
cd7f1b9a
JM
19
20def ft_base_rsn():
21 params = { "wpa": "2",
22 "wpa_key_mgmt": "FT-PSK",
23 "rsn_pairwise": "CCMP" }
24 return params
25
26def ft_base_mixed():
27 params = { "wpa": "3",
28 "wpa_key_mgmt": "WPA-PSK FT-PSK",
29 "wpa_pairwise": "TKIP",
30 "rsn_pairwise": "CCMP" }
31 return params
32
33def ft_params(rsn=True, ssid=None, passphrase=None):
34 if rsn:
35 params = ft_base_rsn()
36 else:
37 params = ft_base_mixed()
38 if ssid:
39 params["ssid"] = ssid
40 if passphrase:
41 params["wpa_passphrase"] = passphrase
42
43 params["mobility_domain"] = "a1b2"
44 params["r0_key_lifetime"] = "10000"
45 params["pmk_r1_push"] = "1"
46 params["reassociation_deadline"] = "1000"
47 return params
48
d0175d6e 49def ft_params1a(rsn=True, ssid=None, passphrase=None):
cd7f1b9a
JM
50 params = ft_params(rsn, ssid, passphrase)
51 params['nas_identifier'] = "nas1.w1.fi"
52 params['r1_key_holder'] = "000102030405"
d0175d6e
MB
53 return params
54
55def ft_params1(rsn=True, ssid=None, passphrase=None):
56 params = ft_params1a(rsn, ssid, passphrase)
cd7f1b9a
JM
57 params['r0kh'] = [ "02:00:00:00:03:00 nas1.w1.fi 100102030405060708090a0b0c0d0e0f",
58 "02:00:00:00:04:00 nas2.w1.fi 300102030405060708090a0b0c0d0e0f" ]
59 params['r1kh'] = "02:00:00:00:04:00 00:01:02:03:04:06 200102030405060708090a0b0c0d0e0f"
60 return params
61
d0175d6e 62def ft_params2a(rsn=True, ssid=None, passphrase=None):
cd7f1b9a
JM
63 params = ft_params(rsn, ssid, passphrase)
64 params['nas_identifier'] = "nas2.w1.fi"
65 params['r1_key_holder'] = "000102030406"
d0175d6e
MB
66 return params
67
68def ft_params2(rsn=True, ssid=None, passphrase=None):
69 params = ft_params2a(rsn, ssid, passphrase)
cd7f1b9a
JM
70 params['r0kh'] = [ "02:00:00:00:03:00 nas1.w1.fi 200102030405060708090a0b0c0d0e0f",
71 "02:00:00:00:04:00 nas2.w1.fi 000102030405060708090a0b0c0d0e0f" ]
72 params['r1kh'] = "02:00:00:00:03:00 00:01:02:03:04:05 300102030405060708090a0b0c0d0e0f"
73 return params
74
3b808945
JM
75def ft_params1_r0kh_mismatch(rsn=True, ssid=None, passphrase=None):
76 params = ft_params(rsn, ssid, passphrase)
77 params['nas_identifier'] = "nas1.w1.fi"
78 params['r1_key_holder'] = "000102030405"
79 params['r0kh'] = [ "02:00:00:00:03:00 nas1.w1.fi 100102030405060708090a0b0c0d0e0f",
80 "12:00:00:00:04:00 nas2.w1.fi 300102030405060708090a0b0c0d0e0f" ]
81 params['r1kh'] = "12:00:00:00:04:00 10:01:02:03:04:06 200102030405060708090a0b0c0d0e0f"
82 return params
83
84def ft_params2_incorrect_rrb_key(rsn=True, ssid=None, passphrase=None):
85 params = ft_params(rsn, ssid, passphrase)
86 params['nas_identifier'] = "nas2.w1.fi"
87 params['r1_key_holder'] = "000102030406"
88 params['r0kh'] = [ "02:00:00:00:03:00 nas1.w1.fi 200102030405060708090a0b0c0d0ef1",
89 "02:00:00:00:04:00 nas2.w1.fi 000102030405060708090a0b0c0d0ef2" ]
90 params['r1kh'] = "02:00:00:00:03:00 00:01:02:03:04:05 300102030405060708090a0b0c0d0ef3"
91 return params
92
93def ft_params2_r0kh_mismatch(rsn=True, ssid=None, passphrase=None):
94 params = ft_params(rsn, ssid, passphrase)
95 params['nas_identifier'] = "nas2.w1.fi"
96 params['r1_key_holder'] = "000102030406"
97 params['r0kh'] = [ "12:00:00:00:03:00 nas1.w1.fi 200102030405060708090a0b0c0d0e0f",
98 "02:00:00:00:04:00 nas2.w1.fi 000102030405060708090a0b0c0d0e0f" ]
99 params['r1kh'] = "12:00:00:00:03:00 10:01:02:03:04:05 300102030405060708090a0b0c0d0e0f"
100 return params
101
7b741a53
JM
102def run_roams(dev, apdev, hapd0, hapd1, ssid, passphrase, over_ds=False,
103 sae=False, eap=False, fail_test=False, roams=1,
1025603b 104 pairwise_cipher="CCMP", group_cipher="TKIP CCMP", ptk_rekey="0"):
cd7f1b9a 105 logger.info("Connect to first AP")
6f62809b
JM
106 if eap:
107 dev.connect(ssid, key_mgmt="FT-EAP", proto="WPA2", ieee80211w="1",
2f816c21
JM
108 eap="GPSK", identity="gpsk user",
109 password="abcdefghijklmnop0123456789abcdef",
7b741a53 110 scan_freq="2412",
1025603b
JM
111 pairwise=pairwise_cipher, group=group_cipher,
112 wpa_ptk_rekey=ptk_rekey)
6e658cc4 113 else:
6f62809b
JM
114 if sae:
115 key_mgmt="FT-SAE"
116 else:
117 key_mgmt="FT-PSK"
118 dev.connect(ssid, psk=passphrase, key_mgmt=key_mgmt, proto="WPA2",
7b741a53 119 ieee80211w="1", scan_freq="2412",
1025603b
JM
120 pairwise=pairwise_cipher, group=group_cipher,
121 wpa_ptk_rekey=ptk_rekey)
cd7f1b9a
JM
122 if dev.get_status_field('bssid') == apdev[0]['bssid']:
123 ap1 = apdev[0]
124 ap2 = apdev[1]
a8375c94
JM
125 hapd1ap = hapd0
126 hapd2ap = hapd1
cd7f1b9a
JM
127 else:
128 ap1 = apdev[1]
129 ap2 = apdev[0]
a8375c94
JM
130 hapd1ap = hapd1
131 hapd2ap = hapd0
132 hwsim_utils.test_connectivity(dev, hapd1ap)
cd7f1b9a 133
655bc8bf 134 dev.scan_for_bss(ap2['bssid'], freq="2412")
40602101
JM
135
136 for i in range(0, roams):
137 logger.info("Roam to the second AP")
138 if over_ds:
139 dev.roam_over_ds(ap2['bssid'], fail_test=fail_test)
140 else:
141 dev.roam(ap2['bssid'], fail_test=fail_test)
142 if fail_test:
143 return
144 if dev.get_status_field('bssid') != ap2['bssid']:
145 raise Exception("Did not connect to correct AP")
146 if i == 0 or i == roams - 1:
a8375c94 147 hwsim_utils.test_connectivity(dev, hapd2ap)
40602101
JM
148
149 logger.info("Roam back to the first AP")
150 if over_ds:
151 dev.roam_over_ds(ap1['bssid'])
152 else:
153 dev.roam(ap1['bssid'])
154 if dev.get_status_field('bssid') != ap1['bssid']:
155 raise Exception("Did not connect to correct AP")
156 if i == 0 or i == roams - 1:
a8375c94 157 hwsim_utils.test_connectivity(dev, hapd1ap)
cd7f1b9a
JM
158
159def test_ap_ft(dev, apdev):
160 """WPA2-PSK-FT AP"""
161 ssid = "test-ft"
162 passphrase="12345678"
163
164 params = ft_params1(ssid=ssid, passphrase=passphrase)
8b8a1864 165 hapd0 = hostapd.add_ap(apdev[0], params)
cd7f1b9a 166 params = ft_params2(ssid=ssid, passphrase=passphrase)
8b8a1864 167 hapd1 = hostapd.add_ap(apdev[1], params)
cd7f1b9a 168
a8375c94 169 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase)
91bc6c36
JM
170 if "[WPA2-FT/PSK-CCMP]" not in dev[0].request("SCAN_RESULTS"):
171 raise Exception("Scan results missing RSN element info")
cd7f1b9a 172
d0175d6e
MB
173def test_ap_ft_local_key_gen(dev, apdev):
174 """WPA2-PSK-FT AP with local key generation (without pull/push)"""
175 ssid = "test-ft"
176 passphrase="12345678"
177
178 params = ft_params1a(ssid=ssid, passphrase=passphrase)
179 params['ft_psk_generate_local'] = "1";
180 hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
181 params = ft_params2a(ssid=ssid, passphrase=passphrase)
182 params['ft_psk_generate_local'] = "1";
183 hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
184
185 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase)
186 if "[WPA2-FT/PSK-CCMP]" not in dev[0].request("SCAN_RESULTS"):
187 raise Exception("Scan results missing RSN element info")
188
40602101
JM
189def test_ap_ft_many(dev, apdev):
190 """WPA2-PSK-FT AP multiple times"""
191 ssid = "test-ft"
192 passphrase="12345678"
193
194 params = ft_params1(ssid=ssid, passphrase=passphrase)
8b8a1864 195 hapd0 = hostapd.add_ap(apdev[0], params)
40602101 196 params = ft_params2(ssid=ssid, passphrase=passphrase)
8b8a1864 197 hapd1 = hostapd.add_ap(apdev[1], params)
40602101 198
a8375c94 199 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, roams=50)
40602101 200
cd7f1b9a
JM
201def test_ap_ft_mixed(dev, apdev):
202 """WPA2-PSK-FT mixed-mode AP"""
203 ssid = "test-ft-mixed"
204 passphrase="12345678"
205
206 params = ft_params1(rsn=False, ssid=ssid, passphrase=passphrase)
8b8a1864 207 hapd = hostapd.add_ap(apdev[0], params)
65038313
JM
208 key_mgmt = hapd.get_config()['key_mgmt']
209 vals = key_mgmt.split(' ')
210 if vals[0] != "WPA-PSK" or vals[1] != "FT-PSK":
211 raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
cd7f1b9a 212 params = ft_params2(rsn=False, ssid=ssid, passphrase=passphrase)
8b8a1864 213 hapd1 = hostapd.add_ap(apdev[1], params)
cd7f1b9a 214
a8375c94 215 run_roams(dev[0], apdev, hapd, hapd1, ssid, passphrase)
cd7f1b9a
JM
216
217def test_ap_ft_pmf(dev, apdev):
218 """WPA2-PSK-FT AP with PMF"""
219 ssid = "test-ft"
220 passphrase="12345678"
221
222 params = ft_params1(ssid=ssid, passphrase=passphrase)
bc6e3288 223 params["ieee80211w"] = "2"
8b8a1864 224 hapd0 = hostapd.add_ap(apdev[0], params)
cd7f1b9a 225 params = ft_params2(ssid=ssid, passphrase=passphrase)
bc6e3288 226 params["ieee80211w"] = "2"
8b8a1864 227 hapd1 = hostapd.add_ap(apdev[1], params)
cd7f1b9a 228
a8375c94 229 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase)
b553eab1
JM
230
231def test_ap_ft_over_ds(dev, apdev):
232 """WPA2-PSK-FT AP over DS"""
233 ssid = "test-ft"
234 passphrase="12345678"
235
236 params = ft_params1(ssid=ssid, passphrase=passphrase)
8b8a1864 237 hapd0 = hostapd.add_ap(apdev[0], params)
b553eab1 238 params = ft_params2(ssid=ssid, passphrase=passphrase)
8b8a1864 239 hapd1 = hostapd.add_ap(apdev[1], params)
b553eab1 240
a8375c94 241 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True)
eaf3f9b1
JM
242 check_mib(dev[0], [ ("dot11RSNAAuthenticationSuiteRequested", "00-0f-ac-4"),
243 ("dot11RSNAAuthenticationSuiteSelected", "00-0f-ac-4") ])
b553eab1 244
40602101
JM
245def test_ap_ft_over_ds_many(dev, apdev):
246 """WPA2-PSK-FT AP over DS multiple times"""
247 ssid = "test-ft"
248 passphrase="12345678"
249
250 params = ft_params1(ssid=ssid, passphrase=passphrase)
8b8a1864 251 hapd0 = hostapd.add_ap(apdev[0], params)
40602101 252 params = ft_params2(ssid=ssid, passphrase=passphrase)
8b8a1864 253 hapd1 = hostapd.add_ap(apdev[1], params)
40602101 254
a8375c94
JM
255 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
256 roams=50)
40602101 257
9fd6804d 258@remote_compatible
c337d07a
JM
259def test_ap_ft_over_ds_unknown_target(dev, apdev):
260 """WPA2-PSK-FT AP"""
261 ssid = "test-ft"
262 passphrase="12345678"
263
264 params = ft_params1(ssid=ssid, passphrase=passphrase)
8b8a1864 265 hapd0 = hostapd.add_ap(apdev[0], params)
c337d07a
JM
266
267 dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
268 scan_freq="2412")
269 dev[0].roam_over_ds("02:11:22:33:44:55", fail_test=True)
270
9fd6804d 271@remote_compatible
211bb7c5
JM
272def test_ap_ft_over_ds_unexpected(dev, apdev):
273 """WPA2-PSK-FT AP over DS and unexpected response"""
274 ssid = "test-ft"
275 passphrase="12345678"
276
277 params = ft_params1(ssid=ssid, passphrase=passphrase)
8b8a1864 278 hapd0 = hostapd.add_ap(apdev[0], params)
211bb7c5 279 params = ft_params2(ssid=ssid, passphrase=passphrase)
8b8a1864 280 hapd1 = hostapd.add_ap(apdev[1], params)
211bb7c5
JM
281
282 dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
283 scan_freq="2412")
284 if dev[0].get_status_field('bssid') == apdev[0]['bssid']:
285 ap1 = apdev[0]
286 ap2 = apdev[1]
287 hapd1ap = hapd0
288 hapd2ap = hapd1
289 else:
290 ap1 = apdev[1]
291 ap2 = apdev[0]
292 hapd1ap = hapd1
293 hapd2ap = hapd0
294
295 addr = dev[0].own_addr()
296 hapd1ap.set("ext_mgmt_frame_handling", "1")
297 logger.info("Foreign STA address")
298 msg = {}
299 msg['fc'] = 13 << 4
300 msg['da'] = addr
301 msg['sa'] = ap1['bssid']
302 msg['bssid'] = ap1['bssid']
303 msg['payload'] = binascii.unhexlify("06021122334455660102030405060000")
304 hapd1ap.mgmt_tx(msg)
305
306 logger.info("No over-the-DS in progress")
307 msg['payload'] = binascii.unhexlify("0602" + addr.replace(':', '') + "0102030405060000")
308 hapd1ap.mgmt_tx(msg)
309
310 logger.info("Non-zero status code")
311 msg['payload'] = binascii.unhexlify("0602" + addr.replace(':', '') + "0102030405060100")
312 hapd1ap.mgmt_tx(msg)
313
314 hapd1ap.dump_monitor()
315
316 dev[0].scan_for_bss(ap2['bssid'], freq="2412")
317 if "OK" not in dev[0].request("FT_DS " + ap2['bssid']):
318 raise Exception("FT_DS failed")
319
320 req = hapd1ap.mgmt_rx()
321
322 logger.info("Foreign Target AP")
323 msg['payload'] = binascii.unhexlify("0602" + addr.replace(':', '') + "0102030405060000")
324 hapd1ap.mgmt_tx(msg)
325
326 addrs = addr.replace(':', '') + ap2['bssid'].replace(':', '')
327
328 logger.info("No IEs")
329 msg['payload'] = binascii.unhexlify("0602" + addrs + "0000")
330 hapd1ap.mgmt_tx(msg)
331
332 logger.info("Invalid IEs (trigger parsing failure)")
333 msg['payload'] = binascii.unhexlify("0602" + addrs + "00003700")
334 hapd1ap.mgmt_tx(msg)
335
336 logger.info("Too short MDIE")
337 msg['payload'] = binascii.unhexlify("0602" + addrs + "000036021122")
338 hapd1ap.mgmt_tx(msg)
339
340 logger.info("Mobility domain mismatch")
341 msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603112201")
342 hapd1ap.mgmt_tx(msg)
343
344 logger.info("No FTIE")
345 msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603a1b201")
346 hapd1ap.mgmt_tx(msg)
347
348 logger.info("FTIE SNonce mismatch")
349 msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603a1b201375e0000" + "00000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + "1000000000000000000000000000000000000000000000000000000000000001" + "030a6e6173322e77312e6669")
350 hapd1ap.mgmt_tx(msg)
351
352 logger.info("No R0KH-ID subelem in FTIE")
353 snonce = binascii.hexlify(req['payload'][111:111+32])
354 msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603a1b20137520000" + "00000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + snonce)
355 hapd1ap.mgmt_tx(msg)
356
357 logger.info("No R0KH-ID subelem mismatch in FTIE")
358 snonce = binascii.hexlify(req['payload'][111:111+32])
359 msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603a1b201375e0000" + "00000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + snonce + "030a11223344556677889900")
360 hapd1ap.mgmt_tx(msg)
361
362 logger.info("No R1KH-ID subelem in FTIE")
363 r0khid = binascii.hexlify(req['payload'][145:145+10])
364 msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603a1b201375e0000" + "00000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + snonce + "030a" + r0khid)
365 hapd1ap.mgmt_tx(msg)
366
367 logger.info("No RSNE")
368 r0khid = binascii.hexlify(req['payload'][145:145+10])
369 msg['payload'] = binascii.unhexlify("0602" + addrs + "00003603a1b20137660000" + "00000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000" + snonce + "030a" + r0khid + "0106000102030405")
370 hapd1ap.mgmt_tx(msg)
371
b553eab1
JM
372def test_ap_ft_pmf_over_ds(dev, apdev):
373 """WPA2-PSK-FT AP over DS with PMF"""
374 ssid = "test-ft"
375 passphrase="12345678"
376
377 params = ft_params1(ssid=ssid, passphrase=passphrase)
bc6e3288 378 params["ieee80211w"] = "2"
8b8a1864 379 hapd0 = hostapd.add_ap(apdev[0], params)
b553eab1 380 params = ft_params2(ssid=ssid, passphrase=passphrase)
bc6e3288 381 params["ieee80211w"] = "2"
8b8a1864 382 hapd1 = hostapd.add_ap(apdev[1], params)
b553eab1 383
a8375c94 384 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True)
6e658cc4 385
aaba98d3
JM
386def test_ap_ft_over_ds_pull(dev, apdev):
387 """WPA2-PSK-FT AP over DS (pull PMK)"""
388 ssid = "test-ft"
389 passphrase="12345678"
390
391 params = ft_params1(ssid=ssid, passphrase=passphrase)
392 params["pmk_r1_push"] = "0"
8b8a1864 393 hapd0 = hostapd.add_ap(apdev[0], params)
aaba98d3
JM
394 params = ft_params2(ssid=ssid, passphrase=passphrase)
395 params["pmk_r1_push"] = "0"
8b8a1864 396 hapd1 = hostapd.add_ap(apdev[1], params)
aaba98d3 397
a8375c94 398 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True)
aaba98d3 399
6e658cc4
JM
400def test_ap_ft_sae(dev, apdev):
401 """WPA2-PSK-FT-SAE AP"""
b9749b6a
JM
402 if "SAE" not in dev[0].get_capability("auth_alg"):
403 raise HwsimSkip("SAE not supported")
6e658cc4
JM
404 ssid = "test-ft"
405 passphrase="12345678"
406
407 params = ft_params1(ssid=ssid, passphrase=passphrase)
408 params['wpa_key_mgmt'] = "FT-SAE"
8b8a1864 409 hapd0 = hostapd.add_ap(apdev[0], params)
6e658cc4
JM
410 params = ft_params2(ssid=ssid, passphrase=passphrase)
411 params['wpa_key_mgmt'] = "FT-SAE"
8b8a1864 412 hapd = hostapd.add_ap(apdev[1], params)
65038313
JM
413 key_mgmt = hapd.get_config()['key_mgmt']
414 if key_mgmt.split(' ')[0] != "FT-SAE":
415 raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
6e658cc4 416
17ffdf39 417 dev[0].request("SET sae_groups ")
a8375c94 418 run_roams(dev[0], apdev, hapd0, hapd, ssid, passphrase, sae=True)
6e658cc4
JM
419
420def test_ap_ft_sae_over_ds(dev, apdev):
421 """WPA2-PSK-FT-SAE AP over DS"""
b9749b6a
JM
422 if "SAE" not in dev[0].get_capability("auth_alg"):
423 raise HwsimSkip("SAE not supported")
6e658cc4
JM
424 ssid = "test-ft"
425 passphrase="12345678"
426
427 params = ft_params1(ssid=ssid, passphrase=passphrase)
428 params['wpa_key_mgmt'] = "FT-SAE"
8b8a1864 429 hapd0 = hostapd.add_ap(apdev[0], params)
6e658cc4
JM
430 params = ft_params2(ssid=ssid, passphrase=passphrase)
431 params['wpa_key_mgmt'] = "FT-SAE"
8b8a1864 432 hapd1 = hostapd.add_ap(apdev[1], params)
6e658cc4 433
17ffdf39 434 dev[0].request("SET sae_groups ")
a8375c94
JM
435 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, sae=True,
436 over_ds=True)
6f62809b
JM
437
438def test_ap_ft_eap(dev, apdev):
439 """WPA2-EAP-FT AP"""
440 ssid = "test-ft"
441 passphrase="12345678"
442
443 radius = hostapd.radius_params()
444 params = ft_params1(ssid=ssid, passphrase=passphrase)
445 params['wpa_key_mgmt'] = "FT-EAP"
446 params["ieee8021x"] = "1"
447 params = dict(radius.items() + params.items())
8b8a1864 448 hapd = hostapd.add_ap(apdev[0], params)
65038313
JM
449 key_mgmt = hapd.get_config()['key_mgmt']
450 if key_mgmt.split(' ')[0] != "FT-EAP":
451 raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
6f62809b
JM
452 params = ft_params2(ssid=ssid, passphrase=passphrase)
453 params['wpa_key_mgmt'] = "FT-EAP"
454 params["ieee8021x"] = "1"
455 params = dict(radius.items() + params.items())
8b8a1864 456 hapd1 = hostapd.add_ap(apdev[1], params)
6f62809b 457
a8375c94 458 run_roams(dev[0], apdev, hapd, hapd1, ssid, passphrase, eap=True)
91bc6c36
JM
459 if "[WPA2-FT/EAP-CCMP]" not in dev[0].request("SCAN_RESULTS"):
460 raise Exception("Scan results missing RSN element info")
eaf3f9b1
JM
461 check_mib(dev[0], [ ("dot11RSNAAuthenticationSuiteRequested", "00-0f-ac-3"),
462 ("dot11RSNAAuthenticationSuiteSelected", "00-0f-ac-3") ])
aaba98d3 463
4013d688
JM
464 # Verify EAPOL reauthentication after FT protocol
465 if dev[0].get_status_field('bssid') == apdev[0]['bssid']:
466 ap = hapd
467 else:
468 ap = hapd1
469 ap.request("EAPOL_REAUTH " + dev[0].own_addr())
470 ev = dev[0].wait_event(["CTRL-EVENT-EAP-STARTED"], timeout=5)
471 if ev is None:
472 raise Exception("EAP authentication did not start")
473 ev = dev[0].wait_event(["CTRL-EVENT-EAP-SUCCESS"], timeout=5)
474 if ev is None:
475 raise Exception("EAP authentication did not succeed")
476 time.sleep(0.1)
477 hwsim_utils.test_connectivity(dev[0], ap)
478
aaba98d3
JM
479def test_ap_ft_eap_pull(dev, apdev):
480 """WPA2-EAP-FT AP (pull PMK)"""
481 ssid = "test-ft"
482 passphrase="12345678"
483
484 radius = hostapd.radius_params()
485 params = ft_params1(ssid=ssid, passphrase=passphrase)
486 params['wpa_key_mgmt'] = "FT-EAP"
487 params["ieee8021x"] = "1"
488 params["pmk_r1_push"] = "0"
489 params = dict(radius.items() + params.items())
8b8a1864 490 hapd = hostapd.add_ap(apdev[0], params)
aaba98d3
JM
491 key_mgmt = hapd.get_config()['key_mgmt']
492 if key_mgmt.split(' ')[0] != "FT-EAP":
493 raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
494 params = ft_params2(ssid=ssid, passphrase=passphrase)
495 params['wpa_key_mgmt'] = "FT-EAP"
496 params["ieee8021x"] = "1"
497 params["pmk_r1_push"] = "0"
498 params = dict(radius.items() + params.items())
8b8a1864 499 hapd1 = hostapd.add_ap(apdev[1], params)
aaba98d3 500
a8375c94 501 run_roams(dev[0], apdev, hapd, hapd1, ssid, passphrase, eap=True)
3b808945 502
9fd6804d 503@remote_compatible
3b808945
JM
504def test_ap_ft_mismatching_rrb_key_push(dev, apdev):
505 """WPA2-PSK-FT AP over DS with mismatching RRB key (push)"""
506 ssid = "test-ft"
507 passphrase="12345678"
508
509 params = ft_params1(ssid=ssid, passphrase=passphrase)
bc6e3288 510 params["ieee80211w"] = "2"
8b8a1864 511 hapd0 = hostapd.add_ap(apdev[0], params)
3b808945 512 params = ft_params2_incorrect_rrb_key(ssid=ssid, passphrase=passphrase)
bc6e3288 513 params["ieee80211w"] = "2"
8b8a1864 514 hapd1 = hostapd.add_ap(apdev[1], params)
3b808945 515
a8375c94
JM
516 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
517 fail_test=True)
3b808945 518
9fd6804d 519@remote_compatible
3b808945
JM
520def test_ap_ft_mismatching_rrb_key_pull(dev, apdev):
521 """WPA2-PSK-FT AP over DS with mismatching RRB key (pull)"""
522 ssid = "test-ft"
523 passphrase="12345678"
524
525 params = ft_params1(ssid=ssid, passphrase=passphrase)
526 params["pmk_r1_push"] = "0"
8b8a1864 527 hapd0 = hostapd.add_ap(apdev[0], params)
3b808945
JM
528 params = ft_params2_incorrect_rrb_key(ssid=ssid, passphrase=passphrase)
529 params["pmk_r1_push"] = "0"
8b8a1864 530 hapd1 = hostapd.add_ap(apdev[1], params)
3b808945 531
a8375c94
JM
532 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
533 fail_test=True)
3b808945 534
9fd6804d 535@remote_compatible
ae14a2e2
JM
536def test_ap_ft_mismatching_r0kh_id_pull(dev, apdev):
537 """WPA2-PSK-FT AP over DS with mismatching R0KH-ID (pull)"""
538 ssid = "test-ft"
539 passphrase="12345678"
540
541 params = ft_params1(ssid=ssid, passphrase=passphrase)
542 params["pmk_r1_push"] = "0"
543 params["nas_identifier"] = "nas0.w1.fi"
8b8a1864 544 hostapd.add_ap(apdev[0], params)
2f816c21
JM
545 dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
546 scan_freq="2412")
ae14a2e2
JM
547
548 params = ft_params2(ssid=ssid, passphrase=passphrase)
549 params["pmk_r1_push"] = "0"
8b8a1864 550 hostapd.add_ap(apdev[1], params)
ae14a2e2
JM
551
552 dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
553 dev[0].roam_over_ds(apdev[1]['bssid'], fail_test=True)
554
9fd6804d 555@remote_compatible
3b808945
JM
556def test_ap_ft_mismatching_rrb_r0kh_push(dev, apdev):
557 """WPA2-PSK-FT AP over DS with mismatching R0KH key (push)"""
558 ssid = "test-ft"
559 passphrase="12345678"
560
561 params = ft_params1(ssid=ssid, passphrase=passphrase)
bc6e3288 562 params["ieee80211w"] = "2"
8b8a1864 563 hapd0 = hostapd.add_ap(apdev[0], params)
3b808945 564 params = ft_params2_r0kh_mismatch(ssid=ssid, passphrase=passphrase)
bc6e3288 565 params["ieee80211w"] = "2"
8b8a1864 566 hapd1 = hostapd.add_ap(apdev[1], params)
3b808945 567
a8375c94
JM
568 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
569 fail_test=True)
3b808945 570
9fd6804d 571@remote_compatible
3b808945
JM
572def test_ap_ft_mismatching_rrb_r0kh_pull(dev, apdev):
573 """WPA2-PSK-FT AP over DS with mismatching R0KH key (pull)"""
574 ssid = "test-ft"
575 passphrase="12345678"
576
577 params = ft_params1_r0kh_mismatch(ssid=ssid, passphrase=passphrase)
578 params["pmk_r1_push"] = "0"
8b8a1864 579 hapd0 = hostapd.add_ap(apdev[0], params)
3b808945
JM
580 params = ft_params2(ssid=ssid, passphrase=passphrase)
581 params["pmk_r1_push"] = "0"
8b8a1864 582 hapd1 = hostapd.add_ap(apdev[1], params)
3b808945 583
a8375c94
JM
584 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
585 fail_test=True)
c6b6e105 586
150948e6
MB
587def test_ap_ft_mismatching_rrb_key_push_eap(dev, apdev):
588 """WPA2-EAP-FT AP over DS with mismatching RRB key (push)"""
589 ssid = "test-ft"
590 passphrase="12345678"
591
592 radius = hostapd.radius_params()
593 params = ft_params1(ssid=ssid, passphrase=passphrase)
594 params["ieee80211w"] = "2";
595 params['wpa_key_mgmt'] = "FT-EAP"
596 params["ieee8021x"] = "1"
597 params = dict(radius.items() + params.items())
598 hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
599 params = ft_params2_incorrect_rrb_key(ssid=ssid, passphrase=passphrase)
600 params["ieee80211w"] = "2";
601 params['wpa_key_mgmt'] = "FT-EAP"
602 params["ieee8021x"] = "1"
603 params = dict(radius.items() + params.items())
604 hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
605
606 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
607 fail_test=True, eap=True)
608
609def test_ap_ft_mismatching_rrb_key_pull_eap(dev, apdev):
610 """WPA2-EAP-FT AP over DS with mismatching RRB key (pull)"""
611 ssid = "test-ft"
612 passphrase="12345678"
613
614 radius = hostapd.radius_params()
615 params = ft_params1(ssid=ssid, passphrase=passphrase)
616 params["pmk_r1_push"] = "0"
617 params['wpa_key_mgmt'] = "FT-EAP"
618 params["ieee8021x"] = "1"
619 params = dict(radius.items() + params.items())
620 hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
621 params = ft_params2_incorrect_rrb_key(ssid=ssid, passphrase=passphrase)
622 params["pmk_r1_push"] = "0"
623 params['wpa_key_mgmt'] = "FT-EAP"
624 params["ieee8021x"] = "1"
625 params = dict(radius.items() + params.items())
626 hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
627
628 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
629 fail_test=True, eap=True)
630
631def test_ap_ft_mismatching_r0kh_id_pull_eap(dev, apdev):
632 """WPA2-EAP-FT AP over DS with mismatching R0KH-ID (pull)"""
633 ssid = "test-ft"
634 passphrase="12345678"
635
636 radius = hostapd.radius_params()
637 params = ft_params1(ssid=ssid, passphrase=passphrase)
638 params["pmk_r1_push"] = "0"
639 params["nas_identifier"] = "nas0.w1.fi"
640 params['wpa_key_mgmt'] = "FT-EAP"
641 params["ieee8021x"] = "1"
642 params = dict(radius.items() + params.items())
643 hostapd.add_ap(apdev[0]['ifname'], params)
644 dev[0].connect(ssid, key_mgmt="FT-EAP", proto="WPA2", ieee80211w="1",
645 eap="GPSK", identity="gpsk user",
646 password="abcdefghijklmnop0123456789abcdef",
647 scan_freq="2412")
648
649 params = ft_params2(ssid=ssid, passphrase=passphrase)
650 params["pmk_r1_push"] = "0"
651 params['wpa_key_mgmt'] = "FT-EAP"
652 params["ieee8021x"] = "1"
653 params = dict(radius.items() + params.items())
654 hostapd.add_ap(apdev[1]['ifname'], params)
655
656 dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
657 dev[0].roam_over_ds(apdev[1]['bssid'], fail_test=True)
658
659def test_ap_ft_mismatching_rrb_r0kh_push_eap(dev, apdev):
660 """WPA2-EAP-FT AP over DS with mismatching R0KH key (push)"""
661 ssid = "test-ft"
662 passphrase="12345678"
663
664 radius = hostapd.radius_params()
665 params = ft_params1(ssid=ssid, passphrase=passphrase)
666 params["ieee80211w"] = "2";
667 params['wpa_key_mgmt'] = "FT-EAP"
668 params["ieee8021x"] = "1"
669 params = dict(radius.items() + params.items())
670 hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
671 params = ft_params2_r0kh_mismatch(ssid=ssid, passphrase=passphrase)
672 params["ieee80211w"] = "2";
673 params['wpa_key_mgmt'] = "FT-EAP"
674 params["ieee8021x"] = "1"
675 params = dict(radius.items() + params.items())
676 hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
677
678 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
679 fail_test=True, eap=True)
680
681def test_ap_ft_mismatching_rrb_r0kh_pull_eap(dev, apdev):
682 """WPA2-EAP-FT AP over DS with mismatching R0KH key (pull)"""
683 ssid = "test-ft"
684 passphrase="12345678"
685
686 radius = hostapd.radius_params()
687 params = ft_params1_r0kh_mismatch(ssid=ssid, passphrase=passphrase)
688 params["pmk_r1_push"] = "0"
689 params['wpa_key_mgmt'] = "FT-EAP"
690 params["ieee8021x"] = "1"
691 params = dict(radius.items() + params.items())
692 hapd0 = hostapd.add_ap(apdev[0]['ifname'], params)
693 params = ft_params2(ssid=ssid, passphrase=passphrase)
694 params["pmk_r1_push"] = "0"
695 params['wpa_key_mgmt'] = "FT-EAP"
696 params["ieee8021x"] = "1"
697 params = dict(radius.items() + params.items())
698 hapd1 = hostapd.add_ap(apdev[1]['ifname'], params)
699
700 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, over_ds=True,
701 fail_test=True, eap=True)
702
c6b6e105
JM
703def test_ap_ft_gtk_rekey(dev, apdev):
704 """WPA2-PSK-FT AP and GTK rekey"""
705 ssid = "test-ft"
706 passphrase="12345678"
707
708 params = ft_params1(ssid=ssid, passphrase=passphrase)
709 params['wpa_group_rekey'] = '1'
8b8a1864 710 hapd = hostapd.add_ap(apdev[0], params)
c6b6e105
JM
711
712 dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2f816c21 713 ieee80211w="1", scan_freq="2412")
c6b6e105
JM
714
715 ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=2)
716 if ev is None:
717 raise Exception("GTK rekey timed out after initial association")
a8375c94 718 hwsim_utils.test_connectivity(dev[0], hapd)
c6b6e105
JM
719
720 params = ft_params2(ssid=ssid, passphrase=passphrase)
721 params['wpa_group_rekey'] = '1'
8b8a1864 722 hapd1 = hostapd.add_ap(apdev[1], params)
c6b6e105
JM
723
724 dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
725 dev[0].roam(apdev[1]['bssid'])
726 if dev[0].get_status_field('bssid') != apdev[1]['bssid']:
727 raise Exception("Did not connect to correct AP")
a8375c94 728 hwsim_utils.test_connectivity(dev[0], hapd1)
c6b6e105
JM
729
730 ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=2)
731 if ev is None:
732 raise Exception("GTK rekey timed out after FT protocol")
a8375c94 733 hwsim_utils.test_connectivity(dev[0], hapd1)
5b3c40a6
JM
734
735def test_ft_psk_key_lifetime_in_memory(dev, apdev, params):
736 """WPA2-PSK-FT and key lifetime in memory"""
737 ssid = "test-ft"
738 passphrase="04c2726b4b8d5f1b4db9c07aa4d9e9d8f765cb5d25ec817e6cc4fcdd5255db0"
739 psk = '93c90846ff67af9037ed83fb72b63dbeddaa81d47f926c20909b5886f1d9358d'
740 pmk = binascii.unhexlify(psk)
741 p = ft_params1(ssid=ssid, passphrase=passphrase)
8b8a1864 742 hapd0 = hostapd.add_ap(apdev[0], p)
5b3c40a6 743 p = ft_params2(ssid=ssid, passphrase=passphrase)
8b8a1864 744 hapd1 = hostapd.add_ap(apdev[1], p)
5b3c40a6
JM
745
746 pid = find_wpas_process(dev[0])
747
748 dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
749 scan_freq="2412")
8e416cec
JM
750 # The decrypted copy of GTK is freed only after the CTRL-EVENT-CONNECTED
751 # event has been delivered, so verify that wpa_supplicant has returned to
752 # eloop before reading process memory.
54f2cae2 753 time.sleep(1)
8e416cec 754 dev[0].ping()
5b3c40a6
JM
755
756 buf = read_process_memory(pid, pmk)
757
758 dev[0].request("DISCONNECT")
759 dev[0].wait_disconnected()
760
761 dev[0].relog()
762 pmkr0 = None
763 pmkr1 = None
764 ptk = None
765 gtk = None
766 with open(os.path.join(params['logdir'], 'log0'), 'r') as f:
767 for l in f.readlines():
768 if "FT: PMK-R0 - hexdump" in l:
769 val = l.strip().split(':')[3].replace(' ', '')
770 pmkr0 = binascii.unhexlify(val)
771 if "FT: PMK-R1 - hexdump" in l:
772 val = l.strip().split(':')[3].replace(' ', '')
773 pmkr1 = binascii.unhexlify(val)
f918b95b 774 if "FT: KCK - hexdump" in l:
5b3c40a6 775 val = l.strip().split(':')[3].replace(' ', '')
f918b95b
JM
776 kck = binascii.unhexlify(val)
777 if "FT: KEK - hexdump" in l:
778 val = l.strip().split(':')[3].replace(' ', '')
779 kek = binascii.unhexlify(val)
780 if "FT: TK - hexdump" in l:
781 val = l.strip().split(':')[3].replace(' ', '')
782 tk = binascii.unhexlify(val)
5b3c40a6
JM
783 if "WPA: Group Key - hexdump" in l:
784 val = l.strip().split(':')[3].replace(' ', '')
785 gtk = binascii.unhexlify(val)
f918b95b 786 if not pmkr0 or not pmkr1 or not kck or not kek or not tk or not gtk:
5b3c40a6
JM
787 raise Exception("Could not find keys from debug log")
788 if len(gtk) != 16:
789 raise Exception("Unexpected GTK length")
790
5b3c40a6
JM
791 logger.info("Checking keys in memory while associated")
792 get_key_locations(buf, pmk, "PMK")
793 get_key_locations(buf, pmkr0, "PMK-R0")
794 get_key_locations(buf, pmkr1, "PMK-R1")
795 if pmk not in buf:
81e787b7 796 raise HwsimSkip("PMK not found while associated")
5b3c40a6 797 if pmkr0 not in buf:
81e787b7 798 raise HwsimSkip("PMK-R0 not found while associated")
5b3c40a6 799 if pmkr1 not in buf:
81e787b7 800 raise HwsimSkip("PMK-R1 not found while associated")
5b3c40a6
JM
801 if kck not in buf:
802 raise Exception("KCK not found while associated")
803 if kek not in buf:
804 raise Exception("KEK not found while associated")
805 if tk in buf:
806 raise Exception("TK found from memory")
807 if gtk in buf:
8eb45bde 808 get_key_locations(buf, gtk, "GTK")
5b3c40a6
JM
809 raise Exception("GTK found from memory")
810
811 logger.info("Checking keys in memory after disassociation")
812 buf = read_process_memory(pid, pmk)
813 get_key_locations(buf, pmk, "PMK")
814 get_key_locations(buf, pmkr0, "PMK-R0")
815 get_key_locations(buf, pmkr1, "PMK-R1")
816
817 # Note: PMK/PSK is still present in network configuration
818
819 fname = os.path.join(params['logdir'],
820 'ft_psk_key_lifetime_in_memory.memctx-')
821 verify_not_present(buf, pmkr0, fname, "PMK-R0")
822 verify_not_present(buf, pmkr1, fname, "PMK-R1")
823 verify_not_present(buf, kck, fname, "KCK")
824 verify_not_present(buf, kek, fname, "KEK")
825 verify_not_present(buf, tk, fname, "TK")
826 verify_not_present(buf, gtk, fname, "GTK")
827
828 dev[0].request("REMOVE_NETWORK all")
829
830 logger.info("Checking keys in memory after network profile removal")
831 buf = read_process_memory(pid, pmk)
832 get_key_locations(buf, pmk, "PMK")
833 get_key_locations(buf, pmkr0, "PMK-R0")
834 get_key_locations(buf, pmkr1, "PMK-R1")
835
836 verify_not_present(buf, pmk, fname, "PMK")
837 verify_not_present(buf, pmkr0, fname, "PMK-R0")
838 verify_not_present(buf, pmkr1, fname, "PMK-R1")
839 verify_not_present(buf, kck, fname, "KCK")
840 verify_not_present(buf, kek, fname, "KEK")
841 verify_not_present(buf, tk, fname, "TK")
842 verify_not_present(buf, gtk, fname, "GTK")
664093b5 843
9fd6804d 844@remote_compatible
664093b5
JM
845def test_ap_ft_invalid_resp(dev, apdev):
846 """WPA2-PSK-FT AP and invalid response IEs"""
847 ssid = "test-ft"
848 passphrase="12345678"
849
850 params = ft_params1(ssid=ssid, passphrase=passphrase)
8b8a1864 851 hapd0 = hostapd.add_ap(apdev[0], params)
664093b5
JM
852 dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
853 scan_freq="2412")
854
855 params = ft_params2(ssid=ssid, passphrase=passphrase)
8b8a1864 856 hapd1 = hostapd.add_ap(apdev[1], params)
664093b5
JM
857
858 tests = [
859 # Various IEs for test coverage. The last one is FTIE with invalid
860 # R1KH-ID subelement.
861 "020002000000" + "3800" + "38051122334455" + "3754000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010100",
862 # FTIE with invalid R0KH-ID subelement (len=0).
863 "020002000000" + "3754000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010300",
864 # FTIE with invalid R0KH-ID subelement (len=49).
865 "020002000000" + "378500010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001033101020304050607080910111213141516171819202122232425262728293031323334353637383940414243444546474849",
866 # Invalid RSNE.
867 "020002000000" + "3000",
868 # Required IEs missing from protected IE count.
869 "020002000000" + "3603a1b201" + "375200010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001" + "3900",
870 # RIC missing from protected IE count.
871 "020002000000" + "3603a1b201" + "375200020203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001" + "3900",
872 # Protected IE missing.
873 "020002000000" + "3603a1b201" + "375200ff0203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001" + "3900" + "0000" ]
874 for t in tests:
875 dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
876 hapd1.set("ext_mgmt_frame_handling", "1")
877 hapd1.dump_monitor()
878 if "OK" not in dev[0].request("ROAM " + apdev[1]['bssid']):
879 raise Exception("ROAM failed")
880 auth = None
881 for i in range(20):
882 msg = hapd1.mgmt_rx()
883 if msg['subtype'] == 11:
884 auth = msg
885 break
886 if not auth:
887 raise Exception("Authentication frame not seen")
888
889 resp = {}
890 resp['fc'] = auth['fc']
891 resp['da'] = auth['sa']
892 resp['sa'] = auth['da']
893 resp['bssid'] = auth['bssid']
894 resp['payload'] = binascii.unhexlify(t)
895 hapd1.mgmt_tx(resp)
896 hapd1.set("ext_mgmt_frame_handling", "0")
897 dev[0].wait_disconnected()
898
899 dev[0].request("RECONNECT")
900 dev[0].wait_connected()
7b741a53
JM
901
902def test_ap_ft_gcmp_256(dev, apdev):
903 """WPA2-PSK-FT AP with GCMP-256 cipher"""
904 if "GCMP-256" not in dev[0].get_capability("pairwise"):
905 raise HwsimSkip("Cipher GCMP-256 not supported")
906 ssid = "test-ft"
907 passphrase="12345678"
908
909 params = ft_params1(ssid=ssid, passphrase=passphrase)
910 params['rsn_pairwise'] = "GCMP-256"
8b8a1864 911 hapd0 = hostapd.add_ap(apdev[0], params)
7b741a53
JM
912 params = ft_params2(ssid=ssid, passphrase=passphrase)
913 params['rsn_pairwise'] = "GCMP-256"
8b8a1864 914 hapd1 = hostapd.add_ap(apdev[1], params)
7b741a53
JM
915
916 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase,
917 pairwise_cipher="GCMP-256", group_cipher="GCMP-256")
cf671d54
JM
918
919def test_ap_ft_oom(dev, apdev):
920 """WPA2-PSK-FT and OOM"""
38934ed1 921 skip_with_fips(dev[0])
cf671d54
JM
922 ssid = "test-ft"
923 passphrase="12345678"
924
925 params = ft_params1(ssid=ssid, passphrase=passphrase)
8b8a1864 926 hapd0 = hostapd.add_ap(apdev[0], params)
cf671d54 927 params = ft_params2(ssid=ssid, passphrase=passphrase)
8b8a1864 928 hapd1 = hostapd.add_ap(apdev[1], params)
cf671d54
JM
929
930 dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
931 scan_freq="2412")
932 if dev[0].get_status_field('bssid') == apdev[0]['bssid']:
933 dst = apdev[1]['bssid']
934 else:
935 dst = apdev[0]['bssid']
936
937 dev[0].scan_for_bss(dst, freq="2412")
938 with alloc_fail(dev[0], 1, "wpa_ft_gen_req_ies"):
939 dev[0].roam(dst)
7cbc8e67 940 with fail_test(dev[0], 1, "wpa_ft_mic"):
cf671d54
JM
941 dev[0].roam(dst, fail_test=True)
942 with fail_test(dev[0], 1, "os_get_random;wpa_ft_prepare_auth_request"):
943 dev[0].roam(dst, fail_test=True)
34d3eaa8 944
dcbb5d80
JM
945 dev[0].request("REMOVE_NETWORK all")
946 with alloc_fail(dev[0], 1, "=sme_update_ft_ies"):
947 dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
948 scan_freq="2412")
949
34d3eaa8
JM
950def test_ap_ft_over_ds_proto(dev, apdev):
951 """WPA2-PSK-FT AP over DS protocol testing"""
952 ssid = "test-ft"
953 passphrase="12345678"
954
955 params = ft_params1(ssid=ssid, passphrase=passphrase)
8b8a1864 956 hapd0 = hostapd.add_ap(apdev[0], params)
34d3eaa8
JM
957 dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
958 scan_freq="2412")
959
960 # FT Action Response while no FT-over-DS in progress
961 msg = {}
962 msg['fc'] = 13 << 4
963 msg['da'] = dev[0].own_addr()
964 msg['sa'] = apdev[0]['bssid']
965 msg['bssid'] = apdev[0]['bssid']
966 msg['payload'] = binascii.unhexlify("06020200000000000200000004000000")
967 hapd0.mgmt_tx(msg)
968
969 params = ft_params2(ssid=ssid, passphrase=passphrase)
8b8a1864 970 hapd1 = hostapd.add_ap(apdev[1], params)
34d3eaa8
JM
971 dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
972 hapd0.set("ext_mgmt_frame_handling", "1")
973 hapd0.dump_monitor()
974 dev[0].request("FT_DS " + apdev[1]['bssid'])
975 for i in range(0, 10):
976 req = hapd0.mgmt_rx()
977 if req is None:
978 raise Exception("MGMT RX wait timed out")
979 if req['subtype'] == 13:
980 break
981 req = None
982 if not req:
983 raise Exception("FT Action frame not received")
984
985 # FT Action Response for unexpected Target AP
986 msg['payload'] = binascii.unhexlify("0602020000000000" + "f20000000400" + "0000")
987 hapd0.mgmt_tx(msg)
988
989 # FT Action Response without MDIE
990 msg['payload'] = binascii.unhexlify("0602020000000000" + "020000000400" + "0000")
991 hapd0.mgmt_tx(msg)
992
993 # FT Action Response without FTIE
994 msg['payload'] = binascii.unhexlify("0602020000000000" + "020000000400" + "0000" + "3603a1b201")
995 hapd0.mgmt_tx(msg)
996
997 # FT Action Response with FTIE SNonce mismatch
998 msg['payload'] = binascii.unhexlify("0602020000000000" + "020000000400" + "0000" + "3603a1b201" + "3766000000000000000000000000000000000000c4e67ac1999bebd00ff4ae4d5dcaf87896bb060b469f7c78d49623fb395c3455ffffff6b693fe6f8d8c5dfac0a22344750775bd09437f98b238c9f87b97f790c0106000102030406030a6e6173312e77312e6669")
999 hapd0.mgmt_tx(msg)
6f3815c0 1000
9fd6804d 1001@remote_compatible
6f3815c0
JM
1002def test_ap_ft_rrb(dev, apdev):
1003 """WPA2-PSK-FT RRB protocol testing"""
1004 ssid = "test-ft"
1005 passphrase="12345678"
1006
1007 params = ft_params1(ssid=ssid, passphrase=passphrase)
8b8a1864 1008 hapd0 = hostapd.add_ap(apdev[0], params)
6f3815c0
JM
1009
1010 dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
1011 scan_freq="2412")
1012
1013 _dst_ll = binascii.unhexlify(apdev[0]['bssid'].replace(':',''))
1014 _src_ll = binascii.unhexlify(dev[0].own_addr().replace(':',''))
1015 proto = '\x89\x0d'
1016 ehdr = _dst_ll + _src_ll + proto
1017
1018 # Too short RRB frame
1019 pkt = ehdr + '\x01'
1020 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
1021 raise Exception("DATA_TEST_FRAME failed")
1022
1023 # RRB discarded frame wikth unrecognized type
1024 pkt = ehdr + '\x02' + '\x02' + '\x01\x00' + _src_ll
1025 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
1026 raise Exception("DATA_TEST_FRAME failed")
1027
1028 # RRB frame too short for action frame
1029 pkt = ehdr + '\x01' + '\x02' + '\x01\x00' + _src_ll
1030 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
1031 raise Exception("DATA_TEST_FRAME failed")
1032
1033 # Too short RRB frame (not enough room for Action Frame body)
1034 pkt = ehdr + '\x01' + '\x02' + '\x00\x00' + _src_ll
1035 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
1036 raise Exception("DATA_TEST_FRAME failed")
1037
1038 # Unexpected Action frame category
1039 pkt = ehdr + '\x01' + '\x02' + '\x0e\x00' + _src_ll + '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
1040 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
1041 raise Exception("DATA_TEST_FRAME failed")
1042
1043 # Unexpected Action in RRB Request
1044 pkt = ehdr + '\x01' + '\x00' + '\x0e\x00' + _src_ll + '\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
1045 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
1046 raise Exception("DATA_TEST_FRAME failed")
1047
1048 # Target AP address in RRB Request does not match with own address
1049 pkt = ehdr + '\x01' + '\x00' + '\x0e\x00' + _src_ll + '\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
1050 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
1051 raise Exception("DATA_TEST_FRAME failed")
1052
1053 # Not enough room for status code in RRB Response
1054 pkt = ehdr + '\x01' + '\x01' + '\x0e\x00' + _src_ll + '\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
1055 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
1056 raise Exception("DATA_TEST_FRAME failed")
1057
1058 # RRB discarded frame with unknown packet_type
1059 pkt = ehdr + '\x01' + '\x02' + '\x0e\x00' + _src_ll + '\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
1060 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
1061 raise Exception("DATA_TEST_FRAME failed")
1062
1063 # RRB Response with non-zero status code; no STA match
1064 pkt = ehdr + '\x01' + '\x01' + '\x10\x00' + _src_ll + '\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + '\xff\xff'
1065 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
1066 raise Exception("DATA_TEST_FRAME failed")
1067
1068 # RRB Response with zero status code and extra data; STA match
1069 pkt = ehdr + '\x01' + '\x01' + '\x11\x00' + _src_ll + '\x06\x01' + _src_ll + '\x00\x00\x00\x00\x00\x00' + '\x00\x00' + '\x00'
1070 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
1071 raise Exception("DATA_TEST_FRAME failed")
1072
1073 # Too short PMK-R1 pull
1074 pkt = ehdr + '\x01' + '\xc8' + '\x0e\x00' + _src_ll + '\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
1075 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
1076 raise Exception("DATA_TEST_FRAME failed")
1077
1078 # Too short PMK-R1 resp
1079 pkt = ehdr + '\x01' + '\xc9' + '\x0e\x00' + _src_ll + '\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
1080 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
1081 raise Exception("DATA_TEST_FRAME failed")
1082
1083 # Too short PMK-R1 push
1084 pkt = ehdr + '\x01' + '\xca' + '\x0e\x00' + _src_ll + '\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
1085 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
1086 raise Exception("DATA_TEST_FRAME failed")
1087
1088 # No matching R0KH address found for PMK-R0 pull response
1089 pkt = ehdr + '\x01' + '\xc9' + '\x5a\x00' + _src_ll + '\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + 76*'\00'
1090 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
1091 raise Exception("DATA_TEST_FRAME failed")
ecafa0cf 1092
9fd6804d 1093@remote_compatible
ecafa0cf
JM
1094def test_rsn_ie_proto_ft_psk_sta(dev, apdev):
1095 """RSN element protocol testing for FT-PSK + PMF cases on STA side"""
1096 bssid = apdev[0]['bssid']
1097 ssid = "test-ft"
1098 passphrase="12345678"
1099
1100 params = ft_params1(ssid=ssid, passphrase=passphrase)
bc6e3288 1101 params["ieee80211w"] = "1"
ecafa0cf
JM
1102 # This is the RSN element used normally by hostapd
1103 params['own_ie_override'] = '30140100000fac040100000fac040100000fac048c00' + '3603a1b201'
8b8a1864 1104 hapd = hostapd.add_ap(apdev[0], params)
ecafa0cf
JM
1105 id = dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
1106 ieee80211w="1", scan_freq="2412",
1107 pairwise="CCMP", group="CCMP")
1108
1109 tests = [ ('PMKIDCount field included',
1110 '30160100000fac040100000fac040100000fac048c000000' + '3603a1b201'),
1111 ('Extra IE before RSNE',
1112 'dd0400000000' + '30140100000fac040100000fac040100000fac048c00' + '3603a1b201'),
1113 ('PMKIDCount and Group Management Cipher suite fields included',
1114 '301a0100000fac040100000fac040100000fac048c000000000fac06' + '3603a1b201'),
1115 ('Extra octet after defined fields (future extensibility)',
1116 '301b0100000fac040100000fac040100000fac048c000000000fac0600' + '3603a1b201'),
1117 ('No RSN Capabilities field (PMF disabled in practice)',
1118 '30120100000fac040100000fac040100000fac04' + '3603a1b201') ]
1119 for txt,ie in tests:
1120 dev[0].request("DISCONNECT")
1121 dev[0].wait_disconnected()
1122 logger.info(txt)
1123 hapd.disable()
1124 hapd.set('own_ie_override', ie)
1125 hapd.enable()
1126 dev[0].request("BSS_FLUSH 0")
1127 dev[0].scan_for_bss(bssid, 2412, force_scan=True, only_new=True)
1128 dev[0].select_network(id, freq=2412)
1129 dev[0].wait_connected()
1130
1131 dev[0].request("DISCONNECT")
1132 dev[0].wait_disconnected()
1133
1134 logger.info('Invalid RSNE causing internal hostapd error')
1135 hapd.disable()
1136 hapd.set('own_ie_override', '30130100000fac040100000fac040100000fac048c' + '3603a1b201')
1137 hapd.enable()
1138 dev[0].request("BSS_FLUSH 0")
1139 dev[0].scan_for_bss(bssid, 2412, force_scan=True, only_new=True)
1140 dev[0].select_network(id, freq=2412)
1141 # hostapd fails to generate EAPOL-Key msg 3/4, so this connection cannot
1142 # complete.
1143 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
1144 if ev is not None:
1145 raise Exception("Unexpected connection")
1146 dev[0].request("DISCONNECT")
1147
1148 logger.info('Unexpected PMKID causing internal hostapd error')
1149 hapd.disable()
1150 hapd.set('own_ie_override', '30260100000fac040100000fac040100000fac048c000100ffffffffffffffffffffffffffffffff' + '3603a1b201')
1151 hapd.enable()
1152 dev[0].request("BSS_FLUSH 0")
1153 dev[0].scan_for_bss(bssid, 2412, force_scan=True, only_new=True)
1154 dev[0].select_network(id, freq=2412)
1155 # hostapd fails to generate EAPOL-Key msg 3/4, so this connection cannot
1156 # complete.
1157 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
1158 if ev is not None:
1159 raise Exception("Unexpected connection")
1160 dev[0].request("DISCONNECT")
1025603b
JM
1161
1162def test_ap_ft_ptk_rekey(dev, apdev):
1163 """WPA2-PSK-FT PTK rekeying triggered by station after roam"""
1164 ssid = "test-ft"
1165 passphrase="12345678"
1166
1167 params = ft_params1(ssid=ssid, passphrase=passphrase)
8b8a1864 1168 hapd0 = hostapd.add_ap(apdev[0], params)
1025603b 1169 params = ft_params2(ssid=ssid, passphrase=passphrase)
8b8a1864 1170 hapd1 = hostapd.add_ap(apdev[1], params)
1025603b
JM
1171
1172 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, ptk_rekey="1")
1173
1174 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED",
1175 "WPA: Key negotiation completed"], timeout=5)
1176 if ev is None:
1177 raise Exception("No event received after roam")
1178 if "CTRL-EVENT-DISCONNECTED" in ev:
1179 raise Exception("Unexpected disconnection after roam")
1180
1181 if dev[0].get_status_field('bssid') == apdev[0]['bssid']:
1182 hapd = hapd0
1183 else:
1184 hapd = hapd1
1185 hwsim_utils.test_connectivity(dev[0], hapd)
1186
1187def test_ap_ft_ptk_rekey_ap(dev, apdev):
1188 """WPA2-PSK-FT PTK rekeying triggered by AP after roam"""
1189 ssid = "test-ft"
1190 passphrase="12345678"
1191
1192 params = ft_params1(ssid=ssid, passphrase=passphrase)
1193 params['wpa_ptk_rekey'] = '2'
8b8a1864 1194 hapd0 = hostapd.add_ap(apdev[0], params)
1025603b
JM
1195 params = ft_params2(ssid=ssid, passphrase=passphrase)
1196 params['wpa_ptk_rekey'] = '2'
8b8a1864 1197 hapd1 = hostapd.add_ap(apdev[1], params)
1025603b
JM
1198
1199 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase)
1200
1201 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED",
1202 "WPA: Key negotiation completed"], timeout=5)
1203 if ev is None:
1204 raise Exception("No event received after roam")
1205 if "CTRL-EVENT-DISCONNECTED" in ev:
1206 raise Exception("Unexpected disconnection after roam")
1207
1208 if dev[0].get_status_field('bssid') == apdev[0]['bssid']:
1209 hapd = hapd0
1210 else:
1211 hapd = hapd1
1212 hwsim_utils.test_connectivity(dev[0], hapd)
186ca473
MB
1213
1214def test_ap_ft_internal_rrb_check(dev, apdev):
1215 """RRB internal delivery only to WPA enabled BSS"""
1216 ssid = "test-ft"
1217 passphrase="12345678"
1218
1219 radius = hostapd.radius_params()
1220 params = ft_params1(ssid=ssid, passphrase=passphrase)
1221 params['wpa_key_mgmt'] = "FT-EAP"
1222 params["ieee8021x"] = "1"
1223 params = dict(radius.items() + params.items())
8b8a1864 1224 hapd = hostapd.add_ap(apdev[0], params)
186ca473
MB
1225 key_mgmt = hapd.get_config()['key_mgmt']
1226 if key_mgmt.split(' ')[0] != "FT-EAP":
1227 raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
1228
8b8a1864 1229 hapd1 = hostapd.add_ap(apdev[1], { "ssid" : ssid })
186ca473
MB
1230
1231 # Connect to WPA enabled AP
1232 dev[0].connect(ssid, key_mgmt="FT-EAP", proto="WPA2", ieee80211w="1",
1233 eap="GPSK", identity="gpsk user",
1234 password="abcdefghijklmnop0123456789abcdef",
1235 scan_freq="2412")
1236
1237 # Try over_ds roaming to non-WPA-enabled AP.
1238 # If hostapd does not check hapd->wpa_auth internally, it will crash now.
1239 dev[0].roam_over_ds(apdev[1]['bssid'], fail_test=True)
c85fcff2
JM
1240
1241def test_ap_ft_extra_ie(dev, apdev):
1242 """WPA2-PSK-FT AP with WPA2-PSK enabled and unexpected MDE"""
1243 ssid = "test-ft"
1244 passphrase="12345678"
1245
1246 params = ft_params1(ssid=ssid, passphrase=passphrase)
1247 params["wpa_key_mgmt"] = "WPA-PSK FT-PSK"
1248 hapd0 = hostapd.add_ap(apdev[0], params)
1249 dev[1].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
1250 scan_freq="2412")
1251 dev[2].connect(ssid, psk=passphrase, key_mgmt="WPA-PSK", proto="WPA2",
1252 scan_freq="2412")
1253 try:
1254 # Add Mobility Domain element to test AP validation code.
1255 dev[0].request("VENDOR_ELEM_ADD 13 3603a1b201")
1256 dev[0].connect(ssid, psk=passphrase, key_mgmt="WPA-PSK", proto="WPA2",
1257 scan_freq="2412", wait_connect=False)
1258 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED",
1259 "CTRL-EVENT-ASSOC-REJECT"], timeout=10)
1260 if ev is None:
1261 raise Exception("No connection result")
1262 if "CTRL-EVENT-CONNECTED" in ev:
1263 raise Exception("Non-FT association accepted with MDE")
1264 if "status_code=43" not in ev:
1265 raise Exception("Unexpected status code: " + ev)
1266 dev[0].request("DISCONNECT")
1267 finally:
1268 dev[0].request("VENDOR_ELEM_REMOVE 13 *")