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