]>
Commit | Line | Data |
---|---|---|
cd7f1b9a JM |
1 | # Fast BSS Transition tests |
2 | # Copyright (c) 2013, Jouni Malinen <j@w1.fi> | |
3 | # | |
4 | # This software may be distributed under the terms of the BSD license. | |
5 | # See README for more details. | |
6 | ||
7 | import time | |
8 | import subprocess | |
9 | import logging | |
c9aa4308 | 10 | logger = logging.getLogger() |
cd7f1b9a JM |
11 | |
12 | import hwsim_utils | |
13 | import hostapd | |
14 | from wlantest import Wlantest | |
eaf3f9b1 | 15 | from test_ap_psk import check_mib |
cd7f1b9a JM |
16 | |
17 | def ft_base_rsn(): | |
18 | params = { "wpa": "2", | |
19 | "wpa_key_mgmt": "FT-PSK", | |
20 | "rsn_pairwise": "CCMP" } | |
21 | return params | |
22 | ||
23 | def ft_base_mixed(): | |
24 | params = { "wpa": "3", | |
25 | "wpa_key_mgmt": "WPA-PSK FT-PSK", | |
26 | "wpa_pairwise": "TKIP", | |
27 | "rsn_pairwise": "CCMP" } | |
28 | return params | |
29 | ||
30 | def ft_params(rsn=True, ssid=None, passphrase=None): | |
31 | if rsn: | |
32 | params = ft_base_rsn() | |
33 | else: | |
34 | params = ft_base_mixed() | |
35 | if ssid: | |
36 | params["ssid"] = ssid | |
37 | if passphrase: | |
38 | params["wpa_passphrase"] = passphrase | |
39 | ||
40 | params["mobility_domain"] = "a1b2" | |
41 | params["r0_key_lifetime"] = "10000" | |
42 | params["pmk_r1_push"] = "1" | |
43 | params["reassociation_deadline"] = "1000" | |
44 | return params | |
45 | ||
46 | def ft_params1(rsn=True, ssid=None, passphrase=None): | |
47 | params = ft_params(rsn, ssid, passphrase) | |
48 | params['nas_identifier'] = "nas1.w1.fi" | |
49 | params['r1_key_holder'] = "000102030405" | |
50 | params['r0kh'] = [ "02:00:00:00:03:00 nas1.w1.fi 100102030405060708090a0b0c0d0e0f", | |
51 | "02:00:00:00:04:00 nas2.w1.fi 300102030405060708090a0b0c0d0e0f" ] | |
52 | params['r1kh'] = "02:00:00:00:04:00 00:01:02:03:04:06 200102030405060708090a0b0c0d0e0f" | |
53 | return params | |
54 | ||
55 | def ft_params2(rsn=True, ssid=None, passphrase=None): | |
56 | params = ft_params(rsn, ssid, passphrase) | |
57 | params['nas_identifier'] = "nas2.w1.fi" | |
58 | params['r1_key_holder'] = "000102030406" | |
59 | params['r0kh'] = [ "02:00:00:00:03:00 nas1.w1.fi 200102030405060708090a0b0c0d0e0f", | |
60 | "02:00:00:00:04:00 nas2.w1.fi 000102030405060708090a0b0c0d0e0f" ] | |
61 | params['r1kh'] = "02:00:00:00:03:00 00:01:02:03:04:05 300102030405060708090a0b0c0d0e0f" | |
62 | return params | |
63 | ||
3b808945 JM |
64 | def ft_params1_r0kh_mismatch(rsn=True, ssid=None, passphrase=None): |
65 | params = ft_params(rsn, ssid, passphrase) | |
66 | params['nas_identifier'] = "nas1.w1.fi" | |
67 | params['r1_key_holder'] = "000102030405" | |
68 | params['r0kh'] = [ "02:00:00:00:03:00 nas1.w1.fi 100102030405060708090a0b0c0d0e0f", | |
69 | "12:00:00:00:04:00 nas2.w1.fi 300102030405060708090a0b0c0d0e0f" ] | |
70 | params['r1kh'] = "12:00:00:00:04:00 10:01:02:03:04:06 200102030405060708090a0b0c0d0e0f" | |
71 | return params | |
72 | ||
73 | def ft_params2_incorrect_rrb_key(rsn=True, ssid=None, passphrase=None): | |
74 | params = ft_params(rsn, ssid, passphrase) | |
75 | params['nas_identifier'] = "nas2.w1.fi" | |
76 | params['r1_key_holder'] = "000102030406" | |
77 | params['r0kh'] = [ "02:00:00:00:03:00 nas1.w1.fi 200102030405060708090a0b0c0d0ef1", | |
78 | "02:00:00:00:04:00 nas2.w1.fi 000102030405060708090a0b0c0d0ef2" ] | |
79 | params['r1kh'] = "02:00:00:00:03:00 00:01:02:03:04:05 300102030405060708090a0b0c0d0ef3" | |
80 | return params | |
81 | ||
82 | def ft_params2_r0kh_mismatch(rsn=True, ssid=None, passphrase=None): | |
83 | params = ft_params(rsn, ssid, passphrase) | |
84 | params['nas_identifier'] = "nas2.w1.fi" | |
85 | params['r1_key_holder'] = "000102030406" | |
86 | params['r0kh'] = [ "12:00:00:00:03:00 nas1.w1.fi 200102030405060708090a0b0c0d0e0f", | |
87 | "02:00:00:00:04:00 nas2.w1.fi 000102030405060708090a0b0c0d0e0f" ] | |
88 | params['r1kh'] = "12:00:00:00:03:00 10:01:02:03:04:05 300102030405060708090a0b0c0d0e0f" | |
89 | return params | |
90 | ||
91 | def run_roams(dev, apdev, ssid, passphrase, over_ds=False, sae=False, eap=False, fail_test=False): | |
cd7f1b9a | 92 | logger.info("Connect to first AP") |
6f62809b JM |
93 | if eap: |
94 | dev.connect(ssid, key_mgmt="FT-EAP", proto="WPA2", ieee80211w="1", | |
95 | eap="EKE", identity="eke user", password="hello") | |
6e658cc4 | 96 | else: |
6f62809b JM |
97 | if sae: |
98 | key_mgmt="FT-SAE" | |
99 | else: | |
100 | key_mgmt="FT-PSK" | |
101 | dev.connect(ssid, psk=passphrase, key_mgmt=key_mgmt, proto="WPA2", | |
102 | ieee80211w="1") | |
cd7f1b9a JM |
103 | if dev.get_status_field('bssid') == apdev[0]['bssid']: |
104 | ap1 = apdev[0] | |
105 | ap2 = apdev[1] | |
106 | else: | |
107 | ap1 = apdev[1] | |
108 | ap2 = apdev[0] | |
109 | hwsim_utils.test_connectivity(dev.ifname, ap1['ifname']) | |
110 | ||
111 | logger.info("Roam to the second AP") | |
b553eab1 | 112 | if over_ds: |
3b808945 | 113 | dev.roam_over_ds(ap2['bssid'], fail_test=fail_test) |
b553eab1 | 114 | else: |
3b808945 JM |
115 | dev.roam(ap2['bssid'], fail_test=fail_test) |
116 | if fail_test: | |
117 | return | |
cd7f1b9a JM |
118 | if dev.get_status_field('bssid') != ap2['bssid']: |
119 | raise Exception("Did not connect to correct AP") | |
120 | hwsim_utils.test_connectivity(dev.ifname, ap2['ifname']) | |
121 | ||
122 | logger.info("Roam back to the first AP") | |
b553eab1 JM |
123 | if over_ds: |
124 | dev.roam_over_ds(ap1['bssid']) | |
125 | else: | |
126 | dev.roam(ap1['bssid']) | |
cd7f1b9a JM |
127 | if dev.get_status_field('bssid') != ap1['bssid']: |
128 | raise Exception("Did not connect to correct AP") | |
129 | hwsim_utils.test_connectivity(dev.ifname, ap1['ifname']) | |
130 | ||
131 | def test_ap_ft(dev, apdev): | |
132 | """WPA2-PSK-FT AP""" | |
133 | ssid = "test-ft" | |
134 | passphrase="12345678" | |
135 | ||
136 | params = ft_params1(ssid=ssid, passphrase=passphrase) | |
137 | hostapd.add_ap(apdev[0]['ifname'], params) | |
138 | params = ft_params2(ssid=ssid, passphrase=passphrase) | |
139 | hostapd.add_ap(apdev[1]['ifname'], params) | |
140 | ||
141 | run_roams(dev[0], apdev, ssid, passphrase) | |
91bc6c36 JM |
142 | if "[WPA2-FT/PSK-CCMP]" not in dev[0].request("SCAN_RESULTS"): |
143 | raise Exception("Scan results missing RSN element info") | |
cd7f1b9a JM |
144 | |
145 | def test_ap_ft_mixed(dev, apdev): | |
146 | """WPA2-PSK-FT mixed-mode AP""" | |
147 | ssid = "test-ft-mixed" | |
148 | passphrase="12345678" | |
149 | ||
150 | params = ft_params1(rsn=False, ssid=ssid, passphrase=passphrase) | |
65038313 JM |
151 | hapd = hostapd.add_ap(apdev[0]['ifname'], params) |
152 | key_mgmt = hapd.get_config()['key_mgmt'] | |
153 | vals = key_mgmt.split(' ') | |
154 | if vals[0] != "WPA-PSK" or vals[1] != "FT-PSK": | |
155 | raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt) | |
cd7f1b9a JM |
156 | params = ft_params2(rsn=False, ssid=ssid, passphrase=passphrase) |
157 | hostapd.add_ap(apdev[1]['ifname'], params) | |
158 | ||
159 | run_roams(dev[0], apdev, ssid, passphrase) | |
160 | ||
161 | def test_ap_ft_pmf(dev, apdev): | |
162 | """WPA2-PSK-FT AP with PMF""" | |
163 | ssid = "test-ft" | |
164 | passphrase="12345678" | |
165 | ||
166 | params = ft_params1(ssid=ssid, passphrase=passphrase) | |
167 | params["ieee80211w"] = "2"; | |
168 | hostapd.add_ap(apdev[0]['ifname'], params) | |
169 | params = ft_params2(ssid=ssid, passphrase=passphrase) | |
170 | params["ieee80211w"] = "2"; | |
171 | hostapd.add_ap(apdev[1]['ifname'], params) | |
172 | ||
173 | run_roams(dev[0], apdev, ssid, passphrase) | |
b553eab1 JM |
174 | |
175 | def test_ap_ft_over_ds(dev, apdev): | |
176 | """WPA2-PSK-FT AP over DS""" | |
177 | ssid = "test-ft" | |
178 | passphrase="12345678" | |
179 | ||
180 | params = ft_params1(ssid=ssid, passphrase=passphrase) | |
181 | hostapd.add_ap(apdev[0]['ifname'], params) | |
182 | params = ft_params2(ssid=ssid, passphrase=passphrase) | |
183 | hostapd.add_ap(apdev[1]['ifname'], params) | |
184 | ||
185 | run_roams(dev[0], apdev, ssid, passphrase, over_ds=True) | |
eaf3f9b1 JM |
186 | check_mib(dev[0], [ ("dot11RSNAAuthenticationSuiteRequested", "00-0f-ac-4"), |
187 | ("dot11RSNAAuthenticationSuiteSelected", "00-0f-ac-4") ]) | |
b553eab1 JM |
188 | |
189 | def test_ap_ft_pmf_over_ds(dev, apdev): | |
190 | """WPA2-PSK-FT AP over DS with PMF""" | |
191 | ssid = "test-ft" | |
192 | passphrase="12345678" | |
193 | ||
194 | params = ft_params1(ssid=ssid, passphrase=passphrase) | |
195 | params["ieee80211w"] = "2"; | |
196 | hostapd.add_ap(apdev[0]['ifname'], params) | |
197 | params = ft_params2(ssid=ssid, passphrase=passphrase) | |
198 | params["ieee80211w"] = "2"; | |
199 | hostapd.add_ap(apdev[1]['ifname'], params) | |
200 | ||
201 | run_roams(dev[0], apdev, ssid, passphrase, over_ds=True) | |
6e658cc4 | 202 | |
aaba98d3 JM |
203 | def test_ap_ft_over_ds_pull(dev, apdev): |
204 | """WPA2-PSK-FT AP over DS (pull PMK)""" | |
205 | ssid = "test-ft" | |
206 | passphrase="12345678" | |
207 | ||
208 | params = ft_params1(ssid=ssid, passphrase=passphrase) | |
209 | params["pmk_r1_push"] = "0" | |
210 | hostapd.add_ap(apdev[0]['ifname'], params) | |
211 | params = ft_params2(ssid=ssid, passphrase=passphrase) | |
212 | params["pmk_r1_push"] = "0" | |
213 | hostapd.add_ap(apdev[1]['ifname'], params) | |
214 | ||
215 | run_roams(dev[0], apdev, ssid, passphrase, over_ds=True) | |
216 | ||
6e658cc4 JM |
217 | def test_ap_ft_sae(dev, apdev): |
218 | """WPA2-PSK-FT-SAE AP""" | |
219 | ssid = "test-ft" | |
220 | passphrase="12345678" | |
221 | ||
222 | params = ft_params1(ssid=ssid, passphrase=passphrase) | |
223 | params['wpa_key_mgmt'] = "FT-SAE" | |
224 | hostapd.add_ap(apdev[0]['ifname'], params) | |
225 | params = ft_params2(ssid=ssid, passphrase=passphrase) | |
226 | params['wpa_key_mgmt'] = "FT-SAE" | |
65038313 JM |
227 | hapd = hostapd.add_ap(apdev[1]['ifname'], params) |
228 | key_mgmt = hapd.get_config()['key_mgmt'] | |
229 | if key_mgmt.split(' ')[0] != "FT-SAE": | |
230 | raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt) | |
6e658cc4 JM |
231 | |
232 | run_roams(dev[0], apdev, ssid, passphrase, sae=True) | |
233 | ||
234 | def test_ap_ft_sae_over_ds(dev, apdev): | |
235 | """WPA2-PSK-FT-SAE AP over DS""" | |
236 | ssid = "test-ft" | |
237 | passphrase="12345678" | |
238 | ||
239 | params = ft_params1(ssid=ssid, passphrase=passphrase) | |
240 | params['wpa_key_mgmt'] = "FT-SAE" | |
241 | hostapd.add_ap(apdev[0]['ifname'], params) | |
242 | params = ft_params2(ssid=ssid, passphrase=passphrase) | |
243 | params['wpa_key_mgmt'] = "FT-SAE" | |
244 | hostapd.add_ap(apdev[1]['ifname'], params) | |
245 | ||
246 | run_roams(dev[0], apdev, ssid, passphrase, sae=True, over_ds=True) | |
6f62809b JM |
247 | |
248 | def test_ap_ft_eap(dev, apdev): | |
249 | """WPA2-EAP-FT AP""" | |
250 | ssid = "test-ft" | |
251 | passphrase="12345678" | |
252 | ||
253 | radius = hostapd.radius_params() | |
254 | params = ft_params1(ssid=ssid, passphrase=passphrase) | |
255 | params['wpa_key_mgmt'] = "FT-EAP" | |
256 | params["ieee8021x"] = "1" | |
257 | params = dict(radius.items() + params.items()) | |
65038313 JM |
258 | hapd = hostapd.add_ap(apdev[0]['ifname'], params) |
259 | key_mgmt = hapd.get_config()['key_mgmt'] | |
260 | if key_mgmt.split(' ')[0] != "FT-EAP": | |
261 | raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt) | |
6f62809b JM |
262 | params = ft_params2(ssid=ssid, passphrase=passphrase) |
263 | params['wpa_key_mgmt'] = "FT-EAP" | |
264 | params["ieee8021x"] = "1" | |
265 | params = dict(radius.items() + params.items()) | |
266 | hostapd.add_ap(apdev[1]['ifname'], params) | |
267 | ||
268 | run_roams(dev[0], apdev, ssid, passphrase, eap=True) | |
91bc6c36 JM |
269 | if "[WPA2-FT/EAP-CCMP]" not in dev[0].request("SCAN_RESULTS"): |
270 | raise Exception("Scan results missing RSN element info") | |
eaf3f9b1 JM |
271 | check_mib(dev[0], [ ("dot11RSNAAuthenticationSuiteRequested", "00-0f-ac-3"), |
272 | ("dot11RSNAAuthenticationSuiteSelected", "00-0f-ac-3") ]) | |
aaba98d3 JM |
273 | |
274 | def test_ap_ft_eap_pull(dev, apdev): | |
275 | """WPA2-EAP-FT AP (pull PMK)""" | |
276 | ssid = "test-ft" | |
277 | passphrase="12345678" | |
278 | ||
279 | radius = hostapd.radius_params() | |
280 | params = ft_params1(ssid=ssid, passphrase=passphrase) | |
281 | params['wpa_key_mgmt'] = "FT-EAP" | |
282 | params["ieee8021x"] = "1" | |
283 | params["pmk_r1_push"] = "0" | |
284 | params = dict(radius.items() + params.items()) | |
285 | hapd = hostapd.add_ap(apdev[0]['ifname'], params) | |
286 | key_mgmt = hapd.get_config()['key_mgmt'] | |
287 | if key_mgmt.split(' ')[0] != "FT-EAP": | |
288 | raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt) | |
289 | params = ft_params2(ssid=ssid, passphrase=passphrase) | |
290 | params['wpa_key_mgmt'] = "FT-EAP" | |
291 | params["ieee8021x"] = "1" | |
292 | params["pmk_r1_push"] = "0" | |
293 | params = dict(radius.items() + params.items()) | |
294 | hostapd.add_ap(apdev[1]['ifname'], params) | |
295 | ||
296 | run_roams(dev[0], apdev, ssid, passphrase, eap=True) | |
3b808945 JM |
297 | |
298 | def test_ap_ft_mismatching_rrb_key_push(dev, apdev): | |
299 | """WPA2-PSK-FT AP over DS with mismatching RRB key (push)""" | |
300 | ssid = "test-ft" | |
301 | passphrase="12345678" | |
302 | ||
303 | params = ft_params1(ssid=ssid, passphrase=passphrase) | |
304 | params["ieee80211w"] = "2"; | |
305 | hostapd.add_ap(apdev[0]['ifname'], params) | |
306 | params = ft_params2_incorrect_rrb_key(ssid=ssid, passphrase=passphrase) | |
307 | params["ieee80211w"] = "2"; | |
308 | hostapd.add_ap(apdev[1]['ifname'], params) | |
309 | ||
310 | run_roams(dev[0], apdev, ssid, passphrase, over_ds=True, fail_test=True) | |
311 | ||
312 | def test_ap_ft_mismatching_rrb_key_pull(dev, apdev): | |
313 | """WPA2-PSK-FT AP over DS with mismatching RRB key (pull)""" | |
314 | ssid = "test-ft" | |
315 | passphrase="12345678" | |
316 | ||
317 | params = ft_params1(ssid=ssid, passphrase=passphrase) | |
318 | params["pmk_r1_push"] = "0" | |
319 | hostapd.add_ap(apdev[0]['ifname'], params) | |
320 | params = ft_params2_incorrect_rrb_key(ssid=ssid, passphrase=passphrase) | |
321 | params["pmk_r1_push"] = "0" | |
322 | hostapd.add_ap(apdev[1]['ifname'], params) | |
323 | ||
324 | run_roams(dev[0], apdev, ssid, passphrase, over_ds=True, fail_test=True) | |
325 | ||
326 | def test_ap_ft_mismatching_rrb_r0kh_push(dev, apdev): | |
327 | """WPA2-PSK-FT AP over DS with mismatching R0KH key (push)""" | |
328 | ssid = "test-ft" | |
329 | passphrase="12345678" | |
330 | ||
331 | params = ft_params1(ssid=ssid, passphrase=passphrase) | |
332 | params["ieee80211w"] = "2"; | |
333 | hostapd.add_ap(apdev[0]['ifname'], params) | |
334 | params = ft_params2_r0kh_mismatch(ssid=ssid, passphrase=passphrase) | |
335 | params["ieee80211w"] = "2"; | |
336 | hostapd.add_ap(apdev[1]['ifname'], params) | |
337 | ||
338 | run_roams(dev[0], apdev, ssid, passphrase, over_ds=True, fail_test=True) | |
339 | ||
340 | def test_ap_ft_mismatching_rrb_r0kh_pull(dev, apdev): | |
341 | """WPA2-PSK-FT AP over DS with mismatching R0KH key (pull)""" | |
342 | ssid = "test-ft" | |
343 | passphrase="12345678" | |
344 | ||
345 | params = ft_params1_r0kh_mismatch(ssid=ssid, passphrase=passphrase) | |
346 | params["pmk_r1_push"] = "0" | |
347 | hostapd.add_ap(apdev[0]['ifname'], params) | |
348 | params = ft_params2(ssid=ssid, passphrase=passphrase) | |
349 | params["pmk_r1_push"] = "0" | |
350 | hostapd.add_ap(apdev[1]['ifname'], params) | |
351 | ||
352 | run_roams(dev[0], apdev, ssid, passphrase, over_ds=True, fail_test=True) |