]>
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 | ||
c481e1cb JM |
366 | def test_sae_mfp(dev, apdev): |
367 | """SAE and MFP enabled without sae_require_mfp""" | |
4c0af8ad JM |
368 | check_sae_capab(dev[0]) |
369 | check_sae_capab(dev[1]) | |
c481e1cb JM |
370 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
371 | params['wpa_key_mgmt'] = 'SAE' | |
372 | params["ieee80211w"] = "1" | |
373 | hostapd.add_ap(apdev[0], params) | |
374 | ||
375 | dev[0].request("SET sae_groups ") | |
376 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", ieee80211w="2", | |
377 | scan_freq="2412") | |
378 | ||
379 | dev[1].request("SET sae_groups ") | |
380 | dev[1].connect("test-sae", psk="12345678", key_mgmt="SAE", ieee80211w="0", | |
381 | scan_freq="2412") | |
382 | ||
9fd6804d | 383 | @remote_compatible |
acb63c75 JM |
384 | def test_sae_missing_password(dev, apdev): |
385 | """SAE and missing password""" | |
4c0af8ad | 386 | check_sae_capab(dev[0]) |
acb63c75 JM |
387 | params = hostapd.wpa2_params(ssid="test-sae", |
388 | passphrase="12345678") | |
389 | params['wpa_key_mgmt'] = 'SAE' | |
8b8a1864 | 390 | hapd = hostapd.add_ap(apdev[0], params) |
acb63c75 JM |
391 | |
392 | dev[0].request("SET sae_groups ") | |
393 | id = dev[0].connect("test-sae", | |
394 | raw_psk="46b4a73b8a951ad53ebd2e0afdb9c5483257edd4c21d12b7710759da70945858", | |
395 | key_mgmt="SAE", scan_freq="2412", wait_connect=False) | |
396 | ev = dev[0].wait_event(['CTRL-EVENT-SSID-TEMP-DISABLED'], timeout=10) | |
397 | if ev is None: | |
398 | raise Exception("Invalid network not temporarily disabled") | |
5b3c40a6 JM |
399 | |
400 | ||
401 | def test_sae_key_lifetime_in_memory(dev, apdev, params): | |
402 | """SAE and key lifetime in memory""" | |
4c0af8ad | 403 | check_sae_capab(dev[0]) |
5b3c40a6 JM |
404 | password = "5ad144a7c1f5a5503baa6fa01dabc15b1843e8c01662d78d16b70b5cd23cf8b" |
405 | p = hostapd.wpa2_params(ssid="test-sae", passphrase=password) | |
406 | p['wpa_key_mgmt'] = 'SAE' | |
8b8a1864 | 407 | hapd = hostapd.add_ap(apdev[0], p) |
5b3c40a6 JM |
408 | |
409 | pid = find_wpas_process(dev[0]) | |
410 | ||
411 | dev[0].request("SET sae_groups ") | |
412 | id = dev[0].connect("test-sae", psk=password, key_mgmt="SAE", | |
413 | scan_freq="2412") | |
414 | ||
8e416cec JM |
415 | # The decrypted copy of GTK is freed only after the CTRL-EVENT-CONNECTED |
416 | # event has been delivered, so verify that wpa_supplicant has returned to | |
417 | # eloop before reading process memory. | |
54f2cae2 | 418 | time.sleep(1) |
8e416cec | 419 | dev[0].ping() |
b3361e5d | 420 | password = password.encode() |
5b3c40a6 JM |
421 | buf = read_process_memory(pid, password) |
422 | ||
423 | dev[0].request("DISCONNECT") | |
424 | dev[0].wait_disconnected() | |
425 | ||
426 | dev[0].relog() | |
427 | sae_k = None | |
428 | sae_keyseed = None | |
429 | sae_kck = None | |
430 | pmk = None | |
431 | ptk = None | |
432 | gtk = None | |
433 | with open(os.path.join(params['logdir'], 'log0'), 'r') as f: | |
434 | for l in f.readlines(): | |
435 | if "SAE: k - hexdump" in l: | |
436 | val = l.strip().split(':')[3].replace(' ', '') | |
437 | sae_k = binascii.unhexlify(val) | |
438 | if "SAE: keyseed - hexdump" in l: | |
439 | val = l.strip().split(':')[3].replace(' ', '') | |
440 | sae_keyseed = binascii.unhexlify(val) | |
441 | if "SAE: KCK - hexdump" in l: | |
442 | val = l.strip().split(':')[3].replace(' ', '') | |
443 | sae_kck = binascii.unhexlify(val) | |
444 | if "SAE: PMK - hexdump" in l: | |
445 | val = l.strip().split(':')[3].replace(' ', '') | |
446 | pmk = binascii.unhexlify(val) | |
447 | if "WPA: PTK - hexdump" in l: | |
448 | val = l.strip().split(':')[3].replace(' ', '') | |
449 | ptk = binascii.unhexlify(val) | |
450 | if "WPA: Group Key - hexdump" in l: | |
451 | val = l.strip().split(':')[3].replace(' ', '') | |
452 | gtk = binascii.unhexlify(val) | |
453 | if not sae_k or not sae_keyseed or not sae_kck or not pmk or not ptk or not gtk: | |
454 | raise Exception("Could not find keys from debug log") | |
455 | if len(gtk) != 16: | |
456 | raise Exception("Unexpected GTK length") | |
457 | ||
458 | kck = ptk[0:16] | |
459 | kek = ptk[16:32] | |
460 | tk = ptk[32:48] | |
461 | ||
462 | fname = os.path.join(params['logdir'], | |
463 | 'sae_key_lifetime_in_memory.memctx-') | |
464 | ||
465 | logger.info("Checking keys in memory while associated") | |
466 | get_key_locations(buf, password, "Password") | |
467 | get_key_locations(buf, pmk, "PMK") | |
468 | if password not in buf: | |
81e787b7 | 469 | raise HwsimSkip("Password not found while associated") |
5b3c40a6 | 470 | if pmk not in buf: |
81e787b7 | 471 | raise HwsimSkip("PMK not found while associated") |
5b3c40a6 JM |
472 | if kck not in buf: |
473 | raise Exception("KCK not found while associated") | |
474 | if kek not in buf: | |
475 | raise Exception("KEK not found while associated") | |
b74f82a4 JM |
476 | #if tk in buf: |
477 | # raise Exception("TK found from memory") | |
5b3c40a6 JM |
478 | verify_not_present(buf, sae_k, fname, "SAE(k)") |
479 | verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)") | |
480 | verify_not_present(buf, sae_kck, fname, "SAE(KCK)") | |
481 | ||
482 | logger.info("Checking keys in memory after disassociation") | |
483 | buf = read_process_memory(pid, password) | |
484 | ||
485 | # Note: Password is still present in network configuration | |
486 | # Note: PMK is in PMKSA cache | |
487 | ||
488 | get_key_locations(buf, password, "Password") | |
489 | get_key_locations(buf, pmk, "PMK") | |
490 | verify_not_present(buf, kck, fname, "KCK") | |
491 | verify_not_present(buf, kek, fname, "KEK") | |
492 | verify_not_present(buf, tk, fname, "TK") | |
6db556b2 JM |
493 | if gtk in buf: |
494 | get_key_locations(buf, gtk, "GTK") | |
5b3c40a6 JM |
495 | verify_not_present(buf, gtk, fname, "GTK") |
496 | verify_not_present(buf, sae_k, fname, "SAE(k)") | |
497 | verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)") | |
498 | verify_not_present(buf, sae_kck, fname, "SAE(KCK)") | |
499 | ||
500 | dev[0].request("PMKSA_FLUSH") | |
501 | logger.info("Checking keys in memory after PMKSA cache flush") | |
502 | buf = read_process_memory(pid, password) | |
503 | get_key_locations(buf, password, "Password") | |
504 | get_key_locations(buf, pmk, "PMK") | |
505 | verify_not_present(buf, pmk, fname, "PMK") | |
506 | ||
507 | dev[0].request("REMOVE_NETWORK all") | |
508 | ||
509 | logger.info("Checking keys in memory after network profile removal") | |
510 | buf = read_process_memory(pid, password) | |
511 | ||
512 | get_key_locations(buf, password, "Password") | |
513 | get_key_locations(buf, pmk, "PMK") | |
514 | verify_not_present(buf, password, fname, "password") | |
515 | verify_not_present(buf, pmk, fname, "PMK") | |
516 | verify_not_present(buf, kck, fname, "KCK") | |
517 | verify_not_present(buf, kek, fname, "KEK") | |
518 | verify_not_present(buf, tk, fname, "TK") | |
519 | verify_not_present(buf, gtk, fname, "GTK") | |
520 | verify_not_present(buf, sae_k, fname, "SAE(k)") | |
521 | verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)") | |
522 | verify_not_present(buf, sae_kck, fname, "SAE(KCK)") | |
eb6d3532 | 523 | |
9fd6804d | 524 | @remote_compatible |
eb6d3532 JM |
525 | def test_sae_oom_wpas(dev, apdev): |
526 | """SAE and OOM in wpa_supplicant""" | |
4c0af8ad | 527 | check_sae_capab(dev[0]) |
eb6d3532 JM |
528 | params = hostapd.wpa2_params(ssid="test-sae", |
529 | passphrase="12345678") | |
530 | params['wpa_key_mgmt'] = 'SAE' | |
8e607b1b | 531 | params['sae_groups'] = '19 25 26 20' |
8b8a1864 | 532 | hapd = hostapd.add_ap(apdev[0], params) |
eb6d3532 | 533 | |
8e607b1b | 534 | dev[0].request("SET sae_groups 20") |
eb6d3532 JM |
535 | with alloc_fail(dev[0], 1, "sae_set_group"): |
536 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
537 | scan_freq="2412") | |
538 | dev[0].request("REMOVE_NETWORK all") | |
539 | ||
540 | dev[0].request("SET sae_groups ") | |
541 | with alloc_fail(dev[0], 2, "sae_set_group"): | |
542 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
543 | scan_freq="2412") | |
544 | dev[0].request("REMOVE_NETWORK all") | |
5527a391 | 545 | |
2fd44db7 JM |
546 | with alloc_fail(dev[0], 1, "wpabuf_alloc;sme_auth_build_sae_commit"): |
547 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
548 | scan_freq="2412") | |
549 | dev[0].request("REMOVE_NETWORK all") | |
550 | ||
551 | with alloc_fail(dev[0], 1, "wpabuf_alloc;sme_auth_build_sae_confirm"): | |
552 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
553 | scan_freq="2412", wait_connect=False) | |
554 | wait_fail_trigger(dev[0], "GET_ALLOC_FAIL") | |
555 | dev[0].request("REMOVE_NETWORK all") | |
556 | ||
557 | with alloc_fail(dev[0], 1, "=sme_authenticate"): | |
558 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
559 | scan_freq="2412", wait_connect=False) | |
560 | wait_fail_trigger(dev[0], "GET_ALLOC_FAIL") | |
561 | dev[0].request("REMOVE_NETWORK all") | |
562 | ||
563 | with alloc_fail(dev[0], 1, "radio_add_work;sme_authenticate"): | |
564 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
565 | scan_freq="2412", wait_connect=False) | |
566 | wait_fail_trigger(dev[0], "GET_ALLOC_FAIL") | |
567 | dev[0].request("REMOVE_NETWORK all") | |
568 | ||
9fd6804d | 569 | @remote_compatible |
5527a391 JM |
570 | def test_sae_proto_ecc(dev, apdev): |
571 | """SAE protocol testing (ECC)""" | |
4c0af8ad | 572 | check_sae_capab(dev[0]) |
5527a391 JM |
573 | params = hostapd.wpa2_params(ssid="test-sae", |
574 | passphrase="12345678") | |
575 | params['wpa_key_mgmt'] = 'SAE' | |
8b8a1864 | 576 | hapd = hostapd.add_ap(apdev[0], params) |
5527a391 JM |
577 | bssid = apdev[0]['bssid'] |
578 | ||
579 | dev[0].request("SET sae_groups 19") | |
580 | ||
fab49f61 JM |
581 | tests = [("Confirm mismatch", |
582 | "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8", | |
583 | "0000800edebc3f260dc1fe7e0b20888af2b8a3316252ec37388a8504e25b73dc4240"), | |
584 | ("Commit without even full cyclic group field", | |
585 | "13", | |
586 | None), | |
587 | ("Too short commit", | |
588 | "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02", | |
589 | None), | |
590 | ("Invalid commit scalar (0)", | |
591 | "1300" + "0000000000000000000000000000000000000000000000000000000000000000" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8", | |
592 | None), | |
593 | ("Invalid commit scalar (1)", | |
594 | "1300" + "0000000000000000000000000000000000000000000000000000000000000001" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8", | |
595 | None), | |
596 | ("Invalid commit scalar (> r)", | |
597 | "1300" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8", | |
598 | None), | |
599 | ("Commit element not on curve", | |
600 | "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728d0000000000000000000000000000000000000000000000000000000000000000", | |
601 | None), | |
602 | ("Invalid commit element (y coordinate > P)", | |
603 | "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", | |
604 | None), | |
605 | ("Invalid commit element (x coordinate > P)", | |
606 | "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8", | |
607 | None), | |
608 | ("Different group in commit", | |
609 | "1400" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8", | |
610 | None), | |
611 | ("Too short confirm", | |
612 | "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8", | |
613 | "0000800edebc3f260dc1fe7e0b20888af2b8a3316252ec37388a8504e25b73dc42")] | |
5527a391 JM |
614 | for (note, commit, confirm) in tests: |
615 | logger.info(note) | |
616 | dev[0].scan_for_bss(bssid, freq=2412) | |
617 | hapd.set("ext_mgmt_frame_handling", "1") | |
618 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
619 | scan_freq="2412", wait_connect=False) | |
620 | ||
621 | logger.info("Commit") | |
622 | for i in range(0, 10): | |
623 | req = hapd.mgmt_rx() | |
624 | if req is None: | |
625 | raise Exception("MGMT RX wait timed out (commit)") | |
626 | if req['subtype'] == 11: | |
627 | break | |
628 | req = None | |
629 | if not req: | |
630 | raise Exception("Authentication frame (commit) not received") | |
631 | ||
632 | hapd.dump_monitor() | |
633 | resp = {} | |
634 | resp['fc'] = req['fc'] | |
635 | resp['da'] = req['sa'] | |
636 | resp['sa'] = req['da'] | |
637 | resp['bssid'] = req['bssid'] | |
638 | resp['payload'] = binascii.unhexlify("030001000000" + commit) | |
639 | hapd.mgmt_tx(resp) | |
640 | ||
641 | if confirm: | |
642 | logger.info("Confirm") | |
643 | for i in range(0, 10): | |
644 | req = hapd.mgmt_rx() | |
645 | if req is None: | |
646 | raise Exception("MGMT RX wait timed out (confirm)") | |
647 | if req['subtype'] == 11: | |
648 | break | |
649 | req = None | |
650 | if not req: | |
651 | raise Exception("Authentication frame (confirm) not received") | |
652 | ||
653 | hapd.dump_monitor() | |
654 | resp = {} | |
655 | resp['fc'] = req['fc'] | |
656 | resp['da'] = req['sa'] | |
657 | resp['sa'] = req['da'] | |
658 | resp['bssid'] = req['bssid'] | |
659 | resp['payload'] = binascii.unhexlify("030002000000" + confirm) | |
660 | hapd.mgmt_tx(resp) | |
661 | ||
662 | time.sleep(0.1) | |
663 | dev[0].request("REMOVE_NETWORK all") | |
664 | hapd.set("ext_mgmt_frame_handling", "0") | |
665 | hapd.dump_monitor() | |
666 | ||
9fd6804d | 667 | @remote_compatible |
5527a391 JM |
668 | def test_sae_proto_ffc(dev, apdev): |
669 | """SAE protocol testing (FFC)""" | |
4c0af8ad | 670 | check_sae_capab(dev[0]) |
5527a391 JM |
671 | params = hostapd.wpa2_params(ssid="test-sae", |
672 | passphrase="12345678") | |
673 | params['wpa_key_mgmt'] = 'SAE' | |
8b8a1864 | 674 | hapd = hostapd.add_ap(apdev[0], params) |
5527a391 JM |
675 | bssid = apdev[0]['bssid'] |
676 | ||
677 | dev[0].request("SET sae_groups 2") | |
678 | ||
fab49f61 JM |
679 | tests = [("Confirm mismatch", |
680 | "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "a8c00117493cdffa5dd671e934bc9cb1a69f39e25e9dd9cd9afd3aea2441a0f5491211c7ba50a753563f9ce943b043557cb71193b28e86ed9544f4289c471bf91b70af5c018cf4663e004165b0fd0bc1d8f3f78adf42eee92bcbc55246fd3ee9f107ab965dc7d4986f23eb71d616ebfe6bfe0a6c1ac5dc1718acee17c9a17486", | |
681 | "0000f3116a9731f1259622e3eb55d4b3b50ba16f8c5f5565b28e609b180c51460251"), | |
682 | ("Too short commit", | |
683 | "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "a8c00117493cdffa5dd671e934bc9cb1a69f39e25e9dd9cd9afd3aea2441a0f5491211c7ba50a753563f9ce943b043557cb71193b28e86ed9544f4289c471bf91b70af5c018cf4663e004165b0fd0bc1d8f3f78adf42eee92bcbc55246fd3ee9f107ab965dc7d4986f23eb71d616ebfe6bfe0a6c1ac5dc1718acee17c9a174", | |
684 | None), | |
685 | ("Invalid element (0) in commit", | |
686 | "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", | |
687 | None), | |
688 | ("Invalid element (1) in commit", | |
689 | "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", | |
690 | None), | |
691 | ("Invalid element (> P) in commit", | |
692 | "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", | |
693 | None)] | |
5527a391 JM |
694 | for (note, commit, confirm) in tests: |
695 | logger.info(note) | |
696 | dev[0].scan_for_bss(bssid, freq=2412) | |
697 | hapd.set("ext_mgmt_frame_handling", "1") | |
698 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
699 | scan_freq="2412", wait_connect=False) | |
700 | ||
701 | logger.info("Commit") | |
702 | for i in range(0, 10): | |
703 | req = hapd.mgmt_rx() | |
704 | if req is None: | |
705 | raise Exception("MGMT RX wait timed out (commit)") | |
706 | if req['subtype'] == 11: | |
707 | break | |
708 | req = None | |
709 | if not req: | |
710 | raise Exception("Authentication frame (commit) not received") | |
711 | ||
712 | hapd.dump_monitor() | |
713 | resp = {} | |
714 | resp['fc'] = req['fc'] | |
715 | resp['da'] = req['sa'] | |
716 | resp['sa'] = req['da'] | |
717 | resp['bssid'] = req['bssid'] | |
718 | resp['payload'] = binascii.unhexlify("030001000000" + commit) | |
719 | hapd.mgmt_tx(resp) | |
720 | ||
721 | if confirm: | |
722 | logger.info("Confirm") | |
723 | for i in range(0, 10): | |
724 | req = hapd.mgmt_rx() | |
725 | if req is None: | |
726 | raise Exception("MGMT RX wait timed out (confirm)") | |
727 | if req['subtype'] == 11: | |
728 | break | |
729 | req = None | |
730 | if not req: | |
731 | raise Exception("Authentication frame (confirm) not received") | |
732 | ||
733 | hapd.dump_monitor() | |
734 | resp = {} | |
735 | resp['fc'] = req['fc'] | |
736 | resp['da'] = req['sa'] | |
737 | resp['sa'] = req['da'] | |
738 | resp['bssid'] = req['bssid'] | |
739 | resp['payload'] = binascii.unhexlify("030002000000" + confirm) | |
740 | hapd.mgmt_tx(resp) | |
741 | ||
742 | time.sleep(0.1) | |
743 | dev[0].request("REMOVE_NETWORK all") | |
744 | hapd.set("ext_mgmt_frame_handling", "0") | |
745 | hapd.dump_monitor() | |
746 | ||
46746fc1 JM |
747 | |
748 | def test_sae_proto_commit_delayed(dev, apdev): | |
749 | """SAE protocol testing - Commit delayed""" | |
4c0af8ad | 750 | check_sae_capab(dev[0]) |
46746fc1 JM |
751 | params = hostapd.wpa2_params(ssid="test-sae", |
752 | passphrase="12345678") | |
753 | params['wpa_key_mgmt'] = 'SAE' | |
754 | hapd = hostapd.add_ap(apdev[0], params) | |
755 | bssid = apdev[0]['bssid'] | |
756 | ||
757 | dev[0].request("SET sae_groups 19") | |
758 | ||
759 | dev[0].scan_for_bss(bssid, freq=2412) | |
760 | hapd.set("ext_mgmt_frame_handling", "1") | |
761 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
762 | scan_freq="2412", wait_connect=False) | |
763 | ||
764 | logger.info("Commit") | |
765 | for i in range(0, 10): | |
766 | req = hapd.mgmt_rx() | |
767 | if req is None: | |
768 | raise Exception("MGMT RX wait timed out (commit)") | |
769 | if req['subtype'] == 11: | |
770 | break | |
771 | req = None | |
772 | if not req: | |
773 | raise Exception("Authentication frame (commit) not received") | |
774 | ||
775 | hapd.dump_monitor() | |
776 | time.sleep(2.5) | |
777 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) | |
778 | ||
779 | logger.info("Commit/Confirm") | |
780 | for i in range(0, 10): | |
781 | req = hapd.mgmt_rx() | |
782 | if req is None: | |
783 | raise Exception("MGMT RX wait timed out (confirm)") | |
784 | if req['subtype'] == 11: | |
785 | trans, = struct.unpack('<H', req['payload'][2:4]) | |
786 | if trans == 1: | |
787 | logger.info("Extra Commit") | |
788 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) | |
789 | continue | |
790 | break | |
791 | req = None | |
792 | if not req: | |
793 | raise Exception("Authentication frame (confirm) not received") | |
794 | ||
795 | hapd.dump_monitor() | |
796 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) | |
797 | ||
798 | logger.info("Association Request") | |
799 | for i in range(0, 10): | |
800 | req = hapd.mgmt_rx() | |
801 | if req is None: | |
802 | raise Exception("MGMT RX wait timed out (AssocReq)") | |
803 | if req['subtype'] == 0: | |
804 | break | |
805 | req = None | |
806 | if not req: | |
807 | raise Exception("Association Request frame not received") | |
808 | ||
809 | hapd.dump_monitor() | |
810 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) | |
811 | ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5) | |
812 | if ev is None: | |
813 | raise Exception("Management frame TX status not reported (1)") | |
814 | if "stype=1 ok=1" not in ev: | |
815 | raise Exception("Unexpected management frame TX status (1): " + ev) | |
816 | cmd = "MGMT_TX_STATUS_PROCESS %s" % (" ".join(ev.split(' ')[1:4])) | |
817 | if "OK" not in hapd.request(cmd): | |
818 | raise Exception("MGMT_TX_STATUS_PROCESS failed") | |
819 | ||
820 | hapd.set("ext_mgmt_frame_handling", "0") | |
821 | ||
822 | dev[0].wait_connected() | |
823 | ||
824 | def test_sae_proto_commit_replay(dev, apdev): | |
825 | """SAE protocol testing - Commit replay""" | |
4c0af8ad | 826 | check_sae_capab(dev[0]) |
46746fc1 JM |
827 | params = hostapd.wpa2_params(ssid="test-sae", |
828 | passphrase="12345678") | |
829 | params['wpa_key_mgmt'] = 'SAE' | |
830 | hapd = hostapd.add_ap(apdev[0], params) | |
831 | bssid = apdev[0]['bssid'] | |
832 | ||
833 | dev[0].request("SET sae_groups 19") | |
834 | ||
835 | dev[0].scan_for_bss(bssid, freq=2412) | |
836 | hapd.set("ext_mgmt_frame_handling", "1") | |
837 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
838 | scan_freq="2412", wait_connect=False) | |
839 | ||
840 | logger.info("Commit") | |
841 | for i in range(0, 10): | |
842 | req = hapd.mgmt_rx() | |
843 | if req is None: | |
844 | raise Exception("MGMT RX wait timed out (commit)") | |
845 | if req['subtype'] == 11: | |
846 | break | |
847 | req = None | |
848 | if not req: | |
849 | raise Exception("Authentication frame (commit) not received") | |
850 | ||
851 | hapd.dump_monitor() | |
852 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) | |
853 | logger.info("Replay Commit") | |
854 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) | |
855 | ||
856 | logger.info("Confirm") | |
857 | for i in range(0, 10): | |
858 | req = hapd.mgmt_rx() | |
859 | if req is None: | |
860 | raise Exception("MGMT RX wait timed out (confirm)") | |
861 | if req['subtype'] == 11: | |
862 | trans, = struct.unpack('<H', req['payload'][2:4]) | |
863 | if trans == 1: | |
864 | logger.info("Extra Commit") | |
865 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) | |
866 | continue | |
867 | break | |
868 | req = None | |
869 | if not req: | |
870 | raise Exception("Authentication frame (confirm) not received") | |
871 | ||
872 | hapd.dump_monitor() | |
873 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) | |
874 | ||
875 | logger.info("Association Request") | |
876 | for i in range(0, 10): | |
877 | req = hapd.mgmt_rx() | |
878 | if req is None: | |
879 | raise Exception("MGMT RX wait timed out (AssocReq)") | |
880 | if req['subtype'] == 0: | |
881 | break | |
882 | req = None | |
883 | if not req: | |
884 | raise Exception("Association Request frame not received") | |
885 | ||
886 | hapd.dump_monitor() | |
887 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) | |
888 | for i in range(0, 10): | |
889 | ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5) | |
890 | if ev is None: | |
891 | raise Exception("Management frame TX status not reported (1)") | |
892 | if "stype=11 ok=1" in ev: | |
893 | continue | |
894 | if "stype=12 ok=1" in ev: | |
895 | continue | |
896 | if "stype=1 ok=1" not in ev: | |
897 | raise Exception("Unexpected management frame TX status (1): " + ev) | |
898 | cmd = "MGMT_TX_STATUS_PROCESS %s" % (" ".join(ev.split(' ')[1:4])) | |
899 | if "OK" not in hapd.request(cmd): | |
900 | raise Exception("MGMT_TX_STATUS_PROCESS failed") | |
901 | break | |
902 | ||
903 | hapd.set("ext_mgmt_frame_handling", "0") | |
904 | ||
905 | dev[0].wait_connected() | |
906 | ||
2d0a04a8 JM |
907 | def test_sae_proto_confirm_replay(dev, apdev): |
908 | """SAE protocol testing - Confirm replay""" | |
4c0af8ad | 909 | check_sae_capab(dev[0]) |
2d0a04a8 JM |
910 | params = hostapd.wpa2_params(ssid="test-sae", |
911 | passphrase="12345678") | |
912 | params['wpa_key_mgmt'] = 'SAE' | |
913 | hapd = hostapd.add_ap(apdev[0], params) | |
914 | bssid = apdev[0]['bssid'] | |
915 | ||
916 | dev[0].request("SET sae_groups 19") | |
917 | ||
918 | dev[0].scan_for_bss(bssid, freq=2412) | |
919 | hapd.set("ext_mgmt_frame_handling", "1") | |
920 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
921 | scan_freq="2412", wait_connect=False) | |
922 | ||
923 | logger.info("Commit") | |
924 | for i in range(0, 10): | |
925 | req = hapd.mgmt_rx() | |
926 | if req is None: | |
927 | raise Exception("MGMT RX wait timed out (commit)") | |
928 | if req['subtype'] == 11: | |
929 | break | |
930 | req = None | |
931 | if not req: | |
932 | raise Exception("Authentication frame (commit) not received") | |
933 | ||
2d0a04a8 | 934 | hapd.dump_monitor() |
54c58f29 | 935 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) |
2d0a04a8 JM |
936 | |
937 | logger.info("Confirm") | |
938 | for i in range(0, 10): | |
939 | req = hapd.mgmt_rx() | |
940 | if req is None: | |
941 | raise Exception("MGMT RX wait timed out (confirm)") | |
942 | if req['subtype'] == 11: | |
943 | break | |
944 | req = None | |
945 | if not req: | |
946 | raise Exception("Authentication frame (confirm) not received") | |
947 | ||
948 | hapd.dump_monitor() | |
54c58f29 | 949 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) |
2d0a04a8 JM |
950 | |
951 | logger.info("Replay Confirm") | |
54c58f29 | 952 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) |
2d0a04a8 JM |
953 | |
954 | logger.info("Association Request") | |
955 | for i in range(0, 10): | |
956 | req = hapd.mgmt_rx() | |
957 | if req is None: | |
958 | raise Exception("MGMT RX wait timed out (AssocReq)") | |
959 | if req['subtype'] == 0: | |
960 | break | |
961 | req = None | |
962 | if not req: | |
963 | raise Exception("Association Request frame not received") | |
964 | ||
965 | hapd.dump_monitor() | |
54c58f29 | 966 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) |
2d0a04a8 JM |
967 | ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5) |
968 | if ev is None: | |
969 | raise Exception("Management frame TX status not reported (1)") | |
970 | if "stype=1 ok=1" not in ev: | |
971 | raise Exception("Unexpected management frame TX status (1): " + ev) | |
972 | cmd = "MGMT_TX_STATUS_PROCESS %s" % (" ".join(ev.split(' ')[1:4])) | |
973 | if "OK" not in hapd.request(cmd): | |
974 | raise Exception("MGMT_TX_STATUS_PROCESS failed") | |
975 | ||
976 | hapd.set("ext_mgmt_frame_handling", "0") | |
977 | ||
978 | dev[0].wait_connected() | |
979 | ||
7a92dbd7 JM |
980 | def test_sae_proto_hostapd(dev, apdev): |
981 | """SAE protocol testing with hostapd""" | |
982 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") | |
983 | params['wpa_key_mgmt'] = 'SAE' | |
984 | params['sae_groups'] = "19 65535" | |
985 | hapd = hostapd.add_ap(apdev[0], params) | |
986 | hapd.set("ext_mgmt_frame_handling", "1") | |
987 | bssid = hapd.own_addr().replace(':', '') | |
988 | addr = "020000000000" | |
989 | addr2 = "020000000001" | |
990 | hdr = "b0003a01" + bssid + addr + bssid + "1000" | |
991 | hdr2 = "b0003a01" + bssid + addr2 + bssid + "1000" | |
992 | group = "1300" | |
993 | scalar = "f7df19f4a7fef1d3b895ea1de150b7c5a7a705c8ebb31a52b623e0057908bd93" | |
994 | element_x = "21931572027f2e953e2a49fab3d992944102cc95aa19515fc068b394fb25ae3c" | |
995 | element_y = "cb4eeb94d7b0b789abfdb73a67ab9d6d5efa94dd553e0e724a6289821cbce530" | |
996 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030001000000" + group + scalar + element_x + element_y) | |
997 | # "SAE: Not enough data for scalar" | |
998 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030001000000" + group + scalar[:-2]) | |
999 | # "SAE: Do not allow group to be changed" | |
1000 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030001000000" + "ffff" + scalar[:-2]) | |
1001 | # "SAE: Unsupported Finite Cyclic Group 65535" | |
1002 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr2 + "030001000000" + "ffff" + scalar[:-2]) | |
1003 | ||
2b70a82c JM |
1004 | def test_sae_proto_hostapd_ecc(dev, apdev): |
1005 | """SAE protocol testing with hostapd (ECC)""" | |
1006 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="foofoofoo") | |
1007 | params['wpa_key_mgmt'] = 'SAE' | |
1008 | params['sae_groups'] = "19" | |
1009 | hapd = hostapd.add_ap(apdev[0], params) | |
1010 | hapd.set("ext_mgmt_frame_handling", "1") | |
1011 | bssid = hapd.own_addr().replace(':', '') | |
1012 | addr = "020000000000" | |
1013 | addr2 = "020000000001" | |
1014 | hdr = "b0003a01" + bssid + addr + bssid + "1000" | |
1015 | hdr2 = "b0003a01" + bssid + addr2 + bssid + "1000" | |
1016 | group = "1300" | |
1017 | scalar = "9e9a959bf2dda875a4a29ce9b2afef46f2d83060930124cd9e39ddce798cd69a" | |
1018 | element_x = "dfc55fd8622b91d362f4d1fc9646474d7fba0ff7cce6ca58b8e96a931e070220" | |
1019 | element_y = "dac8a4e80724f167c1349cc9e1f9dd82a7c77b29d49789b63b72b4c849301a28" | |
1020 | # sae_parse_commit_element_ecc() failure to parse peer element | |
1021 | # (depending on crypto library, either crypto_ec_point_from_bin() failure | |
1022 | # or crypto_ec_point_is_on_curve() returning 0) | |
1023 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030001000000" + group + scalar + element_x + element_y) | |
1024 | # Unexpected continuation of the connection attempt with confirm | |
1025 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030002000000" + "0000" + "fd7b081ff4e8676f03612a4140eedcd3c179ab3a13b93863c6f7ca451340b9ae") | |
1026 | ||
1027 | def test_sae_proto_hostapd_ffc(dev, apdev): | |
1028 | """SAE protocol testing with hostapd (FFC)""" | |
1029 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="foofoofoo") | |
1030 | params['wpa_key_mgmt'] = 'SAE' | |
1031 | params['sae_groups'] = "22" | |
1032 | hapd = hostapd.add_ap(apdev[0], params) | |
1033 | hapd.set("ext_mgmt_frame_handling", "1") | |
1034 | bssid = hapd.own_addr().replace(':', '') | |
1035 | addr = "020000000000" | |
1036 | addr2 = "020000000001" | |
1037 | hdr = "b0003a01" + bssid + addr + bssid + "1000" | |
1038 | hdr2 = "b0003a01" + bssid + addr2 + bssid + "1000" | |
1039 | group = "1600" | |
1040 | scalar = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044cc46a73c07ef479dc66ec1f5e8ccf25131fa40" | |
1041 | element = "0f1d67025e12fc874cf718c35b19d1ab2db858215623f1ce661cbd1d7b1d7a09ceda7dba46866cf37044259b5cac4db15e7feb778edc8098854b93a84347c1850c02ee4d7dac46db79c477c731085d5b39f56803cda1eeac4a2fbbccb9a546379e258c00ebe93dfdd0a34cf8ce5c55cf905a89564a590b7e159fb89198e9d5cd" | |
1042 | # sae_parse_commit_element_ffc() failure to parse peer element | |
1043 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030001000000" + group + scalar + element) | |
1044 | # Unexpected continuation of the connection attempt with confirm | |
1045 | hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030002000000" + "0000" + "fd7b081ff4e8676f03612a4140eedcd3c179ab3a13b93863c6f7ca451340b9ae") | |
1046 | ||
9fd6804d | 1047 | @remote_compatible |
5527a391 JM |
1048 | def test_sae_no_ffc_by_default(dev, apdev): |
1049 | """SAE and default groups rejecting FFC""" | |
4c0af8ad | 1050 | check_sae_capab(dev[0]) |
5527a391 JM |
1051 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
1052 | params['wpa_key_mgmt'] = 'SAE' | |
8b8a1864 | 1053 | hapd = hostapd.add_ap(apdev[0], params) |
5527a391 | 1054 | |
8e607b1b | 1055 | dev[0].request("SET sae_groups 15") |
5527a391 JM |
1056 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412", |
1057 | wait_connect=False) | |
1058 | ev = dev[0].wait_event(["SME: Trying to authenticate"], timeout=3) | |
1059 | if ev is None: | |
1060 | raise Exception("Did not try to authenticate") | |
1061 | ev = dev[0].wait_event(["SME: Trying to authenticate"], timeout=3) | |
1062 | if ev is None: | |
1063 | raise Exception("Did not try to authenticate (2)") | |
1064 | dev[0].request("REMOVE_NETWORK all") | |
939527b5 JM |
1065 | |
1066 | def sae_reflection_attack(apdev, dev, group): | |
4c0af8ad | 1067 | check_sae_capab(dev) |
939527b5 JM |
1068 | params = hostapd.wpa2_params(ssid="test-sae", |
1069 | passphrase="no-knowledge-of-passphrase") | |
1070 | params['wpa_key_mgmt'] = 'SAE' | |
afc26df2 | 1071 | hapd = hostapd.add_ap(apdev, params) |
939527b5 JM |
1072 | bssid = apdev['bssid'] |
1073 | ||
1074 | dev.scan_for_bss(bssid, freq=2412) | |
1075 | hapd.set("ext_mgmt_frame_handling", "1") | |
1076 | ||
1077 | dev.request("SET sae_groups %d" % group) | |
1078 | dev.connect("test-sae", psk="reflection-attack", key_mgmt="SAE", | |
1079 | scan_freq="2412", wait_connect=False) | |
1080 | ||
1081 | # Commit | |
1082 | for i in range(0, 10): | |
1083 | req = hapd.mgmt_rx() | |
1084 | if req is None: | |
1085 | raise Exception("MGMT RX wait timed out") | |
1086 | if req['subtype'] == 11: | |
1087 | break | |
1088 | req = None | |
1089 | if not req: | |
1090 | raise Exception("Authentication frame not received") | |
1091 | ||
1092 | resp = {} | |
1093 | resp['fc'] = req['fc'] | |
1094 | resp['da'] = req['sa'] | |
1095 | resp['sa'] = req['da'] | |
1096 | resp['bssid'] = req['bssid'] | |
1097 | resp['payload'] = req['payload'] | |
1098 | hapd.mgmt_tx(resp) | |
1099 | ||
1100 | # Confirm | |
1101 | req = hapd.mgmt_rx(timeout=0.5) | |
1102 | if req is not None: | |
1103 | if req['subtype'] == 11: | |
1104 | raise Exception("Unexpected Authentication frame seen") | |
1105 | ||
9fd6804d | 1106 | @remote_compatible |
939527b5 JM |
1107 | def test_sae_reflection_attack_ecc(dev, apdev): |
1108 | """SAE reflection attack (ECC)""" | |
1109 | sae_reflection_attack(apdev[0], dev[0], 19) | |
1110 | ||
9fd6804d | 1111 | @remote_compatible |
939527b5 JM |
1112 | def test_sae_reflection_attack_ffc(dev, apdev): |
1113 | """SAE reflection attack (FFC)""" | |
8e607b1b | 1114 | sae_reflection_attack(apdev[0], dev[0], 15) |
1965e196 | 1115 | |
1342c47a | 1116 | def sae_reflection_attack_internal(apdev, dev, group): |
4c0af8ad | 1117 | check_sae_capab(dev) |
1342c47a JM |
1118 | params = hostapd.wpa2_params(ssid="test-sae", |
1119 | passphrase="no-knowledge-of-passphrase") | |
1120 | params['wpa_key_mgmt'] = 'SAE' | |
1121 | params['sae_reflection_attack'] = '1' | |
1122 | hapd = hostapd.add_ap(apdev, params) | |
1123 | bssid = apdev['bssid'] | |
1124 | ||
1125 | dev.scan_for_bss(bssid, freq=2412) | |
1126 | dev.request("SET sae_groups %d" % group) | |
1127 | dev.connect("test-sae", psk="reflection-attack", key_mgmt="SAE", | |
1128 | scan_freq="2412", wait_connect=False) | |
8e607b1b JM |
1129 | ev = dev.wait_event(["SME: Trying to authenticate"], timeout=10) |
1130 | if ev is None: | |
1131 | raise Exception("No authentication attempt seen") | |
1342c47a JM |
1132 | ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) |
1133 | if ev is not None: | |
1134 | raise Exception("Unexpected connection") | |
1135 | ||
1136 | @remote_compatible | |
1137 | def test_sae_reflection_attack_ecc_internal(dev, apdev): | |
1138 | """SAE reflection attack (ECC) - internal""" | |
1139 | sae_reflection_attack_internal(apdev[0], dev[0], 19) | |
1140 | ||
1141 | @remote_compatible | |
1142 | def test_sae_reflection_attack_ffc_internal(dev, apdev): | |
1143 | """SAE reflection attack (FFC) - internal""" | |
8e607b1b | 1144 | sae_reflection_attack_internal(apdev[0], dev[0], 15) |
1342c47a | 1145 | |
cd06e266 JM |
1146 | @remote_compatible |
1147 | def test_sae_commit_override(dev, apdev): | |
1148 | """SAE commit override (hostapd)""" | |
4c0af8ad | 1149 | check_sae_capab(dev[0]) |
cd06e266 JM |
1150 | params = hostapd.wpa2_params(ssid="test-sae", |
1151 | passphrase="12345678") | |
1152 | params['wpa_key_mgmt'] = 'SAE' | |
1153 | params['sae_commit_override'] = '13ffbad00d215867a7c5ff37d87bb9bdb7cb116e520f71e8d7a794ca2606d537ddc6c099c40e7a25372b80a8fd443cd7dd222c8ea21b8ef372d4b3e316c26a73fd999cc79ad483eb826e7b3893ea332da68fa13224bcdeb4fb18b0584dd100a2c514' | |
1154 | hapd = hostapd.add_ap(apdev[0], params) | |
1155 | dev[0].request("SET sae_groups ") | |
1156 | dev[0].connect("test-sae", psk="test-sae", key_mgmt="SAE", | |
1157 | scan_freq="2412", wait_connect=False) | |
1158 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) | |
1159 | if ev is not None: | |
1160 | raise Exception("Unexpected connection") | |
1161 | ||
eea62048 JM |
1162 | @remote_compatible |
1163 | def test_sae_commit_override2(dev, apdev): | |
1164 | """SAE commit override (wpa_supplicant)""" | |
4c0af8ad | 1165 | check_sae_capab(dev[0]) |
eea62048 JM |
1166 | params = hostapd.wpa2_params(ssid="test-sae", |
1167 | passphrase="12345678") | |
1168 | params['wpa_key_mgmt'] = 'SAE' | |
1169 | hapd = hostapd.add_ap(apdev[0], params) | |
1170 | dev[0].request("SET sae_groups ") | |
1171 | dev[0].set('sae_commit_override', '13ffbad00d215867a7c5ff37d87bb9bdb7cb116e520f71e8d7a794ca2606d537ddc6c099c40e7a25372b80a8fd443cd7dd222c8ea21b8ef372d4b3e316c26a73fd999cc79ad483eb826e7b3893ea332da68fa13224bcdeb4fb18b0584dd100a2c514') | |
1172 | dev[0].connect("test-sae", psk="test-sae", key_mgmt="SAE", | |
1173 | scan_freq="2412", wait_connect=False) | |
1174 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) | |
1175 | if ev is not None: | |
1176 | raise Exception("Unexpected connection") | |
1177 | ||
faddd025 JM |
1178 | def test_sae_commit_invalid_scalar_element_ap(dev, apdev): |
1179 | """SAE commit invalid scalar/element from AP""" | |
4c0af8ad | 1180 | check_sae_capab(dev[0]) |
faddd025 JM |
1181 | params = hostapd.wpa2_params(ssid="test-sae", |
1182 | passphrase="12345678") | |
1183 | params['wpa_key_mgmt'] = 'SAE' | |
1184 | params['sae_commit_override'] = '1300' + 96*'00' | |
1185 | hapd = hostapd.add_ap(apdev[0], params) | |
1186 | dev[0].request("SET sae_groups ") | |
1187 | dev[0].connect("test-sae", psk="test-sae", key_mgmt="SAE", | |
1188 | scan_freq="2412", wait_connect=False) | |
1189 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) | |
1190 | if ev is not None: | |
1191 | raise Exception("Unexpected connection") | |
1192 | ||
1193 | def test_sae_commit_invalid_element_ap(dev, apdev): | |
1194 | """SAE commit invalid element from AP""" | |
4c0af8ad | 1195 | check_sae_capab(dev[0]) |
faddd025 JM |
1196 | params = hostapd.wpa2_params(ssid="test-sae", |
1197 | passphrase="12345678") | |
1198 | params['wpa_key_mgmt'] = 'SAE' | |
1199 | params['sae_commit_override'] = '1300' + 31*'00' + '02' + 64*'00' | |
1200 | hapd = hostapd.add_ap(apdev[0], params) | |
1201 | dev[0].request("SET sae_groups ") | |
1202 | dev[0].connect("test-sae", psk="test-sae", key_mgmt="SAE", | |
1203 | scan_freq="2412", wait_connect=False) | |
1204 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) | |
1205 | if ev is not None: | |
1206 | raise Exception("Unexpected connection") | |
1207 | ||
1208 | def test_sae_commit_invalid_scalar_element_sta(dev, apdev): | |
1209 | """SAE commit invalid scalar/element from STA""" | |
4c0af8ad | 1210 | check_sae_capab(dev[0]) |
faddd025 JM |
1211 | params = hostapd.wpa2_params(ssid="test-sae", |
1212 | passphrase="12345678") | |
1213 | params['wpa_key_mgmt'] = 'SAE' | |
1214 | hapd = hostapd.add_ap(apdev[0], params) | |
1215 | dev[0].request("SET sae_groups ") | |
1216 | dev[0].set('sae_commit_override', '1300' + 96*'00') | |
1217 | dev[0].connect("test-sae", psk="test-sae", key_mgmt="SAE", | |
1218 | scan_freq="2412", wait_connect=False) | |
1219 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) | |
1220 | if ev is not None: | |
1221 | raise Exception("Unexpected connection") | |
1222 | ||
1223 | def test_sae_commit_invalid_element_sta(dev, apdev): | |
1224 | """SAE commit invalid element from STA""" | |
4c0af8ad | 1225 | check_sae_capab(dev[0]) |
faddd025 JM |
1226 | params = hostapd.wpa2_params(ssid="test-sae", |
1227 | passphrase="12345678") | |
1228 | params['wpa_key_mgmt'] = 'SAE' | |
1229 | hapd = hostapd.add_ap(apdev[0], params) | |
1230 | dev[0].request("SET sae_groups ") | |
1231 | dev[0].set('sae_commit_override', '1300' + 31*'00' + '02' + 64*'00') | |
1232 | dev[0].connect("test-sae", psk="test-sae", key_mgmt="SAE", | |
1233 | scan_freq="2412", wait_connect=False) | |
1234 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) | |
1235 | if ev is not None: | |
1236 | raise Exception("Unexpected connection") | |
1237 | ||
9fd6804d | 1238 | @remote_compatible |
1965e196 JM |
1239 | def test_sae_anti_clogging_proto(dev, apdev): |
1240 | """SAE anti clogging protocol testing""" | |
4c0af8ad | 1241 | check_sae_capab(dev[0]) |
1965e196 JM |
1242 | params = hostapd.wpa2_params(ssid="test-sae", |
1243 | passphrase="no-knowledge-of-passphrase") | |
1244 | params['wpa_key_mgmt'] = 'SAE' | |
8b8a1864 | 1245 | hapd = hostapd.add_ap(apdev[0], params) |
1965e196 JM |
1246 | bssid = apdev[0]['bssid'] |
1247 | ||
1248 | dev[0].scan_for_bss(bssid, freq=2412) | |
1249 | hapd.set("ext_mgmt_frame_handling", "1") | |
1250 | ||
1251 | dev[0].request("SET sae_groups ") | |
1252 | dev[0].connect("test-sae", psk="anti-cloggign", key_mgmt="SAE", | |
1253 | scan_freq="2412", wait_connect=False) | |
1254 | ||
1255 | # Commit | |
1256 | for i in range(0, 10): | |
1257 | req = hapd.mgmt_rx() | |
1258 | if req is None: | |
1259 | raise Exception("MGMT RX wait timed out") | |
1260 | if req['subtype'] == 11: | |
1261 | break | |
1262 | req = None | |
1263 | if not req: | |
1264 | raise Exception("Authentication frame not received") | |
1265 | ||
1266 | resp = {} | |
1267 | resp['fc'] = req['fc'] | |
1268 | resp['da'] = req['sa'] | |
1269 | resp['sa'] = req['da'] | |
1270 | resp['bssid'] = req['bssid'] | |
1271 | resp['payload'] = binascii.unhexlify("030001004c00" + "ffff00") | |
1272 | hapd.mgmt_tx(resp) | |
1273 | ||
1274 | # Confirm (not received due to DH group being rejected) | |
1275 | req = hapd.mgmt_rx(timeout=0.5) | |
1276 | if req is not None: | |
1277 | if req['subtype'] == 11: | |
1278 | raise Exception("Unexpected Authentication frame seen") | |
10ba4ae4 | 1279 | |
9fd6804d | 1280 | @remote_compatible |
10ba4ae4 JM |
1281 | def test_sae_no_random(dev, apdev): |
1282 | """SAE and no random numbers available""" | |
4c0af8ad | 1283 | check_sae_capab(dev[0]) |
10ba4ae4 JM |
1284 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
1285 | params['wpa_key_mgmt'] = 'SAE' | |
8b8a1864 | 1286 | hapd = hostapd.add_ap(apdev[0], params) |
10ba4ae4 JM |
1287 | |
1288 | dev[0].request("SET sae_groups ") | |
fbd671ac | 1289 | tests = [(1, "os_get_random;sae_derive_pwe_ecc")] |
10ba4ae4 JM |
1290 | for count, func in tests: |
1291 | with fail_test(dev[0], count, func): | |
1292 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
1293 | scan_freq="2412") | |
1294 | dev[0].request("REMOVE_NETWORK all") | |
1295 | dev[0].wait_disconnected() | |
4f6985de | 1296 | |
9fd6804d | 1297 | @remote_compatible |
4f6985de JM |
1298 | def test_sae_pwe_failure(dev, apdev): |
1299 | """SAE and pwe failure""" | |
4c0af8ad | 1300 | check_sae_capab(dev[0]) |
4f6985de JM |
1301 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
1302 | params['wpa_key_mgmt'] = 'SAE' | |
8e607b1b | 1303 | params['sae_groups'] = '19 15' |
8b8a1864 | 1304 | hapd = hostapd.add_ap(apdev[0], params) |
4f6985de JM |
1305 | |
1306 | dev[0].request("SET sae_groups 19") | |
1307 | with fail_test(dev[0], 1, "hmac_sha256_vector;sae_derive_pwe_ecc"): | |
1308 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
1309 | scan_freq="2412") | |
1310 | dev[0].request("REMOVE_NETWORK all") | |
1311 | dev[0].wait_disconnected() | |
51761ba2 JM |
1312 | with fail_test(dev[0], 1, "sae_test_pwd_seed_ecc"): |
1313 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
1314 | scan_freq="2412") | |
1315 | dev[0].request("REMOVE_NETWORK all") | |
1316 | dev[0].wait_disconnected() | |
4f6985de | 1317 | |
8e607b1b | 1318 | dev[0].request("SET sae_groups 15") |
4f6985de JM |
1319 | with fail_test(dev[0], 1, "hmac_sha256_vector;sae_derive_pwe_ffc"): |
1320 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
1321 | scan_freq="2412") | |
1322 | dev[0].request("REMOVE_NETWORK all") | |
1323 | dev[0].wait_disconnected() | |
1324 | ||
8e607b1b | 1325 | dev[0].request("SET sae_groups 15") |
4f6985de JM |
1326 | with fail_test(dev[0], 1, "sae_test_pwd_seed_ffc"): |
1327 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
1328 | scan_freq="2412") | |
1329 | dev[0].request("REMOVE_NETWORK all") | |
1330 | dev[0].wait_disconnected() | |
1331 | with fail_test(dev[0], 2, "sae_test_pwd_seed_ffc"): | |
1332 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
1333 | scan_freq="2412") | |
1334 | dev[0].request("REMOVE_NETWORK all") | |
1335 | dev[0].wait_disconnected() | |
51761ba2 | 1336 | |
9fd6804d | 1337 | @remote_compatible |
51761ba2 JM |
1338 | def test_sae_bignum_failure(dev, apdev): |
1339 | """SAE and bignum failure""" | |
4c0af8ad | 1340 | check_sae_capab(dev[0]) |
51761ba2 JM |
1341 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
1342 | params['wpa_key_mgmt'] = 'SAE' | |
8e607b1b | 1343 | params['sae_groups'] = '19 15 22' |
8b8a1864 | 1344 | hapd = hostapd.add_ap(apdev[0], params) |
51761ba2 JM |
1345 | |
1346 | dev[0].request("SET sae_groups 19") | |
a5dbddbf JM |
1347 | tests = [(1, "crypto_bignum_init_set;dragonfly_get_rand_1_to_p_1"), |
1348 | (1, "crypto_bignum_init;dragonfly_is_quadratic_residue_blind"), | |
1349 | (1, "crypto_bignum_mulmod;dragonfly_is_quadratic_residue_blind"), | |
1350 | (2, "crypto_bignum_mulmod;dragonfly_is_quadratic_residue_blind"), | |
1351 | (3, "crypto_bignum_mulmod;dragonfly_is_quadratic_residue_blind"), | |
1352 | (1, "crypto_bignum_legendre;dragonfly_is_quadratic_residue_blind"), | |
fab49f61 JM |
1353 | (1, "crypto_bignum_init_set;sae_test_pwd_seed_ecc"), |
1354 | (1, "crypto_ec_point_compute_y_sqr;sae_test_pwd_seed_ecc"), | |
fab49f61 JM |
1355 | (1, "crypto_bignum_to_bin;sae_derive_pwe_ecc"), |
1356 | (1, "crypto_ec_point_init;sae_derive_pwe_ecc"), | |
1357 | (1, "crypto_ec_point_solve_y_coord;sae_derive_pwe_ecc"), | |
1358 | (1, "crypto_ec_point_init;sae_derive_commit_element_ecc"), | |
1359 | (1, "crypto_ec_point_mul;sae_derive_commit_element_ecc"), | |
1360 | (1, "crypto_ec_point_invert;sae_derive_commit_element_ecc"), | |
1361 | (1, "crypto_bignum_init;=sae_derive_commit"), | |
1362 | (1, "crypto_ec_point_init;sae_derive_k_ecc"), | |
1363 | (1, "crypto_ec_point_mul;sae_derive_k_ecc"), | |
1364 | (1, "crypto_ec_point_add;sae_derive_k_ecc"), | |
1365 | (2, "crypto_ec_point_mul;sae_derive_k_ecc"), | |
1366 | (1, "crypto_ec_point_to_bin;sae_derive_k_ecc"), | |
a5dbddbf | 1367 | (1, "crypto_bignum_legendre;dragonfly_get_random_qr_qnr"), |
fab49f61 JM |
1368 | (1, "sha256_prf;sae_derive_keys"), |
1369 | (1, "crypto_bignum_init;sae_derive_keys"), | |
1370 | (1, "crypto_bignum_init_set;sae_parse_commit_scalar"), | |
1371 | (1, "crypto_bignum_to_bin;sae_parse_commit_element_ecc"), | |
1372 | (1, "crypto_ec_point_from_bin;sae_parse_commit_element_ecc")] | |
51761ba2 JM |
1373 | for count, func in tests: |
1374 | with fail_test(dev[0], count, func): | |
e96fa197 | 1375 | hapd.request("NOTE STA failure testing %d:%s" % (count, func)) |
51761ba2 JM |
1376 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", |
1377 | scan_freq="2412", wait_connect=False) | |
7bcb6391 | 1378 | wait_fail_trigger(dev[0], "GET_FAIL", timeout=0.1) |
51761ba2 | 1379 | dev[0].request("REMOVE_NETWORK all") |
e96fa197 JM |
1380 | dev[0].dump_monitor() |
1381 | hapd.dump_monitor() | |
51761ba2 | 1382 | |
8e607b1b | 1383 | dev[0].request("SET sae_groups 15") |
fab49f61 JM |
1384 | tests = [(1, "crypto_bignum_init_set;sae_set_group"), |
1385 | (2, "crypto_bignum_init_set;sae_set_group"), | |
fbd671ac JM |
1386 | (1, "crypto_bignum_init;sae_derive_commit"), |
1387 | (2, "crypto_bignum_init;sae_derive_commit"), | |
fab49f61 JM |
1388 | (1, "crypto_bignum_init_set;sae_test_pwd_seed_ffc"), |
1389 | (1, "crypto_bignum_exptmod;sae_test_pwd_seed_ffc"), | |
1390 | (1, "crypto_bignum_init;sae_derive_pwe_ffc"), | |
1391 | (1, "crypto_bignum_init;sae_derive_commit_element_ffc"), | |
1392 | (1, "crypto_bignum_exptmod;sae_derive_commit_element_ffc"), | |
1393 | (1, "crypto_bignum_inverse;sae_derive_commit_element_ffc"), | |
1394 | (1, "crypto_bignum_init;sae_derive_k_ffc"), | |
1395 | (1, "crypto_bignum_exptmod;sae_derive_k_ffc"), | |
1396 | (1, "crypto_bignum_mulmod;sae_derive_k_ffc"), | |
1397 | (2, "crypto_bignum_exptmod;sae_derive_k_ffc"), | |
1398 | (1, "crypto_bignum_to_bin;sae_derive_k_ffc"), | |
1399 | (1, "crypto_bignum_init_set;sae_parse_commit_element_ffc"), | |
1400 | (1, "crypto_bignum_init;sae_parse_commit_element_ffc"), | |
1401 | (2, "crypto_bignum_init_set;sae_parse_commit_element_ffc"), | |
1402 | (1, "crypto_bignum_exptmod;sae_parse_commit_element_ffc")] | |
51761ba2 JM |
1403 | for count, func in tests: |
1404 | with fail_test(dev[0], count, func): | |
e96fa197 | 1405 | hapd.request("NOTE STA failure testing %d:%s" % (count, func)) |
51761ba2 JM |
1406 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", |
1407 | scan_freq="2412", wait_connect=False) | |
7bcb6391 | 1408 | wait_fail_trigger(dev[0], "GET_FAIL", timeout=0.1) |
51761ba2 | 1409 | dev[0].request("REMOVE_NETWORK all") |
e96fa197 JM |
1410 | dev[0].dump_monitor() |
1411 | hapd.dump_monitor() | |
51761ba2 | 1412 | |
8e607b1b JM |
1413 | def test_sae_bignum_failure_unsafe_group(dev, apdev): |
1414 | """SAE and bignum failure unsafe group""" | |
4c0af8ad | 1415 | check_sae_capab(dev[0]) |
8e607b1b JM |
1416 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
1417 | params['wpa_key_mgmt'] = 'SAE' | |
1418 | params['sae_groups'] = '22' | |
1419 | hapd = hostapd.add_ap(apdev[0], params) | |
1420 | ||
51761ba2 | 1421 | dev[0].request("SET sae_groups 22") |
fab49f61 JM |
1422 | tests = [(1, "crypto_bignum_init_set;sae_test_pwd_seed_ffc"), |
1423 | (1, "crypto_bignum_sub;sae_test_pwd_seed_ffc"), | |
1424 | (1, "crypto_bignum_div;sae_test_pwd_seed_ffc")] | |
51761ba2 JM |
1425 | for count, func in tests: |
1426 | with fail_test(dev[0], count, func): | |
e96fa197 | 1427 | hapd.request("NOTE STA failure testing %d:%s" % (count, func)) |
51761ba2 JM |
1428 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", |
1429 | scan_freq="2412", wait_connect=False) | |
1430 | wait_fail_trigger(dev[0], "GET_FAIL") | |
1431 | dev[0].request("REMOVE_NETWORK all") | |
e96fa197 JM |
1432 | dev[0].dump_monitor() |
1433 | hapd.dump_monitor() | |
28be769b JM |
1434 | |
1435 | def test_sae_invalid_anti_clogging_token_req(dev, apdev): | |
1436 | """SAE and invalid anti-clogging token request""" | |
4c0af8ad | 1437 | check_sae_capab(dev[0]) |
28be769b JM |
1438 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
1439 | params['wpa_key_mgmt'] = 'SAE' | |
77f52098 JM |
1440 | # Beacon more frequently since Probe Request frames are practically ignored |
1441 | # in this test setup (ext_mgmt_frame_handled=1 on hostapd side) and | |
1442 | # wpa_supplicant scans may end up getting ignored if no new results are | |
1443 | # available due to the missing Probe Response frames. | |
1444 | params['beacon_int'] = '20' | |
28be769b JM |
1445 | hapd = hostapd.add_ap(apdev[0], params) |
1446 | bssid = apdev[0]['bssid'] | |
1447 | ||
1448 | dev[0].request("SET sae_groups 19") | |
1449 | dev[0].scan_for_bss(bssid, freq=2412) | |
1450 | hapd.set("ext_mgmt_frame_handling", "1") | |
1451 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
1452 | scan_freq="2412", wait_connect=False) | |
1453 | ev = dev[0].wait_event(["SME: Trying to authenticate"]) | |
1454 | if ev is None: | |
77f52098 | 1455 | raise Exception("No authentication attempt seen (1)") |
28be769b JM |
1456 | dev[0].dump_monitor() |
1457 | ||
1458 | for i in range(0, 10): | |
1459 | req = hapd.mgmt_rx() | |
1460 | if req is None: | |
1461 | raise Exception("MGMT RX wait timed out (commit)") | |
1462 | if req['subtype'] == 11: | |
1463 | break | |
1464 | req = None | |
1465 | if not req: | |
1466 | raise Exception("Authentication frame (commit) not received") | |
1467 | ||
1468 | hapd.dump_monitor() | |
1469 | resp = {} | |
1470 | resp['fc'] = req['fc'] | |
1471 | resp['da'] = req['sa'] | |
1472 | resp['sa'] = req['da'] | |
1473 | resp['bssid'] = req['bssid'] | |
1474 | resp['payload'] = binascii.unhexlify("030001004c0013") | |
1475 | hapd.mgmt_tx(resp) | |
77f52098 JM |
1476 | ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5) |
1477 | if ev is None: | |
1478 | raise Exception("Management frame TX status not reported (1)") | |
1479 | if "stype=11 ok=1" not in ev: | |
1480 | raise Exception("Unexpected management frame TX status (1): " + ev) | |
28be769b JM |
1481 | |
1482 | ev = dev[0].wait_event(["SME: Trying to authenticate"]) | |
1483 | if ev is None: | |
77f52098 | 1484 | raise Exception("No authentication attempt seen (2)") |
28be769b JM |
1485 | dev[0].dump_monitor() |
1486 | ||
1487 | for i in range(0, 10): | |
1488 | req = hapd.mgmt_rx() | |
1489 | if req is None: | |
1490 | raise Exception("MGMT RX wait timed out (commit) (2)") | |
1491 | if req['subtype'] == 11: | |
1492 | break | |
1493 | req = None | |
1494 | if not req: | |
1495 | raise Exception("Authentication frame (commit) not received (2)") | |
1496 | ||
1497 | hapd.dump_monitor() | |
1498 | resp = {} | |
1499 | resp['fc'] = req['fc'] | |
1500 | resp['da'] = req['sa'] | |
1501 | resp['sa'] = req['da'] | |
1502 | resp['bssid'] = req['bssid'] | |
1503 | resp['payload'] = binascii.unhexlify("030001000100") | |
1504 | hapd.mgmt_tx(resp) | |
77f52098 JM |
1505 | ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5) |
1506 | if ev is None: | |
1507 | raise Exception("Management frame TX status not reported (1)") | |
1508 | if "stype=11 ok=1" not in ev: | |
1509 | raise Exception("Unexpected management frame TX status (1): " + ev) | |
28be769b JM |
1510 | |
1511 | ev = dev[0].wait_event(["SME: Trying to authenticate"]) | |
1512 | if ev is None: | |
77f52098 | 1513 | raise Exception("No authentication attempt seen (3)") |
28be769b JM |
1514 | dev[0].dump_monitor() |
1515 | ||
1516 | dev[0].request("DISCONNECT") | |
606ef7d3 JM |
1517 | |
1518 | def test_sae_password(dev, apdev): | |
1519 | """SAE and sae_password in hostapd configuration""" | |
4c0af8ad | 1520 | check_sae_capab(dev[0]) |
606ef7d3 JM |
1521 | params = hostapd.wpa2_params(ssid="test-sae", |
1522 | passphrase="12345678") | |
1523 | params['wpa_key_mgmt'] = 'SAE WPA-PSK' | |
1524 | params['sae_password'] = "sae-password" | |
1525 | hapd = hostapd.add_ap(apdev[0], params) | |
1526 | ||
1527 | dev[0].request("SET sae_groups ") | |
1528 | dev[0].connect("test-sae", psk="sae-password", key_mgmt="SAE", | |
1529 | scan_freq="2412") | |
1530 | dev[1].connect("test-sae", psk="12345678", scan_freq="2412") | |
1531 | dev[2].request("SET sae_groups ") | |
1532 | dev[2].connect("test-sae", sae_password="sae-password", key_mgmt="SAE", | |
1533 | scan_freq="2412") | |
1534 | ||
1535 | def test_sae_password_short(dev, apdev): | |
1536 | """SAE and short password""" | |
4c0af8ad | 1537 | check_sae_capab(dev[0]) |
606ef7d3 JM |
1538 | params = hostapd.wpa2_params(ssid="test-sae") |
1539 | params['wpa_key_mgmt'] = 'SAE' | |
1540 | params['sae_password'] = "secret" | |
1541 | hapd = hostapd.add_ap(apdev[0], params) | |
1542 | ||
1543 | dev[0].request("SET sae_groups ") | |
1544 | dev[0].connect("test-sae", sae_password="secret", key_mgmt="SAE", | |
1545 | scan_freq="2412") | |
1546 | ||
1547 | def test_sae_password_long(dev, apdev): | |
1548 | """SAE and long password""" | |
4c0af8ad | 1549 | check_sae_capab(dev[0]) |
606ef7d3 JM |
1550 | params = hostapd.wpa2_params(ssid="test-sae") |
1551 | params['wpa_key_mgmt'] = 'SAE' | |
1552 | params['sae_password'] = 100*"A" | |
1553 | hapd = hostapd.add_ap(apdev[0], params) | |
1554 | ||
1555 | dev[0].request("SET sae_groups ") | |
1556 | dev[0].connect("test-sae", sae_password=100*"A", key_mgmt="SAE", | |
1557 | scan_freq="2412") | |
33822240 JM |
1558 | |
1559 | def test_sae_connect_cmd(dev, apdev): | |
1560 | """SAE with connect command""" | |
1561 | wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') | |
1562 | wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") | |
4c0af8ad | 1563 | check_sae_capab(wpas) |
33822240 JM |
1564 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
1565 | params['wpa_key_mgmt'] = 'SAE' | |
1566 | hapd = hostapd.add_ap(apdev[0], params) | |
1567 | ||
1568 | wpas.request("SET sae_groups ") | |
1569 | wpas.connect("test-sae", psk="12345678", key_mgmt="SAE", | |
1570 | scan_freq="2412", wait_connect=False) | |
1571 | # mac80211_hwsim does not support SAE offload, so accept both a successful | |
1572 | # connection and association rejection. | |
1573 | ev = wpas.wait_event(["CTRL-EVENT-CONNECTED", "CTRL-EVENT-ASSOC-REJECT", | |
1574 | "Association request to the driver failed"], | |
1575 | timeout=15) | |
1576 | if ev is None: | |
1577 | raise Exception("No connection result reported") | |
9a0ae89d | 1578 | |
be5e7a07 | 1579 | def run_sae_password_id(dev, apdev, groups=None): |
4c0af8ad | 1580 | check_sae_capab(dev[0]) |
9a0ae89d JM |
1581 | params = hostapd.wpa2_params(ssid="test-sae") |
1582 | params['wpa_key_mgmt'] = 'SAE' | |
be5e7a07 JM |
1583 | if groups: |
1584 | params['sae_groups'] = groups | |
1585 | else: | |
1586 | groups = "" | |
fab49f61 JM |
1587 | params['sae_password'] = ['secret|mac=ff:ff:ff:ff:ff:ff|id=pw id', |
1588 | 'foo|mac=02:02:02:02:02:02', | |
1589 | 'another secret|mac=ff:ff:ff:ff:ff:ff|id=' + 29*'A'] | |
9a0ae89d JM |
1590 | hapd = hostapd.add_ap(apdev[0], params) |
1591 | ||
be5e7a07 | 1592 | dev[0].request("SET sae_groups " + groups) |
9a0ae89d JM |
1593 | dev[0].connect("test-sae", sae_password="secret", sae_password_id="pw id", |
1594 | key_mgmt="SAE", scan_freq="2412") | |
1595 | dev[0].request("REMOVE_NETWORK all") | |
1596 | dev[0].wait_disconnected() | |
1597 | ||
1598 | # SAE Password Identifier element with the exact same length as the | |
1599 | # optional Anti-Clogging Token field | |
1600 | dev[0].connect("test-sae", sae_password="another secret", | |
1601 | sae_password_id=29*'A', | |
1602 | key_mgmt="SAE", scan_freq="2412") | |
1603 | dev[0].request("REMOVE_NETWORK all") | |
1604 | dev[0].wait_disconnected() | |
1605 | ||
1606 | dev[0].connect("test-sae", sae_password="secret", sae_password_id="unknown", | |
1607 | key_mgmt="SAE", scan_freq="2412", wait_connect=False) | |
1608 | ||
1609 | ev = dev[0].wait_event(["CTRL-EVENT-SAE-UNKNOWN-PASSWORD-IDENTIFIER"], | |
1610 | timeout=10) | |
1611 | if ev is None: | |
1612 | raise Exception("Unknown password identifier not reported") | |
1613 | dev[0].request("REMOVE_NETWORK all") | |
1614 | ||
be5e7a07 JM |
1615 | def test_sae_password_id(dev, apdev): |
1616 | """SAE and password identifier""" | |
1617 | run_sae_password_id(dev, apdev, "") | |
1618 | ||
1619 | def test_sae_password_id_ecc(dev, apdev): | |
1620 | """SAE and password identifier (ECC)""" | |
1621 | run_sae_password_id(dev, apdev, "19") | |
1622 | ||
1623 | def test_sae_password_id_ffc(dev, apdev): | |
1624 | """SAE and password identifier (FFC)""" | |
8e607b1b | 1625 | run_sae_password_id(dev, apdev, "15") |
be5e7a07 | 1626 | |
6de2a809 JM |
1627 | def test_sae_password_id_only(dev, apdev): |
1628 | """SAE and password identifier (exclusively)""" | |
4c0af8ad | 1629 | check_sae_capab(dev[0]) |
6de2a809 JM |
1630 | params = hostapd.wpa2_params(ssid="test-sae") |
1631 | params['wpa_key_mgmt'] = 'SAE' | |
1632 | params['sae_password'] = 'secret|id=pw id' | |
1633 | hapd = hostapd.add_ap(apdev[0], params) | |
1634 | ||
1635 | dev[0].request("SET sae_groups ") | |
1636 | dev[0].connect("test-sae", sae_password="secret", sae_password_id="pw id", | |
1637 | key_mgmt="SAE", scan_freq="2412") | |
1638 | ||
c90822a5 JM |
1639 | def test_sae_password_id_pwe_looping(dev, apdev): |
1640 | """SAE and password identifier with forced PWE looping)""" | |
1641 | check_sae_capab(dev[0]) | |
1642 | params = hostapd.wpa2_params(ssid="test-sae") | |
1643 | params['wpa_key_mgmt'] = 'SAE' | |
1644 | params['sae_password'] = 'secret|id=pw id' | |
1645 | params['sae_pwe'] = "3" | |
1646 | hapd = hostapd.add_ap(apdev[0], params) | |
1647 | ||
1648 | dev[0].request("SET sae_groups ") | |
1649 | try: | |
1650 | dev[0].set("sae_pwe", "3") | |
1651 | dev[0].connect("test-sae", sae_password="secret", | |
1652 | sae_password_id="pw id", | |
1653 | key_mgmt="SAE", scan_freq="2412") | |
1654 | finally: | |
1655 | dev[0].set("sae_pwe", "0") | |
1656 | ||
1657 | def test_sae_password_id_pwe_check_ap(dev, apdev): | |
1658 | """SAE and password identifier with STA using unexpected PWE derivation)""" | |
1659 | check_sae_capab(dev[0]) | |
1660 | params = hostapd.wpa2_params(ssid="test-sae") | |
1661 | params['wpa_key_mgmt'] = 'SAE' | |
1662 | params['sae_password'] = 'secret|id=pw id' | |
1663 | hapd = hostapd.add_ap(apdev[0], params) | |
1664 | ||
1665 | dev[0].request("SET sae_groups ") | |
1666 | try: | |
1667 | dev[0].set("sae_pwe", "3") | |
1668 | dev[0].connect("test-sae", sae_password="secret", | |
1669 | sae_password_id="pw id", | |
1670 | key_mgmt="SAE", scan_freq="2412", wait_connect=False) | |
1671 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", | |
1672 | "CTRL-EVENT-SSID-TEMP-DISABLED"], timeout=10) | |
1673 | if ev is None or "CTRL-EVENT-SSID-TEMP-DISABLED" not in ev: | |
1674 | raise Exception("Connection failure not reported") | |
1675 | finally: | |
1676 | dev[0].set("sae_pwe", "0") | |
1677 | ||
1678 | def test_sae_password_id_pwe_check_sta(dev, apdev): | |
1679 | """SAE and password identifier with AP using unexpected PWE derivation)""" | |
1680 | check_sae_capab(dev[0]) | |
1681 | params = hostapd.wpa2_params(ssid="test-sae") | |
1682 | params['wpa_key_mgmt'] = 'SAE' | |
1683 | params['sae_pwe'] = "3" | |
1684 | params['sae_password'] = 'secret|id=pw id' | |
1685 | hapd = hostapd.add_ap(apdev[0], params) | |
1686 | ||
1687 | dev[0].request("SET sae_groups ") | |
1688 | dev[0].connect("test-sae", sae_password="secret", | |
1689 | sae_password_id="pw id", | |
1690 | key_mgmt="SAE", scan_freq="2412", wait_connect=False) | |
1691 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", | |
1692 | "CTRL-EVENT-NETWORK-NOT-FOUND"], timeout=10) | |
1693 | if ev is None or "CTRL-EVENT-NETWORK-NOT-FOUND" not in ev: | |
1694 | raise Exception("Connection failure not reported") | |
1695 | ||
9a0ae89d JM |
1696 | def test_sae_forced_anti_clogging_pw_id(dev, apdev): |
1697 | """SAE anti clogging (forced and Password Identifier)""" | |
4c0af8ad | 1698 | check_sae_capab(dev[0]) |
9a0ae89d JM |
1699 | params = hostapd.wpa2_params(ssid="test-sae") |
1700 | params['wpa_key_mgmt'] = 'SAE' | |
1701 | params['sae_anti_clogging_threshold'] = '0' | |
1702 | params['sae_password'] = 'secret|id=' + 29*'A' | |
1703 | hostapd.add_ap(apdev[0], params) | |
1704 | for i in range(0, 2): | |
1705 | dev[i].request("SET sae_groups ") | |
1706 | dev[i].connect("test-sae", sae_password="secret", | |
1707 | sae_password_id=29*'A', key_mgmt="SAE", scan_freq="2412") | |
fe102801 JM |
1708 | |
1709 | def test_sae_reauth(dev, apdev): | |
1710 | """SAE reauthentication""" | |
4c0af8ad | 1711 | check_sae_capab(dev[0]) |
fe102801 JM |
1712 | params = hostapd.wpa2_params(ssid="test-sae", |
1713 | passphrase="12345678") | |
1714 | params['wpa_key_mgmt'] = 'SAE' | |
1715 | params["ieee80211w"] = "2" | |
1716 | hapd = hostapd.add_ap(apdev[0], params) | |
1717 | ||
1718 | dev[0].request("SET sae_groups ") | |
1719 | id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
1720 | ieee80211w="2", scan_freq="2412") | |
1721 | ||
1722 | hapd.set("ext_mgmt_frame_handling", "1") | |
1723 | dev[0].request("DISCONNECT") | |
1724 | dev[0].wait_disconnected(timeout=10) | |
1725 | hapd.set("ext_mgmt_frame_handling", "0") | |
1726 | dev[0].request("PMKSA_FLUSH") | |
1727 | dev[0].request("REASSOCIATE") | |
1728 | dev[0].wait_connected(timeout=10, error="Timeout on re-connection") | |
e43352ff JM |
1729 | |
1730 | def test_sae_anti_clogging_during_attack(dev, apdev): | |
1731 | """SAE anti clogging during an attack""" | |
1732 | try: | |
1733 | run_sae_anti_clogging_during_attack(dev, apdev) | |
1734 | finally: | |
3507968f | 1735 | stop_monitor(apdev[1]["ifname"]) |
e43352ff JM |
1736 | |
1737 | def build_sae_commit(bssid, addr, group=21, token=None): | |
1738 | if group == 19: | |
1739 | scalar = binascii.unhexlify("7332d3ebff24804005ccd8c56141e3ed8d84f40638aa31cd2fac11d4d2e89e7b") | |
1740 | element = binascii.unhexlify("954d0f4457066bff3168376a1d7174f4e66620d1792406f613055b98513a7f03a538c13dfbaf2029e2adc6aa96aa0ddcf08ac44887b02f004b7f29b9dbf4b7d9") | |
1741 | elif group == 21: | |
1742 | scalar = binascii.unhexlify("001eec673111b902f5c8a61c8cb4c1c4793031aeea8c8c319410903bc64bcbaea134ab01c4e016d51436f5b5426f7e2af635759a3033fb4031ea79f89a62a3e2f828") | |
1743 | element = binascii.unhexlify("00580eb4b448ea600ea277d5e66e4ed37db82bb04ac90442e9c3727489f366ba4b82f0a472d02caf4cdd142e96baea5915d71374660ee23acbaca38cf3fe8c5fb94b01abbc5278121635d7c06911c5dad8f18d516e1fbe296c179b7c87a1dddfab393337d3d215ed333dd396da6d8f20f798c60d054f1093c24d9c2d98e15c030cc375f0") | |
1744 | pass | |
1745 | frame = binascii.unhexlify("b0003a01") | |
1746 | frame += bssid + addr + bssid | |
1747 | frame += binascii.unhexlify("1000") | |
1748 | auth_alg = 3 | |
1749 | transact = 1 | |
1750 | status = 0 | |
1751 | frame += struct.pack("<HHHH", auth_alg, transact, status, group) | |
1752 | if token: | |
1753 | frame += token | |
1754 | frame += scalar + element | |
1755 | return frame | |
1756 | ||
1757 | def sae_rx_commit_token_req(sock, radiotap, send_two=False): | |
1758 | msg = sock.recv(1500) | |
fab49f61 | 1759 | ver, pad, len, present = struct.unpack('<BBHL', msg[0:8]) |
e43352ff | 1760 | frame = msg[len:] |
fab49f61 | 1761 | fc, duration = struct.unpack('<HH', frame[0:4]) |
e43352ff JM |
1762 | if fc != 0xb0: |
1763 | return False | |
1764 | frame = frame[4:] | |
1765 | da = frame[0:6] | |
1766 | if da[0] != 0xf2: | |
1767 | return False | |
1768 | sa = frame[6:12] | |
1769 | bssid = frame[12:18] | |
1770 | body = frame[20:] | |
1771 | ||
fab49f61 | 1772 | alg, seq, status, group = struct.unpack('<HHHH', body[0:8]) |
e43352ff JM |
1773 | if alg != 3 or seq != 1 or status != 76: |
1774 | return False | |
1775 | token = body[8:] | |
1776 | ||
1777 | frame = build_sae_commit(bssid, da, token=token) | |
1778 | sock.send(radiotap + frame) | |
1779 | if send_two: | |
1780 | sock.send(radiotap + frame) | |
1781 | return True | |
1782 | ||
1783 | def run_sae_anti_clogging_during_attack(dev, apdev): | |
4c0af8ad | 1784 | check_sae_capab(dev[0]) |
e43352ff JM |
1785 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
1786 | params['wpa_key_mgmt'] = 'SAE' | |
1787 | params['sae_groups'] = '21' | |
1788 | hapd = hostapd.add_ap(apdev[0], params) | |
1789 | ||
1790 | dev[0].scan_for_bss(hapd.own_addr(), freq=2412) | |
1791 | dev[0].request("SET sae_groups 21") | |
1792 | dev[1].scan_for_bss(hapd.own_addr(), freq=2412) | |
1793 | dev[1].request("SET sae_groups 21") | |
1794 | ||
3507968f JM |
1795 | sock = start_monitor(apdev[1]["ifname"]) |
1796 | radiotap = radiotap_build() | |
e43352ff JM |
1797 | |
1798 | bssid = binascii.unhexlify(hapd.own_addr().replace(':', '')) | |
1799 | for i in range(16): | |
1800 | addr = binascii.unhexlify("f2%010x" % i) | |
1801 | frame = build_sae_commit(bssid, addr) | |
1802 | sock.send(radiotap + frame) | |
1803 | sock.send(radiotap + frame) | |
1804 | ||
1805 | count = 0 | |
1806 | for i in range(150): | |
1807 | if sae_rx_commit_token_req(sock, radiotap, send_two=True): | |
1808 | count += 1 | |
1809 | logger.info("Number of token responses sent: %d" % count) | |
1810 | if count < 10: | |
1811 | raise Exception("Too few token responses seen: %d" % count) | |
1812 | ||
1813 | for i in range(16): | |
1814 | addr = binascii.unhexlify("f201%08x" % i) | |
1815 | frame = build_sae_commit(bssid, addr) | |
1816 | sock.send(radiotap + frame) | |
1817 | ||
1818 | count = 0 | |
1819 | for i in range(150): | |
1820 | if sae_rx_commit_token_req(sock, radiotap): | |
1821 | count += 1 | |
1822 | if count == 10: | |
1823 | break | |
a1983aa7 | 1824 | if count < 5: |
e43352ff JM |
1825 | raise Exception("Too few token responses in second round: %d" % count) |
1826 | ||
1827 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
1828 | scan_freq="2412", wait_connect=False) | |
1829 | dev[1].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
1830 | scan_freq="2412", wait_connect=False) | |
1831 | ||
1832 | count = 0 | |
1833 | connected0 = False | |
1834 | connected1 = False | |
1835 | for i in range(1000): | |
1836 | if sae_rx_commit_token_req(sock, radiotap): | |
1837 | count += 1 | |
1838 | addr = binascii.unhexlify("f202%08x" % i) | |
1839 | frame = build_sae_commit(bssid, addr) | |
1840 | sock.send(radiotap + frame) | |
1841 | while dev[0].mon.pending(): | |
1842 | ev = dev[0].mon.recv() | |
1843 | logger.debug("EV0: " + ev) | |
1844 | if "CTRL-EVENT-CONNECTED" in ev: | |
1845 | connected0 = True | |
1846 | while dev[1].mon.pending(): | |
1847 | ev = dev[1].mon.recv() | |
1848 | logger.debug("EV1: " + ev) | |
1849 | if "CTRL-EVENT-CONNECTED" in ev: | |
1850 | connected1 = True | |
1851 | if connected0 and connected1: | |
1852 | break | |
1df79115 | 1853 | time.sleep(0.00000001) |
e43352ff JM |
1854 | if not connected0: |
1855 | raise Exception("Real station(0) did not get connected") | |
1856 | if not connected1: | |
1857 | raise Exception("Real station(1) did not get connected") | |
1858 | if count < 1: | |
1859 | raise Exception("Too few token responses in third round: %d" % count) | |
ed98d4d7 JM |
1860 | |
1861 | def test_sae_sync(dev, apdev): | |
1862 | """SAE dot11RSNASAESync""" | |
4c0af8ad | 1863 | check_sae_capab(dev[0]) |
ed98d4d7 JM |
1864 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
1865 | params['wpa_key_mgmt'] = 'SAE' | |
1866 | params['sae_sync'] = '1' | |
1867 | hostapd.add_ap(apdev[0], params) | |
1868 | ||
1869 | # TODO: More complete dot11RSNASAESync testing. For now, this is really only | |
1870 | # checking that sae_sync config parameter is accepted. | |
1871 | dev[0].request("SET sae_groups ") | |
1872 | dev[1].request("SET sae_groups ") | |
1873 | id = {} | |
1874 | for i in range(0, 2): | |
1875 | dev[i].scan(freq="2412") | |
1876 | id[i] = dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
1877 | scan_freq="2412", only_add_network=True) | |
1878 | for i in range(0, 2): | |
1879 | dev[i].select_network(id[i]) | |
1880 | for i in range(0, 2): | |
1881 | dev[i].wait_connected(timeout=10) | |
8a9658db JM |
1882 | |
1883 | def test_sae_confirm_immediate(dev, apdev): | |
1884 | """SAE and AP sending Confirm message without waiting STA""" | |
4c0af8ad | 1885 | check_sae_capab(dev[0]) |
8a9658db JM |
1886 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
1887 | params['wpa_key_mgmt'] = 'SAE' | |
1888 | params['sae_confirm_immediate'] = '1' | |
1889 | hapd = hostapd.add_ap(apdev[0], params) | |
1890 | ||
1891 | dev[0].request("SET sae_groups ") | |
1892 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412") | |
3fa701b5 | 1893 | |
283be365 JM |
1894 | def test_sae_confirm_immediate2(dev, apdev): |
1895 | """SAE and AP sending Confirm message without waiting STA (2)""" | |
4c0af8ad | 1896 | check_sae_capab(dev[0]) |
283be365 JM |
1897 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
1898 | params['wpa_key_mgmt'] = 'SAE' | |
1899 | params['sae_confirm_immediate'] = '2' | |
1900 | hapd = hostapd.add_ap(apdev[0], params) | |
1901 | ||
1902 | dev[0].request("SET sae_groups ") | |
1903 | dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412") | |
1904 | ||
3fa701b5 JM |
1905 | def test_sae_pwe_group_19(dev, apdev): |
1906 | """SAE PWE derivation options with group 19""" | |
1907 | run_sae_pwe_group(dev, apdev, 19) | |
1908 | ||
1909 | def test_sae_pwe_group_20(dev, apdev): | |
1910 | """SAE PWE derivation options with group 20""" | |
1911 | run_sae_pwe_group(dev, apdev, 20) | |
1912 | ||
1913 | def test_sae_pwe_group_21(dev, apdev): | |
1914 | """SAE PWE derivation options with group 21""" | |
1915 | run_sae_pwe_group(dev, apdev, 21) | |
1916 | ||
1917 | def test_sae_pwe_group_25(dev, apdev): | |
71e276f9 JM |
1918 | """SAE PWE derivation options with group 25""" |
1919 | run_sae_pwe_group(dev, apdev, 25) | |
3fa701b5 | 1920 | |
3fa701b5 | 1921 | def test_sae_pwe_group_28(dev, apdev): |
71e276f9 JM |
1922 | """SAE PWE derivation options with group 28""" |
1923 | run_sae_pwe_group(dev, apdev, 28) | |
3fa701b5 JM |
1924 | |
1925 | def test_sae_pwe_group_29(dev, apdev): | |
71e276f9 JM |
1926 | """SAE PWE derivation options with group 29""" |
1927 | run_sae_pwe_group(dev, apdev, 29) | |
3fa701b5 JM |
1928 | |
1929 | def test_sae_pwe_group_30(dev, apdev): | |
71e276f9 JM |
1930 | """SAE PWE derivation options with group 30""" |
1931 | run_sae_pwe_group(dev, apdev, 30) | |
3fa701b5 JM |
1932 | |
1933 | def test_sae_pwe_group_1(dev, apdev): | |
1934 | """SAE PWE derivation options with group 1""" | |
1935 | run_sae_pwe_group(dev, apdev, 1) | |
1936 | ||
1937 | def test_sae_pwe_group_2(dev, apdev): | |
1938 | """SAE PWE derivation options with group 2""" | |
1939 | run_sae_pwe_group(dev, apdev, 2) | |
1940 | ||
1941 | def test_sae_pwe_group_5(dev, apdev): | |
1942 | """SAE PWE derivation options with group 5""" | |
1943 | run_sae_pwe_group(dev, apdev, 5) | |
1944 | ||
1945 | def test_sae_pwe_group_14(dev, apdev): | |
1946 | """SAE PWE derivation options with group 14""" | |
1947 | run_sae_pwe_group(dev, apdev, 14) | |
1948 | ||
1949 | def test_sae_pwe_group_15(dev, apdev): | |
1950 | """SAE PWE derivation options with group 15""" | |
1951 | run_sae_pwe_group(dev, apdev, 15) | |
1952 | ||
1953 | def test_sae_pwe_group_16(dev, apdev): | |
1954 | """SAE PWE derivation options with group 16""" | |
1955 | run_sae_pwe_group(dev, apdev, 16) | |
1956 | ||
1957 | def test_sae_pwe_group_22(dev, apdev): | |
1958 | """SAE PWE derivation options with group 22""" | |
1959 | run_sae_pwe_group(dev, apdev, 22) | |
1960 | ||
1961 | def test_sae_pwe_group_23(dev, apdev): | |
1962 | """SAE PWE derivation options with group 23""" | |
1963 | run_sae_pwe_group(dev, apdev, 23) | |
1964 | ||
1965 | def test_sae_pwe_group_24(dev, apdev): | |
1966 | """SAE PWE derivation options with group 24""" | |
1967 | run_sae_pwe_group(dev, apdev, 24) | |
1968 | ||
1969 | def start_sae_pwe_ap(apdev, group, sae_pwe): | |
1970 | params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678") | |
1971 | params['wpa_key_mgmt'] = 'SAE' | |
1972 | params['sae_groups'] = str(group) | |
1973 | params['sae_pwe'] = str(sae_pwe) | |
1974 | return hostapd.add_ap(apdev, params) | |
1975 | ||
1976 | def run_sae_pwe_group(dev, apdev, group): | |
4c0af8ad | 1977 | check_sae_capab(dev[0]) |
3fa701b5 JM |
1978 | tls = dev[0].request("GET tls_library") |
1979 | if group in [27, 28, 29, 30]: | |
1980 | if tls.startswith("OpenSSL") and "run=OpenSSL 1." in tls: | |
1981 | logger.info("Add Brainpool EC groups since OpenSSL is new enough") | |
1982 | else: | |
1983 | raise HwsimSkip("Brainpool curve not supported") | |
1984 | start_sae_pwe_ap(apdev[0], group, 2) | |
1985 | try: | |
1986 | check_sae_pwe_group(dev[0], group, 0) | |
1987 | check_sae_pwe_group(dev[0], group, 1) | |
1988 | check_sae_pwe_group(dev[0], group, 2) | |
1989 | finally: | |
1990 | dev[0].set("sae_groups", "") | |
1991 | dev[0].set("sae_pwe", "0") | |
1992 | ||
1993 | def check_sae_pwe_group(dev, group, sae_pwe): | |
1994 | dev.set("sae_groups", str(group)) | |
1995 | dev.set("sae_pwe", str(sae_pwe)) | |
1996 | dev.connect("sae-pwe", psk="12345678", key_mgmt="SAE", scan_freq="2412") | |
1997 | dev.request("REMOVE_NETWORK all") | |
1998 | dev.wait_disconnected() | |
1999 | dev.dump_monitor() | |
2000 | ||
2001 | def test_sae_pwe_h2e_only_ap(dev, apdev): | |
2002 | """SAE PWE derivation with H2E-only AP""" | |
4c0af8ad | 2003 | check_sae_capab(dev[0]) |
3fa701b5 JM |
2004 | start_sae_pwe_ap(apdev[0], 19, 1) |
2005 | try: | |
2006 | check_sae_pwe_group(dev[0], 19, 1) | |
2007 | check_sae_pwe_group(dev[0], 19, 2) | |
2008 | finally: | |
2009 | dev[0].set("sae_groups", "") | |
2010 | dev[0].set("sae_pwe", "0") | |
2011 | ||
2012 | dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", scan_freq="2412", | |
2013 | wait_connect=False) | |
2014 | ev = dev[0].wait_event(["CTRL-EVENT-NETWORK-NOT-FOUND"], timeout=10) | |
2015 | if ev is None: | |
2016 | raise Exception("No indication of mismatching network seen") | |
2017 | ||
b1905c7d JM |
2018 | def test_sae_pwe_h2e_only_ap_sta_forcing_loop(dev, apdev): |
2019 | """SAE PWE derivation with H2E-only AP and STA forcing loop""" | |
4c0af8ad | 2020 | check_sae_capab(dev[0]) |
b1905c7d JM |
2021 | start_sae_pwe_ap(apdev[0], 19, 1) |
2022 | dev[0].set("ignore_sae_h2e_only", "1") | |
2023 | dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", scan_freq="2412", | |
2024 | wait_connect=False) | |
2025 | ev = dev[0].wait_event(["CTRL-EVENT-SSID-TEMP-DISABLED"], timeout=10) | |
2026 | dev[0].request("DISCONNECT") | |
2027 | if ev is None: | |
2028 | raise Exception("No indication of temporary disabled network seen") | |
2029 | ||
3fa701b5 JM |
2030 | def test_sae_pwe_loop_only_ap(dev, apdev): |
2031 | """SAE PWE derivation with loop-only AP""" | |
4c0af8ad | 2032 | check_sae_capab(dev[0]) |
3fa701b5 JM |
2033 | start_sae_pwe_ap(apdev[0], 19, 0) |
2034 | try: | |
2035 | check_sae_pwe_group(dev[0], 19, 0) | |
2036 | check_sae_pwe_group(dev[0], 19, 2) | |
2037 | dev[0].set("sae_pwe", "1") | |
2038 | dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", | |
2039 | scan_freq="2412", wait_connect=False) | |
2040 | ev = dev[0].wait_event(["CTRL-EVENT-NETWORK-NOT-FOUND"], timeout=10) | |
2041 | if ev is None: | |
2042 | raise Exception("No indication of mismatching network seen") | |
2043 | finally: | |
2044 | dev[0].set("sae_groups", "") | |
2045 | dev[0].set("sae_pwe", "0") | |
2046 | ||
2047 | def test_sae_h2e_rejected_groups(dev, apdev): | |
2048 | """SAE H2E and rejected groups indication""" | |
4c0af8ad | 2049 | check_sae_capab(dev[0]) |
3fa701b5 JM |
2050 | params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678") |
2051 | params['wpa_key_mgmt'] = 'SAE' | |
2052 | params['sae_groups'] = "19" | |
2053 | params['sae_pwe'] = "1" | |
2054 | hapd = hostapd.add_ap(apdev[0], params) | |
2055 | try: | |
2056 | dev[0].set("sae_groups", "21 20 19") | |
2057 | dev[0].set("sae_pwe", "1") | |
2058 | dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", | |
2059 | scan_freq="2412") | |
fb3ef06d JM |
2060 | addr = dev[0].own_addr() |
2061 | hapd.wait_sta(addr) | |
2062 | sta = hapd.get_sta(addr) | |
2063 | if 'sae_rejected_groups' not in sta: | |
2064 | raise Exception("No sae_rejected_groups") | |
2065 | val = sta['sae_rejected_groups'] | |
2066 | if val != "21 20": | |
2067 | raise Exception("Unexpected sae_rejected_groups value: " + val) | |
3fa701b5 JM |
2068 | finally: |
2069 | dev[0].set("sae_groups", "") | |
2070 | dev[0].set("sae_pwe", "0") | |
2071 | ||
90d84bc5 JM |
2072 | def test_sae_h2e_rejected_groups_unexpected(dev, apdev): |
2073 | """SAE H2E and rejected groups indication (unexpected group)""" | |
4c0af8ad | 2074 | check_sae_capab(dev[0]) |
90d84bc5 JM |
2075 | params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678") |
2076 | params['wpa_key_mgmt'] = 'SAE' | |
2077 | params['sae_groups'] = "19 20" | |
2078 | params['sae_pwe'] = "1" | |
2079 | hapd = hostapd.add_ap(apdev[0], params) | |
2080 | try: | |
2081 | dev[0].set("sae_groups", "21 19") | |
2082 | dev[0].set("extra_sae_rejected_groups", "19") | |
2083 | dev[0].set("sae_pwe", "1") | |
2084 | dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", | |
2085 | scan_freq="2412", wait_connect=False) | |
2086 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", | |
2087 | "CTRL-EVENT-SSID-TEMP-DISABLED"], timeout=10) | |
2088 | dev[0].request("DISCONNECT") | |
2089 | if ev is None: | |
2090 | raise Exception("No indication of temporary disabled network seen") | |
2091 | if "CTRL-EVENT-CONNECTED" in ev: | |
2092 | raise Exception("Unexpected connection") | |
2093 | finally: | |
2094 | dev[0].set("sae_groups", "") | |
2095 | dev[0].set("sae_pwe", "0") | |
2096 | ||
3fa701b5 JM |
2097 | def test_sae_h2e_password_id(dev, apdev): |
2098 | """SAE H2E and password identifier""" | |
4c0af8ad | 2099 | check_sae_capab(dev[0]) |
3fa701b5 JM |
2100 | params = hostapd.wpa2_params(ssid="test-sae") |
2101 | params['wpa_key_mgmt'] = 'SAE' | |
2102 | params['sae_pwe'] = '1' | |
2103 | params['sae_password'] = 'secret|id=pw id' | |
2104 | hapd = hostapd.add_ap(apdev[0], params) | |
2105 | ||
2106 | try: | |
2107 | dev[0].request("SET sae_groups ") | |
2108 | dev[0].set("sae_pwe", "1") | |
2109 | dev[0].connect("test-sae", sae_password="secret", | |
2110 | sae_password_id="pw id", | |
2111 | key_mgmt="SAE", scan_freq="2412") | |
2112 | finally: | |
2113 | dev[0].set("sae_groups", "") | |
2114 | dev[0].set("sae_pwe", "0") | |
01b2cd64 | 2115 | |
dd8eb44e JM |
2116 | def test_sae_pwe_in_psk_ap(dev, apdev): |
2117 | """sae_pwe parameter in PSK-only-AP""" | |
2118 | params = hostapd.wpa2_params(ssid="test-psk", passphrase="12345678") | |
2119 | params['sae_pwe'] = '1' | |
2120 | hapd = hostapd.add_ap(apdev[0], params) | |
2121 | ||
2122 | dev[0].connect("test-psk", psk="12345678", scan_freq="2412") | |
2123 | ||
01b2cd64 JM |
2124 | def test_sae_auth_restart(dev, apdev): |
2125 | """SAE and authentication restarts with H2E/looping""" | |
4c0af8ad | 2126 | check_sae_capab(dev[0]) |
01b2cd64 JM |
2127 | params = hostapd.wpa2_params(ssid="test-sae") |
2128 | params['wpa_key_mgmt'] = 'SAE' | |
2129 | params['sae_pwe'] = '2' | |
2130 | params['sae_password'] = 'secret|id=pw id' | |
2131 | hapd = hostapd.add_ap(apdev[0], params) | |
2132 | ||
2133 | try: | |
2134 | dev[0].request("SET sae_groups ") | |
2135 | for pwe in [1, 0, 1]: | |
2136 | dev[0].set("sae_pwe", str(pwe)) | |
2137 | dev[0].connect("test-sae", sae_password="secret", | |
2138 | sae_password_id="pw id", | |
2139 | key_mgmt="SAE", scan_freq="2412") | |
2140 | # Disconnect without hostapd removing the STA entry so that the | |
2141 | # following SAE authentication instance starts with an existing | |
2142 | # STA entry that has maintained some SAE state. | |
2143 | hapd.set("ext_mgmt_frame_handling", "1") | |
2144 | dev[0].request("REMOVE_NETWORK all") | |
2145 | req = hapd.mgmt_rx() | |
2146 | dev[0].wait_disconnected() | |
2147 | dev[0].dump_monitor() | |
2148 | hapd.set("ext_mgmt_frame_handling", "0") | |
2149 | finally: | |
2150 | dev[0].set("sae_groups", "") | |
2151 | dev[0].set("sae_pwe", "0") | |
250db2ab JM |
2152 | |
2153 | def test_sae_h2e_rsnxe_mismatch(dev, apdev): | |
2154 | """SAE H2E and RSNXE mismatch in EAPOL-Key msg 2/4""" | |
4c0af8ad | 2155 | check_sae_capab(dev[0]) |
250db2ab JM |
2156 | params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678") |
2157 | params['wpa_key_mgmt'] = 'SAE' | |
2158 | params['sae_pwe'] = "1" | |
2159 | hapd = hostapd.add_ap(apdev[0], params) | |
2160 | try: | |
2161 | dev[0].set("sae_groups", "19") | |
2162 | dev[0].set("sae_pwe", "1") | |
2163 | for rsnxe in ["F40100", "F400", ""]: | |
2164 | dev[0].set("rsnxe_override_eapol", rsnxe) | |
2165 | dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", | |
2166 | scan_freq="2412", wait_connect=False) | |
2167 | ev = dev[0].wait_event(["Associated with"], timeout=10) | |
2168 | if ev is None: | |
2169 | raise Exception("No indication of association seen") | |
2170 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", | |
2171 | "CTRL-EVENT-DISCONNECTED"], timeout=5) | |
2172 | dev[0].request("REMOVE_NETWORK all") | |
2173 | if ev is None: | |
2174 | raise Exception("No disconnection seen") | |
2175 | if "CTRL-EVENT-DISCONNECTED" not in ev: | |
2176 | raise Exception("Unexpected connection") | |
2177 | dev[0].dump_monitor() | |
2178 | finally: | |
2179 | dev[0].set("sae_groups", "") | |
2180 | dev[0].set("sae_pwe", "0") | |
2181 | ||
06540f23 JM |
2182 | def test_sae_h2e_rsnxe_mismatch_retries(dev, apdev): |
2183 | """SAE H2E and RSNXE mismatch in EAPOL-Key msg 2/4 retries""" | |
4c0af8ad | 2184 | check_sae_capab(dev[0]) |
06540f23 JM |
2185 | params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678") |
2186 | params['wpa_key_mgmt'] = 'SAE' | |
2187 | params['sae_pwe'] = "1" | |
2188 | hapd = hostapd.add_ap(apdev[0], params) | |
2189 | try: | |
2190 | dev[0].set("sae_groups", "19") | |
2191 | dev[0].set("sae_pwe", "1") | |
2192 | rsnxe = "F40100" | |
2193 | dev[0].set("rsnxe_override_eapol", rsnxe) | |
2194 | dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", | |
2195 | scan_freq="2412", wait_connect=False) | |
2196 | ev = dev[0].wait_event(["Associated with"], timeout=10) | |
2197 | if ev is None: | |
2198 | raise Exception("No indication of association seen") | |
2199 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", | |
2200 | "CTRL-EVENT-DISCONNECTED"], timeout=5) | |
2201 | if ev is None: | |
2202 | raise Exception("No disconnection seen") | |
2203 | if "CTRL-EVENT-DISCONNECTED" not in ev: | |
2204 | raise Exception("Unexpected connection") | |
2205 | ||
2206 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", | |
2207 | "CTRL-EVENT-DISCONNECTED"], timeout=10) | |
2208 | if ev is None: | |
2209 | raise Exception("No disconnection seen (2)") | |
2210 | if "CTRL-EVENT-DISCONNECTED" not in ev: | |
2211 | raise Exception("Unexpected connection (2)") | |
2212 | ||
2213 | dev[0].dump_monitor() | |
2214 | finally: | |
2215 | dev[0].set("sae_groups", "") | |
2216 | dev[0].set("sae_pwe", "0") | |
2217 | ||
250db2ab JM |
2218 | def test_sae_h2e_rsnxe_mismatch_assoc(dev, apdev): |
2219 | """SAE H2E and RSNXE mismatch in EAPOL-Key msg 2/4 (assoc)""" | |
4c0af8ad | 2220 | check_sae_capab(dev[0]) |
250db2ab JM |
2221 | params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678") |
2222 | params['wpa_key_mgmt'] = 'SAE' | |
2223 | params['sae_pwe'] = "1" | |
2224 | hapd = hostapd.add_ap(apdev[0], params) | |
2225 | try: | |
2226 | dev[0].set("sae_groups", "19") | |
2227 | dev[0].set("sae_pwe", "1") | |
2228 | for rsnxe in ["F40100", "F400", ""]: | |
2229 | dev[0].set("rsnxe_override_assoc", rsnxe) | |
2230 | dev[0].set("rsnxe_override_eapol", "F40120") | |
2231 | dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", | |
2232 | scan_freq="2412", wait_connect=False) | |
2233 | ev = dev[0].wait_event(["Associated with"], timeout=10) | |
2234 | if ev is None: | |
2235 | raise Exception("No indication of association seen") | |
2236 | ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", | |
2237 | "CTRL-EVENT-DISCONNECTED"], timeout=5) | |
2238 | dev[0].request("REMOVE_NETWORK all") | |
2239 | if ev is None: | |
2240 | raise Exception("No disconnection seen") | |
2241 | if "CTRL-EVENT-DISCONNECTED" not in ev: | |
2242 | raise Exception("Unexpected connection") | |
2243 | dev[0].dump_monitor() | |
2244 | finally: | |
2245 | dev[0].set("sae_groups", "") | |
2246 | dev[0].set("sae_pwe", "0") | |
63585099 JM |
2247 | |
2248 | def test_sae_h2e_rsnxe_mismatch_ap(dev, apdev): | |
2249 | """SAE H2E and RSNXE mismatch in EAPOL-Key msg 3/4""" | |
2250 | run_sae_h2e_rsnxe_mismatch_ap(dev, apdev, "F40100") | |
2251 | ||
2252 | def test_sae_h2e_rsnxe_mismatch_ap2(dev, apdev): | |
2253 | """SAE H2E and RSNXE mismatch in EAPOL-Key msg 3/4""" | |
2254 | run_sae_h2e_rsnxe_mismatch_ap(dev, apdev, "F400") | |
2255 | ||
2256 | def run_sae_h2e_rsnxe_mismatch_ap(dev, apdev, rsnxe): | |
4c0af8ad | 2257 | check_sae_capab(dev[0]) |
63585099 JM |
2258 | params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678") |
2259 | params['wpa_key_mgmt'] = 'SAE' | |
2260 | params['sae_pwe'] = "1" | |
2261 | params['rsnxe_override_eapol'] = rsnxe | |
2262 | hapd = hostapd.add_ap(apdev[0], params) | |
2263 | try: | |
2264 | dev[0].set("sae_groups", "19") | |
2265 | dev[0].set("sae_pwe", "1") | |
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 | dev[0].request("REMOVE_NETWORK all") | |
2274 | if ev is None: | |
2275 | raise Exception("No disconnection seen") | |
2276 | if "CTRL-EVENT-DISCONNECTED" not in ev: | |
2277 | raise Exception("Unexpected connection") | |
2278 | finally: | |
2279 | dev[0].set("sae_groups", "") | |
2280 | dev[0].set("sae_pwe", "0") | |
6ce883de JM |
2281 | |
2282 | def test_sae_forced_anti_clogging_h2e(dev, apdev): | |
2283 | """SAE anti clogging (forced, H2E)""" | |
4c0af8ad JM |
2284 | check_sae_capab(dev[0]) |
2285 | check_sae_capab(dev[1]) | |
6ce883de JM |
2286 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") |
2287 | params['wpa_key_mgmt'] = 'SAE WPA-PSK' | |
2288 | params['sae_pwe'] = "1" | |
2289 | params['sae_anti_clogging_threshold'] = '0' | |
2290 | hostapd.add_ap(apdev[0], params) | |
2291 | dev[2].connect("test-sae", psk="12345678", scan_freq="2412") | |
2292 | try: | |
2293 | for i in range(2): | |
2294 | dev[i].request("SET sae_groups ") | |
2295 | dev[i].set("sae_pwe", "1") | |
2296 | dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
2297 | scan_freq="2412") | |
2298 | finally: | |
2299 | for i in range(2): | |
2300 | dev[i].set("sae_pwe", "0") | |
3ecaddd6 JM |
2301 | |
2302 | def test_sae_forced_anti_clogging_h2e_loop(dev, apdev): | |
2303 | """SAE anti clogging (forced, H2E + loop)""" | |
2304 | check_sae_capab(dev[0]) | |
2305 | check_sae_capab(dev[1]) | |
2306 | params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") | |
2307 | params['wpa_key_mgmt'] = 'SAE WPA-PSK' | |
2308 | params['sae_pwe'] = "2" | |
2309 | params['sae_anti_clogging_threshold'] = '0' | |
2310 | hostapd.add_ap(apdev[0], params) | |
2311 | dev[2].connect("test-sae", psk="12345678", scan_freq="2412") | |
2312 | try: | |
2313 | for i in range(2): | |
2314 | dev[i].request("SET sae_groups ") | |
2315 | dev[i].set("sae_pwe", "2") | |
2316 | dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE", | |
2317 | scan_freq="2412") | |
2318 | finally: | |
2319 | for i in range(2): | |
2320 | dev[i].set("sae_pwe", "0") |