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