]>
Commit | Line | Data |
---|---|---|
1640a2e4 | 1 | # Test cases for SAE |
4c0af8ad | 2 | # Copyright (c) 2013-2020, Jouni Malinen <j@w1.fi> |
1640a2e4 JM |
3 | # |
4 | # This software may be distributed under the terms of the BSD license. | |
5 | # See README for more details. | |
6 | ||
9fd6804d | 7 | from remotehost import remote_compatible |
5b3c40a6 JM |
8 | import binascii |
9 | import os | |
1640a2e4 | 10 | import time |
1640a2e4 JM |
11 | import logging |
12 | logger = logging.getLogger() | |
e43352ff JM |
13 | import socket |
14 | import struct | |
15 | import subprocess | |
1640a2e4 JM |
16 | |
17 | import hwsim_utils | |
18 | import hostapd | |
33822240 | 19 | from wpasupplicant import WpaSupplicant |
8030e2b5 | 20 | from utils import HwsimSkip, alloc_fail, fail_test, wait_fail_trigger, start_monitor, stop_monitor, radiotap_build |
5b3c40a6 | 21 | from test_ap_psk import find_wpas_process, read_process_memory, verify_not_present, get_key_locations |
1640a2e4 | 22 | |
4c0af8ad JM |
23 | def check_sae_capab(dev): |
24 | if "SAE" not in dev.get_capability("auth_alg"): | |
25 | raise HwsimSkip("SAE not supported") | |
26 | ||
9fd6804d | 27 | @remote_compatible |
1640a2e4 JM |
28 | def test_sae(dev, apdev): |
29 | """SAE with default group""" | |
4c0af8ad | 30 | check_sae_capab(dev[0]) |
1640a2e4 JM |
31 | params = hostapd.wpa2_params(ssid="test-sae", |
32 | passphrase="12345678") | |
33 | params['wpa_key_mgmt'] = 'SAE' | |
8b8a1864 | 34 | hapd = hostapd.add_ap(apdev[0], params) |
65038313 JM |
35 | key_mgmt = hapd.get_config()['key_mgmt'] |
36 | if key_mgmt.split(' ')[0] != "SAE": | |
37 | raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt) | |
1640a2e4 JM |
38 | |
39 | dev[0].request("SET sae_groups ") | |
40 | id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
41 | scan_freq="2412") | |
6478f437 | 42 | hapd.wait_sta() |
1640a2e4 JM |
43 | if dev[0].get_status_field('sae_group') != '19': |
44 | raise Exception("Expected default SAE group not used") | |
d463c556 JM |
45 | bss = dev[0].get_bss(apdev[0]['bssid']) |
46 | if 'flags' not in bss: | |
47 | raise Exception("Could not get BSS flags from BSS table") | |
48 | if "[WPA2-SAE-CCMP]" not in bss['flags']: | |
49 | raise Exception("Unexpected BSS flags: " + bss['flags']) | |
1640a2e4 | 50 | |
7b28c408 JM |
51 | res = hapd.request("STA-FIRST") |
52 | if "sae_group=19" not in res.splitlines(): | |
53 | raise Exception("hostapd STA output did not specify SAE group") | |
54 | ||
6478f437 JM |
55 | pmk_h = hapd.request("GET_PMK " + dev[0].own_addr()) |
56 | pmk_w = dev[0].get_pmk(id) | |
57 | if pmk_h != pmk_w: | |
58 | raise Exception("Fetched PMK does not match: hostapd %s, wpa_supplicant %s" % (pmk_h, pmk_w)) | |
59 | ||
9fd6804d | 60 | @remote_compatible |
33dcced5 JM |
61 | def test_sae_password_ecc(dev, apdev): |
62 | """SAE with number of different passwords (ECC)""" | |
4c0af8ad | 63 | check_sae_capab(dev[0]) |
33dcced5 JM |
64 | params = hostapd.wpa2_params(ssid="test-sae", |
65 | passphrase="12345678") | |
66 | params['wpa_key_mgmt'] = 'SAE' | |
8b8a1864 | 67 | hapd = hostapd.add_ap(apdev[0], params) |
33dcced5 JM |
68 | |
69 | dev[0].request("SET sae_groups 19") | |
70 | ||
71 | for i in range(10): | |
72 | password = "12345678-" + str(i) | |
73 | hapd.set("wpa_passphrase", password) | |
74 | dev[0].connect("test-sae", psk=password, key_mgmt="SAE", | |
75 | scan_freq="2412") | |
76 | dev[0].request("REMOVE_NETWORK all") | |
77 | dev[0].wait_disconnected() | |
78 | ||
9fd6804d | 79 | @remote_compatible |
33dcced5 JM |
80 | def test_sae_password_ffc(dev, apdev): |
81 | """SAE with number of different passwords (FFC)""" | |
4c0af8ad | 82 | check_sae_capab(dev[0]) |
33dcced5 JM |
83 | params = hostapd.wpa2_params(ssid="test-sae", |
84 | passphrase="12345678") | |
85 | params['wpa_key_mgmt'] = 'SAE' | |
8e607b1b | 86 | params['sae_groups'] = '15' |
8b8a1864 | 87 | hapd = hostapd.add_ap(apdev[0], params) |
33dcced5 | 88 | |
8e607b1b | 89 | dev[0].request("SET sae_groups 15") |
33dcced5 JM |
90 | |
91 | for i in range(10): | |
92 | password = "12345678-" + str(i) | |
93 | hapd.set("wpa_passphrase", password) | |
94 | dev[0].connect("test-sae", psk=password, key_mgmt="SAE", | |
95 | scan_freq="2412") | |
96 | dev[0].request("REMOVE_NETWORK all") | |
97 | dev[0].wait_disconnected() | |
98 | ||
9fd6804d | 99 | @remote_compatible |
19d3a6e3 JM |
100 | def test_sae_pmksa_caching(dev, apdev): |
101 | """SAE and PMKSA caching""" | |
b6fe6e8b JM |
102 | run_sae_pmksa_caching(dev, apdev) |
103 | ||
104 | @remote_compatible | |
105 | def test_sae_pmksa_caching_pmkid(dev, apdev): | |
106 | """SAE and PMKSA caching (PMKID in AssocReq after SAE)""" | |
107 | try: | |
108 | dev[0].set("sae_pmkid_in_assoc", "1") | |
109 | run_sae_pmksa_caching(dev, apdev) | |
110 | finally: | |
111 | dev[0].set("sae_pmkid_in_assoc", "0") | |
112 | ||
113 | def run_sae_pmksa_caching(dev, apdev): | |
4c0af8ad | 114 | check_sae_capab(dev[0]) |
19d3a6e3 JM |
115 | params = hostapd.wpa2_params(ssid="test-sae", |
116 | passphrase="12345678") | |
117 | params['wpa_key_mgmt'] = 'SAE' | |
8b8a1864 | 118 | hapd = hostapd.add_ap(apdev[0], params) |
19d3a6e3 JM |
119 | |
120 | dev[0].request("SET sae_groups ") | |
121 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
122 | scan_freq="2412") | |
fab49f61 | 123 | ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=5) |
7cc9a81f JM |
124 | if ev is None: |
125 | raise Exception("No connection event received from hostapd") | |
61ec2353 JM |
126 | sta0 = hapd.get_sta(dev[0].own_addr()) |
127 | if sta0['wpa'] != '2' or sta0['AKMSuiteSelector'] != '00-0f-ac-8': | |
128 | raise Exception("SAE STA(0) AKM suite selector reported incorrectly") | |
19d3a6e3 | 129 | dev[0].request("DISCONNECT") |
7cc9a81f | 130 | dev[0].wait_disconnected() |
19d3a6e3 | 131 | dev[0].request("RECONNECT") |
5f35a5e2 | 132 | dev[0].wait_connected(timeout=15, error="Reconnect timed out") |
19d3a6e3 JM |
133 | if dev[0].get_status_field('sae_group') is not None: |
134 | raise Exception("SAE group claimed to have been used") | |
61ec2353 JM |
135 | sta0 = hapd.get_sta(dev[0].own_addr()) |
136 | if sta0['wpa'] != '2' or sta0['AKMSuiteSelector'] != '00-0f-ac-8': | |
137 | raise Exception("SAE STA(0) AKM suite selector reported incorrectly after PMKSA caching") | |
19d3a6e3 | 138 | |
9fd6804d | 139 | @remote_compatible |
19d3a6e3 JM |
140 | def test_sae_pmksa_caching_disabled(dev, apdev): |
141 | """SAE and PMKSA caching disabled""" | |
4c0af8ad | 142 | check_sae_capab(dev[0]) |
19d3a6e3 JM |
143 | params = hostapd.wpa2_params(ssid="test-sae", |
144 | passphrase="12345678") | |
145 | params['wpa_key_mgmt'] = 'SAE' | |
146 | params['disable_pmksa_caching'] = '1' | |
8b8a1864 | 147 | hapd = hostapd.add_ap(apdev[0], params) |
19d3a6e3 JM |
148 | |
149 | dev[0].request("SET sae_groups ") | |
150 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
151 | scan_freq="2412") | |
fab49f61 | 152 | ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=5) |
7cc9a81f JM |
153 | if ev is None: |
154 | raise Exception("No connection event received from hostapd") | |
19d3a6e3 | 155 | dev[0].request("DISCONNECT") |
7cc9a81f | 156 | dev[0].wait_disconnected() |
19d3a6e3 | 157 | dev[0].request("RECONNECT") |
5f35a5e2 | 158 | dev[0].wait_connected(timeout=15, error="Reconnect timed out") |
19d3a6e3 JM |
159 | if dev[0].get_status_field('sae_group') != '19': |
160 | raise Exception("Expected default SAE group not used") | |
161 | ||
1640a2e4 JM |
162 | def test_sae_groups(dev, apdev): |
163 | """SAE with all supported groups""" | |
4c0af8ad | 164 | check_sae_capab(dev[0]) |
b1f487cb JM |
165 | # This is the full list of supported groups, but groups 14-16 (2048-4096 bit |
166 | # MODP) and group 21 (521-bit random ECP group) are a bit too slow on some | |
167 | # VMs and can result in hitting the mac80211 authentication timeout, so | |
168 | # allow them to fail and just report such failures in the debug log. | |
fab49f61 | 169 | sae_groups = [19, 25, 26, 20, 21, 1, 2, 5, 14, 15, 16, 22, 23, 24] |
9e286d5e | 170 | tls = dev[0].request("GET tls_library") |
a053ab95 | 171 | if tls.startswith("OpenSSL") and "run=OpenSSL 1." in tls: |
9e286d5e | 172 | logger.info("Add Brainpool EC groups since OpenSSL is new enough") |
fab49f61 JM |
173 | sae_groups += [27, 28, 29, 30] |
174 | heavy_groups = [14, 15, 16] | |
e57e3f12 | 175 | suitable_groups = [15, 16, 17, 18, 19, 20, 21] |
1640a2e4 JM |
176 | groups = [str(g) for g in sae_groups] |
177 | params = hostapd.wpa2_params(ssid="test-sae-groups", | |
178 | passphrase="12345678") | |
179 | params['wpa_key_mgmt'] = 'SAE' | |
180 | params['sae_groups'] = ' '.join(groups) | |
48e999e9 | 181 | hapd = hostapd.add_ap(apdev[0], params) |
1640a2e4 JM |
182 | |
183 | for g in groups: | |
184 | logger.info("Testing SAE group " + g) | |
185 | dev[0].request("SET sae_groups " + g) | |
186 | id = dev[0].connect("test-sae-groups", psk="12345678", key_mgmt="SAE", | |
b1f487cb JM |
187 | scan_freq="2412", wait_connect=False) |
188 | if int(g) in heavy_groups: | |
189 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=5) | |
190 | if ev is None: | |
191 | logger.info("No connection with heavy SAE group %s did not connect - likely hitting timeout in mac80211" % g) | |
192 | dev[0].remove_network(id) | |
193 | time.sleep(0.1) | |
194 | dev[0].dump_monitor() | |
195 | continue | |
196 | logger.info("Connection with heavy SAE group " + g) | |
197 | else: | |
a68d1792 JM |
198 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=10) |
199 | if ev is None: | |
fab49f61 | 200 | if "BoringSSL" in tls and int(g) in [25]: |
a68d1792 JM |
201 | logger.info("Ignore connection failure with group " + g + " with BoringSSL") |
202 | dev[0].remove_network(id) | |
203 | dev[0].dump_monitor() | |
204 | continue | |
8e607b1b JM |
205 | if int(g) not in suitable_groups: |
206 | logger.info("Ignore connection failure with unsuitable group " + g) | |
207 | dev[0].remove_network(id) | |
208 | dev[0].dump_monitor() | |
209 | continue | |
a68d1792 | 210 | raise Exception("Connection timed out with group " + g) |
1640a2e4 JM |
211 | if dev[0].get_status_field('sae_group') != g: |
212 | raise Exception("Expected SAE group not used") | |
48e999e9 JM |
213 | pmksa = dev[0].get_pmksa(hapd.own_addr()) |
214 | if not pmksa: | |
215 | raise Exception("No PMKSA cache entry added") | |
216 | if pmksa['pmkid'] == '00000000000000000000000000000000': | |
217 | raise Exception("All zeros PMKID derived for group %s" % g) | |
1640a2e4 | 218 | dev[0].remove_network(id) |
b1f487cb JM |
219 | dev[0].wait_disconnected() |
220 | dev[0].dump_monitor() | |
1640a2e4 | 221 | |
9fd6804d | 222 | @remote_compatible |
1640a2e4 JM |
223 | def test_sae_group_nego(dev, apdev): |
224 | """SAE group negotiation""" | |
4c0af8ad | 225 | check_sae_capab(dev[0]) |
1640a2e4 JM |
226 | params = hostapd.wpa2_params(ssid="test-sae-group-nego", |
227 | passphrase="12345678") | |
228 | params['wpa_key_mgmt'] = 'SAE' | |
229 | params['sae_groups'] = '19' | |
8b8a1864 | 230 | hostapd.add_ap(apdev[0], params) |
1640a2e4 JM |
231 | |
232 | dev[0].request("SET sae_groups 25 26 20 19") | |
233 | dev[0].connect("test-sae-group-nego", psk="12345678", key_mgmt="SAE", | |
234 | scan_freq="2412") | |
235 | if dev[0].get_status_field('sae_group') != '19': | |
236 | raise Exception("Expected SAE group not used") | |
a6cf5cd6 | 237 | |
914d8eca JM |
238 | def test_sae_group_nego_no_match(dev, apdev): |
239 | """SAE group negotiation (no match)""" | |
4c0af8ad | 240 | check_sae_capab(dev[0]) |
914d8eca JM |
241 | params = hostapd.wpa2_params(ssid="test-sae-group-nego", |
242 | passphrase="12345678") | |
243 | params['wpa_key_mgmt'] = 'SAE' | |
244 | # None-existing SAE group to force all attempts to be rejected | |
245 | params['sae_groups'] = '0' | |
246 | hostapd.add_ap(apdev[0], params) | |
247 | ||
248 | dev[0].request("SET sae_groups ") | |
249 | dev[0].connect("test-sae-group-nego", psk="12345678", key_mgmt="SAE", | |
250 | scan_freq="2412", wait_connect=False) | |
fab49f61 | 251 | ev = dev[0].wait_event(["CTRL-EVENT-SSID-TEMP-DISABLED"], timeout=10) |
914d8eca JM |
252 | dev[0].request("REMOVE_NETWORK all") |
253 | if ev is None: | |
254 | raise Exception("Network profile disabling not reported") | |
255 | ||
9fd6804d | 256 | @remote_compatible |
a6cf5cd6 JM |
257 | def test_sae_anti_clogging(dev, apdev): |
258 | """SAE anti clogging""" | |
4c0af8ad JM |
259 | check_sae_capab(dev[0]) |
260 | check_sae_capab(dev[1]) | |
a6cf5cd6 JM |
261 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
262 | params['wpa_key_mgmt'] = 'SAE' | |
263 | params['sae_anti_clogging_threshold'] = '1' | |
8b8a1864 | 264 | hostapd.add_ap(apdev[0], params) |
a6cf5cd6 JM |
265 | |
266 | dev[0].request("SET sae_groups ") | |
267 | dev[1].request("SET sae_groups ") | |
268 | id = {} | |
269 | for i in range(0, 2): | |
270 | dev[i].scan(freq="2412") | |
271 | id[i] = dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
272 | scan_freq="2412", only_add_network=True) | |
273 | for i in range(0, 2): | |
274 | dev[i].select_network(id[i]) | |
275 | for i in range(0, 2): | |
5f35a5e2 | 276 | dev[i].wait_connected(timeout=10) |
d05ff960 JM |
277 | |
278 | def test_sae_forced_anti_clogging(dev, apdev): | |
279 | """SAE anti clogging (forced)""" | |
4c0af8ad JM |
280 | check_sae_capab(dev[0]) |
281 | check_sae_capab(dev[1]) | |
d05ff960 | 282 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
fd4709ff | 283 | params['wpa_key_mgmt'] = 'SAE WPA-PSK' |
d05ff960 | 284 | params['sae_anti_clogging_threshold'] = '0' |
8b8a1864 | 285 | hostapd.add_ap(apdev[0], params) |
fd4709ff | 286 | dev[2].connect("test-sae", psk="12345678", scan_freq="2412") |
d05ff960 JM |
287 | for i in range(0, 2): |
288 | dev[i].request("SET sae_groups ") | |
289 | dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
290 | scan_freq="2412") | |
291 | ||
292 | def test_sae_mixed(dev, apdev): | |
293 | """Mixed SAE and non-SAE network""" | |
4c0af8ad JM |
294 | check_sae_capab(dev[0]) |
295 | check_sae_capab(dev[1]) | |
d05ff960 JM |
296 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
297 | params['wpa_key_mgmt'] = 'SAE WPA-PSK' | |
298 | params['sae_anti_clogging_threshold'] = '0' | |
61ec2353 | 299 | hapd = hostapd.add_ap(apdev[0], params) |
d05ff960 JM |
300 | |
301 | dev[2].connect("test-sae", psk="12345678", scan_freq="2412") | |
302 | for i in range(0, 2): | |
303 | dev[i].request("SET sae_groups ") | |
304 | dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
305 | scan_freq="2412") | |
61ec2353 JM |
306 | sta0 = hapd.get_sta(dev[0].own_addr()) |
307 | sta2 = hapd.get_sta(dev[2].own_addr()) | |
308 | if sta0['wpa'] != '2' or sta0['AKMSuiteSelector'] != '00-0f-ac-8': | |
309 | raise Exception("SAE STA(0) AKM suite selector reported incorrectly") | |
310 | if sta2['wpa'] != '2' or sta2['AKMSuiteSelector'] != '00-0f-ac-2': | |
311 | raise Exception("PSK STA(2) AKM suite selector reported incorrectly") | |
acb63c75 | 312 | |
fa617ee6 JM |
313 | def test_sae_and_psk(dev, apdev): |
314 | """SAE and PSK enabled in network profile""" | |
4c0af8ad | 315 | check_sae_capab(dev[0]) |
fa617ee6 JM |
316 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
317 | params['wpa_key_mgmt'] = 'SAE' | |
318 | hostapd.add_ap(apdev[0], params) | |
319 | ||
320 | dev[0].request("SET sae_groups ") | |
321 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE WPA-PSK", | |
322 | scan_freq="2412") | |
323 | ||
324 | def test_sae_and_psk2(dev, apdev): | |
325 | """SAE and PSK enabled in network profile (use PSK)""" | |
4c0af8ad | 326 | check_sae_capab(dev[0]) |
fa617ee6 JM |
327 | params = hostapd.wpa2_params(ssid="test-psk", passphrase="12345678") |
328 | hostapd.add_ap(apdev[0], params) | |
329 | ||
330 | dev[0].request("SET sae_groups ") | |
331 | dev[0].connect("test-psk", psk="12345678", key_mgmt="SAE WPA-PSK", | |
332 | scan_freq="2412") | |
333 | ||
5c8df74f JM |
334 | def test_sae_mixed_mfp(dev, apdev): |
335 | """Mixed SAE and non-SAE network and MFP required with SAE""" | |
4c0af8ad JM |
336 | check_sae_capab(dev[0]) |
337 | check_sae_capab(dev[1]) | |
5c8df74f JM |
338 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
339 | params['wpa_key_mgmt'] = 'SAE WPA-PSK' | |
340 | params["ieee80211w"] = "1" | |
341 | params['sae_require_mfp'] = '1' | |
342 | hostapd.add_ap(apdev[0], params) | |
343 | ||
344 | dev[0].request("SET sae_groups ") | |
345 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", ieee80211w="2", | |
346 | scan_freq="2412") | |
347 | dev[0].dump_monitor() | |
348 | ||
349 | dev[1].request("SET sae_groups ") | |
350 | dev[1].connect("test-sae", psk="12345678", key_mgmt="SAE", ieee80211w="0", | |
351 | scan_freq="2412", wait_connect=False) | |
352 | ev = dev[1].wait_event(["CTRL-EVENT-CONNECTED", | |
353 | "CTRL-EVENT-ASSOC-REJECT"], timeout=10) | |
354 | if ev is None: | |
355 | raise Exception("No connection result reported") | |
356 | if "CTRL-EVENT-ASSOC-REJECT" not in ev: | |
357 | raise Exception("SAE connection without MFP was not rejected") | |
358 | if "status_code=31" not in ev: | |
359 | raise Exception("Unexpected status code in rejection: " + ev) | |
360 | dev[1].request("DISCONNECT") | |
361 | dev[1].dump_monitor() | |
362 | ||
363 | dev[2].connect("test-sae", psk="12345678", ieee80211w="0", scan_freq="2412") | |
364 | dev[2].dump_monitor() | |
365 | ||
5cf5680e JM |
366 | def test_sae_and_psk_transition_disable(dev, apdev): |
367 | """SAE and PSK transition disable indication""" | |
368 | check_sae_capab(dev[0]) | |
369 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") | |
370 | params["ieee80211w"] = "1" | |
371 | params['wpa_key_mgmt'] = 'SAE WPA-PSK' | |
372 | params['transition_disable'] = '0x01' | |
373 | hapd = hostapd.add_ap(apdev[0], params) | |
374 | ||
375 | dev[0].request("SET sae_groups ") | |
376 | id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE WPA-PSK", | |
377 | ieee80211w="1", scan_freq="2412") | |
378 | ev = dev[0].wait_event(["TRANSITION-DISABLE"], timeout=1) | |
379 | if ev is None: | |
380 | raise Exception("Transition disable not indicated") | |
381 | if ev.split(' ')[1] != "01": | |
382 | raise Exception("Unexpected transition disable bitmap: " + ev) | |
383 | ||
384 | val = dev[0].get_network(id, "ieee80211w") | |
385 | if val != "2": | |
386 | raise Exception("Unexpected ieee80211w value: " + val) | |
387 | val = dev[0].get_network(id, "key_mgmt") | |
388 | if val != "SAE": | |
389 | raise Exception("Unexpected key_mgmt value: " + val) | |
390 | val = dev[0].get_network(id, "group") | |
391 | if val != "CCMP": | |
392 | raise Exception("Unexpected group value: " + val) | |
393 | val = dev[0].get_network(id, "proto") | |
394 | if val != "RSN": | |
395 | raise Exception("Unexpected proto value: " + val) | |
396 | ||
397 | dev[0].request("DISCONNECT") | |
398 | dev[0].wait_disconnected() | |
399 | dev[0].request("RECONNECT") | |
400 | dev[0].wait_connected() | |
401 | ||
c481e1cb JM |
402 | def test_sae_mfp(dev, apdev): |
403 | """SAE and MFP enabled without sae_require_mfp""" | |
4c0af8ad JM |
404 | check_sae_capab(dev[0]) |
405 | check_sae_capab(dev[1]) | |
c481e1cb JM |
406 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
407 | params['wpa_key_mgmt'] = 'SAE' | |
408 | params["ieee80211w"] = "1" | |
409 | hostapd.add_ap(apdev[0], params) | |
410 | ||
411 | dev[0].request("SET sae_groups ") | |
412 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", ieee80211w="2", | |
413 | scan_freq="2412") | |
414 | ||
415 | dev[1].request("SET sae_groups ") | |
416 | dev[1].connect("test-sae", psk="12345678", key_mgmt="SAE", ieee80211w="0", | |
417 | scan_freq="2412") | |
418 | ||
9fd6804d | 419 | @remote_compatible |
acb63c75 JM |
420 | def test_sae_missing_password(dev, apdev): |
421 | """SAE and missing password""" | |
4c0af8ad | 422 | check_sae_capab(dev[0]) |
acb63c75 JM |
423 | params = hostapd.wpa2_params(ssid="test-sae", |
424 | passphrase="12345678") | |
425 | params['wpa_key_mgmt'] = 'SAE' | |
8b8a1864 | 426 | hapd = hostapd.add_ap(apdev[0], params) |
acb63c75 JM |
427 | |
428 | dev[0].request("SET sae_groups ") | |
429 | id = dev[0].connect("test-sae", | |
430 | raw_psk="46b4a73b8a951ad53ebd2e0afdb9c5483257edd4c21d12b7710759da70945858", | |
431 | key_mgmt="SAE", scan_freq="2412", wait_connect=False) | |
432 | ev = dev[0].wait_event(['CTRL-EVENT-SSID-TEMP-DISABLED'], timeout=10) | |
433 | if ev is None: | |
434 | raise Exception("Invalid network not temporarily disabled") | |
5b3c40a6 JM |
435 | |
436 | ||
437 | def test_sae_key_lifetime_in_memory(dev, apdev, params): | |
438 | """SAE and key lifetime in memory""" | |
4c0af8ad | 439 | check_sae_capab(dev[0]) |
5b3c40a6 JM |
440 | password = "5ad144a7c1f5a5503baa6fa01dabc15b1843e8c01662d78d16b70b5cd23cf8b" |
441 | p = hostapd.wpa2_params(ssid="test-sae", passphrase=password) | |
442 | p['wpa_key_mgmt'] = 'SAE' | |
8b8a1864 | 443 | hapd = hostapd.add_ap(apdev[0], p) |
5b3c40a6 JM |
444 | |
445 | pid = find_wpas_process(dev[0]) | |
446 | ||
447 | dev[0].request("SET sae_groups ") | |
448 | id = dev[0].connect("test-sae", psk=password, key_mgmt="SAE", | |
449 | scan_freq="2412") | |
450 | ||
8e416cec JM |
451 | # The decrypted copy of GTK is freed only after the CTRL-EVENT-CONNECTED |
452 | # event has been delivered, so verify that wpa_supplicant has returned to | |
453 | # eloop before reading process memory. | |
54f2cae2 | 454 | time.sleep(1) |
8e416cec | 455 | dev[0].ping() |
b3361e5d | 456 | password = password.encode() |
5b3c40a6 JM |
457 | buf = read_process_memory(pid, password) |
458 | ||
459 | dev[0].request("DISCONNECT") | |
460 | dev[0].wait_disconnected() | |
461 | ||
462 | dev[0].relog() | |
463 | sae_k = None | |
464 | sae_keyseed = None | |
465 | sae_kck = None | |
466 | pmk = None | |
467 | ptk = None | |
468 | gtk = None | |
469 | with open(os.path.join(params['logdir'], 'log0'), 'r') as f: | |
470 | for l in f.readlines(): | |
471 | if "SAE: k - hexdump" in l: | |
472 | val = l.strip().split(':')[3].replace(' ', '') | |
473 | sae_k = binascii.unhexlify(val) | |
474 | if "SAE: keyseed - hexdump" in l: | |
475 | val = l.strip().split(':')[3].replace(' ', '') | |
476 | sae_keyseed = binascii.unhexlify(val) | |
477 | if "SAE: KCK - hexdump" in l: | |
478 | val = l.strip().split(':')[3].replace(' ', '') | |
479 | sae_kck = binascii.unhexlify(val) | |
480 | if "SAE: PMK - hexdump" in l: | |
481 | val = l.strip().split(':')[3].replace(' ', '') | |
482 | pmk = binascii.unhexlify(val) | |
483 | if "WPA: PTK - hexdump" in l: | |
484 | val = l.strip().split(':')[3].replace(' ', '') | |
485 | ptk = binascii.unhexlify(val) | |
486 | if "WPA: Group Key - hexdump" in l: | |
487 | val = l.strip().split(':')[3].replace(' ', '') | |
488 | gtk = binascii.unhexlify(val) | |
489 | if not sae_k or not sae_keyseed or not sae_kck or not pmk or not ptk or not gtk: | |
490 | raise Exception("Could not find keys from debug log") | |
491 | if len(gtk) != 16: | |
492 | raise Exception("Unexpected GTK length") | |
493 | ||
494 | kck = ptk[0:16] | |
495 | kek = ptk[16:32] | |
496 | tk = ptk[32:48] | |
497 | ||
498 | fname = os.path.join(params['logdir'], | |
499 | 'sae_key_lifetime_in_memory.memctx-') | |
500 | ||
501 | logger.info("Checking keys in memory while associated") | |
502 | get_key_locations(buf, password, "Password") | |
503 | get_key_locations(buf, pmk, "PMK") | |
504 | if password not in buf: | |
81e787b7 | 505 | raise HwsimSkip("Password not found while associated") |
5b3c40a6 | 506 | if pmk not in buf: |
81e787b7 | 507 | raise HwsimSkip("PMK not found while associated") |
5b3c40a6 JM |
508 | if kck not in buf: |
509 | raise Exception("KCK not found while associated") | |
510 | if kek not in buf: | |
511 | raise Exception("KEK not found while associated") | |
b74f82a4 JM |
512 | #if tk in buf: |
513 | # raise Exception("TK found from memory") | |
5b3c40a6 JM |
514 | verify_not_present(buf, sae_k, fname, "SAE(k)") |
515 | verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)") | |
516 | verify_not_present(buf, sae_kck, fname, "SAE(KCK)") | |
517 | ||
518 | logger.info("Checking keys in memory after disassociation") | |
519 | buf = read_process_memory(pid, password) | |
520 | ||
521 | # Note: Password is still present in network configuration | |
522 | # Note: PMK is in PMKSA cache | |
523 | ||
524 | get_key_locations(buf, password, "Password") | |
525 | get_key_locations(buf, pmk, "PMK") | |
526 | verify_not_present(buf, kck, fname, "KCK") | |
527 | verify_not_present(buf, kek, fname, "KEK") | |
528 | verify_not_present(buf, tk, fname, "TK") | |
6db556b2 JM |
529 | if gtk in buf: |
530 | get_key_locations(buf, gtk, "GTK") | |
5b3c40a6 JM |
531 | verify_not_present(buf, gtk, fname, "GTK") |
532 | verify_not_present(buf, sae_k, fname, "SAE(k)") | |
533 | verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)") | |
534 | verify_not_present(buf, sae_kck, fname, "SAE(KCK)") | |
535 | ||
536 | dev[0].request("PMKSA_FLUSH") | |
537 | logger.info("Checking keys in memory after PMKSA cache flush") | |
538 | buf = read_process_memory(pid, password) | |
539 | get_key_locations(buf, password, "Password") | |
540 | get_key_locations(buf, pmk, "PMK") | |
541 | verify_not_present(buf, pmk, fname, "PMK") | |
542 | ||
543 | dev[0].request("REMOVE_NETWORK all") | |
544 | ||
545 | logger.info("Checking keys in memory after network profile removal") | |
546 | buf = read_process_memory(pid, password) | |
547 | ||
548 | get_key_locations(buf, password, "Password") | |
549 | get_key_locations(buf, pmk, "PMK") | |
550 | verify_not_present(buf, password, fname, "password") | |
551 | verify_not_present(buf, pmk, fname, "PMK") | |
552 | verify_not_present(buf, kck, fname, "KCK") | |
553 | verify_not_present(buf, kek, fname, "KEK") | |
554 | verify_not_present(buf, tk, fname, "TK") | |
555 | verify_not_present(buf, gtk, fname, "GTK") | |
556 | verify_not_present(buf, sae_k, fname, "SAE(k)") | |
557 | verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)") | |
558 | verify_not_present(buf, sae_kck, fname, "SAE(KCK)") | |
eb6d3532 | 559 | |
9fd6804d | 560 | @remote_compatible |
eb6d3532 JM |
561 | def test_sae_oom_wpas(dev, apdev): |
562 | """SAE and OOM in wpa_supplicant""" | |
4c0af8ad | 563 | check_sae_capab(dev[0]) |
eb6d3532 JM |
564 | params = hostapd.wpa2_params(ssid="test-sae", |
565 | passphrase="12345678") | |
566 | params['wpa_key_mgmt'] = 'SAE' | |
8e607b1b | 567 | params['sae_groups'] = '19 25 26 20' |
8b8a1864 | 568 | hapd = hostapd.add_ap(apdev[0], params) |
eb6d3532 | 569 | |
8e607b1b | 570 | dev[0].request("SET sae_groups 20") |
eb6d3532 JM |
571 | with alloc_fail(dev[0], 1, "sae_set_group"): |
572 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
573 | scan_freq="2412") | |
574 | dev[0].request("REMOVE_NETWORK all") | |
575 | ||
576 | dev[0].request("SET sae_groups ") | |
577 | with alloc_fail(dev[0], 2, "sae_set_group"): | |
578 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
579 | scan_freq="2412") | |
580 | dev[0].request("REMOVE_NETWORK all") | |
5527a391 | 581 | |
2fd44db7 JM |
582 | with alloc_fail(dev[0], 1, "wpabuf_alloc;sme_auth_build_sae_commit"): |
583 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
584 | scan_freq="2412") | |
585 | dev[0].request("REMOVE_NETWORK all") | |
586 | ||
587 | with alloc_fail(dev[0], 1, "wpabuf_alloc;sme_auth_build_sae_confirm"): | |
588 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
589 | scan_freq="2412", wait_connect=False) | |
590 | wait_fail_trigger(dev[0], "GET_ALLOC_FAIL") | |
591 | dev[0].request("REMOVE_NETWORK all") | |
592 | ||
593 | with alloc_fail(dev[0], 1, "=sme_authenticate"): | |
594 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
595 | scan_freq="2412", wait_connect=False) | |
596 | wait_fail_trigger(dev[0], "GET_ALLOC_FAIL") | |
597 | dev[0].request("REMOVE_NETWORK all") | |
598 | ||
599 | with alloc_fail(dev[0], 1, "radio_add_work;sme_authenticate"): | |
600 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
601 | scan_freq="2412", wait_connect=False) | |
602 | wait_fail_trigger(dev[0], "GET_ALLOC_FAIL") | |
603 | dev[0].request("REMOVE_NETWORK all") | |
604 | ||
9fd6804d | 605 | @remote_compatible |
5527a391 JM |
606 | def test_sae_proto_ecc(dev, apdev): |
607 | """SAE protocol testing (ECC)""" | |
4c0af8ad | 608 | check_sae_capab(dev[0]) |
5527a391 JM |
609 | params = hostapd.wpa2_params(ssid="test-sae", |
610 | passphrase="12345678") | |
611 | params['wpa_key_mgmt'] = 'SAE' | |
8b8a1864 | 612 | hapd = hostapd.add_ap(apdev[0], params) |
5527a391 JM |
613 | bssid = apdev[0]['bssid'] |
614 | ||
615 | dev[0].request("SET sae_groups 19") | |
616 | ||
fab49f61 JM |
617 | tests = [("Confirm mismatch", |
618 | "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8", | |
619 | "0000800edebc3f260dc1fe7e0b20888af2b8a3316252ec37388a8504e25b73dc4240"), | |
620 | ("Commit without even full cyclic group field", | |
621 | "13", | |
622 | None), | |
623 | ("Too short commit", | |
624 | "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02", | |
625 | None), | |
626 | ("Invalid commit scalar (0)", | |
627 | "1300" + "0000000000000000000000000000000000000000000000000000000000000000" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8", | |
628 | None), | |
629 | ("Invalid commit scalar (1)", | |
630 | "1300" + "0000000000000000000000000000000000000000000000000000000000000001" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8", | |
631 | None), | |
632 | ("Invalid commit scalar (> r)", | |
633 | "1300" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8", | |
634 | None), | |
635 | ("Commit element not on curve", | |
636 | "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728d0000000000000000000000000000000000000000000000000000000000000000", | |
637 | None), | |
638 | ("Invalid commit element (y coordinate > P)", | |
639 | "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", | |
640 | None), | |
641 | ("Invalid commit element (x coordinate > P)", | |
642 | "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8", | |
643 | None), | |
644 | ("Different group in commit", | |
645 | "1400" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8", | |
646 | None), | |
647 | ("Too short confirm", | |
648 | "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8", | |
649 | "0000800edebc3f260dc1fe7e0b20888af2b8a3316252ec37388a8504e25b73dc42")] | |
5527a391 JM |
650 | for (note, commit, confirm) in tests: |
651 | logger.info(note) | |
652 | dev[0].scan_for_bss(bssid, freq=2412) | |
653 | hapd.set("ext_mgmt_frame_handling", "1") | |
654 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
655 | scan_freq="2412", wait_connect=False) | |
656 | ||
657 | logger.info("Commit") | |
658 | for i in range(0, 10): | |
659 | req = hapd.mgmt_rx() | |
660 | if req is None: | |
661 | raise Exception("MGMT RX wait timed out (commit)") | |
662 | if req['subtype'] == 11: | |
663 | break | |
664 | req = None | |
665 | if not req: | |
666 | raise Exception("Authentication frame (commit) not received") | |
667 | ||
668 | hapd.dump_monitor() | |
669 | resp = {} | |
670 | resp['fc'] = req['fc'] | |
671 | resp['da'] = req['sa'] | |
672 | resp['sa'] = req['da'] | |
673 | resp['bssid'] = req['bssid'] | |
674 | resp['payload'] = binascii.unhexlify("030001000000" + commit) | |
675 | hapd.mgmt_tx(resp) | |
676 | ||
677 | if confirm: | |
678 | logger.info("Confirm") | |
679 | for i in range(0, 10): | |
680 | req = hapd.mgmt_rx() | |
681 | if req is None: | |
682 | raise Exception("MGMT RX wait timed out (confirm)") | |
683 | if req['subtype'] == 11: | |
684 | break | |
685 | req = None | |
686 | if not req: | |
687 | raise Exception("Authentication frame (confirm) not received") | |
688 | ||
689 | hapd.dump_monitor() | |
690 | resp = {} | |
691 | resp['fc'] = req['fc'] | |
692 | resp['da'] = req['sa'] | |
693 | resp['sa'] = req['da'] | |
694 | resp['bssid'] = req['bssid'] | |
695 | resp['payload'] = binascii.unhexlify("030002000000" + confirm) | |
696 | hapd.mgmt_tx(resp) | |
697 | ||
698 | time.sleep(0.1) | |
699 | dev[0].request("REMOVE_NETWORK all") | |
700 | hapd.set("ext_mgmt_frame_handling", "0") | |
701 | hapd.dump_monitor() | |
702 | ||
9fd6804d | 703 | @remote_compatible |
5527a391 JM |
704 | def test_sae_proto_ffc(dev, apdev): |
705 | """SAE protocol testing (FFC)""" | |
4c0af8ad | 706 | check_sae_capab(dev[0]) |
5527a391 JM |
707 | params = hostapd.wpa2_params(ssid="test-sae", |
708 | passphrase="12345678") | |
709 | params['wpa_key_mgmt'] = 'SAE' | |
8b8a1864 | 710 | hapd = hostapd.add_ap(apdev[0], params) |
5527a391 JM |
711 | bssid = apdev[0]['bssid'] |
712 | ||
713 | dev[0].request("SET sae_groups 2") | |
714 | ||
fab49f61 JM |
715 | tests = [("Confirm mismatch", |
716 | "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "a8c00117493cdffa5dd671e934bc9cb1a69f39e25e9dd9cd9afd3aea2441a0f5491211c7ba50a753563f9ce943b043557cb71193b28e86ed9544f4289c471bf91b70af5c018cf4663e004165b0fd0bc1d8f3f78adf42eee92bcbc55246fd3ee9f107ab965dc7d4986f23eb71d616ebfe6bfe0a6c1ac5dc1718acee17c9a17486", | |
717 | "0000f3116a9731f1259622e3eb55d4b3b50ba16f8c5f5565b28e609b180c51460251"), | |
718 | ("Too short commit", | |
719 | "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "a8c00117493cdffa5dd671e934bc9cb1a69f39e25e9dd9cd9afd3aea2441a0f5491211c7ba50a753563f9ce943b043557cb71193b28e86ed9544f4289c471bf91b70af5c018cf4663e004165b0fd0bc1d8f3f78adf42eee92bcbc55246fd3ee9f107ab965dc7d4986f23eb71d616ebfe6bfe0a6c1ac5dc1718acee17c9a174", | |
720 | None), | |
721 | ("Invalid element (0) in commit", | |
722 | "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", | |
723 | None), | |
724 | ("Invalid element (1) in commit", | |
725 | "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", | |
726 | None), | |
727 | ("Invalid element (> P) in commit", | |
728 | "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", | |
729 | None)] | |
5527a391 JM |
730 | for (note, commit, confirm) in tests: |
731 | logger.info(note) | |
732 | dev[0].scan_for_bss(bssid, freq=2412) | |
733 | hapd.set("ext_mgmt_frame_handling", "1") | |
734 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
735 | scan_freq="2412", wait_connect=False) | |
736 | ||
737 | logger.info("Commit") | |
738 | for i in range(0, 10): | |
739 | req = hapd.mgmt_rx() | |
740 | if req is None: | |
741 | raise Exception("MGMT RX wait timed out (commit)") | |
742 | if req['subtype'] == 11: | |
743 | break | |
744 | req = None | |
745 | if not req: | |
746 | raise Exception("Authentication frame (commit) not received") | |
747 | ||
748 | hapd.dump_monitor() | |
749 | resp = {} | |
750 | resp['fc'] = req['fc'] | |
751 | resp['da'] = req['sa'] | |
752 | resp['sa'] = req['da'] | |
753 | resp['bssid'] = req['bssid'] | |
754 | resp['payload'] = binascii.unhexlify("030001000000" + commit) | |
755 | hapd.mgmt_tx(resp) | |
756 | ||
757 | if confirm: | |
758 | logger.info("Confirm") | |
759 | for i in range(0, 10): | |
760 | req = hapd.mgmt_rx() | |
761 | if req is None: | |
762 | raise Exception("MGMT RX wait timed out (confirm)") | |
763 | if req['subtype'] == 11: | |
764 | break | |
765 | req = None | |
766 | if not req: | |
767 | raise Exception("Authentication frame (confirm) not received") | |
768 | ||
769 | hapd.dump_monitor() | |
770 | resp = {} | |
771 | resp['fc'] = req['fc'] | |
772 | resp['da'] = req['sa'] | |
773 | resp['sa'] = req['da'] | |
774 | resp['bssid'] = req['bssid'] | |
775 | resp['payload'] = binascii.unhexlify("030002000000" + confirm) | |
776 | hapd.mgmt_tx(resp) | |
777 | ||
778 | time.sleep(0.1) | |
779 | dev[0].request("REMOVE_NETWORK all") | |
780 | hapd.set("ext_mgmt_frame_handling", "0") | |
781 | hapd.dump_monitor() | |
782 | ||
46746fc1 JM |
783 | |
784 | def test_sae_proto_commit_delayed(dev, apdev): | |
785 | """SAE protocol testing - Commit delayed""" | |
4c0af8ad | 786 | check_sae_capab(dev[0]) |
46746fc1 JM |
787 | params = hostapd.wpa2_params(ssid="test-sae", |
788 | passphrase="12345678") | |
789 | params['wpa_key_mgmt'] = 'SAE' | |
790 | hapd = hostapd.add_ap(apdev[0], params) | |
791 | bssid = apdev[0]['bssid'] | |
792 | ||
793 | dev[0].request("SET sae_groups 19") | |
794 | ||
795 | dev[0].scan_for_bss(bssid, freq=2412) | |
796 | hapd.set("ext_mgmt_frame_handling", "1") | |
797 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
798 | scan_freq="2412", wait_connect=False) | |
799 | ||
800 | logger.info("Commit") | |
801 | for i in range(0, 10): | |
802 | req = hapd.mgmt_rx() | |
803 | if req is None: | |
804 | raise Exception("MGMT RX wait timed out (commit)") | |
805 | if req['subtype'] == 11: | |
806 | break | |
807 | req = None | |
808 | if not req: | |
809 | raise Exception("Authentication frame (commit) not received") | |
810 | ||
811 | hapd.dump_monitor() | |
812 | time.sleep(2.5) | |
813 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) | |
814 | ||
815 | logger.info("Commit/Confirm") | |
816 | for i in range(0, 10): | |
817 | req = hapd.mgmt_rx() | |
818 | if req is None: | |
819 | raise Exception("MGMT RX wait timed out (confirm)") | |
820 | if req['subtype'] == 11: | |
821 | trans, = struct.unpack('<H', req['payload'][2:4]) | |
822 | if trans == 1: | |
823 | logger.info("Extra Commit") | |
824 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) | |
825 | continue | |
826 | break | |
827 | req = None | |
828 | if not req: | |
829 | raise Exception("Authentication frame (confirm) not received") | |
830 | ||
831 | hapd.dump_monitor() | |
832 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) | |
833 | ||
834 | logger.info("Association Request") | |
835 | for i in range(0, 10): | |
836 | req = hapd.mgmt_rx() | |
837 | if req is None: | |
838 | raise Exception("MGMT RX wait timed out (AssocReq)") | |
839 | if req['subtype'] == 0: | |
840 | break | |
841 | req = None | |
842 | if not req: | |
843 | raise Exception("Association Request frame not received") | |
844 | ||
845 | hapd.dump_monitor() | |
846 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) | |
847 | ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5) | |
848 | if ev is None: | |
849 | raise Exception("Management frame TX status not reported (1)") | |
850 | if "stype=1 ok=1" not in ev: | |
851 | raise Exception("Unexpected management frame TX status (1): " + ev) | |
852 | cmd = "MGMT_TX_STATUS_PROCESS %s" % (" ".join(ev.split(' ')[1:4])) | |
853 | if "OK" not in hapd.request(cmd): | |
854 | raise Exception("MGMT_TX_STATUS_PROCESS failed") | |
855 | ||
856 | hapd.set("ext_mgmt_frame_handling", "0") | |
857 | ||
858 | dev[0].wait_connected() | |
859 | ||
860 | def test_sae_proto_commit_replay(dev, apdev): | |
861 | """SAE protocol testing - Commit replay""" | |
4c0af8ad | 862 | check_sae_capab(dev[0]) |
46746fc1 JM |
863 | params = hostapd.wpa2_params(ssid="test-sae", |
864 | passphrase="12345678") | |
865 | params['wpa_key_mgmt'] = 'SAE' | |
866 | hapd = hostapd.add_ap(apdev[0], params) | |
867 | bssid = apdev[0]['bssid'] | |
868 | ||
869 | dev[0].request("SET sae_groups 19") | |
870 | ||
871 | dev[0].scan_for_bss(bssid, freq=2412) | |
872 | hapd.set("ext_mgmt_frame_handling", "1") | |
873 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
874 | scan_freq="2412", wait_connect=False) | |
875 | ||
876 | logger.info("Commit") | |
877 | for i in range(0, 10): | |
878 | req = hapd.mgmt_rx() | |
879 | if req is None: | |
880 | raise Exception("MGMT RX wait timed out (commit)") | |
881 | if req['subtype'] == 11: | |
882 | break | |
883 | req = None | |
884 | if not req: | |
885 | raise Exception("Authentication frame (commit) not received") | |
886 | ||
887 | hapd.dump_monitor() | |
888 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) | |
889 | logger.info("Replay Commit") | |
890 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) | |
891 | ||
892 | logger.info("Confirm") | |
893 | for i in range(0, 10): | |
894 | req = hapd.mgmt_rx() | |
895 | if req is None: | |
896 | raise Exception("MGMT RX wait timed out (confirm)") | |
897 | if req['subtype'] == 11: | |
898 | trans, = struct.unpack('<H', req['payload'][2:4]) | |
899 | if trans == 1: | |
900 | logger.info("Extra Commit") | |
901 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) | |
902 | continue | |
903 | break | |
904 | req = None | |
905 | if not req: | |
906 | raise Exception("Authentication frame (confirm) not received") | |
907 | ||
908 | hapd.dump_monitor() | |
909 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) | |
910 | ||
911 | logger.info("Association Request") | |
912 | for i in range(0, 10): | |
913 | req = hapd.mgmt_rx() | |
914 | if req is None: | |
915 | raise Exception("MGMT RX wait timed out (AssocReq)") | |
916 | if req['subtype'] == 0: | |
917 | break | |
918 | req = None | |
919 | if not req: | |
920 | raise Exception("Association Request frame not received") | |
921 | ||
922 | hapd.dump_monitor() | |
923 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) | |
924 | for i in range(0, 10): | |
925 | ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5) | |
926 | if ev is None: | |
927 | raise Exception("Management frame TX status not reported (1)") | |
928 | if "stype=11 ok=1" in ev: | |
929 | continue | |
930 | if "stype=12 ok=1" in ev: | |
931 | continue | |
932 | if "stype=1 ok=1" not in ev: | |
933 | raise Exception("Unexpected management frame TX status (1): " + ev) | |
934 | cmd = "MGMT_TX_STATUS_PROCESS %s" % (" ".join(ev.split(' ')[1:4])) | |
935 | if "OK" not in hapd.request(cmd): | |
936 | raise Exception("MGMT_TX_STATUS_PROCESS failed") | |
937 | break | |
938 | ||
939 | hapd.set("ext_mgmt_frame_handling", "0") | |
940 | ||
941 | dev[0].wait_connected() | |
942 | ||
2d0a04a8 JM |
943 | def test_sae_proto_confirm_replay(dev, apdev): |
944 | """SAE protocol testing - Confirm replay""" | |
4c0af8ad | 945 | check_sae_capab(dev[0]) |
2d0a04a8 JM |
946 | params = hostapd.wpa2_params(ssid="test-sae", |
947 | passphrase="12345678") | |
948 | params['wpa_key_mgmt'] = 'SAE' | |
949 | hapd = hostapd.add_ap(apdev[0], params) | |
950 | bssid = apdev[0]['bssid'] | |
951 | ||
952 | dev[0].request("SET sae_groups 19") | |
953 | ||
954 | dev[0].scan_for_bss(bssid, freq=2412) | |
955 | hapd.set("ext_mgmt_frame_handling", "1") | |
956 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
957 | scan_freq="2412", wait_connect=False) | |
958 | ||
959 | logger.info("Commit") | |
960 | for i in range(0, 10): | |
961 | req = hapd.mgmt_rx() | |
962 | if req is None: | |
963 | raise Exception("MGMT RX wait timed out (commit)") | |
964 | if req['subtype'] == 11: | |
965 | break | |
966 | req = None | |
967 | if not req: | |
968 | raise Exception("Authentication frame (commit) not received") | |
969 | ||
2d0a04a8 | 970 | hapd.dump_monitor() |
54c58f29 | 971 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) |
2d0a04a8 JM |
972 | |
973 | logger.info("Confirm") | |
974 | for i in range(0, 10): | |
975 | req = hapd.mgmt_rx() | |
976 | if req is None: | |
977 | raise Exception("MGMT RX wait timed out (confirm)") | |
978 | if req['subtype'] == 11: | |
979 | break | |
980 | req = None | |
981 | if not req: | |
982 | raise Exception("Authentication frame (confirm) not received") | |
983 | ||
984 | hapd.dump_monitor() | |
54c58f29 | 985 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) |
2d0a04a8 JM |
986 | |
987 | logger.info("Replay Confirm") | |
54c58f29 | 988 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) |
2d0a04a8 JM |
989 | |
990 | logger.info("Association Request") | |
991 | for i in range(0, 10): | |
992 | req = hapd.mgmt_rx() | |
993 | if req is None: | |
994 | raise Exception("MGMT RX wait timed out (AssocReq)") | |
995 | if req['subtype'] == 0: | |
996 | break | |
997 | req = None | |
998 | if not req: | |
999 | raise Exception("Association Request frame not received") | |
1000 | ||
1001 | hapd.dump_monitor() | |
54c58f29 | 1002 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) |
2d0a04a8 JM |
1003 | ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5) |
1004 | if ev is None: | |
1005 | raise Exception("Management frame TX status not reported (1)") | |
1006 | if "stype=1 ok=1" not in ev: | |
1007 | raise Exception("Unexpected management frame TX status (1): " + ev) | |
1008 | cmd = "MGMT_TX_STATUS_PROCESS %s" % (" ".join(ev.split(' ')[1:4])) | |
1009 | if "OK" not in hapd.request(cmd): | |
1010 | raise Exception("MGMT_TX_STATUS_PROCESS failed") | |
1011 | ||
1012 | hapd.set("ext_mgmt_frame_handling", "0") | |
1013 | ||
1014 | dev[0].wait_connected() | |
1015 | ||
7a92dbd7 JM |
1016 | def test_sae_proto_hostapd(dev, apdev): |
1017 | """SAE protocol testing with hostapd""" | |
1018 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") | |
1019 | params['wpa_key_mgmt'] = 'SAE' | |
1020 | params['sae_groups'] = "19 65535" | |
1021 | hapd = hostapd.add_ap(apdev[0], params) | |
1022 | hapd.set("ext_mgmt_frame_handling", "1") | |
1023 | bssid = hapd.own_addr().replace(':', '') | |
1024 | addr = "020000000000" | |
1025 | addr2 = "020000000001" | |
1026 | hdr = "b0003a01" + bssid + addr + bssid + "1000" | |
1027 | hdr2 = "b0003a01" + bssid + addr2 + bssid + "1000" | |
1028 | group = "1300" | |
1029 | scalar = "f7df19f4a7fef1d3b895ea1de150b7c5a7a705c8ebb31a52b623e0057908bd93" | |
1030 | element_x = "21931572027f2e953e2a49fab3d992944102cc95aa19515fc068b394fb25ae3c" | |
1031 | element_y = "cb4eeb94d7b0b789abfdb73a67ab9d6d5efa94dd553e0e724a6289821cbce530" | |
1032 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030001000000" + group + scalar + element_x + element_y) | |
1033 | # "SAE: Not enough data for scalar" | |
1034 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030001000000" + group + scalar[:-2]) | |
1035 | # "SAE: Do not allow group to be changed" | |
1036 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030001000000" + "ffff" + scalar[:-2]) | |
1037 | # "SAE: Unsupported Finite Cyclic Group 65535" | |
1038 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr2 + "030001000000" + "ffff" + scalar[:-2]) | |
1039 | ||
2b70a82c JM |
1040 | def test_sae_proto_hostapd_ecc(dev, apdev): |
1041 | """SAE protocol testing with hostapd (ECC)""" | |
1042 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="foofoofoo") | |
1043 | params['wpa_key_mgmt'] = 'SAE' | |
1044 | params['sae_groups'] = "19" | |
1045 | hapd = hostapd.add_ap(apdev[0], params) | |
1046 | hapd.set("ext_mgmt_frame_handling", "1") | |
1047 | bssid = hapd.own_addr().replace(':', '') | |
1048 | addr = "020000000000" | |
1049 | addr2 = "020000000001" | |
1050 | hdr = "b0003a01" + bssid + addr + bssid + "1000" | |
1051 | hdr2 = "b0003a01" + bssid + addr2 + bssid + "1000" | |
1052 | group = "1300" | |
1053 | scalar = "9e9a959bf2dda875a4a29ce9b2afef46f2d83060930124cd9e39ddce798cd69a" | |
1054 | element_x = "dfc55fd8622b91d362f4d1fc9646474d7fba0ff7cce6ca58b8e96a931e070220" | |
1055 | element_y = "dac8a4e80724f167c1349cc9e1f9dd82a7c77b29d49789b63b72b4c849301a28" | |
1056 | # sae_parse_commit_element_ecc() failure to parse peer element | |
1057 | # (depending on crypto library, either crypto_ec_point_from_bin() failure | |
1058 | # or crypto_ec_point_is_on_curve() returning 0) | |
1059 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030001000000" + group + scalar + element_x + element_y) | |
1060 | # Unexpected continuation of the connection attempt with confirm | |
1061 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030002000000" + "0000" + "fd7b081ff4e8676f03612a4140eedcd3c179ab3a13b93863c6f7ca451340b9ae") | |
1062 | ||
1063 | def test_sae_proto_hostapd_ffc(dev, apdev): | |
1064 | """SAE protocol testing with hostapd (FFC)""" | |
1065 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="foofoofoo") | |
1066 | params['wpa_key_mgmt'] = 'SAE' | |
1067 | params['sae_groups'] = "22" | |
1068 | hapd = hostapd.add_ap(apdev[0], params) | |
1069 | hapd.set("ext_mgmt_frame_handling", "1") | |
1070 | bssid = hapd.own_addr().replace(':', '') | |
1071 | addr = "020000000000" | |
1072 | addr2 = "020000000001" | |
1073 | hdr = "b0003a01" + bssid + addr + bssid + "1000" | |
1074 | hdr2 = "b0003a01" + bssid + addr2 + bssid + "1000" | |
1075 | group = "1600" | |
1076 | scalar = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044cc46a73c07ef479dc66ec1f5e8ccf25131fa40" | |
1077 | element = "0f1d67025e12fc874cf718c35b19d1ab2db858215623f1ce661cbd1d7b1d7a09ceda7dba46866cf37044259b5cac4db15e7feb778edc8098854b93a84347c1850c02ee4d7dac46db79c477c731085d5b39f56803cda1eeac4a2fbbccb9a546379e258c00ebe93dfdd0a34cf8ce5c55cf905a89564a590b7e159fb89198e9d5cd" | |
1078 | # sae_parse_commit_element_ffc() failure to parse peer element | |
1079 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030001000000" + group + scalar + element) | |
1080 | # Unexpected continuation of the connection attempt with confirm | |
1081 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030002000000" + "0000" + "fd7b081ff4e8676f03612a4140eedcd3c179ab3a13b93863c6f7ca451340b9ae") | |
1082 | ||
9fd6804d | 1083 | @remote_compatible |
5527a391 JM |
1084 | def test_sae_no_ffc_by_default(dev, apdev): |
1085 | """SAE and default groups rejecting FFC""" | |
4c0af8ad | 1086 | check_sae_capab(dev[0]) |
5527a391 JM |
1087 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
1088 | params['wpa_key_mgmt'] = 'SAE' | |
8b8a1864 | 1089 | hapd = hostapd.add_ap(apdev[0], params) |
5527a391 | 1090 | |
8e607b1b | 1091 | dev[0].request("SET sae_groups 15") |
5527a391 JM |
1092 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412", |
1093 | wait_connect=False) | |
1094 | ev = dev[0].wait_event(["SME: Trying to authenticate"], timeout=3) | |
1095 | if ev is None: | |
1096 | raise Exception("Did not try to authenticate") | |
1097 | ev = dev[0].wait_event(["SME: Trying to authenticate"], timeout=3) | |
1098 | if ev is None: | |
1099 | raise Exception("Did not try to authenticate (2)") | |
1100 | dev[0].request("REMOVE_NETWORK all") | |
939527b5 JM |
1101 | |
1102 | def sae_reflection_attack(apdev, dev, group): | |
4c0af8ad | 1103 | check_sae_capab(dev) |
939527b5 JM |
1104 | params = hostapd.wpa2_params(ssid="test-sae", |
1105 | passphrase="no-knowledge-of-passphrase") | |
1106 | params['wpa_key_mgmt'] = 'SAE' | |
afc26df2 | 1107 | hapd = hostapd.add_ap(apdev, params) |
939527b5 JM |
1108 | bssid = apdev['bssid'] |
1109 | ||
1110 | dev.scan_for_bss(bssid, freq=2412) | |
1111 | hapd.set("ext_mgmt_frame_handling", "1") | |
1112 | ||
1113 | dev.request("SET sae_groups %d" % group) | |
1114 | dev.connect("test-sae", psk="reflection-attack", key_mgmt="SAE", | |
1115 | scan_freq="2412", wait_connect=False) | |
1116 | ||
1117 | # Commit | |
1118 | for i in range(0, 10): | |
1119 | req = hapd.mgmt_rx() | |
1120 | if req is None: | |
1121 | raise Exception("MGMT RX wait timed out") | |
1122 | if req['subtype'] == 11: | |
1123 | break | |
1124 | req = None | |
1125 | if not req: | |
1126 | raise Exception("Authentication frame not received") | |
1127 | ||
1128 | resp = {} | |
1129 | resp['fc'] = req['fc'] | |
1130 | resp['da'] = req['sa'] | |
1131 | resp['sa'] = req['da'] | |
1132 | resp['bssid'] = req['bssid'] | |
1133 | resp['payload'] = req['payload'] | |
1134 | hapd.mgmt_tx(resp) | |
1135 | ||
1136 | # Confirm | |
1137 | req = hapd.mgmt_rx(timeout=0.5) | |
1138 | if req is not None: | |
1139 | if req['subtype'] == 11: | |
1140 | raise Exception("Unexpected Authentication frame seen") | |
1141 | ||
9fd6804d | 1142 | @remote_compatible |
939527b5 JM |
1143 | def test_sae_reflection_attack_ecc(dev, apdev): |
1144 | """SAE reflection attack (ECC)""" | |
1145 | sae_reflection_attack(apdev[0], dev[0], 19) | |
1146 | ||
9fd6804d | 1147 | @remote_compatible |
939527b5 JM |
1148 | def test_sae_reflection_attack_ffc(dev, apdev): |
1149 | """SAE reflection attack (FFC)""" | |
8e607b1b | 1150 | sae_reflection_attack(apdev[0], dev[0], 15) |
1965e196 | 1151 | |
1342c47a | 1152 | def sae_reflection_attack_internal(apdev, dev, group): |
4c0af8ad | 1153 | check_sae_capab(dev) |
1342c47a JM |
1154 | params = hostapd.wpa2_params(ssid="test-sae", |
1155 | passphrase="no-knowledge-of-passphrase") | |
1156 | params['wpa_key_mgmt'] = 'SAE' | |
1157 | params['sae_reflection_attack'] = '1' | |
1158 | hapd = hostapd.add_ap(apdev, params) | |
1159 | bssid = apdev['bssid'] | |
1160 | ||
1161 | dev.scan_for_bss(bssid, freq=2412) | |
1162 | dev.request("SET sae_groups %d" % group) | |
1163 | dev.connect("test-sae", psk="reflection-attack", key_mgmt="SAE", | |
1164 | scan_freq="2412", wait_connect=False) | |
8e607b1b JM |
1165 | ev = dev.wait_event(["SME: Trying to authenticate"], timeout=10) |
1166 | if ev is None: | |
1167 | raise Exception("No authentication attempt seen") | |
1342c47a JM |
1168 | ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) |
1169 | if ev is not None: | |
1170 | raise Exception("Unexpected connection") | |
1171 | ||
1172 | @remote_compatible | |
1173 | def test_sae_reflection_attack_ecc_internal(dev, apdev): | |
1174 | """SAE reflection attack (ECC) - internal""" | |
1175 | sae_reflection_attack_internal(apdev[0], dev[0], 19) | |
1176 | ||
1177 | @remote_compatible | |
1178 | def test_sae_reflection_attack_ffc_internal(dev, apdev): | |
1179 | """SAE reflection attack (FFC) - internal""" | |
8e607b1b | 1180 | sae_reflection_attack_internal(apdev[0], dev[0], 15) |
1342c47a | 1181 | |
cd06e266 JM |
1182 | @remote_compatible |
1183 | def test_sae_commit_override(dev, apdev): | |
1184 | """SAE commit override (hostapd)""" | |
4c0af8ad | 1185 | check_sae_capab(dev[0]) |
cd06e266 JM |
1186 | params = hostapd.wpa2_params(ssid="test-sae", |
1187 | passphrase="12345678") | |
1188 | params['wpa_key_mgmt'] = 'SAE' | |
1189 | params['sae_commit_override'] = '13ffbad00d215867a7c5ff37d87bb9bdb7cb116e520f71e8d7a794ca2606d537ddc6c099c40e7a25372b80a8fd443cd7dd222c8ea21b8ef372d4b3e316c26a73fd999cc79ad483eb826e7b3893ea332da68fa13224bcdeb4fb18b0584dd100a2c514' | |
1190 | hapd = hostapd.add_ap(apdev[0], params) | |
1191 | dev[0].request("SET sae_groups ") | |
1192 | dev[0].connect("test-sae", psk="test-sae", key_mgmt="SAE", | |
1193 | scan_freq="2412", wait_connect=False) | |
1194 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) | |
1195 | if ev is not None: | |
1196 | raise Exception("Unexpected connection") | |
1197 | ||
eea62048 JM |
1198 | @remote_compatible |
1199 | def test_sae_commit_override2(dev, apdev): | |
1200 | """SAE commit override (wpa_supplicant)""" | |
4c0af8ad | 1201 | check_sae_capab(dev[0]) |
eea62048 JM |
1202 | params = hostapd.wpa2_params(ssid="test-sae", |
1203 | passphrase="12345678") | |
1204 | params['wpa_key_mgmt'] = 'SAE' | |
1205 | hapd = hostapd.add_ap(apdev[0], params) | |
1206 | dev[0].request("SET sae_groups ") | |
1207 | dev[0].set('sae_commit_override', '13ffbad00d215867a7c5ff37d87bb9bdb7cb116e520f71e8d7a794ca2606d537ddc6c099c40e7a25372b80a8fd443cd7dd222c8ea21b8ef372d4b3e316c26a73fd999cc79ad483eb826e7b3893ea332da68fa13224bcdeb4fb18b0584dd100a2c514') | |
1208 | dev[0].connect("test-sae", psk="test-sae", key_mgmt="SAE", | |
1209 | scan_freq="2412", wait_connect=False) | |
1210 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) | |
1211 | if ev is not None: | |
1212 | raise Exception("Unexpected connection") | |
1213 | ||
faddd025 JM |
1214 | def test_sae_commit_invalid_scalar_element_ap(dev, apdev): |
1215 | """SAE commit invalid scalar/element from AP""" | |
4c0af8ad | 1216 | check_sae_capab(dev[0]) |
faddd025 JM |
1217 | params = hostapd.wpa2_params(ssid="test-sae", |
1218 | passphrase="12345678") | |
1219 | params['wpa_key_mgmt'] = 'SAE' | |
1220 | params['sae_commit_override'] = '1300' + 96*'00' | |
1221 | hapd = hostapd.add_ap(apdev[0], params) | |
1222 | dev[0].request("SET sae_groups ") | |
1223 | dev[0].connect("test-sae", psk="test-sae", key_mgmt="SAE", | |
1224 | scan_freq="2412", wait_connect=False) | |
1225 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) | |
1226 | if ev is not None: | |
1227 | raise Exception("Unexpected connection") | |
1228 | ||
1229 | def test_sae_commit_invalid_element_ap(dev, apdev): | |
1230 | """SAE commit invalid element from AP""" | |
4c0af8ad | 1231 | check_sae_capab(dev[0]) |
faddd025 JM |
1232 | params = hostapd.wpa2_params(ssid="test-sae", |
1233 | passphrase="12345678") | |
1234 | params['wpa_key_mgmt'] = 'SAE' | |
1235 | params['sae_commit_override'] = '1300' + 31*'00' + '02' + 64*'00' | |
1236 | hapd = hostapd.add_ap(apdev[0], params) | |
1237 | dev[0].request("SET sae_groups ") | |
1238 | dev[0].connect("test-sae", psk="test-sae", key_mgmt="SAE", | |
1239 | scan_freq="2412", wait_connect=False) | |
1240 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) | |
1241 | if ev is not None: | |
1242 | raise Exception("Unexpected connection") | |
1243 | ||
1244 | def test_sae_commit_invalid_scalar_element_sta(dev, apdev): | |
1245 | """SAE commit invalid scalar/element from STA""" | |
4c0af8ad | 1246 | check_sae_capab(dev[0]) |
faddd025 JM |
1247 | params = hostapd.wpa2_params(ssid="test-sae", |
1248 | passphrase="12345678") | |
1249 | params['wpa_key_mgmt'] = 'SAE' | |
1250 | hapd = hostapd.add_ap(apdev[0], params) | |
1251 | dev[0].request("SET sae_groups ") | |
1252 | dev[0].set('sae_commit_override', '1300' + 96*'00') | |
1253 | dev[0].connect("test-sae", psk="test-sae", key_mgmt="SAE", | |
1254 | scan_freq="2412", wait_connect=False) | |
1255 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) | |
1256 | if ev is not None: | |
1257 | raise Exception("Unexpected connection") | |
1258 | ||
1259 | def test_sae_commit_invalid_element_sta(dev, apdev): | |
1260 | """SAE commit invalid element from STA""" | |
4c0af8ad | 1261 | check_sae_capab(dev[0]) |
faddd025 JM |
1262 | params = hostapd.wpa2_params(ssid="test-sae", |
1263 | passphrase="12345678") | |
1264 | params['wpa_key_mgmt'] = 'SAE' | |
1265 | hapd = hostapd.add_ap(apdev[0], params) | |
1266 | dev[0].request("SET sae_groups ") | |
1267 | dev[0].set('sae_commit_override', '1300' + 31*'00' + '02' + 64*'00') | |
1268 | dev[0].connect("test-sae", psk="test-sae", key_mgmt="SAE", | |
1269 | scan_freq="2412", wait_connect=False) | |
1270 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) | |
1271 | if ev is not None: | |
1272 | raise Exception("Unexpected connection") | |
1273 | ||
9fd6804d | 1274 | @remote_compatible |
1965e196 JM |
1275 | def test_sae_anti_clogging_proto(dev, apdev): |
1276 | """SAE anti clogging protocol testing""" | |
4c0af8ad | 1277 | check_sae_capab(dev[0]) |
1965e196 JM |
1278 | params = hostapd.wpa2_params(ssid="test-sae", |
1279 | passphrase="no-knowledge-of-passphrase") | |
1280 | params['wpa_key_mgmt'] = 'SAE' | |
8b8a1864 | 1281 | hapd = hostapd.add_ap(apdev[0], params) |
1965e196 JM |
1282 | bssid = apdev[0]['bssid'] |
1283 | ||
1284 | dev[0].scan_for_bss(bssid, freq=2412) | |
1285 | hapd.set("ext_mgmt_frame_handling", "1") | |
1286 | ||
1287 | dev[0].request("SET sae_groups ") | |
1288 | dev[0].connect("test-sae", psk="anti-cloggign", key_mgmt="SAE", | |
1289 | scan_freq="2412", wait_connect=False) | |
1290 | ||
1291 | # Commit | |
1292 | for i in range(0, 10): | |
1293 | req = hapd.mgmt_rx() | |
1294 | if req is None: | |
1295 | raise Exception("MGMT RX wait timed out") | |
1296 | if req['subtype'] == 11: | |
1297 | break | |
1298 | req = None | |
1299 | if not req: | |
1300 | raise Exception("Authentication frame not received") | |
1301 | ||
1302 | resp = {} | |
1303 | resp['fc'] = req['fc'] | |
1304 | resp['da'] = req['sa'] | |
1305 | resp['sa'] = req['da'] | |
1306 | resp['bssid'] = req['bssid'] | |
1307 | resp['payload'] = binascii.unhexlify("030001004c00" + "ffff00") | |
1308 | hapd.mgmt_tx(resp) | |
1309 | ||
1310 | # Confirm (not received due to DH group being rejected) | |
1311 | req = hapd.mgmt_rx(timeout=0.5) | |
1312 | if req is not None: | |
1313 | if req['subtype'] == 11: | |
1314 | raise Exception("Unexpected Authentication frame seen") | |
10ba4ae4 | 1315 | |
9fd6804d | 1316 | @remote_compatible |
10ba4ae4 JM |
1317 | def test_sae_no_random(dev, apdev): |
1318 | """SAE and no random numbers available""" | |
4c0af8ad | 1319 | check_sae_capab(dev[0]) |
10ba4ae4 JM |
1320 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
1321 | params['wpa_key_mgmt'] = 'SAE' | |
8b8a1864 | 1322 | hapd = hostapd.add_ap(apdev[0], params) |
10ba4ae4 JM |
1323 | |
1324 | dev[0].request("SET sae_groups ") | |
fbd671ac | 1325 | tests = [(1, "os_get_random;sae_derive_pwe_ecc")] |
10ba4ae4 JM |
1326 | for count, func in tests: |
1327 | with fail_test(dev[0], count, func): | |
1328 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
1329 | scan_freq="2412") | |
1330 | dev[0].request("REMOVE_NETWORK all") | |
1331 | dev[0].wait_disconnected() | |
4f6985de | 1332 | |
9fd6804d | 1333 | @remote_compatible |
4f6985de JM |
1334 | def test_sae_pwe_failure(dev, apdev): |
1335 | """SAE and pwe failure""" | |
4c0af8ad | 1336 | check_sae_capab(dev[0]) |
4f6985de JM |
1337 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
1338 | params['wpa_key_mgmt'] = 'SAE' | |
8e607b1b | 1339 | params['sae_groups'] = '19 15' |
8b8a1864 | 1340 | hapd = hostapd.add_ap(apdev[0], params) |
4f6985de JM |
1341 | |
1342 | dev[0].request("SET sae_groups 19") | |
1343 | with fail_test(dev[0], 1, "hmac_sha256_vector;sae_derive_pwe_ecc"): | |
1344 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
1345 | scan_freq="2412") | |
1346 | dev[0].request("REMOVE_NETWORK all") | |
1347 | dev[0].wait_disconnected() | |
51761ba2 JM |
1348 | with fail_test(dev[0], 1, "sae_test_pwd_seed_ecc"): |
1349 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
1350 | scan_freq="2412") | |
1351 | dev[0].request("REMOVE_NETWORK all") | |
1352 | dev[0].wait_disconnected() | |
4f6985de | 1353 | |
8e607b1b | 1354 | dev[0].request("SET sae_groups 15") |
4f6985de JM |
1355 | with fail_test(dev[0], 1, "hmac_sha256_vector;sae_derive_pwe_ffc"): |
1356 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
1357 | scan_freq="2412") | |
1358 | dev[0].request("REMOVE_NETWORK all") | |
1359 | dev[0].wait_disconnected() | |
1360 | ||
8e607b1b | 1361 | dev[0].request("SET sae_groups 15") |
4f6985de JM |
1362 | with fail_test(dev[0], 1, "sae_test_pwd_seed_ffc"): |
1363 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
1364 | scan_freq="2412") | |
1365 | dev[0].request("REMOVE_NETWORK all") | |
1366 | dev[0].wait_disconnected() | |
1367 | with fail_test(dev[0], 2, "sae_test_pwd_seed_ffc"): | |
1368 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
1369 | scan_freq="2412") | |
1370 | dev[0].request("REMOVE_NETWORK all") | |
1371 | dev[0].wait_disconnected() | |
51761ba2 | 1372 | |
9fd6804d | 1373 | @remote_compatible |
51761ba2 JM |
1374 | def test_sae_bignum_failure(dev, apdev): |
1375 | """SAE and bignum failure""" | |
4c0af8ad | 1376 | check_sae_capab(dev[0]) |
51761ba2 JM |
1377 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
1378 | params['wpa_key_mgmt'] = 'SAE' | |
8e607b1b | 1379 | params['sae_groups'] = '19 15 22' |
8b8a1864 | 1380 | hapd = hostapd.add_ap(apdev[0], params) |
51761ba2 JM |
1381 | |
1382 | dev[0].request("SET sae_groups 19") | |
a5dbddbf JM |
1383 | tests = [(1, "crypto_bignum_init_set;dragonfly_get_rand_1_to_p_1"), |
1384 | (1, "crypto_bignum_init;dragonfly_is_quadratic_residue_blind"), | |
1385 | (1, "crypto_bignum_mulmod;dragonfly_is_quadratic_residue_blind"), | |
1386 | (2, "crypto_bignum_mulmod;dragonfly_is_quadratic_residue_blind"), | |
1387 | (3, "crypto_bignum_mulmod;dragonfly_is_quadratic_residue_blind"), | |
1388 | (1, "crypto_bignum_legendre;dragonfly_is_quadratic_residue_blind"), | |
fab49f61 JM |
1389 | (1, "crypto_bignum_init_set;sae_test_pwd_seed_ecc"), |
1390 | (1, "crypto_ec_point_compute_y_sqr;sae_test_pwd_seed_ecc"), | |
fab49f61 JM |
1391 | (1, "crypto_bignum_to_bin;sae_derive_pwe_ecc"), |
1392 | (1, "crypto_ec_point_init;sae_derive_pwe_ecc"), | |
1393 | (1, "crypto_ec_point_solve_y_coord;sae_derive_pwe_ecc"), | |
1394 | (1, "crypto_ec_point_init;sae_derive_commit_element_ecc"), | |
1395 | (1, "crypto_ec_point_mul;sae_derive_commit_element_ecc"), | |
1396 | (1, "crypto_ec_point_invert;sae_derive_commit_element_ecc"), | |
1397 | (1, "crypto_bignum_init;=sae_derive_commit"), | |
1398 | (1, "crypto_ec_point_init;sae_derive_k_ecc"), | |
1399 | (1, "crypto_ec_point_mul;sae_derive_k_ecc"), | |
1400 | (1, "crypto_ec_point_add;sae_derive_k_ecc"), | |
1401 | (2, "crypto_ec_point_mul;sae_derive_k_ecc"), | |
1402 | (1, "crypto_ec_point_to_bin;sae_derive_k_ecc"), | |
a5dbddbf | 1403 | (1, "crypto_bignum_legendre;dragonfly_get_random_qr_qnr"), |
fab49f61 JM |
1404 | (1, "sha256_prf;sae_derive_keys"), |
1405 | (1, "crypto_bignum_init;sae_derive_keys"), | |
1406 | (1, "crypto_bignum_init_set;sae_parse_commit_scalar"), | |
1407 | (1, "crypto_bignum_to_bin;sae_parse_commit_element_ecc"), | |
1408 | (1, "crypto_ec_point_from_bin;sae_parse_commit_element_ecc")] | |
51761ba2 JM |
1409 | for count, func in tests: |
1410 | with fail_test(dev[0], count, func): | |
e96fa197 | 1411 | hapd.request("NOTE STA failure testing %d:%s" % (count, func)) |
51761ba2 JM |
1412 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", |
1413 | scan_freq="2412", wait_connect=False) | |
7bcb6391 | 1414 | wait_fail_trigger(dev[0], "GET_FAIL", timeout=0.1) |
51761ba2 | 1415 | dev[0].request("REMOVE_NETWORK all") |
e96fa197 JM |
1416 | dev[0].dump_monitor() |
1417 | hapd.dump_monitor() | |
51761ba2 | 1418 | |
8e607b1b | 1419 | dev[0].request("SET sae_groups 15") |
fab49f61 JM |
1420 | tests = [(1, "crypto_bignum_init_set;sae_set_group"), |
1421 | (2, "crypto_bignum_init_set;sae_set_group"), | |
fbd671ac JM |
1422 | (1, "crypto_bignum_init;sae_derive_commit"), |
1423 | (2, "crypto_bignum_init;sae_derive_commit"), | |
fab49f61 JM |
1424 | (1, "crypto_bignum_init_set;sae_test_pwd_seed_ffc"), |
1425 | (1, "crypto_bignum_exptmod;sae_test_pwd_seed_ffc"), | |
1426 | (1, "crypto_bignum_init;sae_derive_pwe_ffc"), | |
1427 | (1, "crypto_bignum_init;sae_derive_commit_element_ffc"), | |
1428 | (1, "crypto_bignum_exptmod;sae_derive_commit_element_ffc"), | |
1429 | (1, "crypto_bignum_inverse;sae_derive_commit_element_ffc"), | |
1430 | (1, "crypto_bignum_init;sae_derive_k_ffc"), | |
1431 | (1, "crypto_bignum_exptmod;sae_derive_k_ffc"), | |
1432 | (1, "crypto_bignum_mulmod;sae_derive_k_ffc"), | |
1433 | (2, "crypto_bignum_exptmod;sae_derive_k_ffc"), | |
1434 | (1, "crypto_bignum_to_bin;sae_derive_k_ffc"), | |
1435 | (1, "crypto_bignum_init_set;sae_parse_commit_element_ffc"), | |
1436 | (1, "crypto_bignum_init;sae_parse_commit_element_ffc"), | |
1437 | (2, "crypto_bignum_init_set;sae_parse_commit_element_ffc"), | |
1438 | (1, "crypto_bignum_exptmod;sae_parse_commit_element_ffc")] | |
51761ba2 JM |
1439 | for count, func in tests: |
1440 | with fail_test(dev[0], count, func): | |
e96fa197 | 1441 | hapd.request("NOTE STA failure testing %d:%s" % (count, func)) |
51761ba2 JM |
1442 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", |
1443 | scan_freq="2412", wait_connect=False) | |
7bcb6391 | 1444 | wait_fail_trigger(dev[0], "GET_FAIL", timeout=0.1) |
51761ba2 | 1445 | dev[0].request("REMOVE_NETWORK all") |
e96fa197 JM |
1446 | dev[0].dump_monitor() |
1447 | hapd.dump_monitor() | |
51761ba2 | 1448 | |
8e607b1b JM |
1449 | def test_sae_bignum_failure_unsafe_group(dev, apdev): |
1450 | """SAE and bignum failure unsafe group""" | |
4c0af8ad | 1451 | check_sae_capab(dev[0]) |
8e607b1b JM |
1452 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
1453 | params['wpa_key_mgmt'] = 'SAE' | |
1454 | params['sae_groups'] = '22' | |
1455 | hapd = hostapd.add_ap(apdev[0], params) | |
1456 | ||
51761ba2 | 1457 | dev[0].request("SET sae_groups 22") |
fab49f61 JM |
1458 | tests = [(1, "crypto_bignum_init_set;sae_test_pwd_seed_ffc"), |
1459 | (1, "crypto_bignum_sub;sae_test_pwd_seed_ffc"), | |
1460 | (1, "crypto_bignum_div;sae_test_pwd_seed_ffc")] | |
51761ba2 JM |
1461 | for count, func in tests: |
1462 | with fail_test(dev[0], count, func): | |
e96fa197 | 1463 | hapd.request("NOTE STA failure testing %d:%s" % (count, func)) |
51761ba2 JM |
1464 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", |
1465 | scan_freq="2412", wait_connect=False) | |
1466 | wait_fail_trigger(dev[0], "GET_FAIL") | |
1467 | dev[0].request("REMOVE_NETWORK all") | |
e96fa197 JM |
1468 | dev[0].dump_monitor() |
1469 | hapd.dump_monitor() | |
28be769b JM |
1470 | |
1471 | def test_sae_invalid_anti_clogging_token_req(dev, apdev): | |
1472 | """SAE and invalid anti-clogging token request""" | |
4c0af8ad | 1473 | check_sae_capab(dev[0]) |
28be769b JM |
1474 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
1475 | params['wpa_key_mgmt'] = 'SAE' | |
77f52098 JM |
1476 | # Beacon more frequently since Probe Request frames are practically ignored |
1477 | # in this test setup (ext_mgmt_frame_handled=1 on hostapd side) and | |
1478 | # wpa_supplicant scans may end up getting ignored if no new results are | |
1479 | # available due to the missing Probe Response frames. | |
1480 | params['beacon_int'] = '20' | |
28be769b JM |
1481 | hapd = hostapd.add_ap(apdev[0], params) |
1482 | bssid = apdev[0]['bssid'] | |
1483 | ||
1484 | dev[0].request("SET sae_groups 19") | |
1485 | dev[0].scan_for_bss(bssid, freq=2412) | |
1486 | hapd.set("ext_mgmt_frame_handling", "1") | |
1487 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
1488 | scan_freq="2412", wait_connect=False) | |
1489 | ev = dev[0].wait_event(["SME: Trying to authenticate"]) | |
1490 | if ev is None: | |
77f52098 | 1491 | raise Exception("No authentication attempt seen (1)") |
28be769b JM |
1492 | dev[0].dump_monitor() |
1493 | ||
1494 | for i in range(0, 10): | |
1495 | req = hapd.mgmt_rx() | |
1496 | if req is None: | |
1497 | raise Exception("MGMT RX wait timed out (commit)") | |
1498 | if req['subtype'] == 11: | |
1499 | break | |
1500 | req = None | |
1501 | if not req: | |
1502 | raise Exception("Authentication frame (commit) not received") | |
1503 | ||
1504 | hapd.dump_monitor() | |
1505 | resp = {} | |
1506 | resp['fc'] = req['fc'] | |
1507 | resp['da'] = req['sa'] | |
1508 | resp['sa'] = req['da'] | |
1509 | resp['bssid'] = req['bssid'] | |
1510 | resp['payload'] = binascii.unhexlify("030001004c0013") | |
1511 | hapd.mgmt_tx(resp) | |
77f52098 JM |
1512 | ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5) |
1513 | if ev is None: | |
1514 | raise Exception("Management frame TX status not reported (1)") | |
1515 | if "stype=11 ok=1" not in ev: | |
1516 | raise Exception("Unexpected management frame TX status (1): " + ev) | |
28be769b JM |
1517 | |
1518 | ev = dev[0].wait_event(["SME: Trying to authenticate"]) | |
1519 | if ev is None: | |
77f52098 | 1520 | raise Exception("No authentication attempt seen (2)") |
28be769b JM |
1521 | dev[0].dump_monitor() |
1522 | ||
1523 | for i in range(0, 10): | |
1524 | req = hapd.mgmt_rx() | |
1525 | if req is None: | |
1526 | raise Exception("MGMT RX wait timed out (commit) (2)") | |
1527 | if req['subtype'] == 11: | |
1528 | break | |
1529 | req = None | |
1530 | if not req: | |
1531 | raise Exception("Authentication frame (commit) not received (2)") | |
1532 | ||
1533 | hapd.dump_monitor() | |
1534 | resp = {} | |
1535 | resp['fc'] = req['fc'] | |
1536 | resp['da'] = req['sa'] | |
1537 | resp['sa'] = req['da'] | |
1538 | resp['bssid'] = req['bssid'] | |
1539 | resp['payload'] = binascii.unhexlify("030001000100") | |
1540 | hapd.mgmt_tx(resp) | |
77f52098 JM |
1541 | ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5) |
1542 | if ev is None: | |
1543 | raise Exception("Management frame TX status not reported (1)") | |
1544 | if "stype=11 ok=1" not in ev: | |
1545 | raise Exception("Unexpected management frame TX status (1): " + ev) | |
28be769b JM |
1546 | |
1547 | ev = dev[0].wait_event(["SME: Trying to authenticate"]) | |
1548 | if ev is None: | |
77f52098 | 1549 | raise Exception("No authentication attempt seen (3)") |
28be769b JM |
1550 | dev[0].dump_monitor() |
1551 | ||
1552 | dev[0].request("DISCONNECT") | |
606ef7d3 JM |
1553 | |
1554 | def test_sae_password(dev, apdev): | |
1555 | """SAE and sae_password in hostapd configuration""" | |
4c0af8ad | 1556 | check_sae_capab(dev[0]) |
606ef7d3 JM |
1557 | params = hostapd.wpa2_params(ssid="test-sae", |
1558 | passphrase="12345678") | |
1559 | params['wpa_key_mgmt'] = 'SAE WPA-PSK' | |
1560 | params['sae_password'] = "sae-password" | |
1561 | hapd = hostapd.add_ap(apdev[0], params) | |
1562 | ||
1563 | dev[0].request("SET sae_groups ") | |
1564 | dev[0].connect("test-sae", psk="sae-password", key_mgmt="SAE", | |
1565 | scan_freq="2412") | |
1566 | dev[1].connect("test-sae", psk="12345678", scan_freq="2412") | |
1567 | dev[2].request("SET sae_groups ") | |
1568 | dev[2].connect("test-sae", sae_password="sae-password", key_mgmt="SAE", | |
1569 | scan_freq="2412") | |
1570 | ||
1571 | def test_sae_password_short(dev, apdev): | |
1572 | """SAE and short password""" | |
4c0af8ad | 1573 | check_sae_capab(dev[0]) |
606ef7d3 JM |
1574 | params = hostapd.wpa2_params(ssid="test-sae") |
1575 | params['wpa_key_mgmt'] = 'SAE' | |
1576 | params['sae_password'] = "secret" | |
1577 | hapd = hostapd.add_ap(apdev[0], params) | |
1578 | ||
1579 | dev[0].request("SET sae_groups ") | |
1580 | dev[0].connect("test-sae", sae_password="secret", key_mgmt="SAE", | |
1581 | scan_freq="2412") | |
1582 | ||
1583 | def test_sae_password_long(dev, apdev): | |
1584 | """SAE and long password""" | |
4c0af8ad | 1585 | check_sae_capab(dev[0]) |
606ef7d3 JM |
1586 | params = hostapd.wpa2_params(ssid="test-sae") |
1587 | params['wpa_key_mgmt'] = 'SAE' | |
1588 | params['sae_password'] = 100*"A" | |
1589 | hapd = hostapd.add_ap(apdev[0], params) | |
1590 | ||
1591 | dev[0].request("SET sae_groups ") | |
1592 | dev[0].connect("test-sae", sae_password=100*"A", key_mgmt="SAE", | |
1593 | scan_freq="2412") | |
33822240 JM |
1594 | |
1595 | def test_sae_connect_cmd(dev, apdev): | |
1596 | """SAE with connect command""" | |
1597 | wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') | |
1598 | wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") | |
4c0af8ad | 1599 | check_sae_capab(wpas) |
33822240 JM |
1600 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
1601 | params['wpa_key_mgmt'] = 'SAE' | |
1602 | hapd = hostapd.add_ap(apdev[0], params) | |
1603 | ||
1604 | wpas.request("SET sae_groups ") | |
1605 | wpas.connect("test-sae", psk="12345678", key_mgmt="SAE", | |
1606 | scan_freq="2412", wait_connect=False) | |
1607 | # mac80211_hwsim does not support SAE offload, so accept both a successful | |
1608 | # connection and association rejection. | |
1609 | ev = wpas.wait_event(["CTRL-EVENT-CONNECTED", "CTRL-EVENT-ASSOC-REJECT", | |
1610 | "Association request to the driver failed"], | |
1611 | timeout=15) | |
1612 | if ev is None: | |
1613 | raise Exception("No connection result reported") | |
9a0ae89d | 1614 | |
be5e7a07 | 1615 | def run_sae_password_id(dev, apdev, groups=None): |
4c0af8ad | 1616 | check_sae_capab(dev[0]) |
9a0ae89d JM |
1617 | params = hostapd.wpa2_params(ssid="test-sae") |
1618 | params['wpa_key_mgmt'] = 'SAE' | |
be5e7a07 JM |
1619 | if groups: |
1620 | params['sae_groups'] = groups | |
1621 | else: | |
1622 | groups = "" | |
fab49f61 JM |
1623 | params['sae_password'] = ['secret|mac=ff:ff:ff:ff:ff:ff|id=pw id', |
1624 | 'foo|mac=02:02:02:02:02:02', | |
1625 | 'another secret|mac=ff:ff:ff:ff:ff:ff|id=' + 29*'A'] | |
9a0ae89d JM |
1626 | hapd = hostapd.add_ap(apdev[0], params) |
1627 | ||
be5e7a07 | 1628 | dev[0].request("SET sae_groups " + groups) |
9a0ae89d JM |
1629 | dev[0].connect("test-sae", sae_password="secret", sae_password_id="pw id", |
1630 | key_mgmt="SAE", scan_freq="2412") | |
1631 | dev[0].request("REMOVE_NETWORK all") | |
1632 | dev[0].wait_disconnected() | |
1633 | ||
1634 | # SAE Password Identifier element with the exact same length as the | |
1635 | # optional Anti-Clogging Token field | |
1636 | dev[0].connect("test-sae", sae_password="another secret", | |
1637 | sae_password_id=29*'A', | |
1638 | key_mgmt="SAE", scan_freq="2412") | |
1639 | dev[0].request("REMOVE_NETWORK all") | |
1640 | dev[0].wait_disconnected() | |
1641 | ||
1642 | dev[0].connect("test-sae", sae_password="secret", sae_password_id="unknown", | |
1643 | key_mgmt="SAE", scan_freq="2412", wait_connect=False) | |
1644 | ||
1645 | ev = dev[0].wait_event(["CTRL-EVENT-SAE-UNKNOWN-PASSWORD-IDENTIFIER"], | |
1646 | timeout=10) | |
1647 | if ev is None: | |
1648 | raise Exception("Unknown password identifier not reported") | |
1649 | dev[0].request("REMOVE_NETWORK all") | |
1650 | ||
be5e7a07 JM |
1651 | def test_sae_password_id(dev, apdev): |
1652 | """SAE and password identifier""" | |
1653 | run_sae_password_id(dev, apdev, "") | |
1654 | ||
1655 | def test_sae_password_id_ecc(dev, apdev): | |
1656 | """SAE and password identifier (ECC)""" | |
1657 | run_sae_password_id(dev, apdev, "19") | |
1658 | ||
1659 | def test_sae_password_id_ffc(dev, apdev): | |
1660 | """SAE and password identifier (FFC)""" | |
8e607b1b | 1661 | run_sae_password_id(dev, apdev, "15") |
be5e7a07 | 1662 | |
6de2a809 JM |
1663 | def test_sae_password_id_only(dev, apdev): |
1664 | """SAE and password identifier (exclusively)""" | |
4c0af8ad | 1665 | check_sae_capab(dev[0]) |
6de2a809 JM |
1666 | params = hostapd.wpa2_params(ssid="test-sae") |
1667 | params['wpa_key_mgmt'] = 'SAE' | |
1668 | params['sae_password'] = 'secret|id=pw id' | |
1669 | hapd = hostapd.add_ap(apdev[0], params) | |
1670 | ||
1671 | dev[0].request("SET sae_groups ") | |
1672 | dev[0].connect("test-sae", sae_password="secret", sae_password_id="pw id", | |
1673 | key_mgmt="SAE", scan_freq="2412") | |
1674 | ||
c90822a5 JM |
1675 | def test_sae_password_id_pwe_looping(dev, apdev): |
1676 | """SAE and password identifier with forced PWE looping)""" | |
1677 | check_sae_capab(dev[0]) | |
1678 | params = hostapd.wpa2_params(ssid="test-sae") | |
1679 | params['wpa_key_mgmt'] = 'SAE' | |
1680 | params['sae_password'] = 'secret|id=pw id' | |
1681 | params['sae_pwe'] = "3" | |
1682 | hapd = hostapd.add_ap(apdev[0], params) | |
1683 | ||
1684 | dev[0].request("SET sae_groups ") | |
1685 | try: | |
1686 | dev[0].set("sae_pwe", "3") | |
1687 | dev[0].connect("test-sae", sae_password="secret", | |
1688 | sae_password_id="pw id", | |
1689 | key_mgmt="SAE", scan_freq="2412") | |
1690 | finally: | |
1691 | dev[0].set("sae_pwe", "0") | |
1692 | ||
1693 | def test_sae_password_id_pwe_check_ap(dev, apdev): | |
1694 | """SAE and password identifier with STA using unexpected PWE derivation)""" | |
1695 | check_sae_capab(dev[0]) | |
1696 | params = hostapd.wpa2_params(ssid="test-sae") | |
1697 | params['wpa_key_mgmt'] = 'SAE' | |
1698 | params['sae_password'] = 'secret|id=pw id' | |
1699 | hapd = hostapd.add_ap(apdev[0], params) | |
1700 | ||
1701 | dev[0].request("SET sae_groups ") | |
1702 | try: | |
1703 | dev[0].set("sae_pwe", "3") | |
1704 | dev[0].connect("test-sae", sae_password="secret", | |
1705 | sae_password_id="pw id", | |
1706 | key_mgmt="SAE", scan_freq="2412", wait_connect=False) | |
1707 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", | |
1708 | "CTRL-EVENT-SSID-TEMP-DISABLED"], timeout=10) | |
1709 | if ev is None or "CTRL-EVENT-SSID-TEMP-DISABLED" not in ev: | |
1710 | raise Exception("Connection failure not reported") | |
1711 | finally: | |
1712 | dev[0].set("sae_pwe", "0") | |
1713 | ||
1714 | def test_sae_password_id_pwe_check_sta(dev, apdev): | |
1715 | """SAE and password identifier with AP using unexpected PWE derivation)""" | |
1716 | check_sae_capab(dev[0]) | |
1717 | params = hostapd.wpa2_params(ssid="test-sae") | |
1718 | params['wpa_key_mgmt'] = 'SAE' | |
1719 | params['sae_pwe'] = "3" | |
1720 | params['sae_password'] = 'secret|id=pw id' | |
1721 | hapd = hostapd.add_ap(apdev[0], params) | |
1722 | ||
1723 | dev[0].request("SET sae_groups ") | |
1724 | dev[0].connect("test-sae", sae_password="secret", | |
1725 | sae_password_id="pw id", | |
1726 | key_mgmt="SAE", scan_freq="2412", wait_connect=False) | |
1727 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", | |
1728 | "CTRL-EVENT-NETWORK-NOT-FOUND"], timeout=10) | |
1729 | if ev is None or "CTRL-EVENT-NETWORK-NOT-FOUND" not in ev: | |
1730 | raise Exception("Connection failure not reported") | |
1731 | ||
9a0ae89d JM |
1732 | def test_sae_forced_anti_clogging_pw_id(dev, apdev): |
1733 | """SAE anti clogging (forced and Password Identifier)""" | |
4c0af8ad | 1734 | check_sae_capab(dev[0]) |
9a0ae89d JM |
1735 | params = hostapd.wpa2_params(ssid="test-sae") |
1736 | params['wpa_key_mgmt'] = 'SAE' | |
1737 | params['sae_anti_clogging_threshold'] = '0' | |
1738 | params['sae_password'] = 'secret|id=' + 29*'A' | |
1739 | hostapd.add_ap(apdev[0], params) | |
1740 | for i in range(0, 2): | |
1741 | dev[i].request("SET sae_groups ") | |
1742 | dev[i].connect("test-sae", sae_password="secret", | |
1743 | sae_password_id=29*'A', key_mgmt="SAE", scan_freq="2412") | |
fe102801 JM |
1744 | |
1745 | def test_sae_reauth(dev, apdev): | |
1746 | """SAE reauthentication""" | |
4c0af8ad | 1747 | check_sae_capab(dev[0]) |
fe102801 JM |
1748 | params = hostapd.wpa2_params(ssid="test-sae", |
1749 | passphrase="12345678") | |
1750 | params['wpa_key_mgmt'] = 'SAE' | |
1751 | params["ieee80211w"] = "2" | |
1752 | hapd = hostapd.add_ap(apdev[0], params) | |
1753 | ||
1754 | dev[0].request("SET sae_groups ") | |
1755 | id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
1756 | ieee80211w="2", scan_freq="2412") | |
1757 | ||
1758 | hapd.set("ext_mgmt_frame_handling", "1") | |
1759 | dev[0].request("DISCONNECT") | |
1760 | dev[0].wait_disconnected(timeout=10) | |
1761 | hapd.set("ext_mgmt_frame_handling", "0") | |
1762 | dev[0].request("PMKSA_FLUSH") | |
1763 | dev[0].request("REASSOCIATE") | |
1764 | dev[0].wait_connected(timeout=10, error="Timeout on re-connection") | |
e43352ff JM |
1765 | |
1766 | def test_sae_anti_clogging_during_attack(dev, apdev): | |
1767 | """SAE anti clogging during an attack""" | |
1768 | try: | |
1769 | run_sae_anti_clogging_during_attack(dev, apdev) | |
1770 | finally: | |
3507968f | 1771 | stop_monitor(apdev[1]["ifname"]) |
e43352ff JM |
1772 | |
1773 | def build_sae_commit(bssid, addr, group=21, token=None): | |
1774 | if group == 19: | |
1775 | scalar = binascii.unhexlify("7332d3ebff24804005ccd8c56141e3ed8d84f40638aa31cd2fac11d4d2e89e7b") | |
1776 | element = binascii.unhexlify("954d0f4457066bff3168376a1d7174f4e66620d1792406f613055b98513a7f03a538c13dfbaf2029e2adc6aa96aa0ddcf08ac44887b02f004b7f29b9dbf4b7d9") | |
1777 | elif group == 21: | |
1778 | scalar = binascii.unhexlify("001eec673111b902f5c8a61c8cb4c1c4793031aeea8c8c319410903bc64bcbaea134ab01c4e016d51436f5b5426f7e2af635759a3033fb4031ea79f89a62a3e2f828") | |
1779 | element = binascii.unhexlify("00580eb4b448ea600ea277d5e66e4ed37db82bb04ac90442e9c3727489f366ba4b82f0a472d02caf4cdd142e96baea5915d71374660ee23acbaca38cf3fe8c5fb94b01abbc5278121635d7c06911c5dad8f18d516e1fbe296c179b7c87a1dddfab393337d3d215ed333dd396da6d8f20f798c60d054f1093c24d9c2d98e15c030cc375f0") | |
1780 | pass | |
1781 | frame = binascii.unhexlify("b0003a01") | |
1782 | frame += bssid + addr + bssid | |
1783 | frame += binascii.unhexlify("1000") | |
1784 | auth_alg = 3 | |
1785 | transact = 1 | |
1786 | status = 0 | |
1787 | frame += struct.pack("<HHHH", auth_alg, transact, status, group) | |
1788 | if token: | |
1789 | frame += token | |
1790 | frame += scalar + element | |
1791 | return frame | |
1792 | ||
1793 | def sae_rx_commit_token_req(sock, radiotap, send_two=False): | |
1794 | msg = sock.recv(1500) | |
fab49f61 | 1795 | ver, pad, len, present = struct.unpack('<BBHL', msg[0:8]) |
e43352ff | 1796 | frame = msg[len:] |
fab49f61 | 1797 | fc, duration = struct.unpack('<HH', frame[0:4]) |
e43352ff JM |
1798 | if fc != 0xb0: |
1799 | return False | |
1800 | frame = frame[4:] | |
1801 | da = frame[0:6] | |
1802 | if da[0] != 0xf2: | |
1803 | return False | |
1804 | sa = frame[6:12] | |
1805 | bssid = frame[12:18] | |
1806 | body = frame[20:] | |
1807 | ||
fab49f61 | 1808 | alg, seq, status, group = struct.unpack('<HHHH', body[0:8]) |
e43352ff JM |
1809 | if alg != 3 or seq != 1 or status != 76: |
1810 | return False | |
1811 | token = body[8:] | |
1812 | ||
1813 | frame = build_sae_commit(bssid, da, token=token) | |
1814 | sock.send(radiotap + frame) | |
1815 | if send_two: | |
1816 | sock.send(radiotap + frame) | |
1817 | return True | |
1818 | ||
1819 | def run_sae_anti_clogging_during_attack(dev, apdev): | |
4c0af8ad | 1820 | check_sae_capab(dev[0]) |
e43352ff JM |
1821 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
1822 | params['wpa_key_mgmt'] = 'SAE' | |
1823 | params['sae_groups'] = '21' | |
1824 | hapd = hostapd.add_ap(apdev[0], params) | |
1825 | ||
1826 | dev[0].scan_for_bss(hapd.own_addr(), freq=2412) | |
1827 | dev[0].request("SET sae_groups 21") | |
1828 | dev[1].scan_for_bss(hapd.own_addr(), freq=2412) | |
1829 | dev[1].request("SET sae_groups 21") | |
1830 | ||
3507968f JM |
1831 | sock = start_monitor(apdev[1]["ifname"]) |
1832 | radiotap = radiotap_build() | |
e43352ff JM |
1833 | |
1834 | bssid = binascii.unhexlify(hapd.own_addr().replace(':', '')) | |
1835 | for i in range(16): | |
1836 | addr = binascii.unhexlify("f2%010x" % i) | |
1837 | frame = build_sae_commit(bssid, addr) | |
1838 | sock.send(radiotap + frame) | |
1839 | sock.send(radiotap + frame) | |
1840 | ||
1841 | count = 0 | |
1842 | for i in range(150): | |
1843 | if sae_rx_commit_token_req(sock, radiotap, send_two=True): | |
1844 | count += 1 | |
1845 | logger.info("Number of token responses sent: %d" % count) | |
1846 | if count < 10: | |
1847 | raise Exception("Too few token responses seen: %d" % count) | |
1848 | ||
1849 | for i in range(16): | |
1850 | addr = binascii.unhexlify("f201%08x" % i) | |
1851 | frame = build_sae_commit(bssid, addr) | |
1852 | sock.send(radiotap + frame) | |
1853 | ||
1854 | count = 0 | |
1855 | for i in range(150): | |
1856 | if sae_rx_commit_token_req(sock, radiotap): | |
1857 | count += 1 | |
1858 | if count == 10: | |
1859 | break | |
a1983aa7 | 1860 | if count < 5: |
e43352ff JM |
1861 | raise Exception("Too few token responses in second round: %d" % count) |
1862 | ||
1863 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
1864 | scan_freq="2412", wait_connect=False) | |
1865 | dev[1].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
1866 | scan_freq="2412", wait_connect=False) | |
1867 | ||
1868 | count = 0 | |
1869 | connected0 = False | |
1870 | connected1 = False | |
1871 | for i in range(1000): | |
1872 | if sae_rx_commit_token_req(sock, radiotap): | |
1873 | count += 1 | |
1874 | addr = binascii.unhexlify("f202%08x" % i) | |
1875 | frame = build_sae_commit(bssid, addr) | |
1876 | sock.send(radiotap + frame) | |
1877 | while dev[0].mon.pending(): | |
1878 | ev = dev[0].mon.recv() | |
1879 | logger.debug("EV0: " + ev) | |
1880 | if "CTRL-EVENT-CONNECTED" in ev: | |
1881 | connected0 = True | |
1882 | while dev[1].mon.pending(): | |
1883 | ev = dev[1].mon.recv() | |
1884 | logger.debug("EV1: " + ev) | |
1885 | if "CTRL-EVENT-CONNECTED" in ev: | |
1886 | connected1 = True | |
1887 | if connected0 and connected1: | |
1888 | break | |
1df79115 | 1889 | time.sleep(0.00000001) |
e43352ff JM |
1890 | if not connected0: |
1891 | raise Exception("Real station(0) did not get connected") | |
1892 | if not connected1: | |
1893 | raise Exception("Real station(1) did not get connected") | |
1894 | if count < 1: | |
1895 | raise Exception("Too few token responses in third round: %d" % count) | |
ed98d4d7 JM |
1896 | |
1897 | def test_sae_sync(dev, apdev): | |
1898 | """SAE dot11RSNASAESync""" | |
4c0af8ad | 1899 | check_sae_capab(dev[0]) |
ed98d4d7 JM |
1900 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
1901 | params['wpa_key_mgmt'] = 'SAE' | |
1902 | params['sae_sync'] = '1' | |
1903 | hostapd.add_ap(apdev[0], params) | |
1904 | ||
1905 | # TODO: More complete dot11RSNASAESync testing. For now, this is really only | |
1906 | # checking that sae_sync config parameter is accepted. | |
1907 | dev[0].request("SET sae_groups ") | |
1908 | dev[1].request("SET sae_groups ") | |
1909 | id = {} | |
1910 | for i in range(0, 2): | |
1911 | dev[i].scan(freq="2412") | |
1912 | id[i] = dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
1913 | scan_freq="2412", only_add_network=True) | |
1914 | for i in range(0, 2): | |
1915 | dev[i].select_network(id[i]) | |
1916 | for i in range(0, 2): | |
1917 | dev[i].wait_connected(timeout=10) | |
8a9658db JM |
1918 | |
1919 | def test_sae_confirm_immediate(dev, apdev): | |
1920 | """SAE and AP sending Confirm message without waiting STA""" | |
4c0af8ad | 1921 | check_sae_capab(dev[0]) |
8a9658db JM |
1922 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
1923 | params['wpa_key_mgmt'] = 'SAE' | |
1924 | params['sae_confirm_immediate'] = '1' | |
1925 | hapd = hostapd.add_ap(apdev[0], params) | |
1926 | ||
1927 | dev[0].request("SET sae_groups ") | |
1928 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412") | |
3fa701b5 | 1929 | |
283be365 JM |
1930 | def test_sae_confirm_immediate2(dev, apdev): |
1931 | """SAE and AP sending Confirm message without waiting STA (2)""" | |
4c0af8ad | 1932 | check_sae_capab(dev[0]) |
283be365 JM |
1933 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
1934 | params['wpa_key_mgmt'] = 'SAE' | |
1935 | params['sae_confirm_immediate'] = '2' | |
1936 | hapd = hostapd.add_ap(apdev[0], params) | |
1937 | ||
1938 | dev[0].request("SET sae_groups ") | |
1939 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412") | |
1940 | ||
3fa701b5 JM |
1941 | def test_sae_pwe_group_19(dev, apdev): |
1942 | """SAE PWE derivation options with group 19""" | |
1943 | run_sae_pwe_group(dev, apdev, 19) | |
1944 | ||
1945 | def test_sae_pwe_group_20(dev, apdev): | |
1946 | """SAE PWE derivation options with group 20""" | |
1947 | run_sae_pwe_group(dev, apdev, 20) | |
1948 | ||
1949 | def test_sae_pwe_group_21(dev, apdev): | |
1950 | """SAE PWE derivation options with group 21""" | |
1951 | run_sae_pwe_group(dev, apdev, 21) | |
1952 | ||
1953 | def test_sae_pwe_group_25(dev, apdev): | |
71e276f9 JM |
1954 | """SAE PWE derivation options with group 25""" |
1955 | run_sae_pwe_group(dev, apdev, 25) | |
3fa701b5 | 1956 | |
3fa701b5 | 1957 | def test_sae_pwe_group_28(dev, apdev): |
71e276f9 JM |
1958 | """SAE PWE derivation options with group 28""" |
1959 | run_sae_pwe_group(dev, apdev, 28) | |
3fa701b5 JM |
1960 | |
1961 | def test_sae_pwe_group_29(dev, apdev): | |
71e276f9 JM |
1962 | """SAE PWE derivation options with group 29""" |
1963 | run_sae_pwe_group(dev, apdev, 29) | |
3fa701b5 JM |
1964 | |
1965 | def test_sae_pwe_group_30(dev, apdev): | |
71e276f9 JM |
1966 | """SAE PWE derivation options with group 30""" |
1967 | run_sae_pwe_group(dev, apdev, 30) | |
3fa701b5 JM |
1968 | |
1969 | def test_sae_pwe_group_1(dev, apdev): | |
1970 | """SAE PWE derivation options with group 1""" | |
1971 | run_sae_pwe_group(dev, apdev, 1) | |
1972 | ||
1973 | def test_sae_pwe_group_2(dev, apdev): | |
1974 | """SAE PWE derivation options with group 2""" | |
1975 | run_sae_pwe_group(dev, apdev, 2) | |
1976 | ||
1977 | def test_sae_pwe_group_5(dev, apdev): | |
1978 | """SAE PWE derivation options with group 5""" | |
1979 | run_sae_pwe_group(dev, apdev, 5) | |
1980 | ||
1981 | def test_sae_pwe_group_14(dev, apdev): | |
1982 | """SAE PWE derivation options with group 14""" | |
1983 | run_sae_pwe_group(dev, apdev, 14) | |
1984 | ||
1985 | def test_sae_pwe_group_15(dev, apdev): | |
1986 | """SAE PWE derivation options with group 15""" | |
1987 | run_sae_pwe_group(dev, apdev, 15) | |
1988 | ||
1989 | def test_sae_pwe_group_16(dev, apdev): | |
1990 | """SAE PWE derivation options with group 16""" | |
1991 | run_sae_pwe_group(dev, apdev, 16) | |
1992 | ||
1993 | def test_sae_pwe_group_22(dev, apdev): | |
1994 | """SAE PWE derivation options with group 22""" | |
1995 | run_sae_pwe_group(dev, apdev, 22) | |
1996 | ||
1997 | def test_sae_pwe_group_23(dev, apdev): | |
1998 | """SAE PWE derivation options with group 23""" | |
1999 | run_sae_pwe_group(dev, apdev, 23) | |
2000 | ||
2001 | def test_sae_pwe_group_24(dev, apdev): | |
2002 | """SAE PWE derivation options with group 24""" | |
2003 | run_sae_pwe_group(dev, apdev, 24) | |
2004 | ||
2005 | def start_sae_pwe_ap(apdev, group, sae_pwe): | |
2006 | params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678") | |
2007 | params['wpa_key_mgmt'] = 'SAE' | |
2008 | params['sae_groups'] = str(group) | |
2009 | params['sae_pwe'] = str(sae_pwe) | |
2010 | return hostapd.add_ap(apdev, params) | |
2011 | ||
2012 | def run_sae_pwe_group(dev, apdev, group): | |
4c0af8ad | 2013 | check_sae_capab(dev[0]) |
3fa701b5 JM |
2014 | tls = dev[0].request("GET tls_library") |
2015 | if group in [27, 28, 29, 30]: | |
2016 | if tls.startswith("OpenSSL") and "run=OpenSSL 1." in tls: | |
2017 | logger.info("Add Brainpool EC groups since OpenSSL is new enough") | |
2018 | else: | |
2019 | raise HwsimSkip("Brainpool curve not supported") | |
2020 | start_sae_pwe_ap(apdev[0], group, 2) | |
2021 | try: | |
2022 | check_sae_pwe_group(dev[0], group, 0) | |
2023 | check_sae_pwe_group(dev[0], group, 1) | |
2024 | check_sae_pwe_group(dev[0], group, 2) | |
2025 | finally: | |
2026 | dev[0].set("sae_groups", "") | |
2027 | dev[0].set("sae_pwe", "0") | |
2028 | ||
2029 | def check_sae_pwe_group(dev, group, sae_pwe): | |
2030 | dev.set("sae_groups", str(group)) | |
2031 | dev.set("sae_pwe", str(sae_pwe)) | |
2032 | dev.connect("sae-pwe", psk="12345678", key_mgmt="SAE", scan_freq="2412") | |
2033 | dev.request("REMOVE_NETWORK all") | |
2034 | dev.wait_disconnected() | |
2035 | dev.dump_monitor() | |
2036 | ||
2037 | def test_sae_pwe_h2e_only_ap(dev, apdev): | |
2038 | """SAE PWE derivation with H2E-only AP""" | |
4c0af8ad | 2039 | check_sae_capab(dev[0]) |
3fa701b5 JM |
2040 | start_sae_pwe_ap(apdev[0], 19, 1) |
2041 | try: | |
2042 | check_sae_pwe_group(dev[0], 19, 1) | |
2043 | check_sae_pwe_group(dev[0], 19, 2) | |
2044 | finally: | |
2045 | dev[0].set("sae_groups", "") | |
2046 | dev[0].set("sae_pwe", "0") | |
2047 | ||
2048 | dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", scan_freq="2412", | |
2049 | wait_connect=False) | |
2050 | ev = dev[0].wait_event(["CTRL-EVENT-NETWORK-NOT-FOUND"], timeout=10) | |
2051 | if ev is None: | |
2052 | raise Exception("No indication of mismatching network seen") | |
2053 | ||
b1905c7d JM |
2054 | def test_sae_pwe_h2e_only_ap_sta_forcing_loop(dev, apdev): |
2055 | """SAE PWE derivation with H2E-only AP and STA forcing loop""" | |
4c0af8ad | 2056 | check_sae_capab(dev[0]) |
b1905c7d JM |
2057 | start_sae_pwe_ap(apdev[0], 19, 1) |
2058 | dev[0].set("ignore_sae_h2e_only", "1") | |
2059 | dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", scan_freq="2412", | |
2060 | wait_connect=False) | |
2061 | ev = dev[0].wait_event(["CTRL-EVENT-SSID-TEMP-DISABLED"], timeout=10) | |
2062 | dev[0].request("DISCONNECT") | |
2063 | if ev is None: | |
2064 | raise Exception("No indication of temporary disabled network seen") | |
2065 | ||
3fa701b5 JM |
2066 | def test_sae_pwe_loop_only_ap(dev, apdev): |
2067 | """SAE PWE derivation with loop-only AP""" | |
4c0af8ad | 2068 | check_sae_capab(dev[0]) |
3fa701b5 JM |
2069 | start_sae_pwe_ap(apdev[0], 19, 0) |
2070 | try: | |
2071 | check_sae_pwe_group(dev[0], 19, 0) | |
2072 | check_sae_pwe_group(dev[0], 19, 2) | |
2073 | dev[0].set("sae_pwe", "1") | |
2074 | dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", | |
2075 | scan_freq="2412", wait_connect=False) | |
2076 | ev = dev[0].wait_event(["CTRL-EVENT-NETWORK-NOT-FOUND"], timeout=10) | |
2077 | if ev is None: | |
2078 | raise Exception("No indication of mismatching network seen") | |
2079 | finally: | |
2080 | dev[0].set("sae_groups", "") | |
2081 | dev[0].set("sae_pwe", "0") | |
2082 | ||
2083 | def test_sae_h2e_rejected_groups(dev, apdev): | |
2084 | """SAE H2E and rejected groups indication""" | |
4c0af8ad | 2085 | check_sae_capab(dev[0]) |
3fa701b5 JM |
2086 | params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678") |
2087 | params['wpa_key_mgmt'] = 'SAE' | |
2088 | params['sae_groups'] = "19" | |
2089 | params['sae_pwe'] = "1" | |
2090 | hapd = hostapd.add_ap(apdev[0], params) | |
2091 | try: | |
2092 | dev[0].set("sae_groups", "21 20 19") | |
2093 | dev[0].set("sae_pwe", "1") | |
2094 | dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", | |
2095 | scan_freq="2412") | |
fb3ef06d JM |
2096 | addr = dev[0].own_addr() |
2097 | hapd.wait_sta(addr) | |
2098 | sta = hapd.get_sta(addr) | |
2099 | if 'sae_rejected_groups' not in sta: | |
2100 | raise Exception("No sae_rejected_groups") | |
2101 | val = sta['sae_rejected_groups'] | |
2102 | if val != "21 20": | |
2103 | raise Exception("Unexpected sae_rejected_groups value: " + val) | |
3fa701b5 JM |
2104 | finally: |
2105 | dev[0].set("sae_groups", "") | |
2106 | dev[0].set("sae_pwe", "0") | |
2107 | ||
90d84bc5 JM |
2108 | def test_sae_h2e_rejected_groups_unexpected(dev, apdev): |
2109 | """SAE H2E and rejected groups indication (unexpected group)""" | |
4c0af8ad | 2110 | check_sae_capab(dev[0]) |
90d84bc5 JM |
2111 | params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678") |
2112 | params['wpa_key_mgmt'] = 'SAE' | |
2113 | params['sae_groups'] = "19 20" | |
2114 | params['sae_pwe'] = "1" | |
2115 | hapd = hostapd.add_ap(apdev[0], params) | |
2116 | try: | |
2117 | dev[0].set("sae_groups", "21 19") | |
2118 | dev[0].set("extra_sae_rejected_groups", "19") | |
2119 | dev[0].set("sae_pwe", "1") | |
2120 | dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", | |
2121 | scan_freq="2412", wait_connect=False) | |
2122 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", | |
2123 | "CTRL-EVENT-SSID-TEMP-DISABLED"], timeout=10) | |
2124 | dev[0].request("DISCONNECT") | |
2125 | if ev is None: | |
2126 | raise Exception("No indication of temporary disabled network seen") | |
2127 | if "CTRL-EVENT-CONNECTED" in ev: | |
2128 | raise Exception("Unexpected connection") | |
2129 | finally: | |
2130 | dev[0].set("sae_groups", "") | |
2131 | dev[0].set("sae_pwe", "0") | |
2132 | ||
3fa701b5 JM |
2133 | def test_sae_h2e_password_id(dev, apdev): |
2134 | """SAE H2E and password identifier""" | |
4c0af8ad | 2135 | check_sae_capab(dev[0]) |
3fa701b5 JM |
2136 | params = hostapd.wpa2_params(ssid="test-sae") |
2137 | params['wpa_key_mgmt'] = 'SAE' | |
2138 | params['sae_pwe'] = '1' | |
2139 | params['sae_password'] = 'secret|id=pw id' | |
2140 | hapd = hostapd.add_ap(apdev[0], params) | |
2141 | ||
2142 | try: | |
2143 | dev[0].request("SET sae_groups ") | |
2144 | dev[0].set("sae_pwe", "1") | |
2145 | dev[0].connect("test-sae", sae_password="secret", | |
2146 | sae_password_id="pw id", | |
2147 | key_mgmt="SAE", scan_freq="2412") | |
2148 | finally: | |
2149 | dev[0].set("sae_groups", "") | |
2150 | dev[0].set("sae_pwe", "0") | |
01b2cd64 | 2151 | |
dd8eb44e JM |
2152 | def test_sae_pwe_in_psk_ap(dev, apdev): |
2153 | """sae_pwe parameter in PSK-only-AP""" | |
2154 | params = hostapd.wpa2_params(ssid="test-psk", passphrase="12345678") | |
2155 | params['sae_pwe'] = '1' | |
2156 | hapd = hostapd.add_ap(apdev[0], params) | |
2157 | ||
2158 | dev[0].connect("test-psk", psk="12345678", scan_freq="2412") | |
2159 | ||
01b2cd64 JM |
2160 | def test_sae_auth_restart(dev, apdev): |
2161 | """SAE and authentication restarts with H2E/looping""" | |
4c0af8ad | 2162 | check_sae_capab(dev[0]) |
01b2cd64 JM |
2163 | params = hostapd.wpa2_params(ssid="test-sae") |
2164 | params['wpa_key_mgmt'] = 'SAE' | |
2165 | params['sae_pwe'] = '2' | |
2166 | params['sae_password'] = 'secret|id=pw id' | |
2167 | hapd = hostapd.add_ap(apdev[0], params) | |
2168 | ||
2169 | try: | |
2170 | dev[0].request("SET sae_groups ") | |
2171 | for pwe in [1, 0, 1]: | |
2172 | dev[0].set("sae_pwe", str(pwe)) | |
2173 | dev[0].connect("test-sae", sae_password="secret", | |
2174 | sae_password_id="pw id", | |
2175 | key_mgmt="SAE", scan_freq="2412") | |
2176 | # Disconnect without hostapd removing the STA entry so that the | |
2177 | # following SAE authentication instance starts with an existing | |
2178 | # STA entry that has maintained some SAE state. | |
2179 | hapd.set("ext_mgmt_frame_handling", "1") | |
2180 | dev[0].request("REMOVE_NETWORK all") | |
2181 | req = hapd.mgmt_rx() | |
2182 | dev[0].wait_disconnected() | |
2183 | dev[0].dump_monitor() | |
2184 | hapd.set("ext_mgmt_frame_handling", "0") | |
2185 | finally: | |
2186 | dev[0].set("sae_groups", "") | |
2187 | dev[0].set("sae_pwe", "0") | |
250db2ab | 2188 | |
60c43549 JM |
2189 | def test_sae_rsne_mismatch(dev, apdev): |
2190 | """SAE and RSNE mismatch in EAPOL-Key msg 2/4""" | |
2191 | check_sae_capab(dev[0]) | |
2192 | dev[0].set("sae_groups", "") | |
2193 | ||
2194 | params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678") | |
2195 | params['wpa_key_mgmt'] = 'SAE' | |
2196 | hapd = hostapd.add_ap(apdev[0], params) | |
2197 | ||
2198 | # First, test with matching RSNE to confirm testing capability | |
2199 | dev[0].set("rsne_override_eapol", | |
2200 | "30140100000fac040100000fac040100000fac080000") | |
2201 | dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", | |
2202 | scan_freq="2412") | |
2203 | dev[0].request("REMOVE_NETWORK all") | |
2204 | dev[0].wait_disconnected() | |
2205 | dev[0].dump_monitor() | |
2206 | ||
2207 | # Then, test with modified RSNE | |
2208 | tests = ["30140100000fac040100000fac040100000fac080010", "0000"] | |
2209 | for ie in tests: | |
2210 | dev[0].set("rsne_override_eapol", ie) | |
2211 | dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", | |
2212 | scan_freq="2412", wait_connect=False) | |
2213 | ev = dev[0].wait_event(["Associated with"], timeout=10) | |
2214 | if ev is None: | |
2215 | raise Exception("No indication of association seen") | |
2216 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", | |
2217 | "CTRL-EVENT-DISCONNECTED"], timeout=5) | |
2218 | dev[0].request("REMOVE_NETWORK all") | |
2219 | if ev is None: | |
2220 | raise Exception("No disconnection seen") | |
2221 | if "CTRL-EVENT-DISCONNECTED" not in ev: | |
2222 | raise Exception("Unexpected connection") | |
2223 | dev[0].dump_monitor() | |
2224 | ||
250db2ab JM |
2225 | def test_sae_h2e_rsnxe_mismatch(dev, apdev): |
2226 | """SAE H2E and RSNXE mismatch in EAPOL-Key msg 2/4""" | |
4c0af8ad | 2227 | check_sae_capab(dev[0]) |
250db2ab JM |
2228 | params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678") |
2229 | params['wpa_key_mgmt'] = 'SAE' | |
2230 | params['sae_pwe'] = "1" | |
2231 | hapd = hostapd.add_ap(apdev[0], params) | |
2232 | try: | |
2233 | dev[0].set("sae_groups", "19") | |
2234 | dev[0].set("sae_pwe", "1") | |
2235 | for rsnxe in ["F40100", "F400", ""]: | |
2236 | dev[0].set("rsnxe_override_eapol", rsnxe) | |
2237 | dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", | |
2238 | scan_freq="2412", wait_connect=False) | |
2239 | ev = dev[0].wait_event(["Associated with"], timeout=10) | |
2240 | if ev is None: | |
2241 | raise Exception("No indication of association seen") | |
2242 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", | |
2243 | "CTRL-EVENT-DISCONNECTED"], timeout=5) | |
2244 | dev[0].request("REMOVE_NETWORK all") | |
2245 | if ev is None: | |
2246 | raise Exception("No disconnection seen") | |
2247 | if "CTRL-EVENT-DISCONNECTED" not in ev: | |
2248 | raise Exception("Unexpected connection") | |
2249 | dev[0].dump_monitor() | |
2250 | finally: | |
2251 | dev[0].set("sae_groups", "") | |
2252 | dev[0].set("sae_pwe", "0") | |
2253 | ||
06540f23 JM |
2254 | def test_sae_h2e_rsnxe_mismatch_retries(dev, apdev): |
2255 | """SAE H2E and RSNXE mismatch in EAPOL-Key msg 2/4 retries""" | |
4c0af8ad | 2256 | check_sae_capab(dev[0]) |
06540f23 JM |
2257 | params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678") |
2258 | params['wpa_key_mgmt'] = 'SAE' | |
2259 | params['sae_pwe'] = "1" | |
2260 | hapd = hostapd.add_ap(apdev[0], params) | |
2261 | try: | |
2262 | dev[0].set("sae_groups", "19") | |
2263 | dev[0].set("sae_pwe", "1") | |
2264 | rsnxe = "F40100" | |
2265 | dev[0].set("rsnxe_override_eapol", rsnxe) | |
2266 | dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", | |
2267 | scan_freq="2412", wait_connect=False) | |
2268 | ev = dev[0].wait_event(["Associated with"], timeout=10) | |
2269 | if ev is None: | |
2270 | raise Exception("No indication of association seen") | |
2271 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", | |
2272 | "CTRL-EVENT-DISCONNECTED"], timeout=5) | |
2273 | if ev is None: | |
2274 | raise Exception("No disconnection seen") | |
2275 | if "CTRL-EVENT-DISCONNECTED" not in ev: | |
2276 | raise Exception("Unexpected connection") | |
2277 | ||
2278 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", | |
2279 | "CTRL-EVENT-DISCONNECTED"], timeout=10) | |
2280 | if ev is None: | |
2281 | raise Exception("No disconnection seen (2)") | |
2282 | if "CTRL-EVENT-DISCONNECTED" not in ev: | |
2283 | raise Exception("Unexpected connection (2)") | |
2284 | ||
2285 | dev[0].dump_monitor() | |
2286 | finally: | |
2287 | dev[0].set("sae_groups", "") | |
2288 | dev[0].set("sae_pwe", "0") | |
2289 | ||
250db2ab JM |
2290 | def test_sae_h2e_rsnxe_mismatch_assoc(dev, apdev): |
2291 | """SAE H2E and RSNXE mismatch in EAPOL-Key msg 2/4 (assoc)""" | |
4c0af8ad | 2292 | check_sae_capab(dev[0]) |
250db2ab JM |
2293 | params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678") |
2294 | params['wpa_key_mgmt'] = 'SAE' | |
2295 | params['sae_pwe'] = "1" | |
2296 | hapd = hostapd.add_ap(apdev[0], params) | |
2297 | try: | |
2298 | dev[0].set("sae_groups", "19") | |
2299 | dev[0].set("sae_pwe", "1") | |
2300 | for rsnxe in ["F40100", "F400", ""]: | |
2301 | dev[0].set("rsnxe_override_assoc", rsnxe) | |
2302 | dev[0].set("rsnxe_override_eapol", "F40120") | |
2303 | dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", | |
2304 | scan_freq="2412", wait_connect=False) | |
2305 | ev = dev[0].wait_event(["Associated with"], timeout=10) | |
2306 | if ev is None: | |
2307 | raise Exception("No indication of association seen") | |
2308 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", | |
2309 | "CTRL-EVENT-DISCONNECTED"], timeout=5) | |
2310 | dev[0].request("REMOVE_NETWORK all") | |
2311 | if ev is None: | |
2312 | raise Exception("No disconnection seen") | |
2313 | if "CTRL-EVENT-DISCONNECTED" not in ev: | |
2314 | raise Exception("Unexpected connection") | |
2315 | dev[0].dump_monitor() | |
2316 | finally: | |
2317 | dev[0].set("sae_groups", "") | |
2318 | dev[0].set("sae_pwe", "0") | |
63585099 JM |
2319 | |
2320 | def test_sae_h2e_rsnxe_mismatch_ap(dev, apdev): | |
2321 | """SAE H2E and RSNXE mismatch in EAPOL-Key msg 3/4""" | |
2322 | run_sae_h2e_rsnxe_mismatch_ap(dev, apdev, "F40100") | |
2323 | ||
2324 | def test_sae_h2e_rsnxe_mismatch_ap2(dev, apdev): | |
2325 | """SAE H2E and RSNXE mismatch in EAPOL-Key msg 3/4""" | |
2326 | run_sae_h2e_rsnxe_mismatch_ap(dev, apdev, "F400") | |
2327 | ||
3396a452 JM |
2328 | def test_sae_h2e_rsnxe_mismatch_ap3(dev, apdev): |
2329 | """SAE H2E and RSNXE mismatch in EAPOL-Key msg 3/4""" | |
2330 | run_sae_h2e_rsnxe_mismatch_ap(dev, apdev, "") | |
2331 | ||
63585099 | 2332 | def run_sae_h2e_rsnxe_mismatch_ap(dev, apdev, rsnxe): |
4c0af8ad | 2333 | check_sae_capab(dev[0]) |
63585099 JM |
2334 | params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678") |
2335 | params['wpa_key_mgmt'] = 'SAE' | |
2336 | params['sae_pwe'] = "1" | |
2337 | params['rsnxe_override_eapol'] = rsnxe | |
2338 | hapd = hostapd.add_ap(apdev[0], params) | |
2339 | try: | |
2340 | dev[0].set("sae_groups", "19") | |
2341 | dev[0].set("sae_pwe", "1") | |
2342 | dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", | |
2343 | scan_freq="2412", wait_connect=False) | |
2344 | ev = dev[0].wait_event(["Associated with"], timeout=10) | |
2345 | if ev is None: | |
2346 | raise Exception("No indication of association seen") | |
2347 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", | |
2348 | "CTRL-EVENT-DISCONNECTED"], timeout=5) | |
2349 | dev[0].request("REMOVE_NETWORK all") | |
2350 | if ev is None: | |
2351 | raise Exception("No disconnection seen") | |
2352 | if "CTRL-EVENT-DISCONNECTED" not in ev: | |
2353 | raise Exception("Unexpected connection") | |
2354 | finally: | |
2355 | dev[0].set("sae_groups", "") | |
2356 | dev[0].set("sae_pwe", "0") | |
6ce883de JM |
2357 | |
2358 | def test_sae_forced_anti_clogging_h2e(dev, apdev): | |
2359 | """SAE anti clogging (forced, H2E)""" | |
4c0af8ad JM |
2360 | check_sae_capab(dev[0]) |
2361 | check_sae_capab(dev[1]) | |
6ce883de JM |
2362 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
2363 | params['wpa_key_mgmt'] = 'SAE WPA-PSK' | |
2364 | params['sae_pwe'] = "1" | |
2365 | params['sae_anti_clogging_threshold'] = '0' | |
2366 | hostapd.add_ap(apdev[0], params) | |
2367 | dev[2].connect("test-sae", psk="12345678", scan_freq="2412") | |
2368 | try: | |
2369 | for i in range(2): | |
2370 | dev[i].request("SET sae_groups ") | |
2371 | dev[i].set("sae_pwe", "1") | |
2372 | dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
2373 | scan_freq="2412") | |
2374 | finally: | |
2375 | for i in range(2): | |
2376 | dev[i].set("sae_pwe", "0") | |
3ecaddd6 JM |
2377 | |
2378 | def test_sae_forced_anti_clogging_h2e_loop(dev, apdev): | |
2379 | """SAE anti clogging (forced, H2E + loop)""" | |
2380 | check_sae_capab(dev[0]) | |
2381 | check_sae_capab(dev[1]) | |
2382 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") | |
2383 | params['wpa_key_mgmt'] = 'SAE WPA-PSK' | |
2384 | params['sae_pwe'] = "2" | |
2385 | params['sae_anti_clogging_threshold'] = '0' | |
2386 | hostapd.add_ap(apdev[0], params) | |
2387 | dev[2].connect("test-sae", psk="12345678", scan_freq="2412") | |
2388 | try: | |
2389 | for i in range(2): | |
2390 | dev[i].request("SET sae_groups ") | |
2391 | dev[i].set("sae_pwe", "2") | |
2392 | dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
2393 | scan_freq="2412") | |
2394 | finally: | |
2395 | for i in range(2): | |
2396 | dev[i].set("sae_pwe", "0") | |
fd189288 JM |
2397 | |
2398 | def test_sae_okc(dev, apdev): | |
2399 | """SAE and opportunistic key caching""" | |
2400 | check_sae_capab(dev[0]) | |
2401 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") | |
2402 | params['wpa_key_mgmt'] = 'SAE' | |
2403 | params['okc'] = '1' | |
2404 | hapd = hostapd.add_ap(apdev[0], params) | |
2405 | bssid = hapd.own_addr() | |
2406 | ||
2407 | dev[0].set("sae_groups", "") | |
2408 | id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
2409 | okc=True, scan_freq="2412") | |
2410 | dev[0].dump_monitor() | |
2411 | hapd.wait_sta() | |
2412 | if "sae_group" not in dev[0].get_status(): | |
2413 | raise Exception("SAE authentication not used") | |
2414 | ||
2415 | hapd2 = hostapd.add_ap(apdev[1], params) | |
2416 | bssid2 = hapd2.own_addr() | |
2417 | ||
2418 | dev[0].scan_for_bss(bssid2, freq=2412) | |
2419 | dev[0].roam(bssid2) | |
2420 | dev[0].dump_monitor() | |
2421 | hapd2.wait_sta() | |
2422 | if "sae_group" in dev[0].get_status(): | |
2423 | raise Exception("SAE authentication used during roam to AP2") | |
2424 | ||
2425 | dev[0].roam(bssid) | |
2426 | dev[0].dump_monitor() | |
2427 | hapd.wait_sta() | |
2428 | if "sae_group" in dev[0].get_status(): | |
2429 | raise Exception("SAE authentication used during roam to AP1") | |
2430 | ||
2431 | def test_sae_okc_sta_only(dev, apdev): | |
2432 | """SAE and opportunistic key caching only on STA""" | |
2433 | check_sae_capab(dev[0]) | |
2434 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") | |
2435 | params['wpa_key_mgmt'] = 'SAE' | |
2436 | hapd = hostapd.add_ap(apdev[0], params) | |
2437 | bssid = hapd.own_addr() | |
2438 | ||
2439 | dev[0].set("sae_groups", "") | |
2440 | id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
2441 | okc=True, scan_freq="2412") | |
2442 | dev[0].dump_monitor() | |
2443 | hapd.wait_sta() | |
2444 | if "sae_group" not in dev[0].get_status(): | |
2445 | raise Exception("SAE authentication not used") | |
2446 | ||
2447 | hapd2 = hostapd.add_ap(apdev[1], params) | |
2448 | bssid2 = hapd2.own_addr() | |
2449 | ||
2450 | dev[0].scan_for_bss(bssid2, freq=2412) | |
2451 | dev[0].roam(bssid2, assoc_reject_ok=True) | |
2452 | dev[0].dump_monitor() | |
2453 | hapd2.wait_sta() | |
2454 | if "sae_group" not in dev[0].get_status(): | |
2455 | raise Exception("SAE authentication not used during roam to AP2") | |
2456 | ||
2457 | def test_sae_okc_pmk_lifetime(dev, apdev): | |
2458 | """SAE and opportunistic key caching and PMK lifetime""" | |
2459 | check_sae_capab(dev[0]) | |
2460 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") | |
2461 | params['wpa_key_mgmt'] = 'SAE' | |
2462 | params['okc'] = '1' | |
2463 | hapd = hostapd.add_ap(apdev[0], params) | |
2464 | bssid = hapd.own_addr() | |
2465 | ||
2466 | dev[0].set("sae_groups", "") | |
2467 | dev[0].set("dot11RSNAConfigPMKLifetime", "10") | |
2468 | dev[0].set("dot11RSNAConfigPMKReauthThreshold", "30") | |
2469 | id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
2470 | okc=True, scan_freq="2412") | |
2471 | dev[0].dump_monitor() | |
2472 | hapd.wait_sta() | |
2473 | if "sae_group" not in dev[0].get_status(): | |
2474 | raise Exception("SAE authentication not used") | |
2475 | ||
2476 | hapd2 = hostapd.add_ap(apdev[1], params) | |
2477 | bssid2 = hapd2.own_addr() | |
2478 | ||
2479 | time.sleep(5) | |
2480 | dev[0].scan_for_bss(bssid2, freq=2412) | |
2481 | dev[0].roam(bssid2) | |
2482 | dev[0].dump_monitor() | |
2483 | hapd2.wait_sta() | |
2484 | if "sae_group" not in dev[0].get_status(): | |
2485 | raise Exception("SAE authentication not used during roam to AP2 after reauth threshold") | |
2486 | ||
2487 | def test_sae_pmk_lifetime(dev, apdev): | |
2488 | """SAE and opportunistic key caching and PMK lifetime""" | |
2489 | check_sae_capab(dev[0]) | |
2490 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") | |
2491 | params['wpa_key_mgmt'] = 'SAE' | |
2492 | hapd = hostapd.add_ap(apdev[0], params) | |
2493 | bssid = hapd.own_addr() | |
2494 | ||
2495 | dev[0].set("sae_groups", "") | |
2496 | dev[0].set("dot11RSNAConfigPMKLifetime", "10") | |
2497 | dev[0].set("dot11RSNAConfigPMKReauthThreshold", "50") | |
2498 | id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
2499 | scan_freq="2412") | |
2500 | dev[0].dump_monitor() | |
2501 | hapd.wait_sta() | |
2502 | if "sae_group" not in dev[0].get_status(): | |
2503 | raise Exception("SAE authentication not used") | |
2504 | ||
2505 | hapd2 = hostapd.add_ap(apdev[1], params) | |
2506 | bssid2 = hapd2.own_addr() | |
2507 | ||
2508 | dev[0].scan_for_bss(bssid2, freq=2412) | |
2509 | dev[0].roam(bssid2) | |
2510 | dev[0].dump_monitor() | |
2511 | hapd2.wait_sta() | |
2512 | if "sae_group" not in dev[0].get_status(): | |
2513 | raise Exception("SAE authentication not used during roam to AP2") | |
2514 | ||
2515 | dev[0].roam(bssid) | |
2516 | dev[0].dump_monitor() | |
2517 | hapd.wait_sta() | |
2518 | if "sae_group" in dev[0].get_status(): | |
2519 | raise Exception("SAE authentication used during roam to AP1") | |
2520 | ||
2521 | time.sleep(6) | |
2522 | dev[0].scan_for_bss(bssid2, freq=2412) | |
2523 | dev[0].roam(bssid2) | |
2524 | dev[0].dump_monitor() | |
2525 | hapd2.wait_sta() | |
2526 | if "sae_group" not in dev[0].get_status(): | |
2527 | raise Exception("SAE authentication not used during roam to AP2 after reauth threshold") | |
2528 | ||
2529 | ev = dev[0].wait_event(["PMKSA-CACHE-REMOVED"], 11) | |
2530 | if ev is None: | |
2531 | raise Exception("PMKSA cache entry did not expire") | |
2532 | if bssid2 not in ev: | |
2533 | ev = dev[0].wait_event(["PMKSA-CACHE-REMOVED"], 11) | |
2534 | if ev is None: | |
2535 | raise Exception("PMKSA cache entry did not expire") | |
2536 | if bssid2 not in ev: | |
2537 | raise Exception("PMKSA cache entry for the current AP did not expire") | |
2538 | ev = dev[0].wait_event(["CTRL-EVENT-DISCONNECTED"], 1) | |
2539 | if ev is None: | |
2540 | raise Exception("Disconnection not reported after PMKSA cache entry expiration") | |
2541 | ||
2542 | dev[0].wait_connected() | |
2543 | if "sae_group" not in dev[0].get_status(): | |
2544 | raise Exception("SAE authentication not used after PMKSA cache entry expiration") | |
d9aafb75 JM |
2545 | |
2546 | def test_sae_and_psk_multiple_passwords(dev, apdev, params): | |
2547 | """SAE and PSK with multiple passwords/passphrases""" | |
2548 | check_sae_capab(dev[0]) | |
2549 | check_sae_capab(dev[1]) | |
2550 | addr0 = dev[0].own_addr() | |
2551 | addr1 = dev[1].own_addr() | |
2552 | psk_file = os.path.join(params['logdir'], | |
2553 | 'sae_and_psk_multiple_passwords.wpa_psk') | |
2554 | with open(psk_file, 'w') as f: | |
2555 | f.write(addr0 + ' passphrase0\n') | |
2556 | f.write(addr1 + ' passphrase1\n') | |
2557 | params = hostapd.wpa2_params(ssid="test-sae") | |
2558 | params['wpa_key_mgmt'] = 'SAE WPA-PSK' | |
2559 | params['sae_password'] = ['passphrase0|mac=' + addr0, | |
2560 | 'passphrase1|mac=' + addr1] | |
2561 | params['wpa_psk_file'] = psk_file | |
2562 | hapd = hostapd.add_ap(apdev[0], params) | |
2563 | ||
2564 | dev[0].set("sae_groups", "") | |
2565 | dev[0].connect("test-sae", sae_password="passphrase0", | |
2566 | key_mgmt="SAE", scan_freq="2412") | |
2567 | dev[0].request("REMOVE_NETWORK all") | |
2568 | dev[0].wait_disconnected() | |
2569 | ||
2570 | dev[0].connect("test-sae", psk="passphrase0", scan_freq="2412") | |
2571 | dev[0].request("REMOVE_NETWORK all") | |
2572 | dev[0].wait_disconnected() | |
2573 | ||
2574 | dev[1].set("sae_groups", "") | |
2575 | dev[1].connect("test-sae", sae_password="passphrase1", | |
2576 | key_mgmt="SAE", scan_freq="2412") | |
2577 | dev[1].request("REMOVE_NETWORK all") | |
2578 | dev[1].wait_disconnected() | |
2579 | ||
2580 | dev[1].connect("test-sae", psk="passphrase1", scan_freq="2412") | |
2581 | dev[1].request("REMOVE_NETWORK all") | |
2582 | dev[1].wait_disconnected() |