]> git.ipfire.org Git - thirdparty/hostap.git/blame - tests/hwsim/test_ap_ft.py
test: FT with locally generated PMK-R0/PMK-R1 from PSK
[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
JM
586
587def test_ap_ft_gtk_rekey(dev, apdev):
588 """WPA2-PSK-FT AP and GTK rekey"""
589 ssid = "test-ft"
590 passphrase="12345678"
591
592 params = ft_params1(ssid=ssid, passphrase=passphrase)
593 params['wpa_group_rekey'] = '1'
8b8a1864 594 hapd = hostapd.add_ap(apdev[0], params)
c6b6e105
JM
595
596 dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
2f816c21 597 ieee80211w="1", scan_freq="2412")
c6b6e105
JM
598
599 ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=2)
600 if ev is None:
601 raise Exception("GTK rekey timed out after initial association")
a8375c94 602 hwsim_utils.test_connectivity(dev[0], hapd)
c6b6e105
JM
603
604 params = ft_params2(ssid=ssid, passphrase=passphrase)
605 params['wpa_group_rekey'] = '1'
8b8a1864 606 hapd1 = hostapd.add_ap(apdev[1], params)
c6b6e105
JM
607
608 dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
609 dev[0].roam(apdev[1]['bssid'])
610 if dev[0].get_status_field('bssid') != apdev[1]['bssid']:
611 raise Exception("Did not connect to correct AP")
a8375c94 612 hwsim_utils.test_connectivity(dev[0], hapd1)
c6b6e105
JM
613
614 ev = dev[0].wait_event(["WPA: Group rekeying completed"], timeout=2)
615 if ev is None:
616 raise Exception("GTK rekey timed out after FT protocol")
a8375c94 617 hwsim_utils.test_connectivity(dev[0], hapd1)
5b3c40a6
JM
618
619def test_ft_psk_key_lifetime_in_memory(dev, apdev, params):
620 """WPA2-PSK-FT and key lifetime in memory"""
621 ssid = "test-ft"
622 passphrase="04c2726b4b8d5f1b4db9c07aa4d9e9d8f765cb5d25ec817e6cc4fcdd5255db0"
623 psk = '93c90846ff67af9037ed83fb72b63dbeddaa81d47f926c20909b5886f1d9358d'
624 pmk = binascii.unhexlify(psk)
625 p = ft_params1(ssid=ssid, passphrase=passphrase)
8b8a1864 626 hapd0 = hostapd.add_ap(apdev[0], p)
5b3c40a6 627 p = ft_params2(ssid=ssid, passphrase=passphrase)
8b8a1864 628 hapd1 = hostapd.add_ap(apdev[1], p)
5b3c40a6
JM
629
630 pid = find_wpas_process(dev[0])
631
632 dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
633 scan_freq="2412")
8e416cec
JM
634 # The decrypted copy of GTK is freed only after the CTRL-EVENT-CONNECTED
635 # event has been delivered, so verify that wpa_supplicant has returned to
636 # eloop before reading process memory.
54f2cae2 637 time.sleep(1)
8e416cec 638 dev[0].ping()
5b3c40a6
JM
639
640 buf = read_process_memory(pid, pmk)
641
642 dev[0].request("DISCONNECT")
643 dev[0].wait_disconnected()
644
645 dev[0].relog()
646 pmkr0 = None
647 pmkr1 = None
648 ptk = None
649 gtk = None
650 with open(os.path.join(params['logdir'], 'log0'), 'r') as f:
651 for l in f.readlines():
652 if "FT: PMK-R0 - hexdump" in l:
653 val = l.strip().split(':')[3].replace(' ', '')
654 pmkr0 = binascii.unhexlify(val)
655 if "FT: PMK-R1 - hexdump" in l:
656 val = l.strip().split(':')[3].replace(' ', '')
657 pmkr1 = binascii.unhexlify(val)
f918b95b 658 if "FT: KCK - hexdump" in l:
5b3c40a6 659 val = l.strip().split(':')[3].replace(' ', '')
f918b95b
JM
660 kck = binascii.unhexlify(val)
661 if "FT: KEK - hexdump" in l:
662 val = l.strip().split(':')[3].replace(' ', '')
663 kek = binascii.unhexlify(val)
664 if "FT: TK - hexdump" in l:
665 val = l.strip().split(':')[3].replace(' ', '')
666 tk = binascii.unhexlify(val)
5b3c40a6
JM
667 if "WPA: Group Key - hexdump" in l:
668 val = l.strip().split(':')[3].replace(' ', '')
669 gtk = binascii.unhexlify(val)
f918b95b 670 if not pmkr0 or not pmkr1 or not kck or not kek or not tk or not gtk:
5b3c40a6
JM
671 raise Exception("Could not find keys from debug log")
672 if len(gtk) != 16:
673 raise Exception("Unexpected GTK length")
674
5b3c40a6
JM
675 logger.info("Checking keys in memory while associated")
676 get_key_locations(buf, pmk, "PMK")
677 get_key_locations(buf, pmkr0, "PMK-R0")
678 get_key_locations(buf, pmkr1, "PMK-R1")
679 if pmk not in buf:
81e787b7 680 raise HwsimSkip("PMK not found while associated")
5b3c40a6 681 if pmkr0 not in buf:
81e787b7 682 raise HwsimSkip("PMK-R0 not found while associated")
5b3c40a6 683 if pmkr1 not in buf:
81e787b7 684 raise HwsimSkip("PMK-R1 not found while associated")
5b3c40a6
JM
685 if kck not in buf:
686 raise Exception("KCK not found while associated")
687 if kek not in buf:
688 raise Exception("KEK not found while associated")
689 if tk in buf:
690 raise Exception("TK found from memory")
691 if gtk in buf:
8eb45bde 692 get_key_locations(buf, gtk, "GTK")
5b3c40a6
JM
693 raise Exception("GTK found from memory")
694
695 logger.info("Checking keys in memory after disassociation")
696 buf = read_process_memory(pid, pmk)
697 get_key_locations(buf, pmk, "PMK")
698 get_key_locations(buf, pmkr0, "PMK-R0")
699 get_key_locations(buf, pmkr1, "PMK-R1")
700
701 # Note: PMK/PSK is still present in network configuration
702
703 fname = os.path.join(params['logdir'],
704 'ft_psk_key_lifetime_in_memory.memctx-')
705 verify_not_present(buf, pmkr0, fname, "PMK-R0")
706 verify_not_present(buf, pmkr1, fname, "PMK-R1")
707 verify_not_present(buf, kck, fname, "KCK")
708 verify_not_present(buf, kek, fname, "KEK")
709 verify_not_present(buf, tk, fname, "TK")
710 verify_not_present(buf, gtk, fname, "GTK")
711
712 dev[0].request("REMOVE_NETWORK all")
713
714 logger.info("Checking keys in memory after network profile removal")
715 buf = read_process_memory(pid, pmk)
716 get_key_locations(buf, pmk, "PMK")
717 get_key_locations(buf, pmkr0, "PMK-R0")
718 get_key_locations(buf, pmkr1, "PMK-R1")
719
720 verify_not_present(buf, pmk, fname, "PMK")
721 verify_not_present(buf, pmkr0, fname, "PMK-R0")
722 verify_not_present(buf, pmkr1, fname, "PMK-R1")
723 verify_not_present(buf, kck, fname, "KCK")
724 verify_not_present(buf, kek, fname, "KEK")
725 verify_not_present(buf, tk, fname, "TK")
726 verify_not_present(buf, gtk, fname, "GTK")
664093b5 727
9fd6804d 728@remote_compatible
664093b5
JM
729def test_ap_ft_invalid_resp(dev, apdev):
730 """WPA2-PSK-FT AP and invalid response IEs"""
731 ssid = "test-ft"
732 passphrase="12345678"
733
734 params = ft_params1(ssid=ssid, passphrase=passphrase)
8b8a1864 735 hapd0 = hostapd.add_ap(apdev[0], params)
664093b5
JM
736 dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
737 scan_freq="2412")
738
739 params = ft_params2(ssid=ssid, passphrase=passphrase)
8b8a1864 740 hapd1 = hostapd.add_ap(apdev[1], params)
664093b5
JM
741
742 tests = [
743 # Various IEs for test coverage. The last one is FTIE with invalid
744 # R1KH-ID subelement.
745 "020002000000" + "3800" + "38051122334455" + "3754000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010100",
746 # FTIE with invalid R0KH-ID subelement (len=0).
747 "020002000000" + "3754000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010300",
748 # FTIE with invalid R0KH-ID subelement (len=49).
749 "020002000000" + "378500010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001033101020304050607080910111213141516171819202122232425262728293031323334353637383940414243444546474849",
750 # Invalid RSNE.
751 "020002000000" + "3000",
752 # Required IEs missing from protected IE count.
753 "020002000000" + "3603a1b201" + "375200010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001" + "3900",
754 # RIC missing from protected IE count.
755 "020002000000" + "3603a1b201" + "375200020203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001" + "3900",
756 # Protected IE missing.
757 "020002000000" + "3603a1b201" + "375200ff0203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001020304050607080900010203040506070809000102030405060708090001" + "3900" + "0000" ]
758 for t in tests:
759 dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
760 hapd1.set("ext_mgmt_frame_handling", "1")
761 hapd1.dump_monitor()
762 if "OK" not in dev[0].request("ROAM " + apdev[1]['bssid']):
763 raise Exception("ROAM failed")
764 auth = None
765 for i in range(20):
766 msg = hapd1.mgmt_rx()
767 if msg['subtype'] == 11:
768 auth = msg
769 break
770 if not auth:
771 raise Exception("Authentication frame not seen")
772
773 resp = {}
774 resp['fc'] = auth['fc']
775 resp['da'] = auth['sa']
776 resp['sa'] = auth['da']
777 resp['bssid'] = auth['bssid']
778 resp['payload'] = binascii.unhexlify(t)
779 hapd1.mgmt_tx(resp)
780 hapd1.set("ext_mgmt_frame_handling", "0")
781 dev[0].wait_disconnected()
782
783 dev[0].request("RECONNECT")
784 dev[0].wait_connected()
7b741a53
JM
785
786def test_ap_ft_gcmp_256(dev, apdev):
787 """WPA2-PSK-FT AP with GCMP-256 cipher"""
788 if "GCMP-256" not in dev[0].get_capability("pairwise"):
789 raise HwsimSkip("Cipher GCMP-256 not supported")
790 ssid = "test-ft"
791 passphrase="12345678"
792
793 params = ft_params1(ssid=ssid, passphrase=passphrase)
794 params['rsn_pairwise'] = "GCMP-256"
8b8a1864 795 hapd0 = hostapd.add_ap(apdev[0], params)
7b741a53
JM
796 params = ft_params2(ssid=ssid, passphrase=passphrase)
797 params['rsn_pairwise'] = "GCMP-256"
8b8a1864 798 hapd1 = hostapd.add_ap(apdev[1], params)
7b741a53
JM
799
800 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase,
801 pairwise_cipher="GCMP-256", group_cipher="GCMP-256")
cf671d54
JM
802
803def test_ap_ft_oom(dev, apdev):
804 """WPA2-PSK-FT and OOM"""
38934ed1 805 skip_with_fips(dev[0])
cf671d54
JM
806 ssid = "test-ft"
807 passphrase="12345678"
808
809 params = ft_params1(ssid=ssid, passphrase=passphrase)
8b8a1864 810 hapd0 = hostapd.add_ap(apdev[0], params)
cf671d54 811 params = ft_params2(ssid=ssid, passphrase=passphrase)
8b8a1864 812 hapd1 = hostapd.add_ap(apdev[1], params)
cf671d54
JM
813
814 dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
815 scan_freq="2412")
816 if dev[0].get_status_field('bssid') == apdev[0]['bssid']:
817 dst = apdev[1]['bssid']
818 else:
819 dst = apdev[0]['bssid']
820
821 dev[0].scan_for_bss(dst, freq="2412")
822 with alloc_fail(dev[0], 1, "wpa_ft_gen_req_ies"):
823 dev[0].roam(dst)
7cbc8e67 824 with fail_test(dev[0], 1, "wpa_ft_mic"):
cf671d54
JM
825 dev[0].roam(dst, fail_test=True)
826 with fail_test(dev[0], 1, "os_get_random;wpa_ft_prepare_auth_request"):
827 dev[0].roam(dst, fail_test=True)
34d3eaa8 828
dcbb5d80
JM
829 dev[0].request("REMOVE_NETWORK all")
830 with alloc_fail(dev[0], 1, "=sme_update_ft_ies"):
831 dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
832 scan_freq="2412")
833
34d3eaa8
JM
834def test_ap_ft_over_ds_proto(dev, apdev):
835 """WPA2-PSK-FT AP over DS protocol testing"""
836 ssid = "test-ft"
837 passphrase="12345678"
838
839 params = ft_params1(ssid=ssid, passphrase=passphrase)
8b8a1864 840 hapd0 = hostapd.add_ap(apdev[0], params)
34d3eaa8
JM
841 dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
842 scan_freq="2412")
843
844 # FT Action Response while no FT-over-DS in progress
845 msg = {}
846 msg['fc'] = 13 << 4
847 msg['da'] = dev[0].own_addr()
848 msg['sa'] = apdev[0]['bssid']
849 msg['bssid'] = apdev[0]['bssid']
850 msg['payload'] = binascii.unhexlify("06020200000000000200000004000000")
851 hapd0.mgmt_tx(msg)
852
853 params = ft_params2(ssid=ssid, passphrase=passphrase)
8b8a1864 854 hapd1 = hostapd.add_ap(apdev[1], params)
34d3eaa8
JM
855 dev[0].scan_for_bss(apdev[1]['bssid'], freq="2412")
856 hapd0.set("ext_mgmt_frame_handling", "1")
857 hapd0.dump_monitor()
858 dev[0].request("FT_DS " + apdev[1]['bssid'])
859 for i in range(0, 10):
860 req = hapd0.mgmt_rx()
861 if req is None:
862 raise Exception("MGMT RX wait timed out")
863 if req['subtype'] == 13:
864 break
865 req = None
866 if not req:
867 raise Exception("FT Action frame not received")
868
869 # FT Action Response for unexpected Target AP
870 msg['payload'] = binascii.unhexlify("0602020000000000" + "f20000000400" + "0000")
871 hapd0.mgmt_tx(msg)
872
873 # FT Action Response without MDIE
874 msg['payload'] = binascii.unhexlify("0602020000000000" + "020000000400" + "0000")
875 hapd0.mgmt_tx(msg)
876
877 # FT Action Response without FTIE
878 msg['payload'] = binascii.unhexlify("0602020000000000" + "020000000400" + "0000" + "3603a1b201")
879 hapd0.mgmt_tx(msg)
880
881 # FT Action Response with FTIE SNonce mismatch
882 msg['payload'] = binascii.unhexlify("0602020000000000" + "020000000400" + "0000" + "3603a1b201" + "3766000000000000000000000000000000000000c4e67ac1999bebd00ff4ae4d5dcaf87896bb060b469f7c78d49623fb395c3455ffffff6b693fe6f8d8c5dfac0a22344750775bd09437f98b238c9f87b97f790c0106000102030406030a6e6173312e77312e6669")
883 hapd0.mgmt_tx(msg)
6f3815c0 884
9fd6804d 885@remote_compatible
6f3815c0
JM
886def test_ap_ft_rrb(dev, apdev):
887 """WPA2-PSK-FT RRB protocol testing"""
888 ssid = "test-ft"
889 passphrase="12345678"
890
891 params = ft_params1(ssid=ssid, passphrase=passphrase)
8b8a1864 892 hapd0 = hostapd.add_ap(apdev[0], params)
6f3815c0
JM
893
894 dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
895 scan_freq="2412")
896
897 _dst_ll = binascii.unhexlify(apdev[0]['bssid'].replace(':',''))
898 _src_ll = binascii.unhexlify(dev[0].own_addr().replace(':',''))
899 proto = '\x89\x0d'
900 ehdr = _dst_ll + _src_ll + proto
901
902 # Too short RRB frame
903 pkt = ehdr + '\x01'
904 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
905 raise Exception("DATA_TEST_FRAME failed")
906
907 # RRB discarded frame wikth unrecognized type
908 pkt = ehdr + '\x02' + '\x02' + '\x01\x00' + _src_ll
909 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
910 raise Exception("DATA_TEST_FRAME failed")
911
912 # RRB frame too short for action frame
913 pkt = ehdr + '\x01' + '\x02' + '\x01\x00' + _src_ll
914 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
915 raise Exception("DATA_TEST_FRAME failed")
916
917 # Too short RRB frame (not enough room for Action Frame body)
918 pkt = ehdr + '\x01' + '\x02' + '\x00\x00' + _src_ll
919 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
920 raise Exception("DATA_TEST_FRAME failed")
921
922 # Unexpected Action frame category
923 pkt = ehdr + '\x01' + '\x02' + '\x0e\x00' + _src_ll + '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
924 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
925 raise Exception("DATA_TEST_FRAME failed")
926
927 # Unexpected Action in RRB Request
928 pkt = ehdr + '\x01' + '\x00' + '\x0e\x00' + _src_ll + '\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
929 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
930 raise Exception("DATA_TEST_FRAME failed")
931
932 # Target AP address in RRB Request does not match with own address
933 pkt = ehdr + '\x01' + '\x00' + '\x0e\x00' + _src_ll + '\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
934 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
935 raise Exception("DATA_TEST_FRAME failed")
936
937 # Not enough room for status code in RRB Response
938 pkt = ehdr + '\x01' + '\x01' + '\x0e\x00' + _src_ll + '\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
939 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
940 raise Exception("DATA_TEST_FRAME failed")
941
942 # RRB discarded frame with unknown packet_type
943 pkt = ehdr + '\x01' + '\x02' + '\x0e\x00' + _src_ll + '\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
944 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
945 raise Exception("DATA_TEST_FRAME failed")
946
947 # RRB Response with non-zero status code; no STA match
948 pkt = ehdr + '\x01' + '\x01' + '\x10\x00' + _src_ll + '\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + '\xff\xff'
949 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
950 raise Exception("DATA_TEST_FRAME failed")
951
952 # RRB Response with zero status code and extra data; STA match
953 pkt = ehdr + '\x01' + '\x01' + '\x11\x00' + _src_ll + '\x06\x01' + _src_ll + '\x00\x00\x00\x00\x00\x00' + '\x00\x00' + '\x00'
954 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
955 raise Exception("DATA_TEST_FRAME failed")
956
957 # Too short PMK-R1 pull
958 pkt = ehdr + '\x01' + '\xc8' + '\x0e\x00' + _src_ll + '\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
959 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
960 raise Exception("DATA_TEST_FRAME failed")
961
962 # Too short PMK-R1 resp
963 pkt = ehdr + '\x01' + '\xc9' + '\x0e\x00' + _src_ll + '\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
964 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
965 raise Exception("DATA_TEST_FRAME failed")
966
967 # Too short PMK-R1 push
968 pkt = ehdr + '\x01' + '\xca' + '\x0e\x00' + _src_ll + '\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
969 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
970 raise Exception("DATA_TEST_FRAME failed")
971
972 # No matching R0KH address found for PMK-R0 pull response
973 pkt = ehdr + '\x01' + '\xc9' + '\x5a\x00' + _src_ll + '\x06\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' + 76*'\00'
974 if "OK" not in dev[0].request("DATA_TEST_FRAME " + binascii.hexlify(pkt)):
975 raise Exception("DATA_TEST_FRAME failed")
ecafa0cf 976
9fd6804d 977@remote_compatible
ecafa0cf
JM
978def test_rsn_ie_proto_ft_psk_sta(dev, apdev):
979 """RSN element protocol testing for FT-PSK + PMF cases on STA side"""
980 bssid = apdev[0]['bssid']
981 ssid = "test-ft"
982 passphrase="12345678"
983
984 params = ft_params1(ssid=ssid, passphrase=passphrase)
bc6e3288 985 params["ieee80211w"] = "1"
ecafa0cf
JM
986 # This is the RSN element used normally by hostapd
987 params['own_ie_override'] = '30140100000fac040100000fac040100000fac048c00' + '3603a1b201'
8b8a1864 988 hapd = hostapd.add_ap(apdev[0], params)
ecafa0cf
JM
989 id = dev[0].connect(ssid, psk=passphrase, key_mgmt="FT-PSK", proto="WPA2",
990 ieee80211w="1", scan_freq="2412",
991 pairwise="CCMP", group="CCMP")
992
993 tests = [ ('PMKIDCount field included',
994 '30160100000fac040100000fac040100000fac048c000000' + '3603a1b201'),
995 ('Extra IE before RSNE',
996 'dd0400000000' + '30140100000fac040100000fac040100000fac048c00' + '3603a1b201'),
997 ('PMKIDCount and Group Management Cipher suite fields included',
998 '301a0100000fac040100000fac040100000fac048c000000000fac06' + '3603a1b201'),
999 ('Extra octet after defined fields (future extensibility)',
1000 '301b0100000fac040100000fac040100000fac048c000000000fac0600' + '3603a1b201'),
1001 ('No RSN Capabilities field (PMF disabled in practice)',
1002 '30120100000fac040100000fac040100000fac04' + '3603a1b201') ]
1003 for txt,ie in tests:
1004 dev[0].request("DISCONNECT")
1005 dev[0].wait_disconnected()
1006 logger.info(txt)
1007 hapd.disable()
1008 hapd.set('own_ie_override', ie)
1009 hapd.enable()
1010 dev[0].request("BSS_FLUSH 0")
1011 dev[0].scan_for_bss(bssid, 2412, force_scan=True, only_new=True)
1012 dev[0].select_network(id, freq=2412)
1013 dev[0].wait_connected()
1014
1015 dev[0].request("DISCONNECT")
1016 dev[0].wait_disconnected()
1017
1018 logger.info('Invalid RSNE causing internal hostapd error')
1019 hapd.disable()
1020 hapd.set('own_ie_override', '30130100000fac040100000fac040100000fac048c' + '3603a1b201')
1021 hapd.enable()
1022 dev[0].request("BSS_FLUSH 0")
1023 dev[0].scan_for_bss(bssid, 2412, force_scan=True, only_new=True)
1024 dev[0].select_network(id, freq=2412)
1025 # hostapd fails to generate EAPOL-Key msg 3/4, so this connection cannot
1026 # complete.
1027 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
1028 if ev is not None:
1029 raise Exception("Unexpected connection")
1030 dev[0].request("DISCONNECT")
1031
1032 logger.info('Unexpected PMKID causing internal hostapd error')
1033 hapd.disable()
1034 hapd.set('own_ie_override', '30260100000fac040100000fac040100000fac048c000100ffffffffffffffffffffffffffffffff' + '3603a1b201')
1035 hapd.enable()
1036 dev[0].request("BSS_FLUSH 0")
1037 dev[0].scan_for_bss(bssid, 2412, force_scan=True, only_new=True)
1038 dev[0].select_network(id, freq=2412)
1039 # hostapd fails to generate EAPOL-Key msg 3/4, so this connection cannot
1040 # complete.
1041 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
1042 if ev is not None:
1043 raise Exception("Unexpected connection")
1044 dev[0].request("DISCONNECT")
1025603b
JM
1045
1046def test_ap_ft_ptk_rekey(dev, apdev):
1047 """WPA2-PSK-FT PTK rekeying triggered by station after roam"""
1048 ssid = "test-ft"
1049 passphrase="12345678"
1050
1051 params = ft_params1(ssid=ssid, passphrase=passphrase)
8b8a1864 1052 hapd0 = hostapd.add_ap(apdev[0], params)
1025603b 1053 params = ft_params2(ssid=ssid, passphrase=passphrase)
8b8a1864 1054 hapd1 = hostapd.add_ap(apdev[1], params)
1025603b
JM
1055
1056 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase, ptk_rekey="1")
1057
1058 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED",
1059 "WPA: Key negotiation completed"], timeout=5)
1060 if ev is None:
1061 raise Exception("No event received after roam")
1062 if "CTRL-EVENT-DISCONNECTED" in ev:
1063 raise Exception("Unexpected disconnection after roam")
1064
1065 if dev[0].get_status_field('bssid') == apdev[0]['bssid']:
1066 hapd = hapd0
1067 else:
1068 hapd = hapd1
1069 hwsim_utils.test_connectivity(dev[0], hapd)
1070
1071def test_ap_ft_ptk_rekey_ap(dev, apdev):
1072 """WPA2-PSK-FT PTK rekeying triggered by AP after roam"""
1073 ssid = "test-ft"
1074 passphrase="12345678"
1075
1076 params = ft_params1(ssid=ssid, passphrase=passphrase)
1077 params['wpa_ptk_rekey'] = '2'
8b8a1864 1078 hapd0 = hostapd.add_ap(apdev[0], params)
1025603b
JM
1079 params = ft_params2(ssid=ssid, passphrase=passphrase)
1080 params['wpa_ptk_rekey'] = '2'
8b8a1864 1081 hapd1 = hostapd.add_ap(apdev[1], params)
1025603b
JM
1082
1083 run_roams(dev[0], apdev, hapd0, hapd1, ssid, passphrase)
1084
1085 ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED",
1086 "WPA: Key negotiation completed"], timeout=5)
1087 if ev is None:
1088 raise Exception("No event received after roam")
1089 if "CTRL-EVENT-DISCONNECTED" in ev:
1090 raise Exception("Unexpected disconnection after roam")
1091
1092 if dev[0].get_status_field('bssid') == apdev[0]['bssid']:
1093 hapd = hapd0
1094 else:
1095 hapd = hapd1
1096 hwsim_utils.test_connectivity(dev[0], hapd)
186ca473
MB
1097
1098def test_ap_ft_internal_rrb_check(dev, apdev):
1099 """RRB internal delivery only to WPA enabled BSS"""
1100 ssid = "test-ft"
1101 passphrase="12345678"
1102
1103 radius = hostapd.radius_params()
1104 params = ft_params1(ssid=ssid, passphrase=passphrase)
1105 params['wpa_key_mgmt'] = "FT-EAP"
1106 params["ieee8021x"] = "1"
1107 params = dict(radius.items() + params.items())
8b8a1864 1108 hapd = hostapd.add_ap(apdev[0], params)
186ca473
MB
1109 key_mgmt = hapd.get_config()['key_mgmt']
1110 if key_mgmt.split(' ')[0] != "FT-EAP":
1111 raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
1112
8b8a1864 1113 hapd1 = hostapd.add_ap(apdev[1], { "ssid" : ssid })
186ca473
MB
1114
1115 # Connect to WPA enabled AP
1116 dev[0].connect(ssid, key_mgmt="FT-EAP", proto="WPA2", ieee80211w="1",
1117 eap="GPSK", identity="gpsk user",
1118 password="abcdefghijklmnop0123456789abcdef",
1119 scan_freq="2412")
1120
1121 # Try over_ds roaming to non-WPA-enabled AP.
1122 # If hostapd does not check hapd->wpa_auth internally, it will crash now.
1123 dev[0].roam_over_ds(apdev[1]['bssid'], fail_test=True)