]> git.ipfire.org Git - thirdparty/hostap.git/blob - tests/hwsim/test_sae.py
tests: Explicit str/bytes conversion for key_lifetime_in_memory
[thirdparty/hostap.git] / tests / hwsim / test_sae.py
1 # Test cases for SAE
2 # Copyright (c) 2013-2016, Jouni Malinen <j@w1.fi>
3 #
4 # This software may be distributed under the terms of the BSD license.
5 # See README for more details.
6
7 from remotehost import remote_compatible
8 import binascii
9 import os
10 import time
11 import logging
12 logger = logging.getLogger()
13
14 import hwsim_utils
15 import hostapd
16 from wpasupplicant import WpaSupplicant
17 from utils import HwsimSkip, alloc_fail, fail_test, wait_fail_trigger
18 from test_ap_psk import find_wpas_process, read_process_memory, verify_not_present, get_key_locations
19
20 @remote_compatible
21 def test_sae(dev, apdev):
22 """SAE with default group"""
23 if "SAE" not in dev[0].get_capability("auth_alg"):
24 raise HwsimSkip("SAE not supported")
25 params = hostapd.wpa2_params(ssid="test-sae",
26 passphrase="12345678")
27 params['wpa_key_mgmt'] = 'SAE'
28 hapd = hostapd.add_ap(apdev[0], params)
29 key_mgmt = hapd.get_config()['key_mgmt']
30 if key_mgmt.split(' ')[0] != "SAE":
31 raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
32
33 dev[0].request("SET sae_groups ")
34 id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
35 scan_freq="2412")
36 if dev[0].get_status_field('sae_group') != '19':
37 raise Exception("Expected default SAE group not used")
38 bss = dev[0].get_bss(apdev[0]['bssid'])
39 if 'flags' not in bss:
40 raise Exception("Could not get BSS flags from BSS table")
41 if "[WPA2-SAE-CCMP]" not in bss['flags']:
42 raise Exception("Unexpected BSS flags: " + bss['flags'])
43
44 res = hapd.request("STA-FIRST")
45 if "sae_group=19" not in res.splitlines():
46 raise Exception("hostapd STA output did not specify SAE group")
47
48 @remote_compatible
49 def test_sae_password_ecc(dev, apdev):
50 """SAE with number of different passwords (ECC)"""
51 if "SAE" not in dev[0].get_capability("auth_alg"):
52 raise HwsimSkip("SAE not supported")
53 params = hostapd.wpa2_params(ssid="test-sae",
54 passphrase="12345678")
55 params['wpa_key_mgmt'] = 'SAE'
56 hapd = hostapd.add_ap(apdev[0], params)
57
58 dev[0].request("SET sae_groups 19")
59
60 for i in range(10):
61 password = "12345678-" + str(i)
62 hapd.set("wpa_passphrase", password)
63 dev[0].connect("test-sae", psk=password, key_mgmt="SAE",
64 scan_freq="2412")
65 dev[0].request("REMOVE_NETWORK all")
66 dev[0].wait_disconnected()
67
68 @remote_compatible
69 def test_sae_password_ffc(dev, apdev):
70 """SAE with number of different passwords (FFC)"""
71 if "SAE" not in dev[0].get_capability("auth_alg"):
72 raise HwsimSkip("SAE not supported")
73 params = hostapd.wpa2_params(ssid="test-sae",
74 passphrase="12345678")
75 params['wpa_key_mgmt'] = 'SAE'
76 params['sae_groups'] = '22'
77 hapd = hostapd.add_ap(apdev[0], params)
78
79 dev[0].request("SET sae_groups 22")
80
81 for i in range(10):
82 password = "12345678-" + str(i)
83 hapd.set("wpa_passphrase", password)
84 dev[0].connect("test-sae", psk=password, key_mgmt="SAE",
85 scan_freq="2412")
86 dev[0].request("REMOVE_NETWORK all")
87 dev[0].wait_disconnected()
88
89 @remote_compatible
90 def test_sae_pmksa_caching(dev, apdev):
91 """SAE and PMKSA caching"""
92 if "SAE" not in dev[0].get_capability("auth_alg"):
93 raise HwsimSkip("SAE not supported")
94 params = hostapd.wpa2_params(ssid="test-sae",
95 passphrase="12345678")
96 params['wpa_key_mgmt'] = 'SAE'
97 hapd = hostapd.add_ap(apdev[0], params)
98
99 dev[0].request("SET sae_groups ")
100 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
101 scan_freq="2412")
102 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
103 if ev is None:
104 raise Exception("No connection event received from hostapd")
105 dev[0].request("DISCONNECT")
106 dev[0].wait_disconnected()
107 dev[0].request("RECONNECT")
108 dev[0].wait_connected(timeout=15, error="Reconnect timed out")
109 if dev[0].get_status_field('sae_group') is not None:
110 raise Exception("SAE group claimed to have been used")
111
112 @remote_compatible
113 def test_sae_pmksa_caching_disabled(dev, apdev):
114 """SAE and PMKSA caching disabled"""
115 if "SAE" not in dev[0].get_capability("auth_alg"):
116 raise HwsimSkip("SAE not supported")
117 params = hostapd.wpa2_params(ssid="test-sae",
118 passphrase="12345678")
119 params['wpa_key_mgmt'] = 'SAE'
120 params['disable_pmksa_caching'] = '1'
121 hapd = hostapd.add_ap(apdev[0], params)
122
123 dev[0].request("SET sae_groups ")
124 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
125 scan_freq="2412")
126 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
127 if ev is None:
128 raise Exception("No connection event received from hostapd")
129 dev[0].request("DISCONNECT")
130 dev[0].wait_disconnected()
131 dev[0].request("RECONNECT")
132 dev[0].wait_connected(timeout=15, error="Reconnect timed out")
133 if dev[0].get_status_field('sae_group') != '19':
134 raise Exception("Expected default SAE group not used")
135
136 def test_sae_groups(dev, apdev):
137 """SAE with all supported groups"""
138 if "SAE" not in dev[0].get_capability("auth_alg"):
139 raise HwsimSkip("SAE not supported")
140 # This is the full list of supported groups, but groups 14-16 (2048-4096 bit
141 # MODP) and group 21 (521-bit random ECP group) are a bit too slow on some
142 # VMs and can result in hitting the mac80211 authentication timeout, so
143 # allow them to fail and just report such failures in the debug log.
144 sae_groups = [ 19, 25, 26, 20, 21, 2, 5, 14, 15, 16, 22, 23, 24 ]
145 tls = dev[0].request("GET tls_library")
146 if tls.startswith("OpenSSL") and "build=OpenSSL 1.0.2" in tls and "run=OpenSSL 1.0.2" in tls:
147 logger.info("Add Brainpool EC groups since OpenSSL is new enough")
148 sae_groups += [ 27, 28, 29, 30 ]
149 heavy_groups = [ 14, 15, 16 ]
150 groups = [str(g) for g in sae_groups]
151 params = hostapd.wpa2_params(ssid="test-sae-groups",
152 passphrase="12345678")
153 params['wpa_key_mgmt'] = 'SAE'
154 params['sae_groups'] = ' '.join(groups)
155 hostapd.add_ap(apdev[0], params)
156
157 for g in groups:
158 logger.info("Testing SAE group " + g)
159 dev[0].request("SET sae_groups " + g)
160 id = dev[0].connect("test-sae-groups", psk="12345678", key_mgmt="SAE",
161 scan_freq="2412", wait_connect=False)
162 if int(g) in heavy_groups:
163 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=5)
164 if ev is None:
165 logger.info("No connection with heavy SAE group %s did not connect - likely hitting timeout in mac80211" % g)
166 dev[0].remove_network(id)
167 time.sleep(0.1)
168 dev[0].dump_monitor()
169 continue
170 logger.info("Connection with heavy SAE group " + g)
171 else:
172 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
173 if ev is None:
174 if "BoringSSL" in tls and int(g) in [ 25 ]:
175 logger.info("Ignore connection failure with group " + g + " with BoringSSL")
176 dev[0].remove_network(id)
177 dev[0].dump_monitor()
178 continue
179 raise Exception("Connection timed out with group " + g)
180 if dev[0].get_status_field('sae_group') != g:
181 raise Exception("Expected SAE group not used")
182 dev[0].remove_network(id)
183 dev[0].wait_disconnected()
184 dev[0].dump_monitor()
185
186 @remote_compatible
187 def test_sae_group_nego(dev, apdev):
188 """SAE group negotiation"""
189 if "SAE" not in dev[0].get_capability("auth_alg"):
190 raise HwsimSkip("SAE not supported")
191 params = hostapd.wpa2_params(ssid="test-sae-group-nego",
192 passphrase="12345678")
193 params['wpa_key_mgmt'] = 'SAE'
194 params['sae_groups'] = '19'
195 hostapd.add_ap(apdev[0], params)
196
197 dev[0].request("SET sae_groups 25 26 20 19")
198 dev[0].connect("test-sae-group-nego", psk="12345678", key_mgmt="SAE",
199 scan_freq="2412")
200 if dev[0].get_status_field('sae_group') != '19':
201 raise Exception("Expected SAE group not used")
202
203 @remote_compatible
204 def test_sae_anti_clogging(dev, apdev):
205 """SAE anti clogging"""
206 if "SAE" not in dev[0].get_capability("auth_alg"):
207 raise HwsimSkip("SAE not supported")
208 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
209 params['wpa_key_mgmt'] = 'SAE'
210 params['sae_anti_clogging_threshold'] = '1'
211 hostapd.add_ap(apdev[0], params)
212
213 dev[0].request("SET sae_groups ")
214 dev[1].request("SET sae_groups ")
215 id = {}
216 for i in range(0, 2):
217 dev[i].scan(freq="2412")
218 id[i] = dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE",
219 scan_freq="2412", only_add_network=True)
220 for i in range(0, 2):
221 dev[i].select_network(id[i])
222 for i in range(0, 2):
223 dev[i].wait_connected(timeout=10)
224
225 def test_sae_forced_anti_clogging(dev, apdev):
226 """SAE anti clogging (forced)"""
227 if "SAE" not in dev[0].get_capability("auth_alg"):
228 raise HwsimSkip("SAE not supported")
229 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
230 params['wpa_key_mgmt'] = 'SAE WPA-PSK'
231 params['sae_anti_clogging_threshold'] = '0'
232 hostapd.add_ap(apdev[0], params)
233 dev[2].connect("test-sae", psk="12345678", scan_freq="2412")
234 for i in range(0, 2):
235 dev[i].request("SET sae_groups ")
236 dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE",
237 scan_freq="2412")
238
239 def test_sae_mixed(dev, apdev):
240 """Mixed SAE and non-SAE network"""
241 if "SAE" not in dev[0].get_capability("auth_alg"):
242 raise HwsimSkip("SAE not supported")
243 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
244 params['wpa_key_mgmt'] = 'SAE WPA-PSK'
245 params['sae_anti_clogging_threshold'] = '0'
246 hostapd.add_ap(apdev[0], params)
247
248 dev[2].connect("test-sae", psk="12345678", scan_freq="2412")
249 for i in range(0, 2):
250 dev[i].request("SET sae_groups ")
251 dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE",
252 scan_freq="2412")
253
254 def test_sae_and_psk(dev, apdev):
255 """SAE and PSK enabled in network profile"""
256 if "SAE" not in dev[0].get_capability("auth_alg"):
257 raise HwsimSkip("SAE not supported")
258 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
259 params['wpa_key_mgmt'] = 'SAE'
260 hostapd.add_ap(apdev[0], params)
261
262 dev[0].request("SET sae_groups ")
263 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE WPA-PSK",
264 scan_freq="2412")
265
266 def test_sae_and_psk2(dev, apdev):
267 """SAE and PSK enabled in network profile (use PSK)"""
268 if "SAE" not in dev[0].get_capability("auth_alg"):
269 raise HwsimSkip("SAE not supported")
270 params = hostapd.wpa2_params(ssid="test-psk", passphrase="12345678")
271 hostapd.add_ap(apdev[0], params)
272
273 dev[0].request("SET sae_groups ")
274 dev[0].connect("test-psk", psk="12345678", key_mgmt="SAE WPA-PSK",
275 scan_freq="2412")
276
277 def test_sae_mixed_mfp(dev, apdev):
278 """Mixed SAE and non-SAE network and MFP required with SAE"""
279 if "SAE" not in dev[0].get_capability("auth_alg"):
280 raise HwsimSkip("SAE not supported")
281 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
282 params['wpa_key_mgmt'] = 'SAE WPA-PSK'
283 params["ieee80211w"] = "1"
284 params['sae_require_mfp'] = '1'
285 hostapd.add_ap(apdev[0], params)
286
287 dev[0].request("SET sae_groups ")
288 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", ieee80211w="2",
289 scan_freq="2412")
290 dev[0].dump_monitor()
291
292 dev[1].request("SET sae_groups ")
293 dev[1].connect("test-sae", psk="12345678", key_mgmt="SAE", ieee80211w="0",
294 scan_freq="2412", wait_connect=False)
295 ev = dev[1].wait_event(["CTRL-EVENT-CONNECTED",
296 "CTRL-EVENT-ASSOC-REJECT"], timeout=10)
297 if ev is None:
298 raise Exception("No connection result reported")
299 if "CTRL-EVENT-ASSOC-REJECT" not in ev:
300 raise Exception("SAE connection without MFP was not rejected")
301 if "status_code=31" not in ev:
302 raise Exception("Unexpected status code in rejection: " + ev)
303 dev[1].request("DISCONNECT")
304 dev[1].dump_monitor()
305
306 dev[2].connect("test-sae", psk="12345678", ieee80211w="0", scan_freq="2412")
307 dev[2].dump_monitor()
308
309 def test_sae_mfp(dev, apdev):
310 """SAE and MFP enabled without sae_require_mfp"""
311 if "SAE" not in dev[0].get_capability("auth_alg"):
312 raise HwsimSkip("SAE not supported")
313 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
314 params['wpa_key_mgmt'] = 'SAE'
315 params["ieee80211w"] = "1"
316 hostapd.add_ap(apdev[0], params)
317
318 dev[0].request("SET sae_groups ")
319 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", ieee80211w="2",
320 scan_freq="2412")
321
322 dev[1].request("SET sae_groups ")
323 dev[1].connect("test-sae", psk="12345678", key_mgmt="SAE", ieee80211w="0",
324 scan_freq="2412")
325
326 @remote_compatible
327 def test_sae_missing_password(dev, apdev):
328 """SAE and missing password"""
329 if "SAE" not in dev[0].get_capability("auth_alg"):
330 raise HwsimSkip("SAE not supported")
331 params = hostapd.wpa2_params(ssid="test-sae",
332 passphrase="12345678")
333 params['wpa_key_mgmt'] = 'SAE'
334 hapd = hostapd.add_ap(apdev[0], params)
335
336 dev[0].request("SET sae_groups ")
337 id = dev[0].connect("test-sae",
338 raw_psk="46b4a73b8a951ad53ebd2e0afdb9c5483257edd4c21d12b7710759da70945858",
339 key_mgmt="SAE", scan_freq="2412", wait_connect=False)
340 ev = dev[0].wait_event(['CTRL-EVENT-SSID-TEMP-DISABLED'], timeout=10)
341 if ev is None:
342 raise Exception("Invalid network not temporarily disabled")
343
344
345 def test_sae_key_lifetime_in_memory(dev, apdev, params):
346 """SAE and key lifetime in memory"""
347 if "SAE" not in dev[0].get_capability("auth_alg"):
348 raise HwsimSkip("SAE not supported")
349 password = "5ad144a7c1f5a5503baa6fa01dabc15b1843e8c01662d78d16b70b5cd23cf8b"
350 p = hostapd.wpa2_params(ssid="test-sae", passphrase=password)
351 p['wpa_key_mgmt'] = 'SAE'
352 hapd = hostapd.add_ap(apdev[0], p)
353
354 pid = find_wpas_process(dev[0])
355
356 dev[0].request("SET sae_groups ")
357 id = dev[0].connect("test-sae", psk=password, key_mgmt="SAE",
358 scan_freq="2412")
359
360 # The decrypted copy of GTK is freed only after the CTRL-EVENT-CONNECTED
361 # event has been delivered, so verify that wpa_supplicant has returned to
362 # eloop before reading process memory.
363 time.sleep(1)
364 dev[0].ping()
365 password = password.encode()
366 buf = read_process_memory(pid, password)
367
368 dev[0].request("DISCONNECT")
369 dev[0].wait_disconnected()
370
371 dev[0].relog()
372 sae_k = None
373 sae_keyseed = None
374 sae_kck = None
375 pmk = None
376 ptk = None
377 gtk = None
378 with open(os.path.join(params['logdir'], 'log0'), 'r') as f:
379 for l in f.readlines():
380 if "SAE: k - hexdump" in l:
381 val = l.strip().split(':')[3].replace(' ', '')
382 sae_k = binascii.unhexlify(val)
383 if "SAE: keyseed - hexdump" in l:
384 val = l.strip().split(':')[3].replace(' ', '')
385 sae_keyseed = binascii.unhexlify(val)
386 if "SAE: KCK - hexdump" in l:
387 val = l.strip().split(':')[3].replace(' ', '')
388 sae_kck = binascii.unhexlify(val)
389 if "SAE: PMK - hexdump" in l:
390 val = l.strip().split(':')[3].replace(' ', '')
391 pmk = binascii.unhexlify(val)
392 if "WPA: PTK - hexdump" in l:
393 val = l.strip().split(':')[3].replace(' ', '')
394 ptk = binascii.unhexlify(val)
395 if "WPA: Group Key - hexdump" in l:
396 val = l.strip().split(':')[3].replace(' ', '')
397 gtk = binascii.unhexlify(val)
398 if not sae_k or not sae_keyseed or not sae_kck or not pmk or not ptk or not gtk:
399 raise Exception("Could not find keys from debug log")
400 if len(gtk) != 16:
401 raise Exception("Unexpected GTK length")
402
403 kck = ptk[0:16]
404 kek = ptk[16:32]
405 tk = ptk[32:48]
406
407 fname = os.path.join(params['logdir'],
408 'sae_key_lifetime_in_memory.memctx-')
409
410 logger.info("Checking keys in memory while associated")
411 get_key_locations(buf, password, "Password")
412 get_key_locations(buf, pmk, "PMK")
413 if password not in buf:
414 raise HwsimSkip("Password not found while associated")
415 if pmk not in buf:
416 raise HwsimSkip("PMK not found while associated")
417 if kck not in buf:
418 raise Exception("KCK not found while associated")
419 if kek not in buf:
420 raise Exception("KEK not found while associated")
421 #if tk in buf:
422 # raise Exception("TK found from memory")
423 verify_not_present(buf, sae_k, fname, "SAE(k)")
424 verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)")
425 verify_not_present(buf, sae_kck, fname, "SAE(KCK)")
426
427 logger.info("Checking keys in memory after disassociation")
428 buf = read_process_memory(pid, password)
429
430 # Note: Password is still present in network configuration
431 # Note: PMK is in PMKSA cache
432
433 get_key_locations(buf, password, "Password")
434 get_key_locations(buf, pmk, "PMK")
435 verify_not_present(buf, kck, fname, "KCK")
436 verify_not_present(buf, kek, fname, "KEK")
437 verify_not_present(buf, tk, fname, "TK")
438 if gtk in buf:
439 get_key_locations(buf, gtk, "GTK")
440 verify_not_present(buf, gtk, fname, "GTK")
441 verify_not_present(buf, sae_k, fname, "SAE(k)")
442 verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)")
443 verify_not_present(buf, sae_kck, fname, "SAE(KCK)")
444
445 dev[0].request("PMKSA_FLUSH")
446 logger.info("Checking keys in memory after PMKSA cache flush")
447 buf = read_process_memory(pid, password)
448 get_key_locations(buf, password, "Password")
449 get_key_locations(buf, pmk, "PMK")
450 verify_not_present(buf, pmk, fname, "PMK")
451
452 dev[0].request("REMOVE_NETWORK all")
453
454 logger.info("Checking keys in memory after network profile removal")
455 buf = read_process_memory(pid, password)
456
457 get_key_locations(buf, password, "Password")
458 get_key_locations(buf, pmk, "PMK")
459 verify_not_present(buf, password, fname, "password")
460 verify_not_present(buf, pmk, fname, "PMK")
461 verify_not_present(buf, kck, fname, "KCK")
462 verify_not_present(buf, kek, fname, "KEK")
463 verify_not_present(buf, tk, fname, "TK")
464 verify_not_present(buf, gtk, fname, "GTK")
465 verify_not_present(buf, sae_k, fname, "SAE(k)")
466 verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)")
467 verify_not_present(buf, sae_kck, fname, "SAE(KCK)")
468
469 @remote_compatible
470 def test_sae_oom_wpas(dev, apdev):
471 """SAE and OOM in wpa_supplicant"""
472 if "SAE" not in dev[0].get_capability("auth_alg"):
473 raise HwsimSkip("SAE not supported")
474 params = hostapd.wpa2_params(ssid="test-sae",
475 passphrase="12345678")
476 params['wpa_key_mgmt'] = 'SAE'
477 hapd = hostapd.add_ap(apdev[0], params)
478
479 dev[0].request("SET sae_groups 25")
480 tls = dev[0].request("GET tls_library")
481 if "BoringSSL" in tls:
482 dev[0].request("SET sae_groups 26")
483 with alloc_fail(dev[0], 1, "sae_set_group"):
484 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
485 scan_freq="2412")
486 dev[0].request("REMOVE_NETWORK all")
487
488 dev[0].request("SET sae_groups ")
489 with alloc_fail(dev[0], 2, "sae_set_group"):
490 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
491 scan_freq="2412")
492 dev[0].request("REMOVE_NETWORK all")
493
494 with alloc_fail(dev[0], 1, "wpabuf_alloc;sme_auth_build_sae_commit"):
495 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
496 scan_freq="2412")
497 dev[0].request("REMOVE_NETWORK all")
498
499 with alloc_fail(dev[0], 1, "wpabuf_alloc;sme_auth_build_sae_confirm"):
500 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
501 scan_freq="2412", wait_connect=False)
502 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
503 dev[0].request("REMOVE_NETWORK all")
504
505 with alloc_fail(dev[0], 1, "=sme_authenticate"):
506 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
507 scan_freq="2412", wait_connect=False)
508 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
509 dev[0].request("REMOVE_NETWORK all")
510
511 with alloc_fail(dev[0], 1, "radio_add_work;sme_authenticate"):
512 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
513 scan_freq="2412", wait_connect=False)
514 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
515 dev[0].request("REMOVE_NETWORK all")
516
517 @remote_compatible
518 def test_sae_proto_ecc(dev, apdev):
519 """SAE protocol testing (ECC)"""
520 if "SAE" not in dev[0].get_capability("auth_alg"):
521 raise HwsimSkip("SAE not supported")
522 params = hostapd.wpa2_params(ssid="test-sae",
523 passphrase="12345678")
524 params['wpa_key_mgmt'] = 'SAE'
525 hapd = hostapd.add_ap(apdev[0], params)
526 bssid = apdev[0]['bssid']
527
528 dev[0].request("SET sae_groups 19")
529
530 tests = [ ("Confirm mismatch",
531 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
532 "0000800edebc3f260dc1fe7e0b20888af2b8a3316252ec37388a8504e25b73dc4240"),
533 ("Commit without even full cyclic group field",
534 "13",
535 None),
536 ("Too short commit",
537 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02",
538 None),
539 ("Invalid commit scalar (0)",
540 "1300" + "0000000000000000000000000000000000000000000000000000000000000000" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
541 None),
542 ("Invalid commit scalar (1)",
543 "1300" + "0000000000000000000000000000000000000000000000000000000000000001" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
544 None),
545 ("Invalid commit scalar (> r)",
546 "1300" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
547 None),
548 ("Commit element not on curve",
549 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728d0000000000000000000000000000000000000000000000000000000000000000",
550 None),
551 ("Invalid commit element (y coordinate > P)",
552 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
553 None),
554 ("Invalid commit element (x coordinate > P)",
555 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
556 None),
557 ("Different group in commit",
558 "1400" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
559 None),
560 ("Too short confirm",
561 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
562 "0000800edebc3f260dc1fe7e0b20888af2b8a3316252ec37388a8504e25b73dc42")]
563 for (note, commit, confirm) in tests:
564 logger.info(note)
565 dev[0].scan_for_bss(bssid, freq=2412)
566 hapd.set("ext_mgmt_frame_handling", "1")
567 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
568 scan_freq="2412", wait_connect=False)
569
570 logger.info("Commit")
571 for i in range(0, 10):
572 req = hapd.mgmt_rx()
573 if req is None:
574 raise Exception("MGMT RX wait timed out (commit)")
575 if req['subtype'] == 11:
576 break
577 req = None
578 if not req:
579 raise Exception("Authentication frame (commit) not received")
580
581 hapd.dump_monitor()
582 resp = {}
583 resp['fc'] = req['fc']
584 resp['da'] = req['sa']
585 resp['sa'] = req['da']
586 resp['bssid'] = req['bssid']
587 resp['payload'] = binascii.unhexlify("030001000000" + commit)
588 hapd.mgmt_tx(resp)
589
590 if confirm:
591 logger.info("Confirm")
592 for i in range(0, 10):
593 req = hapd.mgmt_rx()
594 if req is None:
595 raise Exception("MGMT RX wait timed out (confirm)")
596 if req['subtype'] == 11:
597 break
598 req = None
599 if not req:
600 raise Exception("Authentication frame (confirm) not received")
601
602 hapd.dump_monitor()
603 resp = {}
604 resp['fc'] = req['fc']
605 resp['da'] = req['sa']
606 resp['sa'] = req['da']
607 resp['bssid'] = req['bssid']
608 resp['payload'] = binascii.unhexlify("030002000000" + confirm)
609 hapd.mgmt_tx(resp)
610
611 time.sleep(0.1)
612 dev[0].request("REMOVE_NETWORK all")
613 hapd.set("ext_mgmt_frame_handling", "0")
614 hapd.dump_monitor()
615
616 @remote_compatible
617 def test_sae_proto_ffc(dev, apdev):
618 """SAE protocol testing (FFC)"""
619 if "SAE" not in dev[0].get_capability("auth_alg"):
620 raise HwsimSkip("SAE not supported")
621 params = hostapd.wpa2_params(ssid="test-sae",
622 passphrase="12345678")
623 params['wpa_key_mgmt'] = 'SAE'
624 hapd = hostapd.add_ap(apdev[0], params)
625 bssid = apdev[0]['bssid']
626
627 dev[0].request("SET sae_groups 2")
628
629 tests = [ ("Confirm mismatch",
630 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "a8c00117493cdffa5dd671e934bc9cb1a69f39e25e9dd9cd9afd3aea2441a0f5491211c7ba50a753563f9ce943b043557cb71193b28e86ed9544f4289c471bf91b70af5c018cf4663e004165b0fd0bc1d8f3f78adf42eee92bcbc55246fd3ee9f107ab965dc7d4986f23eb71d616ebfe6bfe0a6c1ac5dc1718acee17c9a17486",
631 "0000f3116a9731f1259622e3eb55d4b3b50ba16f8c5f5565b28e609b180c51460251"),
632 ("Too short commit",
633 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "a8c00117493cdffa5dd671e934bc9cb1a69f39e25e9dd9cd9afd3aea2441a0f5491211c7ba50a753563f9ce943b043557cb71193b28e86ed9544f4289c471bf91b70af5c018cf4663e004165b0fd0bc1d8f3f78adf42eee92bcbc55246fd3ee9f107ab965dc7d4986f23eb71d616ebfe6bfe0a6c1ac5dc1718acee17c9a174",
634 None),
635 ("Invalid element (0) in commit",
636 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
637 None),
638 ("Invalid element (1) in commit",
639 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
640 None),
641 ("Invalid element (> P) in commit",
642 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
643 None) ]
644 for (note, commit, confirm) in tests:
645 logger.info(note)
646 dev[0].scan_for_bss(bssid, freq=2412)
647 hapd.set("ext_mgmt_frame_handling", "1")
648 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
649 scan_freq="2412", wait_connect=False)
650
651 logger.info("Commit")
652 for i in range(0, 10):
653 req = hapd.mgmt_rx()
654 if req is None:
655 raise Exception("MGMT RX wait timed out (commit)")
656 if req['subtype'] == 11:
657 break
658 req = None
659 if not req:
660 raise Exception("Authentication frame (commit) not received")
661
662 hapd.dump_monitor()
663 resp = {}
664 resp['fc'] = req['fc']
665 resp['da'] = req['sa']
666 resp['sa'] = req['da']
667 resp['bssid'] = req['bssid']
668 resp['payload'] = binascii.unhexlify("030001000000" + commit)
669 hapd.mgmt_tx(resp)
670
671 if confirm:
672 logger.info("Confirm")
673 for i in range(0, 10):
674 req = hapd.mgmt_rx()
675 if req is None:
676 raise Exception("MGMT RX wait timed out (confirm)")
677 if req['subtype'] == 11:
678 break
679 req = None
680 if not req:
681 raise Exception("Authentication frame (confirm) not received")
682
683 hapd.dump_monitor()
684 resp = {}
685 resp['fc'] = req['fc']
686 resp['da'] = req['sa']
687 resp['sa'] = req['da']
688 resp['bssid'] = req['bssid']
689 resp['payload'] = binascii.unhexlify("030002000000" + confirm)
690 hapd.mgmt_tx(resp)
691
692 time.sleep(0.1)
693 dev[0].request("REMOVE_NETWORK all")
694 hapd.set("ext_mgmt_frame_handling", "0")
695 hapd.dump_monitor()
696
697 def test_sae_proto_confirm_replay(dev, apdev):
698 """SAE protocol testing - Confirm replay"""
699 if "SAE" not in dev[0].get_capability("auth_alg"):
700 raise HwsimSkip("SAE not supported")
701 params = hostapd.wpa2_params(ssid="test-sae",
702 passphrase="12345678")
703 params['wpa_key_mgmt'] = 'SAE'
704 hapd = hostapd.add_ap(apdev[0], params)
705 bssid = apdev[0]['bssid']
706
707 dev[0].request("SET sae_groups 19")
708
709 dev[0].scan_for_bss(bssid, freq=2412)
710 hapd.set("ext_mgmt_frame_handling", "1")
711 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
712 scan_freq="2412", wait_connect=False)
713
714 logger.info("Commit")
715 for i in range(0, 10):
716 req = hapd.mgmt_rx()
717 if req is None:
718 raise Exception("MGMT RX wait timed out (commit)")
719 if req['subtype'] == 11:
720 break
721 req = None
722 if not req:
723 raise Exception("Authentication frame (commit) not received")
724
725 bssid = hapd.own_addr().replace(':', '')
726 addr = dev[0].own_addr().replace(':', '')
727 hdr = "b0003a01" + bssid + addr + bssid + "1000"
728
729 hapd.dump_monitor()
730 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
731
732 logger.info("Confirm")
733 for i in range(0, 10):
734 req = hapd.mgmt_rx()
735 if req is None:
736 raise Exception("MGMT RX wait timed out (confirm)")
737 if req['subtype'] == 11:
738 break
739 req = None
740 if not req:
741 raise Exception("Authentication frame (confirm) not received")
742
743 hapd.dump_monitor()
744 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
745
746 logger.info("Replay Confirm")
747 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
748
749 logger.info("Association Request")
750 for i in range(0, 10):
751 req = hapd.mgmt_rx()
752 if req is None:
753 raise Exception("MGMT RX wait timed out (AssocReq)")
754 if req['subtype'] == 0:
755 break
756 req = None
757 if not req:
758 raise Exception("Association Request frame not received")
759
760 hapd.dump_monitor()
761 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode())
762 ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5)
763 if ev is None:
764 raise Exception("Management frame TX status not reported (1)")
765 if "stype=1 ok=1" not in ev:
766 raise Exception("Unexpected management frame TX status (1): " + ev)
767 cmd = "MGMT_TX_STATUS_PROCESS %s" % (" ".join(ev.split(' ')[1:4]))
768 if "OK" not in hapd.request(cmd):
769 raise Exception("MGMT_TX_STATUS_PROCESS failed")
770
771 hapd.set("ext_mgmt_frame_handling", "0")
772
773 dev[0].wait_connected()
774
775 def test_sae_proto_hostapd(dev, apdev):
776 """SAE protocol testing with hostapd"""
777 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
778 params['wpa_key_mgmt'] = 'SAE'
779 params['sae_groups'] = "19 65535"
780 hapd = hostapd.add_ap(apdev[0], params)
781 hapd.set("ext_mgmt_frame_handling", "1")
782 bssid = hapd.own_addr().replace(':', '')
783 addr = "020000000000"
784 addr2 = "020000000001"
785 hdr = "b0003a01" + bssid + addr + bssid + "1000"
786 hdr2 = "b0003a01" + bssid + addr2 + bssid + "1000"
787 group = "1300"
788 scalar = "f7df19f4a7fef1d3b895ea1de150b7c5a7a705c8ebb31a52b623e0057908bd93"
789 element_x = "21931572027f2e953e2a49fab3d992944102cc95aa19515fc068b394fb25ae3c"
790 element_y = "cb4eeb94d7b0b789abfdb73a67ab9d6d5efa94dd553e0e724a6289821cbce530"
791 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030001000000" + group + scalar + element_x + element_y)
792 # "SAE: Not enough data for scalar"
793 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030001000000" + group + scalar[:-2])
794 # "SAE: Do not allow group to be changed"
795 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030001000000" + "ffff" + scalar[:-2])
796 # "SAE: Unsupported Finite Cyclic Group 65535"
797 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr2 + "030001000000" + "ffff" + scalar[:-2])
798
799 @remote_compatible
800 def test_sae_no_ffc_by_default(dev, apdev):
801 """SAE and default groups rejecting FFC"""
802 if "SAE" not in dev[0].get_capability("auth_alg"):
803 raise HwsimSkip("SAE not supported")
804 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
805 params['wpa_key_mgmt'] = 'SAE'
806 hapd = hostapd.add_ap(apdev[0], params)
807
808 dev[0].request("SET sae_groups 5")
809 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412",
810 wait_connect=False)
811 ev = dev[0].wait_event(["SME: Trying to authenticate"], timeout=3)
812 if ev is None:
813 raise Exception("Did not try to authenticate")
814 ev = dev[0].wait_event(["SME: Trying to authenticate"], timeout=3)
815 if ev is None:
816 raise Exception("Did not try to authenticate (2)")
817 dev[0].request("REMOVE_NETWORK all")
818
819 def sae_reflection_attack(apdev, dev, group):
820 if "SAE" not in dev.get_capability("auth_alg"):
821 raise HwsimSkip("SAE not supported")
822 params = hostapd.wpa2_params(ssid="test-sae",
823 passphrase="no-knowledge-of-passphrase")
824 params['wpa_key_mgmt'] = 'SAE'
825 hapd = hostapd.add_ap(apdev, params)
826 bssid = apdev['bssid']
827
828 dev.scan_for_bss(bssid, freq=2412)
829 hapd.set("ext_mgmt_frame_handling", "1")
830
831 dev.request("SET sae_groups %d" % group)
832 dev.connect("test-sae", psk="reflection-attack", key_mgmt="SAE",
833 scan_freq="2412", wait_connect=False)
834
835 # Commit
836 for i in range(0, 10):
837 req = hapd.mgmt_rx()
838 if req is None:
839 raise Exception("MGMT RX wait timed out")
840 if req['subtype'] == 11:
841 break
842 req = None
843 if not req:
844 raise Exception("Authentication frame not received")
845
846 resp = {}
847 resp['fc'] = req['fc']
848 resp['da'] = req['sa']
849 resp['sa'] = req['da']
850 resp['bssid'] = req['bssid']
851 resp['payload'] = req['payload']
852 hapd.mgmt_tx(resp)
853
854 # Confirm
855 req = hapd.mgmt_rx(timeout=0.5)
856 if req is not None:
857 if req['subtype'] == 11:
858 raise Exception("Unexpected Authentication frame seen")
859
860 @remote_compatible
861 def test_sae_reflection_attack_ecc(dev, apdev):
862 """SAE reflection attack (ECC)"""
863 sae_reflection_attack(apdev[0], dev[0], 19)
864
865 @remote_compatible
866 def test_sae_reflection_attack_ffc(dev, apdev):
867 """SAE reflection attack (FFC)"""
868 sae_reflection_attack(apdev[0], dev[0], 5)
869
870 def sae_reflection_attack_internal(apdev, dev, group):
871 if "SAE" not in dev.get_capability("auth_alg"):
872 raise HwsimSkip("SAE not supported")
873 params = hostapd.wpa2_params(ssid="test-sae",
874 passphrase="no-knowledge-of-passphrase")
875 params['wpa_key_mgmt'] = 'SAE'
876 params['sae_reflection_attack'] = '1'
877 hapd = hostapd.add_ap(apdev, params)
878 bssid = apdev['bssid']
879
880 dev.scan_for_bss(bssid, freq=2412)
881 dev.request("SET sae_groups %d" % group)
882 dev.connect("test-sae", psk="reflection-attack", key_mgmt="SAE",
883 scan_freq="2412", wait_connect=False)
884 ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
885 if ev is not None:
886 raise Exception("Unexpected connection")
887
888 @remote_compatible
889 def test_sae_reflection_attack_ecc_internal(dev, apdev):
890 """SAE reflection attack (ECC) - internal"""
891 sae_reflection_attack_internal(apdev[0], dev[0], 19)
892
893 @remote_compatible
894 def test_sae_reflection_attack_ffc_internal(dev, apdev):
895 """SAE reflection attack (FFC) - internal"""
896 sae_reflection_attack_internal(apdev[0], dev[0], 5)
897
898 @remote_compatible
899 def test_sae_commit_override(dev, apdev):
900 """SAE commit override (hostapd)"""
901 if "SAE" not in dev[0].get_capability("auth_alg"):
902 raise HwsimSkip("SAE not supported")
903 params = hostapd.wpa2_params(ssid="test-sae",
904 passphrase="12345678")
905 params['wpa_key_mgmt'] = 'SAE'
906 params['sae_commit_override'] = '13ffbad00d215867a7c5ff37d87bb9bdb7cb116e520f71e8d7a794ca2606d537ddc6c099c40e7a25372b80a8fd443cd7dd222c8ea21b8ef372d4b3e316c26a73fd999cc79ad483eb826e7b3893ea332da68fa13224bcdeb4fb18b0584dd100a2c514'
907 hapd = hostapd.add_ap(apdev[0], params)
908 dev[0].request("SET sae_groups ")
909 dev[0].connect("test-sae", psk="test-sae", key_mgmt="SAE",
910 scan_freq="2412", wait_connect=False)
911 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
912 if ev is not None:
913 raise Exception("Unexpected connection")
914
915 @remote_compatible
916 def test_sae_commit_override2(dev, apdev):
917 """SAE commit override (wpa_supplicant)"""
918 if "SAE" not in dev[0].get_capability("auth_alg"):
919 raise HwsimSkip("SAE not supported")
920 params = hostapd.wpa2_params(ssid="test-sae",
921 passphrase="12345678")
922 params['wpa_key_mgmt'] = 'SAE'
923 hapd = hostapd.add_ap(apdev[0], params)
924 dev[0].request("SET sae_groups ")
925 dev[0].set('sae_commit_override', '13ffbad00d215867a7c5ff37d87bb9bdb7cb116e520f71e8d7a794ca2606d537ddc6c099c40e7a25372b80a8fd443cd7dd222c8ea21b8ef372d4b3e316c26a73fd999cc79ad483eb826e7b3893ea332da68fa13224bcdeb4fb18b0584dd100a2c514')
926 dev[0].connect("test-sae", psk="test-sae", key_mgmt="SAE",
927 scan_freq="2412", wait_connect=False)
928 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
929 if ev is not None:
930 raise Exception("Unexpected connection")
931
932 @remote_compatible
933 def test_sae_anti_clogging_proto(dev, apdev):
934 """SAE anti clogging protocol testing"""
935 if "SAE" not in dev[0].get_capability("auth_alg"):
936 raise HwsimSkip("SAE not supported")
937 params = hostapd.wpa2_params(ssid="test-sae",
938 passphrase="no-knowledge-of-passphrase")
939 params['wpa_key_mgmt'] = 'SAE'
940 hapd = hostapd.add_ap(apdev[0], params)
941 bssid = apdev[0]['bssid']
942
943 dev[0].scan_for_bss(bssid, freq=2412)
944 hapd.set("ext_mgmt_frame_handling", "1")
945
946 dev[0].request("SET sae_groups ")
947 dev[0].connect("test-sae", psk="anti-cloggign", key_mgmt="SAE",
948 scan_freq="2412", wait_connect=False)
949
950 # Commit
951 for i in range(0, 10):
952 req = hapd.mgmt_rx()
953 if req is None:
954 raise Exception("MGMT RX wait timed out")
955 if req['subtype'] == 11:
956 break
957 req = None
958 if not req:
959 raise Exception("Authentication frame not received")
960
961 resp = {}
962 resp['fc'] = req['fc']
963 resp['da'] = req['sa']
964 resp['sa'] = req['da']
965 resp['bssid'] = req['bssid']
966 resp['payload'] = binascii.unhexlify("030001004c00" + "ffff00")
967 hapd.mgmt_tx(resp)
968
969 # Confirm (not received due to DH group being rejected)
970 req = hapd.mgmt_rx(timeout=0.5)
971 if req is not None:
972 if req['subtype'] == 11:
973 raise Exception("Unexpected Authentication frame seen")
974
975 @remote_compatible
976 def test_sae_no_random(dev, apdev):
977 """SAE and no random numbers available"""
978 if "SAE" not in dev[0].get_capability("auth_alg"):
979 raise HwsimSkip("SAE not supported")
980 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
981 params['wpa_key_mgmt'] = 'SAE'
982 hapd = hostapd.add_ap(apdev[0], params)
983
984 dev[0].request("SET sae_groups ")
985 tests = [ (1, "os_get_random;sae_get_rand"),
986 (1, "os_get_random;get_rand_1_to_p_1"),
987 (1, "os_get_random;get_random_qr_qnr"),
988 (1, "os_get_random;sae_derive_pwe_ecc") ]
989 for count, func in tests:
990 with fail_test(dev[0], count, func):
991 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
992 scan_freq="2412")
993 dev[0].request("REMOVE_NETWORK all")
994 dev[0].wait_disconnected()
995
996 @remote_compatible
997 def test_sae_pwe_failure(dev, apdev):
998 """SAE and pwe failure"""
999 if "SAE" not in dev[0].get_capability("auth_alg"):
1000 raise HwsimSkip("SAE not supported")
1001 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
1002 params['wpa_key_mgmt'] = 'SAE'
1003 params['sae_groups'] = '19 5'
1004 hapd = hostapd.add_ap(apdev[0], params)
1005
1006 dev[0].request("SET sae_groups 19")
1007 with fail_test(dev[0], 1, "hmac_sha256_vector;sae_derive_pwe_ecc"):
1008 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
1009 scan_freq="2412")
1010 dev[0].request("REMOVE_NETWORK all")
1011 dev[0].wait_disconnected()
1012 with fail_test(dev[0], 1, "sae_test_pwd_seed_ecc"):
1013 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
1014 scan_freq="2412")
1015 dev[0].request("REMOVE_NETWORK all")
1016 dev[0].wait_disconnected()
1017
1018 dev[0].request("SET sae_groups 5")
1019 with fail_test(dev[0], 1, "hmac_sha256_vector;sae_derive_pwe_ffc"):
1020 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
1021 scan_freq="2412")
1022 dev[0].request("REMOVE_NETWORK all")
1023 dev[0].wait_disconnected()
1024
1025 dev[0].request("SET sae_groups 5")
1026 with fail_test(dev[0], 1, "sae_test_pwd_seed_ffc"):
1027 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
1028 scan_freq="2412")
1029 dev[0].request("REMOVE_NETWORK all")
1030 dev[0].wait_disconnected()
1031 with fail_test(dev[0], 2, "sae_test_pwd_seed_ffc"):
1032 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
1033 scan_freq="2412")
1034 dev[0].request("REMOVE_NETWORK all")
1035 dev[0].wait_disconnected()
1036
1037 @remote_compatible
1038 def test_sae_bignum_failure(dev, apdev):
1039 """SAE and bignum failure"""
1040 if "SAE" not in dev[0].get_capability("auth_alg"):
1041 raise HwsimSkip("SAE not supported")
1042 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
1043 params['wpa_key_mgmt'] = 'SAE'
1044 params['sae_groups'] = '19 5 22'
1045 hapd = hostapd.add_ap(apdev[0], params)
1046
1047 dev[0].request("SET sae_groups 19")
1048 tests = [ (1, "crypto_bignum_init_set;get_rand_1_to_p_1"),
1049 (1, "crypto_bignum_init;is_quadratic_residue_blind"),
1050 (1, "crypto_bignum_mulmod;is_quadratic_residue_blind"),
1051 (2, "crypto_bignum_mulmod;is_quadratic_residue_blind"),
1052 (3, "crypto_bignum_mulmod;is_quadratic_residue_blind"),
1053 (1, "crypto_bignum_legendre;is_quadratic_residue_blind"),
1054 (1, "crypto_bignum_init_set;sae_test_pwd_seed_ecc"),
1055 (1, "crypto_ec_point_compute_y_sqr;sae_test_pwd_seed_ecc"),
1056 (1, "crypto_bignum_init_set;get_random_qr_qnr"),
1057 (1, "crypto_bignum_to_bin;sae_derive_pwe_ecc"),
1058 (1, "crypto_ec_point_init;sae_derive_pwe_ecc"),
1059 (1, "crypto_ec_point_solve_y_coord;sae_derive_pwe_ecc"),
1060 (1, "crypto_ec_point_init;sae_derive_commit_element_ecc"),
1061 (1, "crypto_ec_point_mul;sae_derive_commit_element_ecc"),
1062 (1, "crypto_ec_point_invert;sae_derive_commit_element_ecc"),
1063 (1, "crypto_bignum_init;=sae_derive_commit"),
1064 (1, "crypto_ec_point_init;sae_derive_k_ecc"),
1065 (1, "crypto_ec_point_mul;sae_derive_k_ecc"),
1066 (1, "crypto_ec_point_add;sae_derive_k_ecc"),
1067 (2, "crypto_ec_point_mul;sae_derive_k_ecc"),
1068 (1, "crypto_ec_point_to_bin;sae_derive_k_ecc"),
1069 (1, "crypto_bignum_legendre;get_random_qr_qnr"),
1070 (1, "sha256_prf;sae_derive_keys"),
1071 (1, "crypto_bignum_init;sae_derive_keys"),
1072 (1, "crypto_bignum_init_set;sae_parse_commit_scalar"),
1073 (1, "crypto_bignum_to_bin;sae_parse_commit_element_ecc"),
1074 (1, "crypto_ec_point_from_bin;sae_parse_commit_element_ecc") ]
1075 for count, func in tests:
1076 with fail_test(dev[0], count, func):
1077 hapd.request("NOTE STA failure testing %d:%s" % (count, func))
1078 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
1079 scan_freq="2412", wait_connect=False)
1080 wait_fail_trigger(dev[0], "GET_FAIL")
1081 dev[0].request("REMOVE_NETWORK all")
1082 dev[0].dump_monitor()
1083 hapd.dump_monitor()
1084
1085 dev[0].request("SET sae_groups 5")
1086 tests = [ (1, "crypto_bignum_init_set;sae_set_group"),
1087 (2, "crypto_bignum_init_set;sae_set_group"),
1088 (1, "crypto_bignum_init_set;sae_get_rand"),
1089 (1, "crypto_bignum_init_set;sae_test_pwd_seed_ffc"),
1090 (1, "crypto_bignum_exptmod;sae_test_pwd_seed_ffc"),
1091 (1, "crypto_bignum_init;sae_derive_pwe_ffc"),
1092 (1, "crypto_bignum_init;sae_derive_commit_element_ffc"),
1093 (1, "crypto_bignum_exptmod;sae_derive_commit_element_ffc"),
1094 (1, "crypto_bignum_inverse;sae_derive_commit_element_ffc"),
1095 (1, "crypto_bignum_init;sae_derive_k_ffc"),
1096 (1, "crypto_bignum_exptmod;sae_derive_k_ffc"),
1097 (1, "crypto_bignum_mulmod;sae_derive_k_ffc"),
1098 (2, "crypto_bignum_exptmod;sae_derive_k_ffc"),
1099 (1, "crypto_bignum_to_bin;sae_derive_k_ffc"),
1100 (1, "crypto_bignum_init_set;sae_parse_commit_element_ffc"),
1101 (1, "crypto_bignum_init;sae_parse_commit_element_ffc"),
1102 (2, "crypto_bignum_init_set;sae_parse_commit_element_ffc"),
1103 (1, "crypto_bignum_exptmod;sae_parse_commit_element_ffc") ]
1104 for count, func in tests:
1105 with fail_test(dev[0], count, func):
1106 hapd.request("NOTE STA failure testing %d:%s" % (count, func))
1107 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
1108 scan_freq="2412", wait_connect=False)
1109 wait_fail_trigger(dev[0], "GET_FAIL")
1110 dev[0].request("REMOVE_NETWORK all")
1111 dev[0].dump_monitor()
1112 hapd.dump_monitor()
1113
1114 dev[0].request("SET sae_groups 22")
1115 tests = [ (1, "crypto_bignum_init_set;sae_test_pwd_seed_ffc"),
1116 (1, "crypto_bignum_sub;sae_test_pwd_seed_ffc"),
1117 (1, "crypto_bignum_div;sae_test_pwd_seed_ffc") ]
1118 for count, func in tests:
1119 with fail_test(dev[0], count, func):
1120 hapd.request("NOTE STA failure testing %d:%s" % (count, func))
1121 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
1122 scan_freq="2412", wait_connect=False)
1123 wait_fail_trigger(dev[0], "GET_FAIL")
1124 dev[0].request("REMOVE_NETWORK all")
1125 dev[0].dump_monitor()
1126 hapd.dump_monitor()
1127
1128 def test_sae_invalid_anti_clogging_token_req(dev, apdev):
1129 """SAE and invalid anti-clogging token request"""
1130 if "SAE" not in dev[0].get_capability("auth_alg"):
1131 raise HwsimSkip("SAE not supported")
1132 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
1133 params['wpa_key_mgmt'] = 'SAE'
1134 # Beacon more frequently since Probe Request frames are practically ignored
1135 # in this test setup (ext_mgmt_frame_handled=1 on hostapd side) and
1136 # wpa_supplicant scans may end up getting ignored if no new results are
1137 # available due to the missing Probe Response frames.
1138 params['beacon_int'] = '20'
1139 hapd = hostapd.add_ap(apdev[0], params)
1140 bssid = apdev[0]['bssid']
1141
1142 dev[0].request("SET sae_groups 19")
1143 dev[0].scan_for_bss(bssid, freq=2412)
1144 hapd.set("ext_mgmt_frame_handling", "1")
1145 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
1146 scan_freq="2412", wait_connect=False)
1147 ev = dev[0].wait_event(["SME: Trying to authenticate"])
1148 if ev is None:
1149 raise Exception("No authentication attempt seen (1)")
1150 dev[0].dump_monitor()
1151
1152 for i in range(0, 10):
1153 req = hapd.mgmt_rx()
1154 if req is None:
1155 raise Exception("MGMT RX wait timed out (commit)")
1156 if req['subtype'] == 11:
1157 break
1158 req = None
1159 if not req:
1160 raise Exception("Authentication frame (commit) not received")
1161
1162 hapd.dump_monitor()
1163 resp = {}
1164 resp['fc'] = req['fc']
1165 resp['da'] = req['sa']
1166 resp['sa'] = req['da']
1167 resp['bssid'] = req['bssid']
1168 resp['payload'] = binascii.unhexlify("030001004c0013")
1169 hapd.mgmt_tx(resp)
1170 ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5)
1171 if ev is None:
1172 raise Exception("Management frame TX status not reported (1)")
1173 if "stype=11 ok=1" not in ev:
1174 raise Exception("Unexpected management frame TX status (1): " + ev)
1175
1176 ev = dev[0].wait_event(["SME: Trying to authenticate"])
1177 if ev is None:
1178 raise Exception("No authentication attempt seen (2)")
1179 dev[0].dump_monitor()
1180
1181 for i in range(0, 10):
1182 req = hapd.mgmt_rx()
1183 if req is None:
1184 raise Exception("MGMT RX wait timed out (commit) (2)")
1185 if req['subtype'] == 11:
1186 break
1187 req = None
1188 if not req:
1189 raise Exception("Authentication frame (commit) not received (2)")
1190
1191 hapd.dump_monitor()
1192 resp = {}
1193 resp['fc'] = req['fc']
1194 resp['da'] = req['sa']
1195 resp['sa'] = req['da']
1196 resp['bssid'] = req['bssid']
1197 resp['payload'] = binascii.unhexlify("030001000100")
1198 hapd.mgmt_tx(resp)
1199 ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5)
1200 if ev is None:
1201 raise Exception("Management frame TX status not reported (1)")
1202 if "stype=11 ok=1" not in ev:
1203 raise Exception("Unexpected management frame TX status (1): " + ev)
1204
1205 ev = dev[0].wait_event(["SME: Trying to authenticate"])
1206 if ev is None:
1207 raise Exception("No authentication attempt seen (3)")
1208 dev[0].dump_monitor()
1209
1210 dev[0].request("DISCONNECT")
1211
1212 def test_sae_password(dev, apdev):
1213 """SAE and sae_password in hostapd configuration"""
1214 if "SAE" not in dev[0].get_capability("auth_alg"):
1215 raise HwsimSkip("SAE not supported")
1216 params = hostapd.wpa2_params(ssid="test-sae",
1217 passphrase="12345678")
1218 params['wpa_key_mgmt'] = 'SAE WPA-PSK'
1219 params['sae_password'] = "sae-password"
1220 hapd = hostapd.add_ap(apdev[0], params)
1221
1222 dev[0].request("SET sae_groups ")
1223 dev[0].connect("test-sae", psk="sae-password", key_mgmt="SAE",
1224 scan_freq="2412")
1225 dev[1].connect("test-sae", psk="12345678", scan_freq="2412")
1226 dev[2].request("SET sae_groups ")
1227 dev[2].connect("test-sae", sae_password="sae-password", key_mgmt="SAE",
1228 scan_freq="2412")
1229
1230 def test_sae_password_short(dev, apdev):
1231 """SAE and short password"""
1232 if "SAE" not in dev[0].get_capability("auth_alg"):
1233 raise HwsimSkip("SAE not supported")
1234 params = hostapd.wpa2_params(ssid="test-sae")
1235 params['wpa_key_mgmt'] = 'SAE'
1236 params['sae_password'] = "secret"
1237 hapd = hostapd.add_ap(apdev[0], params)
1238
1239 dev[0].request("SET sae_groups ")
1240 dev[0].connect("test-sae", sae_password="secret", key_mgmt="SAE",
1241 scan_freq="2412")
1242
1243 def test_sae_password_long(dev, apdev):
1244 """SAE and long password"""
1245 if "SAE" not in dev[0].get_capability("auth_alg"):
1246 raise HwsimSkip("SAE not supported")
1247 params = hostapd.wpa2_params(ssid="test-sae")
1248 params['wpa_key_mgmt'] = 'SAE'
1249 params['sae_password'] = 100*"A"
1250 hapd = hostapd.add_ap(apdev[0], params)
1251
1252 dev[0].request("SET sae_groups ")
1253 dev[0].connect("test-sae", sae_password=100*"A", key_mgmt="SAE",
1254 scan_freq="2412")
1255
1256 def test_sae_connect_cmd(dev, apdev):
1257 """SAE with connect command"""
1258 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
1259 wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
1260 if "SAE" not in wpas.get_capability("auth_alg"):
1261 raise HwsimSkip("SAE not supported")
1262 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
1263 params['wpa_key_mgmt'] = 'SAE'
1264 hapd = hostapd.add_ap(apdev[0], params)
1265
1266 wpas.request("SET sae_groups ")
1267 wpas.connect("test-sae", psk="12345678", key_mgmt="SAE",
1268 scan_freq="2412", wait_connect=False)
1269 # mac80211_hwsim does not support SAE offload, so accept both a successful
1270 # connection and association rejection.
1271 ev = wpas.wait_event(["CTRL-EVENT-CONNECTED", "CTRL-EVENT-ASSOC-REJECT",
1272 "Association request to the driver failed"],
1273 timeout=15)
1274 if ev is None:
1275 raise Exception("No connection result reported")
1276
1277 def run_sae_password_id(dev, apdev, groups=None):
1278 if "SAE" not in dev[0].get_capability("auth_alg"):
1279 raise HwsimSkip("SAE not supported")
1280 params = hostapd.wpa2_params(ssid="test-sae")
1281 params['wpa_key_mgmt'] = 'SAE'
1282 if groups:
1283 params['sae_groups'] = groups
1284 else:
1285 groups = ""
1286 params['sae_password'] = [ 'secret|mac=ff:ff:ff:ff:ff:ff|id=pw id',
1287 'foo|mac=02:02:02:02:02:02',
1288 'another secret|mac=ff:ff:ff:ff:ff:ff|id=' + 29*'A' ]
1289 hapd = hostapd.add_ap(apdev[0], params)
1290
1291 dev[0].request("SET sae_groups " + groups)
1292 dev[0].connect("test-sae", sae_password="secret", sae_password_id="pw id",
1293 key_mgmt="SAE", scan_freq="2412")
1294 dev[0].request("REMOVE_NETWORK all")
1295 dev[0].wait_disconnected()
1296
1297 # SAE Password Identifier element with the exact same length as the
1298 # optional Anti-Clogging Token field
1299 dev[0].connect("test-sae", sae_password="another secret",
1300 sae_password_id=29*'A',
1301 key_mgmt="SAE", scan_freq="2412")
1302 dev[0].request("REMOVE_NETWORK all")
1303 dev[0].wait_disconnected()
1304
1305 dev[0].connect("test-sae", sae_password="secret", sae_password_id="unknown",
1306 key_mgmt="SAE", scan_freq="2412", wait_connect=False)
1307
1308 ev = dev[0].wait_event(["CTRL-EVENT-SAE-UNKNOWN-PASSWORD-IDENTIFIER"],
1309 timeout=10)
1310 if ev is None:
1311 raise Exception("Unknown password identifier not reported")
1312 dev[0].request("REMOVE_NETWORK all")
1313
1314 def test_sae_password_id(dev, apdev):
1315 """SAE and password identifier"""
1316 run_sae_password_id(dev, apdev, "")
1317
1318 def test_sae_password_id_ecc(dev, apdev):
1319 """SAE and password identifier (ECC)"""
1320 run_sae_password_id(dev, apdev, "19")
1321
1322 def test_sae_password_id_ffc(dev, apdev):
1323 """SAE and password identifier (FFC)"""
1324 run_sae_password_id(dev, apdev, "22")
1325
1326 def test_sae_password_id_only(dev, apdev):
1327 """SAE and password identifier (exclusively)"""
1328 if "SAE" not in dev[0].get_capability("auth_alg"):
1329 raise HwsimSkip("SAE not supported")
1330 params = hostapd.wpa2_params(ssid="test-sae")
1331 params['wpa_key_mgmt'] = 'SAE'
1332 params['sae_password'] = 'secret|id=pw id'
1333 hapd = hostapd.add_ap(apdev[0], params)
1334
1335 dev[0].request("SET sae_groups ")
1336 dev[0].connect("test-sae", sae_password="secret", sae_password_id="pw id",
1337 key_mgmt="SAE", scan_freq="2412")
1338
1339 def test_sae_forced_anti_clogging_pw_id(dev, apdev):
1340 """SAE anti clogging (forced and Password Identifier)"""
1341 if "SAE" not in dev[0].get_capability("auth_alg"):
1342 raise HwsimSkip("SAE not supported")
1343 params = hostapd.wpa2_params(ssid="test-sae")
1344 params['wpa_key_mgmt'] = 'SAE'
1345 params['sae_anti_clogging_threshold'] = '0'
1346 params['sae_password'] = 'secret|id=' + 29*'A'
1347 hostapd.add_ap(apdev[0], params)
1348 for i in range(0, 2):
1349 dev[i].request("SET sae_groups ")
1350 dev[i].connect("test-sae", sae_password="secret",
1351 sae_password_id=29*'A', key_mgmt="SAE", scan_freq="2412")
1352
1353 def test_sae_reauth(dev, apdev):
1354 """SAE reauthentication"""
1355 if "SAE" not in dev[0].get_capability("auth_alg"):
1356 raise HwsimSkip("SAE not supported")
1357 params = hostapd.wpa2_params(ssid="test-sae",
1358 passphrase="12345678")
1359 params['wpa_key_mgmt'] = 'SAE'
1360 params["ieee80211w"] = "2"
1361 hapd = hostapd.add_ap(apdev[0], params)
1362
1363 dev[0].request("SET sae_groups ")
1364 id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
1365 ieee80211w="2", scan_freq="2412")
1366
1367 hapd.set("ext_mgmt_frame_handling", "1")
1368 dev[0].request("DISCONNECT")
1369 dev[0].wait_disconnected(timeout=10)
1370 hapd.set("ext_mgmt_frame_handling", "0")
1371 dev[0].request("PMKSA_FLUSH")
1372 dev[0].request("REASSOCIATE")
1373 dev[0].wait_connected(timeout=10, error="Timeout on re-connection")