2 # Copyright (c) 2013-2016, Jouni Malinen <j@w1.fi>
4 # This software may be distributed under the terms of the BSD license.
5 # See README for more details.
7 from remotehost import remote_compatible
12 logger = logging.getLogger()
16 from utils import HwsimSkip, alloc_fail, fail_test, wait_fail_trigger
17 from test_ap_psk import find_wpas_process, read_process_memory, verify_not_present, get_key_locations
20 def test_sae(dev, apdev):
21 """SAE with default group"""
22 if "SAE" not in dev[0].get_capability("auth_alg"):
23 raise HwsimSkip("SAE not supported")
24 params = hostapd.wpa2_params(ssid="test-sae",
25 passphrase="12345678")
26 params['wpa_key_mgmt'] = 'SAE'
27 hapd = hostapd.add_ap(apdev[0], params)
28 key_mgmt = hapd.get_config()['key_mgmt']
29 if key_mgmt.split(' ')[0] != "SAE":
30 raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
32 dev[0].request("SET sae_groups ")
33 id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
35 if dev[0].get_status_field('sae_group') != '19':
36 raise Exception("Expected default SAE group not used")
37 bss = dev[0].get_bss(apdev[0]['bssid'])
38 if 'flags' not in bss:
39 raise Exception("Could not get BSS flags from BSS table")
40 if "[WPA2-SAE-CCMP]" not in bss['flags']:
41 raise Exception("Unexpected BSS flags: " + bss['flags'])
44 def test_sae_password_ecc(dev, apdev):
45 """SAE with number of different passwords (ECC)"""
46 if "SAE" not in dev[0].get_capability("auth_alg"):
47 raise HwsimSkip("SAE not supported")
48 params = hostapd.wpa2_params(ssid="test-sae",
49 passphrase="12345678")
50 params['wpa_key_mgmt'] = 'SAE'
51 hapd = hostapd.add_ap(apdev[0], params)
53 dev[0].request("SET sae_groups 19")
56 password = "12345678-" + str(i)
57 hapd.set("wpa_passphrase", password)
58 dev[0].connect("test-sae", psk=password, key_mgmt="SAE",
60 dev[0].request("REMOVE_NETWORK all")
61 dev[0].wait_disconnected()
64 def test_sae_password_ffc(dev, apdev):
65 """SAE with number of different passwords (FFC)"""
66 if "SAE" not in dev[0].get_capability("auth_alg"):
67 raise HwsimSkip("SAE not supported")
68 params = hostapd.wpa2_params(ssid="test-sae",
69 passphrase="12345678")
70 params['wpa_key_mgmt'] = 'SAE'
71 params['sae_groups'] = '22'
72 hapd = hostapd.add_ap(apdev[0], params)
74 dev[0].request("SET sae_groups 22")
77 password = "12345678-" + str(i)
78 hapd.set("wpa_passphrase", password)
79 dev[0].connect("test-sae", psk=password, key_mgmt="SAE",
81 dev[0].request("REMOVE_NETWORK all")
82 dev[0].wait_disconnected()
85 def test_sae_pmksa_caching(dev, apdev):
86 """SAE and PMKSA caching"""
87 if "SAE" not in dev[0].get_capability("auth_alg"):
88 raise HwsimSkip("SAE not supported")
89 params = hostapd.wpa2_params(ssid="test-sae",
90 passphrase="12345678")
91 params['wpa_key_mgmt'] = 'SAE'
92 hapd = hostapd.add_ap(apdev[0], params)
94 dev[0].request("SET sae_groups ")
95 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
97 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
99 raise Exception("No connection event received from hostapd")
100 dev[0].request("DISCONNECT")
101 dev[0].wait_disconnected()
102 dev[0].request("RECONNECT")
103 dev[0].wait_connected(timeout=15, error="Reconnect timed out")
104 if dev[0].get_status_field('sae_group') is not None:
105 raise Exception("SAE group claimed to have been used")
108 def test_sae_pmksa_caching_disabled(dev, apdev):
109 """SAE and PMKSA caching disabled"""
110 if "SAE" not in dev[0].get_capability("auth_alg"):
111 raise HwsimSkip("SAE not supported")
112 params = hostapd.wpa2_params(ssid="test-sae",
113 passphrase="12345678")
114 params['wpa_key_mgmt'] = 'SAE'
115 params['disable_pmksa_caching'] = '1'
116 hapd = hostapd.add_ap(apdev[0], params)
118 dev[0].request("SET sae_groups ")
119 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
121 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
123 raise Exception("No connection event received from hostapd")
124 dev[0].request("DISCONNECT")
125 dev[0].wait_disconnected()
126 dev[0].request("RECONNECT")
127 dev[0].wait_connected(timeout=15, error="Reconnect timed out")
128 if dev[0].get_status_field('sae_group') != '19':
129 raise Exception("Expected default SAE group not used")
131 def test_sae_groups(dev, apdev):
132 """SAE with all supported groups"""
133 if "SAE" not in dev[0].get_capability("auth_alg"):
134 raise HwsimSkip("SAE not supported")
135 # This is the full list of supported groups, but groups 14-16 (2048-4096 bit
136 # MODP) and group 21 (521-bit random ECP group) are a bit too slow on some
137 # VMs and can result in hitting the mac80211 authentication timeout, so
138 # allow them to fail and just report such failures in the debug log.
139 sae_groups = [ 19, 25, 26, 20, 21, 2, 5, 14, 15, 16, 22, 23, 24 ]
140 tls = dev[0].request("GET tls_library")
141 if tls.startswith("OpenSSL") and "build=OpenSSL 1.0.2" in tls and "run=OpenSSL 1.0.2" in tls:
142 logger.info("Add Brainpool EC groups since OpenSSL is new enough")
143 sae_groups += [ 27, 28, 29, 30 ]
144 heavy_groups = [ 14, 15, 16 ]
145 groups = [str(g) for g in sae_groups]
146 params = hostapd.wpa2_params(ssid="test-sae-groups",
147 passphrase="12345678")
148 params['wpa_key_mgmt'] = 'SAE'
149 params['sae_groups'] = ' '.join(groups)
150 hostapd.add_ap(apdev[0], params)
153 logger.info("Testing SAE group " + g)
154 dev[0].request("SET sae_groups " + g)
155 id = dev[0].connect("test-sae-groups", psk="12345678", key_mgmt="SAE",
156 scan_freq="2412", wait_connect=False)
157 if int(g) in heavy_groups:
158 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=5)
160 logger.info("No connection with heavy SAE group %s did not connect - likely hitting timeout in mac80211" % g)
161 dev[0].remove_network(id)
163 dev[0].dump_monitor()
165 logger.info("Connection with heavy SAE group " + g)
167 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
169 if "BoringSSL" in tls and int(g) in [ 25 ]:
170 logger.info("Ignore connection failure with group " + g + " with BoringSSL")
171 dev[0].remove_network(id)
172 dev[0].dump_monitor()
174 raise Exception("Connection timed out with group " + g)
175 if dev[0].get_status_field('sae_group') != g:
176 raise Exception("Expected SAE group not used")
177 dev[0].remove_network(id)
178 dev[0].wait_disconnected()
179 dev[0].dump_monitor()
182 def test_sae_group_nego(dev, apdev):
183 """SAE group negotiation"""
184 if "SAE" not in dev[0].get_capability("auth_alg"):
185 raise HwsimSkip("SAE not supported")
186 params = hostapd.wpa2_params(ssid="test-sae-group-nego",
187 passphrase="12345678")
188 params['wpa_key_mgmt'] = 'SAE'
189 params['sae_groups'] = '19'
190 hostapd.add_ap(apdev[0], params)
192 dev[0].request("SET sae_groups 25 26 20 19")
193 dev[0].connect("test-sae-group-nego", psk="12345678", key_mgmt="SAE",
195 if dev[0].get_status_field('sae_group') != '19':
196 raise Exception("Expected SAE group not used")
199 def test_sae_anti_clogging(dev, apdev):
200 """SAE anti clogging"""
201 if "SAE" not in dev[0].get_capability("auth_alg"):
202 raise HwsimSkip("SAE not supported")
203 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
204 params['wpa_key_mgmt'] = 'SAE'
205 params['sae_anti_clogging_threshold'] = '1'
206 hostapd.add_ap(apdev[0], params)
208 dev[0].request("SET sae_groups ")
209 dev[1].request("SET sae_groups ")
211 for i in range(0, 2):
212 dev[i].scan(freq="2412")
213 id[i] = dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE",
214 scan_freq="2412", only_add_network=True)
215 for i in range(0, 2):
216 dev[i].select_network(id[i])
217 for i in range(0, 2):
218 dev[i].wait_connected(timeout=10)
220 def test_sae_forced_anti_clogging(dev, apdev):
221 """SAE anti clogging (forced)"""
222 if "SAE" not in dev[0].get_capability("auth_alg"):
223 raise HwsimSkip("SAE not supported")
224 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
225 params['wpa_key_mgmt'] = 'SAE WPA-PSK'
226 params['sae_anti_clogging_threshold'] = '0'
227 hostapd.add_ap(apdev[0], params)
228 dev[2].connect("test-sae", psk="12345678", scan_freq="2412")
229 for i in range(0, 2):
230 dev[i].request("SET sae_groups ")
231 dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE",
234 def test_sae_mixed(dev, apdev):
235 """Mixed SAE and non-SAE network"""
236 if "SAE" not in dev[0].get_capability("auth_alg"):
237 raise HwsimSkip("SAE not supported")
238 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
239 params['wpa_key_mgmt'] = 'SAE WPA-PSK'
240 params['sae_anti_clogging_threshold'] = '0'
241 hostapd.add_ap(apdev[0], params)
243 dev[2].connect("test-sae", psk="12345678", scan_freq="2412")
244 for i in range(0, 2):
245 dev[i].request("SET sae_groups ")
246 dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE",
250 def test_sae_missing_password(dev, apdev):
251 """SAE and missing password"""
252 if "SAE" not in dev[0].get_capability("auth_alg"):
253 raise HwsimSkip("SAE not supported")
254 params = hostapd.wpa2_params(ssid="test-sae",
255 passphrase="12345678")
256 params['wpa_key_mgmt'] = 'SAE'
257 hapd = hostapd.add_ap(apdev[0], params)
259 dev[0].request("SET sae_groups ")
260 id = dev[0].connect("test-sae",
261 raw_psk="46b4a73b8a951ad53ebd2e0afdb9c5483257edd4c21d12b7710759da70945858",
262 key_mgmt="SAE", scan_freq="2412", wait_connect=False)
263 ev = dev[0].wait_event(['CTRL-EVENT-SSID-TEMP-DISABLED'], timeout=10)
265 raise Exception("Invalid network not temporarily disabled")
268 def test_sae_key_lifetime_in_memory(dev, apdev, params):
269 """SAE and key lifetime in memory"""
270 if "SAE" not in dev[0].get_capability("auth_alg"):
271 raise HwsimSkip("SAE not supported")
272 password = "5ad144a7c1f5a5503baa6fa01dabc15b1843e8c01662d78d16b70b5cd23cf8b"
273 p = hostapd.wpa2_params(ssid="test-sae", passphrase=password)
274 p['wpa_key_mgmt'] = 'SAE'
275 hapd = hostapd.add_ap(apdev[0], p)
277 pid = find_wpas_process(dev[0])
279 dev[0].request("SET sae_groups ")
280 id = dev[0].connect("test-sae", psk=password, key_mgmt="SAE",
283 # The decrypted copy of GTK is freed only after the CTRL-EVENT-CONNECTED
284 # event has been delivered, so verify that wpa_supplicant has returned to
285 # eloop before reading process memory.
288 buf = read_process_memory(pid, password)
290 dev[0].request("DISCONNECT")
291 dev[0].wait_disconnected()
300 with open(os.path.join(params['logdir'], 'log0'), 'r') as f:
301 for l in f.readlines():
302 if "SAE: k - hexdump" in l:
303 val = l.strip().split(':')[3].replace(' ', '')
304 sae_k = binascii.unhexlify(val)
305 if "SAE: keyseed - hexdump" in l:
306 val = l.strip().split(':')[3].replace(' ', '')
307 sae_keyseed = binascii.unhexlify(val)
308 if "SAE: KCK - hexdump" in l:
309 val = l.strip().split(':')[3].replace(' ', '')
310 sae_kck = binascii.unhexlify(val)
311 if "SAE: PMK - hexdump" in l:
312 val = l.strip().split(':')[3].replace(' ', '')
313 pmk = binascii.unhexlify(val)
314 if "WPA: PTK - hexdump" in l:
315 val = l.strip().split(':')[3].replace(' ', '')
316 ptk = binascii.unhexlify(val)
317 if "WPA: Group Key - hexdump" in l:
318 val = l.strip().split(':')[3].replace(' ', '')
319 gtk = binascii.unhexlify(val)
320 if not sae_k or not sae_keyseed or not sae_kck or not pmk or not ptk or not gtk:
321 raise Exception("Could not find keys from debug log")
323 raise Exception("Unexpected GTK length")
329 fname = os.path.join(params['logdir'],
330 'sae_key_lifetime_in_memory.memctx-')
332 logger.info("Checking keys in memory while associated")
333 get_key_locations(buf, password, "Password")
334 get_key_locations(buf, pmk, "PMK")
335 if password not in buf:
336 raise HwsimSkip("Password not found while associated")
338 raise HwsimSkip("PMK not found while associated")
340 raise Exception("KCK not found while associated")
342 raise Exception("KEK not found while associated")
344 raise Exception("TK found from memory")
346 get_key_locations(buf, gtk, "GTK")
347 raise Exception("GTK found from memory")
348 verify_not_present(buf, sae_k, fname, "SAE(k)")
349 verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)")
350 verify_not_present(buf, sae_kck, fname, "SAE(KCK)")
352 logger.info("Checking keys in memory after disassociation")
353 buf = read_process_memory(pid, password)
355 # Note: Password is still present in network configuration
356 # Note: PMK is in PMKSA cache
358 get_key_locations(buf, password, "Password")
359 get_key_locations(buf, pmk, "PMK")
360 verify_not_present(buf, kck, fname, "KCK")
361 verify_not_present(buf, kek, fname, "KEK")
362 verify_not_present(buf, tk, fname, "TK")
363 verify_not_present(buf, gtk, fname, "GTK")
364 verify_not_present(buf, sae_k, fname, "SAE(k)")
365 verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)")
366 verify_not_present(buf, sae_kck, fname, "SAE(KCK)")
368 dev[0].request("PMKSA_FLUSH")
369 logger.info("Checking keys in memory after PMKSA cache flush")
370 buf = read_process_memory(pid, password)
371 get_key_locations(buf, password, "Password")
372 get_key_locations(buf, pmk, "PMK")
373 verify_not_present(buf, pmk, fname, "PMK")
375 dev[0].request("REMOVE_NETWORK all")
377 logger.info("Checking keys in memory after network profile removal")
378 buf = read_process_memory(pid, password)
380 get_key_locations(buf, password, "Password")
381 get_key_locations(buf, pmk, "PMK")
382 verify_not_present(buf, password, fname, "password")
383 verify_not_present(buf, pmk, fname, "PMK")
384 verify_not_present(buf, kck, fname, "KCK")
385 verify_not_present(buf, kek, fname, "KEK")
386 verify_not_present(buf, tk, fname, "TK")
387 verify_not_present(buf, gtk, fname, "GTK")
388 verify_not_present(buf, sae_k, fname, "SAE(k)")
389 verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)")
390 verify_not_present(buf, sae_kck, fname, "SAE(KCK)")
393 def test_sae_oom_wpas(dev, apdev):
394 """SAE and OOM in wpa_supplicant"""
395 if "SAE" not in dev[0].get_capability("auth_alg"):
396 raise HwsimSkip("SAE not supported")
397 params = hostapd.wpa2_params(ssid="test-sae",
398 passphrase="12345678")
399 params['wpa_key_mgmt'] = 'SAE'
400 hapd = hostapd.add_ap(apdev[0], params)
402 dev[0].request("SET sae_groups 25")
403 tls = dev[0].request("GET tls_library")
404 if "BoringSSL" in tls:
405 dev[0].request("SET sae_groups 26")
406 with alloc_fail(dev[0], 1, "sae_set_group"):
407 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
409 dev[0].request("REMOVE_NETWORK all")
411 dev[0].request("SET sae_groups ")
412 with alloc_fail(dev[0], 2, "sae_set_group"):
413 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
415 dev[0].request("REMOVE_NETWORK all")
417 with alloc_fail(dev[0], 1, "wpabuf_alloc;sme_auth_build_sae_commit"):
418 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
420 dev[0].request("REMOVE_NETWORK all")
422 with alloc_fail(dev[0], 1, "wpabuf_alloc;sme_auth_build_sae_confirm"):
423 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
424 scan_freq="2412", wait_connect=False)
425 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
426 dev[0].request("REMOVE_NETWORK all")
428 with alloc_fail(dev[0], 1, "=sme_authenticate"):
429 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
430 scan_freq="2412", wait_connect=False)
431 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
432 dev[0].request("REMOVE_NETWORK all")
434 with alloc_fail(dev[0], 1, "radio_add_work;sme_authenticate"):
435 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
436 scan_freq="2412", wait_connect=False)
437 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
438 dev[0].request("REMOVE_NETWORK all")
441 def test_sae_proto_ecc(dev, apdev):
442 """SAE protocol testing (ECC)"""
443 if "SAE" not in dev[0].get_capability("auth_alg"):
444 raise HwsimSkip("SAE not supported")
445 params = hostapd.wpa2_params(ssid="test-sae",
446 passphrase="12345678")
447 params['wpa_key_mgmt'] = 'SAE'
448 hapd = hostapd.add_ap(apdev[0], params)
449 bssid = apdev[0]['bssid']
451 dev[0].request("SET sae_groups 19")
453 tests = [ ("Confirm mismatch",
454 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
455 "0000800edebc3f260dc1fe7e0b20888af2b8a3316252ec37388a8504e25b73dc4240"),
456 ("Commit without even full cyclic group field",
460 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02",
462 ("Invalid commit scalar (0)",
463 "1300" + "0000000000000000000000000000000000000000000000000000000000000000" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
465 ("Invalid commit scalar (1)",
466 "1300" + "0000000000000000000000000000000000000000000000000000000000000001" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
468 ("Invalid commit scalar (> r)",
469 "1300" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
471 ("Commit element not on curve",
472 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728d0000000000000000000000000000000000000000000000000000000000000000",
474 ("Invalid commit element (y coordinate > P)",
475 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
477 ("Invalid commit element (x coordinate > P)",
478 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
480 ("Different group in commit",
481 "1400" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
483 ("Too short confirm",
484 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
485 "0000800edebc3f260dc1fe7e0b20888af2b8a3316252ec37388a8504e25b73dc42")]
486 for (note, commit, confirm) in tests:
488 dev[0].scan_for_bss(bssid, freq=2412)
489 hapd.set("ext_mgmt_frame_handling", "1")
490 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
491 scan_freq="2412", wait_connect=False)
493 logger.info("Commit")
494 for i in range(0, 10):
497 raise Exception("MGMT RX wait timed out (commit)")
498 if req['subtype'] == 11:
502 raise Exception("Authentication frame (commit) not received")
506 resp['fc'] = req['fc']
507 resp['da'] = req['sa']
508 resp['sa'] = req['da']
509 resp['bssid'] = req['bssid']
510 resp['payload'] = binascii.unhexlify("030001000000" + commit)
514 logger.info("Confirm")
515 for i in range(0, 10):
518 raise Exception("MGMT RX wait timed out (confirm)")
519 if req['subtype'] == 11:
523 raise Exception("Authentication frame (confirm) not received")
527 resp['fc'] = req['fc']
528 resp['da'] = req['sa']
529 resp['sa'] = req['da']
530 resp['bssid'] = req['bssid']
531 resp['payload'] = binascii.unhexlify("030002000000" + confirm)
535 dev[0].request("REMOVE_NETWORK all")
536 hapd.set("ext_mgmt_frame_handling", "0")
540 def test_sae_proto_ffc(dev, apdev):
541 """SAE protocol testing (FFC)"""
542 if "SAE" not in dev[0].get_capability("auth_alg"):
543 raise HwsimSkip("SAE not supported")
544 params = hostapd.wpa2_params(ssid="test-sae",
545 passphrase="12345678")
546 params['wpa_key_mgmt'] = 'SAE'
547 hapd = hostapd.add_ap(apdev[0], params)
548 bssid = apdev[0]['bssid']
550 dev[0].request("SET sae_groups 2")
552 tests = [ ("Confirm mismatch",
553 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "a8c00117493cdffa5dd671e934bc9cb1a69f39e25e9dd9cd9afd3aea2441a0f5491211c7ba50a753563f9ce943b043557cb71193b28e86ed9544f4289c471bf91b70af5c018cf4663e004165b0fd0bc1d8f3f78adf42eee92bcbc55246fd3ee9f107ab965dc7d4986f23eb71d616ebfe6bfe0a6c1ac5dc1718acee17c9a17486",
554 "0000f3116a9731f1259622e3eb55d4b3b50ba16f8c5f5565b28e609b180c51460251"),
556 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "a8c00117493cdffa5dd671e934bc9cb1a69f39e25e9dd9cd9afd3aea2441a0f5491211c7ba50a753563f9ce943b043557cb71193b28e86ed9544f4289c471bf91b70af5c018cf4663e004165b0fd0bc1d8f3f78adf42eee92bcbc55246fd3ee9f107ab965dc7d4986f23eb71d616ebfe6bfe0a6c1ac5dc1718acee17c9a174",
558 ("Invalid element (0) in commit",
559 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
561 ("Invalid element (1) in commit",
562 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
564 ("Invalid element (> P) in commit",
565 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
567 for (note, commit, confirm) in tests:
569 dev[0].scan_for_bss(bssid, freq=2412)
570 hapd.set("ext_mgmt_frame_handling", "1")
571 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
572 scan_freq="2412", wait_connect=False)
574 logger.info("Commit")
575 for i in range(0, 10):
578 raise Exception("MGMT RX wait timed out (commit)")
579 if req['subtype'] == 11:
583 raise Exception("Authentication frame (commit) not received")
587 resp['fc'] = req['fc']
588 resp['da'] = req['sa']
589 resp['sa'] = req['da']
590 resp['bssid'] = req['bssid']
591 resp['payload'] = binascii.unhexlify("030001000000" + commit)
595 logger.info("Confirm")
596 for i in range(0, 10):
599 raise Exception("MGMT RX wait timed out (confirm)")
600 if req['subtype'] == 11:
604 raise Exception("Authentication frame (confirm) not received")
608 resp['fc'] = req['fc']
609 resp['da'] = req['sa']
610 resp['sa'] = req['da']
611 resp['bssid'] = req['bssid']
612 resp['payload'] = binascii.unhexlify("030002000000" + confirm)
616 dev[0].request("REMOVE_NETWORK all")
617 hapd.set("ext_mgmt_frame_handling", "0")
621 def test_sae_no_ffc_by_default(dev, apdev):
622 """SAE and default groups rejecting FFC"""
623 if "SAE" not in dev[0].get_capability("auth_alg"):
624 raise HwsimSkip("SAE not supported")
625 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
626 params['wpa_key_mgmt'] = 'SAE'
627 hapd = hostapd.add_ap(apdev[0], params)
629 dev[0].request("SET sae_groups 5")
630 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412",
632 ev = dev[0].wait_event(["SME: Trying to authenticate"], timeout=3)
634 raise Exception("Did not try to authenticate")
635 ev = dev[0].wait_event(["SME: Trying to authenticate"], timeout=3)
637 raise Exception("Did not try to authenticate (2)")
638 dev[0].request("REMOVE_NETWORK all")
640 def sae_reflection_attack(apdev, dev, group):
641 if "SAE" not in dev.get_capability("auth_alg"):
642 raise HwsimSkip("SAE not supported")
643 params = hostapd.wpa2_params(ssid="test-sae",
644 passphrase="no-knowledge-of-passphrase")
645 params['wpa_key_mgmt'] = 'SAE'
646 hapd = hostapd.add_ap(apdev, params)
647 bssid = apdev['bssid']
649 dev.scan_for_bss(bssid, freq=2412)
650 hapd.set("ext_mgmt_frame_handling", "1")
652 dev.request("SET sae_groups %d" % group)
653 dev.connect("test-sae", psk="reflection-attack", key_mgmt="SAE",
654 scan_freq="2412", wait_connect=False)
657 for i in range(0, 10):
660 raise Exception("MGMT RX wait timed out")
661 if req['subtype'] == 11:
665 raise Exception("Authentication frame not received")
668 resp['fc'] = req['fc']
669 resp['da'] = req['sa']
670 resp['sa'] = req['da']
671 resp['bssid'] = req['bssid']
672 resp['payload'] = req['payload']
676 req = hapd.mgmt_rx(timeout=0.5)
678 if req['subtype'] == 11:
679 raise Exception("Unexpected Authentication frame seen")
682 def test_sae_reflection_attack_ecc(dev, apdev):
683 """SAE reflection attack (ECC)"""
684 sae_reflection_attack(apdev[0], dev[0], 19)
687 def test_sae_reflection_attack_ffc(dev, apdev):
688 """SAE reflection attack (FFC)"""
689 sae_reflection_attack(apdev[0], dev[0], 5)
692 def test_sae_anti_clogging_proto(dev, apdev):
693 """SAE anti clogging protocol testing"""
694 if "SAE" not in dev[0].get_capability("auth_alg"):
695 raise HwsimSkip("SAE not supported")
696 params = hostapd.wpa2_params(ssid="test-sae",
697 passphrase="no-knowledge-of-passphrase")
698 params['wpa_key_mgmt'] = 'SAE'
699 hapd = hostapd.add_ap(apdev[0], params)
700 bssid = apdev[0]['bssid']
702 dev[0].scan_for_bss(bssid, freq=2412)
703 hapd.set("ext_mgmt_frame_handling", "1")
705 dev[0].request("SET sae_groups ")
706 dev[0].connect("test-sae", psk="anti-cloggign", key_mgmt="SAE",
707 scan_freq="2412", wait_connect=False)
710 for i in range(0, 10):
713 raise Exception("MGMT RX wait timed out")
714 if req['subtype'] == 11:
718 raise Exception("Authentication frame not received")
721 resp['fc'] = req['fc']
722 resp['da'] = req['sa']
723 resp['sa'] = req['da']
724 resp['bssid'] = req['bssid']
725 resp['payload'] = binascii.unhexlify("030001004c00" + "ffff00")
728 # Confirm (not received due to DH group being rejected)
729 req = hapd.mgmt_rx(timeout=0.5)
731 if req['subtype'] == 11:
732 raise Exception("Unexpected Authentication frame seen")
735 def test_sae_no_random(dev, apdev):
736 """SAE and no random numbers available"""
737 if "SAE" not in dev[0].get_capability("auth_alg"):
738 raise HwsimSkip("SAE not supported")
739 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
740 params['wpa_key_mgmt'] = 'SAE'
741 hapd = hostapd.add_ap(apdev[0], params)
743 dev[0].request("SET sae_groups ")
744 tests = [ (1, "os_get_random;sae_get_rand"),
745 (1, "os_get_random;get_rand_1_to_p_1"),
746 (1, "os_get_random;get_random_qr_qnr"),
747 (1, "os_get_random;sae_derive_pwe_ecc") ]
748 for count, func in tests:
749 with fail_test(dev[0], count, func):
750 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
752 dev[0].request("REMOVE_NETWORK all")
753 dev[0].wait_disconnected()
756 def test_sae_pwe_failure(dev, apdev):
757 """SAE and pwe failure"""
758 if "SAE" not in dev[0].get_capability("auth_alg"):
759 raise HwsimSkip("SAE not supported")
760 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
761 params['wpa_key_mgmt'] = 'SAE'
762 params['sae_groups'] = '19 5'
763 hapd = hostapd.add_ap(apdev[0], params)
765 dev[0].request("SET sae_groups 19")
766 with fail_test(dev[0], 1, "hmac_sha256_vector;sae_derive_pwe_ecc"):
767 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
769 dev[0].request("REMOVE_NETWORK all")
770 dev[0].wait_disconnected()
771 with fail_test(dev[0], 1, "sae_test_pwd_seed_ecc"):
772 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
774 dev[0].request("REMOVE_NETWORK all")
775 dev[0].wait_disconnected()
777 dev[0].request("SET sae_groups 5")
778 with fail_test(dev[0], 1, "hmac_sha256_vector;sae_derive_pwe_ffc"):
779 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
781 dev[0].request("REMOVE_NETWORK all")
782 dev[0].wait_disconnected()
784 dev[0].request("SET sae_groups 5")
785 with fail_test(dev[0], 1, "sae_test_pwd_seed_ffc"):
786 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
788 dev[0].request("REMOVE_NETWORK all")
789 dev[0].wait_disconnected()
790 with fail_test(dev[0], 2, "sae_test_pwd_seed_ffc"):
791 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
793 dev[0].request("REMOVE_NETWORK all")
794 dev[0].wait_disconnected()
797 def test_sae_bignum_failure(dev, apdev):
798 """SAE and bignum failure"""
799 if "SAE" not in dev[0].get_capability("auth_alg"):
800 raise HwsimSkip("SAE not supported")
801 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
802 params['wpa_key_mgmt'] = 'SAE'
803 params['sae_groups'] = '19 5 22'
804 hapd = hostapd.add_ap(apdev[0], params)
806 dev[0].request("SET sae_groups 19")
807 tests = [ (1, "crypto_bignum_init_set;get_rand_1_to_p_1"),
808 (1, "crypto_bignum_init;is_quadratic_residue_blind"),
809 (1, "crypto_bignum_mulmod;is_quadratic_residue_blind"),
810 (2, "crypto_bignum_mulmod;is_quadratic_residue_blind"),
811 (3, "crypto_bignum_mulmod;is_quadratic_residue_blind"),
812 (1, "crypto_bignum_legendre;is_quadratic_residue_blind"),
813 (1, "crypto_bignum_init_set;sae_test_pwd_seed_ecc"),
814 (1, "crypto_ec_point_compute_y_sqr;sae_test_pwd_seed_ecc"),
815 (1, "crypto_bignum_init_set;get_random_qr_qnr"),
816 (1, "crypto_bignum_to_bin;sae_derive_pwe_ecc"),
817 (1, "crypto_ec_point_init;sae_derive_pwe_ecc"),
818 (1, "crypto_ec_point_solve_y_coord;sae_derive_pwe_ecc"),
819 (1, "crypto_ec_point_init;sae_derive_commit_element_ecc"),
820 (1, "crypto_ec_point_mul;sae_derive_commit_element_ecc"),
821 (1, "crypto_ec_point_invert;sae_derive_commit_element_ecc"),
822 (1, "crypto_bignum_init;=sae_derive_commit"),
823 (1, "crypto_ec_point_init;sae_derive_k_ecc"),
824 (1, "crypto_ec_point_mul;sae_derive_k_ecc"),
825 (1, "crypto_ec_point_add;sae_derive_k_ecc"),
826 (2, "crypto_ec_point_mul;sae_derive_k_ecc"),
827 (1, "crypto_ec_point_to_bin;sae_derive_k_ecc"),
828 (1, "crypto_bignum_legendre;get_random_qr_qnr"),
829 (1, "sha256_prf;sae_derive_keys"),
830 (1, "crypto_bignum_init;sae_derive_keys"),
831 (1, "crypto_bignum_init_set;sae_parse_commit_scalar"),
832 (1, "crypto_bignum_to_bin;sae_parse_commit_element_ecc"),
833 (1, "crypto_ec_point_from_bin;sae_parse_commit_element_ecc") ]
834 for count, func in tests:
835 with fail_test(dev[0], count, func):
836 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
837 scan_freq="2412", wait_connect=False)
838 wait_fail_trigger(dev[0], "GET_FAIL")
839 dev[0].request("REMOVE_NETWORK all")
841 dev[0].request("SET sae_groups 5")
842 tests = [ (1, "crypto_bignum_init_set;sae_set_group"),
843 (2, "crypto_bignum_init_set;sae_set_group"),
844 (1, "crypto_bignum_init_set;sae_get_rand"),
845 (1, "crypto_bignum_init_set;sae_test_pwd_seed_ffc"),
846 (1, "crypto_bignum_exptmod;sae_test_pwd_seed_ffc"),
847 (1, "crypto_bignum_init;sae_derive_pwe_ffc"),
848 (1, "crypto_bignum_init;sae_derive_commit_element_ffc"),
849 (1, "crypto_bignum_exptmod;sae_derive_commit_element_ffc"),
850 (1, "crypto_bignum_inverse;sae_derive_commit_element_ffc"),
851 (1, "crypto_bignum_init;sae_derive_k_ffc"),
852 (1, "crypto_bignum_exptmod;sae_derive_k_ffc"),
853 (1, "crypto_bignum_mulmod;sae_derive_k_ffc"),
854 (2, "crypto_bignum_exptmod;sae_derive_k_ffc"),
855 (1, "crypto_bignum_to_bin;sae_derive_k_ffc"),
856 (1, "crypto_bignum_init_set;sae_parse_commit_element_ffc"),
857 (1, "crypto_bignum_init;sae_parse_commit_element_ffc"),
858 (2, "crypto_bignum_init_set;sae_parse_commit_element_ffc"),
859 (1, "crypto_bignum_exptmod;sae_parse_commit_element_ffc") ]
860 for count, func in tests:
861 with fail_test(dev[0], count, func):
862 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
863 scan_freq="2412", wait_connect=False)
864 wait_fail_trigger(dev[0], "GET_FAIL")
865 dev[0].request("REMOVE_NETWORK all")
867 dev[0].request("SET sae_groups 22")
868 tests = [ (1, "crypto_bignum_init_set;sae_test_pwd_seed_ffc"),
869 (1, "crypto_bignum_sub;sae_test_pwd_seed_ffc"),
870 (1, "crypto_bignum_div;sae_test_pwd_seed_ffc") ]
871 for count, func in tests:
872 with fail_test(dev[0], count, func):
873 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
874 scan_freq="2412", wait_connect=False)
875 wait_fail_trigger(dev[0], "GET_FAIL")
876 dev[0].request("REMOVE_NETWORK all")
878 def test_sae_invalid_anti_clogging_token_req(dev, apdev):
879 """SAE and invalid anti-clogging token request"""
880 if "SAE" not in dev[0].get_capability("auth_alg"):
881 raise HwsimSkip("SAE not supported")
882 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
883 params['wpa_key_mgmt'] = 'SAE'
884 hapd = hostapd.add_ap(apdev[0], params)
885 bssid = apdev[0]['bssid']
887 dev[0].request("SET sae_groups 19")
888 dev[0].scan_for_bss(bssid, freq=2412)
889 hapd.set("ext_mgmt_frame_handling", "1")
890 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
891 scan_freq="2412", wait_connect=False)
892 ev = dev[0].wait_event(["SME: Trying to authenticate"])
894 raise Exception("No authentication attempt seen")
895 dev[0].dump_monitor()
897 for i in range(0, 10):
900 raise Exception("MGMT RX wait timed out (commit)")
901 if req['subtype'] == 11:
905 raise Exception("Authentication frame (commit) not received")
909 resp['fc'] = req['fc']
910 resp['da'] = req['sa']
911 resp['sa'] = req['da']
912 resp['bssid'] = req['bssid']
913 resp['payload'] = binascii.unhexlify("030001004c0013")
916 ev = dev[0].wait_event(["SME: Trying to authenticate"])
918 raise Exception("No authentication attempt seen")
919 dev[0].dump_monitor()
921 for i in range(0, 10):
924 raise Exception("MGMT RX wait timed out (commit) (2)")
925 if req['subtype'] == 11:
929 raise Exception("Authentication frame (commit) not received (2)")
933 resp['fc'] = req['fc']
934 resp['da'] = req['sa']
935 resp['sa'] = req['da']
936 resp['bssid'] = req['bssid']
937 resp['payload'] = binascii.unhexlify("030001000100")
940 ev = dev[0].wait_event(["SME: Trying to authenticate"])
942 raise Exception("No authentication attempt seen")
943 dev[0].dump_monitor()
945 dev[0].request("DISCONNECT")