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.
11 logger = logging.getLogger()
15 from utils import HwsimSkip, alloc_fail, fail_test, wait_fail_trigger
16 from test_ap_psk import find_wpas_process, read_process_memory, verify_not_present, get_key_locations
18 def test_sae(dev, apdev):
19 """SAE with default group"""
20 if "SAE" not in dev[0].get_capability("auth_alg"):
21 raise HwsimSkip("SAE not supported")
22 params = hostapd.wpa2_params(ssid="test-sae",
23 passphrase="12345678")
24 params['wpa_key_mgmt'] = 'SAE'
25 hapd = hostapd.add_ap(apdev[0], params)
26 key_mgmt = hapd.get_config()['key_mgmt']
27 if key_mgmt.split(' ')[0] != "SAE":
28 raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
30 dev[0].request("SET sae_groups ")
31 id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
33 if dev[0].get_status_field('sae_group') != '19':
34 raise Exception("Expected default SAE group not used")
35 bss = dev[0].get_bss(apdev[0]['bssid'])
36 if 'flags' not in bss:
37 raise Exception("Could not get BSS flags from BSS table")
38 if "[WPA2-SAE-CCMP]" not in bss['flags']:
39 raise Exception("Unexpected BSS flags: " + bss['flags'])
41 def test_sae_password_ecc(dev, apdev):
42 """SAE with number of different passwords (ECC)"""
43 if "SAE" not in dev[0].get_capability("auth_alg"):
44 raise HwsimSkip("SAE not supported")
45 params = hostapd.wpa2_params(ssid="test-sae",
46 passphrase="12345678")
47 params['wpa_key_mgmt'] = 'SAE'
48 hapd = hostapd.add_ap(apdev[0], params)
50 dev[0].request("SET sae_groups 19")
53 password = "12345678-" + str(i)
54 hapd.set("wpa_passphrase", password)
55 dev[0].connect("test-sae", psk=password, key_mgmt="SAE",
57 dev[0].request("REMOVE_NETWORK all")
58 dev[0].wait_disconnected()
60 def test_sae_password_ffc(dev, apdev):
61 """SAE with number of different passwords (FFC)"""
62 if "SAE" not in dev[0].get_capability("auth_alg"):
63 raise HwsimSkip("SAE not supported")
64 params = hostapd.wpa2_params(ssid="test-sae",
65 passphrase="12345678")
66 params['wpa_key_mgmt'] = 'SAE'
67 params['sae_groups'] = '22'
68 hapd = hostapd.add_ap(apdev[0], params)
70 dev[0].request("SET sae_groups 22")
73 password = "12345678-" + str(i)
74 hapd.set("wpa_passphrase", password)
75 dev[0].connect("test-sae", psk=password, key_mgmt="SAE",
77 dev[0].request("REMOVE_NETWORK all")
78 dev[0].wait_disconnected()
80 def test_sae_pmksa_caching(dev, apdev):
81 """SAE and PMKSA caching"""
82 if "SAE" not in dev[0].get_capability("auth_alg"):
83 raise HwsimSkip("SAE not supported")
84 params = hostapd.wpa2_params(ssid="test-sae",
85 passphrase="12345678")
86 params['wpa_key_mgmt'] = 'SAE'
87 hapd = hostapd.add_ap(apdev[0], params)
89 dev[0].request("SET sae_groups ")
90 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
92 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
94 raise Exception("No connection event received from hostapd")
95 dev[0].request("DISCONNECT")
96 dev[0].wait_disconnected()
97 dev[0].request("RECONNECT")
98 dev[0].wait_connected(timeout=15, error="Reconnect timed out")
99 if dev[0].get_status_field('sae_group') is not None:
100 raise Exception("SAE group claimed to have been used")
102 def test_sae_pmksa_caching_disabled(dev, apdev):
103 """SAE and PMKSA caching disabled"""
104 if "SAE" not in dev[0].get_capability("auth_alg"):
105 raise HwsimSkip("SAE not supported")
106 params = hostapd.wpa2_params(ssid="test-sae",
107 passphrase="12345678")
108 params['wpa_key_mgmt'] = 'SAE'
109 params['disable_pmksa_caching'] = '1'
110 hapd = hostapd.add_ap(apdev[0], params)
112 dev[0].request("SET sae_groups ")
113 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
115 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
117 raise Exception("No connection event received from hostapd")
118 dev[0].request("DISCONNECT")
119 dev[0].wait_disconnected()
120 dev[0].request("RECONNECT")
121 dev[0].wait_connected(timeout=15, error="Reconnect timed out")
122 if dev[0].get_status_field('sae_group') != '19':
123 raise Exception("Expected default SAE group not used")
125 def test_sae_groups(dev, apdev):
126 """SAE with all supported groups"""
127 if "SAE" not in dev[0].get_capability("auth_alg"):
128 raise HwsimSkip("SAE not supported")
129 # This is the full list of supported groups, but groups 14-16 (2048-4096 bit
130 # MODP) and group 21 (521-bit random ECP group) are a bit too slow on some
131 # VMs and can result in hitting the mac80211 authentication timeout, so
132 # allow them to fail and just report such failures in the debug log.
133 sae_groups = [ 19, 25, 26, 20, 21, 2, 5, 14, 15, 16, 22, 23, 24 ]
134 tls = dev[0].request("GET tls_library")
135 if tls.startswith("OpenSSL") and "build=OpenSSL 1.0.2" in tls and "run=OpenSSL 1.0.2" in tls:
136 logger.info("Add Brainpool EC groups since OpenSSL is new enough")
137 sae_groups += [ 27, 28, 29, 30 ]
138 heavy_groups = [ 14, 15, 16 ]
139 groups = [str(g) for g in sae_groups]
140 params = hostapd.wpa2_params(ssid="test-sae-groups",
141 passphrase="12345678")
142 params['wpa_key_mgmt'] = 'SAE'
143 params['sae_groups'] = ' '.join(groups)
144 hostapd.add_ap(apdev[0], params)
147 logger.info("Testing SAE group " + g)
148 dev[0].request("SET sae_groups " + g)
149 id = dev[0].connect("test-sae-groups", psk="12345678", key_mgmt="SAE",
150 scan_freq="2412", wait_connect=False)
151 if int(g) in heavy_groups:
152 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=5)
154 logger.info("No connection with heavy SAE group %s did not connect - likely hitting timeout in mac80211" % g)
155 dev[0].remove_network(id)
157 dev[0].dump_monitor()
159 logger.info("Connection with heavy SAE group " + g)
161 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
163 if "BoringSSL" in tls and int(g) in [ 25 ]:
164 logger.info("Ignore connection failure with group " + g + " with BoringSSL")
165 dev[0].remove_network(id)
166 dev[0].dump_monitor()
168 raise Exception("Connection timed out with group " + g)
169 if dev[0].get_status_field('sae_group') != g:
170 raise Exception("Expected SAE group not used")
171 dev[0].remove_network(id)
172 dev[0].wait_disconnected()
173 dev[0].dump_monitor()
175 def test_sae_group_nego(dev, apdev):
176 """SAE group negotiation"""
177 if "SAE" not in dev[0].get_capability("auth_alg"):
178 raise HwsimSkip("SAE not supported")
179 params = hostapd.wpa2_params(ssid="test-sae-group-nego",
180 passphrase="12345678")
181 params['wpa_key_mgmt'] = 'SAE'
182 params['sae_groups'] = '19'
183 hostapd.add_ap(apdev[0], params)
185 dev[0].request("SET sae_groups 25 26 20 19")
186 dev[0].connect("test-sae-group-nego", psk="12345678", key_mgmt="SAE",
188 if dev[0].get_status_field('sae_group') != '19':
189 raise Exception("Expected SAE group not used")
191 def test_sae_anti_clogging(dev, apdev):
192 """SAE anti clogging"""
193 if "SAE" not in dev[0].get_capability("auth_alg"):
194 raise HwsimSkip("SAE not supported")
195 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
196 params['wpa_key_mgmt'] = 'SAE'
197 params['sae_anti_clogging_threshold'] = '1'
198 hostapd.add_ap(apdev[0], params)
200 dev[0].request("SET sae_groups ")
201 dev[1].request("SET sae_groups ")
203 for i in range(0, 2):
204 dev[i].scan(freq="2412")
205 id[i] = dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE",
206 scan_freq="2412", only_add_network=True)
207 for i in range(0, 2):
208 dev[i].select_network(id[i])
209 for i in range(0, 2):
210 dev[i].wait_connected(timeout=10)
212 def test_sae_forced_anti_clogging(dev, apdev):
213 """SAE anti clogging (forced)"""
214 if "SAE" not in dev[0].get_capability("auth_alg"):
215 raise HwsimSkip("SAE not supported")
216 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
217 params['wpa_key_mgmt'] = 'SAE WPA-PSK'
218 params['sae_anti_clogging_threshold'] = '0'
219 hostapd.add_ap(apdev[0], params)
220 dev[2].connect("test-sae", psk="12345678", scan_freq="2412")
221 for i in range(0, 2):
222 dev[i].request("SET sae_groups ")
223 dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE",
226 def test_sae_mixed(dev, apdev):
227 """Mixed SAE and non-SAE network"""
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 WPA-PSK'
232 params['sae_anti_clogging_threshold'] = '0'
233 hostapd.add_ap(apdev[0], params)
235 dev[2].connect("test-sae", psk="12345678", scan_freq="2412")
236 for i in range(0, 2):
237 dev[i].request("SET sae_groups ")
238 dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE",
241 def test_sae_missing_password(dev, apdev):
242 """SAE and missing password"""
243 if "SAE" not in dev[0].get_capability("auth_alg"):
244 raise HwsimSkip("SAE not supported")
245 params = hostapd.wpa2_params(ssid="test-sae",
246 passphrase="12345678")
247 params['wpa_key_mgmt'] = 'SAE'
248 hapd = hostapd.add_ap(apdev[0], params)
250 dev[0].request("SET sae_groups ")
251 id = dev[0].connect("test-sae",
252 raw_psk="46b4a73b8a951ad53ebd2e0afdb9c5483257edd4c21d12b7710759da70945858",
253 key_mgmt="SAE", scan_freq="2412", wait_connect=False)
254 ev = dev[0].wait_event(['CTRL-EVENT-SSID-TEMP-DISABLED'], timeout=10)
256 raise Exception("Invalid network not temporarily disabled")
259 def test_sae_key_lifetime_in_memory(dev, apdev, params):
260 """SAE and key lifetime in memory"""
261 if "SAE" not in dev[0].get_capability("auth_alg"):
262 raise HwsimSkip("SAE not supported")
263 password = "5ad144a7c1f5a5503baa6fa01dabc15b1843e8c01662d78d16b70b5cd23cf8b"
264 p = hostapd.wpa2_params(ssid="test-sae", passphrase=password)
265 p['wpa_key_mgmt'] = 'SAE'
266 hapd = hostapd.add_ap(apdev[0], p)
268 pid = find_wpas_process(dev[0])
270 dev[0].request("SET sae_groups ")
271 id = dev[0].connect("test-sae", psk=password, key_mgmt="SAE",
274 # The decrypted copy of GTK is freed only after the CTRL-EVENT-CONNECTED
275 # event has been delivered, so verify that wpa_supplicant has returned to
276 # eloop before reading process memory.
279 buf = read_process_memory(pid, password)
281 dev[0].request("DISCONNECT")
282 dev[0].wait_disconnected()
291 with open(os.path.join(params['logdir'], 'log0'), 'r') as f:
292 for l in f.readlines():
293 if "SAE: k - hexdump" in l:
294 val = l.strip().split(':')[3].replace(' ', '')
295 sae_k = binascii.unhexlify(val)
296 if "SAE: keyseed - hexdump" in l:
297 val = l.strip().split(':')[3].replace(' ', '')
298 sae_keyseed = binascii.unhexlify(val)
299 if "SAE: KCK - hexdump" in l:
300 val = l.strip().split(':')[3].replace(' ', '')
301 sae_kck = binascii.unhexlify(val)
302 if "SAE: PMK - hexdump" in l:
303 val = l.strip().split(':')[3].replace(' ', '')
304 pmk = binascii.unhexlify(val)
305 if "WPA: PTK - hexdump" in l:
306 val = l.strip().split(':')[3].replace(' ', '')
307 ptk = binascii.unhexlify(val)
308 if "WPA: Group Key - hexdump" in l:
309 val = l.strip().split(':')[3].replace(' ', '')
310 gtk = binascii.unhexlify(val)
311 if not sae_k or not sae_keyseed or not sae_kck or not pmk or not ptk or not gtk:
312 raise Exception("Could not find keys from debug log")
314 raise Exception("Unexpected GTK length")
320 fname = os.path.join(params['logdir'],
321 'sae_key_lifetime_in_memory.memctx-')
323 logger.info("Checking keys in memory while associated")
324 get_key_locations(buf, password, "Password")
325 get_key_locations(buf, pmk, "PMK")
326 if password not in buf:
327 raise HwsimSkip("Password not found while associated")
329 raise HwsimSkip("PMK not found while associated")
331 raise Exception("KCK not found while associated")
333 raise Exception("KEK not found while associated")
335 raise Exception("TK found from memory")
337 get_key_locations(buf, gtk, "GTK")
338 raise Exception("GTK found from memory")
339 verify_not_present(buf, sae_k, fname, "SAE(k)")
340 verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)")
341 verify_not_present(buf, sae_kck, fname, "SAE(KCK)")
343 logger.info("Checking keys in memory after disassociation")
344 buf = read_process_memory(pid, password)
346 # Note: Password is still present in network configuration
347 # Note: PMK is in PMKSA cache
349 get_key_locations(buf, password, "Password")
350 get_key_locations(buf, pmk, "PMK")
351 verify_not_present(buf, kck, fname, "KCK")
352 verify_not_present(buf, kek, fname, "KEK")
353 verify_not_present(buf, tk, fname, "TK")
354 verify_not_present(buf, gtk, fname, "GTK")
355 verify_not_present(buf, sae_k, fname, "SAE(k)")
356 verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)")
357 verify_not_present(buf, sae_kck, fname, "SAE(KCK)")
359 dev[0].request("PMKSA_FLUSH")
360 logger.info("Checking keys in memory after PMKSA cache flush")
361 buf = read_process_memory(pid, password)
362 get_key_locations(buf, password, "Password")
363 get_key_locations(buf, pmk, "PMK")
364 verify_not_present(buf, pmk, fname, "PMK")
366 dev[0].request("REMOVE_NETWORK all")
368 logger.info("Checking keys in memory after network profile removal")
369 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, password, fname, "password")
374 verify_not_present(buf, pmk, fname, "PMK")
375 verify_not_present(buf, kck, fname, "KCK")
376 verify_not_present(buf, kek, fname, "KEK")
377 verify_not_present(buf, tk, fname, "TK")
378 verify_not_present(buf, gtk, fname, "GTK")
379 verify_not_present(buf, sae_k, fname, "SAE(k)")
380 verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)")
381 verify_not_present(buf, sae_kck, fname, "SAE(KCK)")
383 def test_sae_oom_wpas(dev, apdev):
384 """SAE and OOM in wpa_supplicant"""
385 if "SAE" not in dev[0].get_capability("auth_alg"):
386 raise HwsimSkip("SAE not supported")
387 params = hostapd.wpa2_params(ssid="test-sae",
388 passphrase="12345678")
389 params['wpa_key_mgmt'] = 'SAE'
390 hapd = hostapd.add_ap(apdev[0], params)
392 dev[0].request("SET sae_groups 25")
393 tls = dev[0].request("GET tls_library")
394 if "BoringSSL" in tls:
395 dev[0].request("SET sae_groups 26")
396 with alloc_fail(dev[0], 1, "sae_set_group"):
397 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
399 dev[0].request("REMOVE_NETWORK all")
401 dev[0].request("SET sae_groups ")
402 with alloc_fail(dev[0], 2, "sae_set_group"):
403 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
405 dev[0].request("REMOVE_NETWORK all")
407 def test_sae_proto_ecc(dev, apdev):
408 """SAE protocol testing (ECC)"""
409 if "SAE" not in dev[0].get_capability("auth_alg"):
410 raise HwsimSkip("SAE not supported")
411 params = hostapd.wpa2_params(ssid="test-sae",
412 passphrase="12345678")
413 params['wpa_key_mgmt'] = 'SAE'
414 hapd = hostapd.add_ap(apdev[0], params)
415 bssid = apdev[0]['bssid']
417 dev[0].request("SET sae_groups 19")
419 tests = [ ("Confirm mismatch",
420 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
421 "0000800edebc3f260dc1fe7e0b20888af2b8a3316252ec37388a8504e25b73dc4240"),
422 ("Commit without even full cyclic group field",
426 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02",
428 ("Invalid commit scalar (0)",
429 "1300" + "0000000000000000000000000000000000000000000000000000000000000000" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
431 ("Invalid commit scalar (1)",
432 "1300" + "0000000000000000000000000000000000000000000000000000000000000001" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
434 ("Invalid commit scalar (> r)",
435 "1300" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
437 ("Commit element not on curve",
438 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728d0000000000000000000000000000000000000000000000000000000000000000",
440 ("Invalid commit element (y coordinate > P)",
441 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
443 ("Invalid commit element (x coordinate > P)",
444 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
446 ("Different group in commit",
447 "1400" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
449 ("Too short confirm",
450 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
451 "0000800edebc3f260dc1fe7e0b20888af2b8a3316252ec37388a8504e25b73dc42")]
452 for (note, commit, confirm) in tests:
454 dev[0].scan_for_bss(bssid, freq=2412)
455 hapd.set("ext_mgmt_frame_handling", "1")
456 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
457 scan_freq="2412", wait_connect=False)
459 logger.info("Commit")
460 for i in range(0, 10):
463 raise Exception("MGMT RX wait timed out (commit)")
464 if req['subtype'] == 11:
468 raise Exception("Authentication frame (commit) not received")
472 resp['fc'] = req['fc']
473 resp['da'] = req['sa']
474 resp['sa'] = req['da']
475 resp['bssid'] = req['bssid']
476 resp['payload'] = binascii.unhexlify("030001000000" + commit)
480 logger.info("Confirm")
481 for i in range(0, 10):
484 raise Exception("MGMT RX wait timed out (confirm)")
485 if req['subtype'] == 11:
489 raise Exception("Authentication frame (confirm) not received")
493 resp['fc'] = req['fc']
494 resp['da'] = req['sa']
495 resp['sa'] = req['da']
496 resp['bssid'] = req['bssid']
497 resp['payload'] = binascii.unhexlify("030002000000" + confirm)
501 dev[0].request("REMOVE_NETWORK all")
502 hapd.set("ext_mgmt_frame_handling", "0")
505 def test_sae_proto_ffc(dev, apdev):
506 """SAE protocol testing (FFC)"""
507 if "SAE" not in dev[0].get_capability("auth_alg"):
508 raise HwsimSkip("SAE not supported")
509 params = hostapd.wpa2_params(ssid="test-sae",
510 passphrase="12345678")
511 params['wpa_key_mgmt'] = 'SAE'
512 hapd = hostapd.add_ap(apdev[0], params)
513 bssid = apdev[0]['bssid']
515 dev[0].request("SET sae_groups 2")
517 tests = [ ("Confirm mismatch",
518 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "a8c00117493cdffa5dd671e934bc9cb1a69f39e25e9dd9cd9afd3aea2441a0f5491211c7ba50a753563f9ce943b043557cb71193b28e86ed9544f4289c471bf91b70af5c018cf4663e004165b0fd0bc1d8f3f78adf42eee92bcbc55246fd3ee9f107ab965dc7d4986f23eb71d616ebfe6bfe0a6c1ac5dc1718acee17c9a17486",
519 "0000f3116a9731f1259622e3eb55d4b3b50ba16f8c5f5565b28e609b180c51460251"),
521 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "a8c00117493cdffa5dd671e934bc9cb1a69f39e25e9dd9cd9afd3aea2441a0f5491211c7ba50a753563f9ce943b043557cb71193b28e86ed9544f4289c471bf91b70af5c018cf4663e004165b0fd0bc1d8f3f78adf42eee92bcbc55246fd3ee9f107ab965dc7d4986f23eb71d616ebfe6bfe0a6c1ac5dc1718acee17c9a174",
523 ("Invalid element (0) in commit",
524 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
526 ("Invalid element (1) in commit",
527 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
529 ("Invalid element (> P) in commit",
530 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
532 for (note, commit, confirm) in tests:
534 dev[0].scan_for_bss(bssid, freq=2412)
535 hapd.set("ext_mgmt_frame_handling", "1")
536 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
537 scan_freq="2412", wait_connect=False)
539 logger.info("Commit")
540 for i in range(0, 10):
543 raise Exception("MGMT RX wait timed out (commit)")
544 if req['subtype'] == 11:
548 raise Exception("Authentication frame (commit) not received")
552 resp['fc'] = req['fc']
553 resp['da'] = req['sa']
554 resp['sa'] = req['da']
555 resp['bssid'] = req['bssid']
556 resp['payload'] = binascii.unhexlify("030001000000" + commit)
560 logger.info("Confirm")
561 for i in range(0, 10):
564 raise Exception("MGMT RX wait timed out (confirm)")
565 if req['subtype'] == 11:
569 raise Exception("Authentication frame (confirm) not received")
573 resp['fc'] = req['fc']
574 resp['da'] = req['sa']
575 resp['sa'] = req['da']
576 resp['bssid'] = req['bssid']
577 resp['payload'] = binascii.unhexlify("030002000000" + confirm)
581 dev[0].request("REMOVE_NETWORK all")
582 hapd.set("ext_mgmt_frame_handling", "0")
585 def test_sae_no_ffc_by_default(dev, apdev):
586 """SAE and default groups rejecting FFC"""
587 if "SAE" not in dev[0].get_capability("auth_alg"):
588 raise HwsimSkip("SAE not supported")
589 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
590 params['wpa_key_mgmt'] = 'SAE'
591 hapd = hostapd.add_ap(apdev[0], params)
593 dev[0].request("SET sae_groups 5")
594 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412",
596 ev = dev[0].wait_event(["SME: Trying to authenticate"], timeout=3)
598 raise Exception("Did not try to authenticate")
599 ev = dev[0].wait_event(["SME: Trying to authenticate"], timeout=3)
601 raise Exception("Did not try to authenticate (2)")
602 dev[0].request("REMOVE_NETWORK all")
604 def sae_reflection_attack(apdev, dev, group):
605 if "SAE" not in dev.get_capability("auth_alg"):
606 raise HwsimSkip("SAE not supported")
607 params = hostapd.wpa2_params(ssid="test-sae",
608 passphrase="no-knowledge-of-passphrase")
609 params['wpa_key_mgmt'] = 'SAE'
610 hapd = hostapd.add_ap(apdev, params)
611 bssid = apdev['bssid']
613 dev.scan_for_bss(bssid, freq=2412)
614 hapd.set("ext_mgmt_frame_handling", "1")
616 dev.request("SET sae_groups %d" % group)
617 dev.connect("test-sae", psk="reflection-attack", key_mgmt="SAE",
618 scan_freq="2412", wait_connect=False)
621 for i in range(0, 10):
624 raise Exception("MGMT RX wait timed out")
625 if req['subtype'] == 11:
629 raise Exception("Authentication frame not received")
632 resp['fc'] = req['fc']
633 resp['da'] = req['sa']
634 resp['sa'] = req['da']
635 resp['bssid'] = req['bssid']
636 resp['payload'] = req['payload']
640 req = hapd.mgmt_rx(timeout=0.5)
642 if req['subtype'] == 11:
643 raise Exception("Unexpected Authentication frame seen")
645 def test_sae_reflection_attack_ecc(dev, apdev):
646 """SAE reflection attack (ECC)"""
647 sae_reflection_attack(apdev[0], dev[0], 19)
649 def test_sae_reflection_attack_ffc(dev, apdev):
650 """SAE reflection attack (FFC)"""
651 sae_reflection_attack(apdev[0], dev[0], 5)
653 def test_sae_anti_clogging_proto(dev, apdev):
654 """SAE anti clogging protocol testing"""
655 if "SAE" not in dev[0].get_capability("auth_alg"):
656 raise HwsimSkip("SAE not supported")
657 params = hostapd.wpa2_params(ssid="test-sae",
658 passphrase="no-knowledge-of-passphrase")
659 params['wpa_key_mgmt'] = 'SAE'
660 hapd = hostapd.add_ap(apdev[0], params)
661 bssid = apdev[0]['bssid']
663 dev[0].scan_for_bss(bssid, freq=2412)
664 hapd.set("ext_mgmt_frame_handling", "1")
666 dev[0].request("SET sae_groups ")
667 dev[0].connect("test-sae", psk="anti-cloggign", key_mgmt="SAE",
668 scan_freq="2412", wait_connect=False)
671 for i in range(0, 10):
674 raise Exception("MGMT RX wait timed out")
675 if req['subtype'] == 11:
679 raise Exception("Authentication frame not received")
682 resp['fc'] = req['fc']
683 resp['da'] = req['sa']
684 resp['sa'] = req['da']
685 resp['bssid'] = req['bssid']
686 resp['payload'] = binascii.unhexlify("030001004c00" + "ffff00")
689 # Confirm (not received due to DH group being rejected)
690 req = hapd.mgmt_rx(timeout=0.5)
692 if req['subtype'] == 11:
693 raise Exception("Unexpected Authentication frame seen")
695 def test_sae_no_random(dev, apdev):
696 """SAE and no random numbers available"""
697 if "SAE" not in dev[0].get_capability("auth_alg"):
698 raise HwsimSkip("SAE not supported")
699 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
700 params['wpa_key_mgmt'] = 'SAE'
701 hapd = hostapd.add_ap(apdev[0], params)
703 dev[0].request("SET sae_groups ")
704 tests = [ (1, "os_get_random;sae_get_rand"),
705 (1, "os_get_random;get_rand_1_to_p_1"),
706 (1, "os_get_random;get_random_qr_qnr"),
707 (1, "os_get_random;sae_derive_pwe_ecc") ]
708 for count, func in tests:
709 with fail_test(dev[0], count, func):
710 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
712 dev[0].request("REMOVE_NETWORK all")
713 dev[0].wait_disconnected()
715 def test_sae_pwe_failure(dev, apdev):
716 """SAE and pwe failure"""
717 if "SAE" not in dev[0].get_capability("auth_alg"):
718 raise HwsimSkip("SAE not supported")
719 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
720 params['wpa_key_mgmt'] = 'SAE'
721 params['sae_groups'] = '19 5'
722 hapd = hostapd.add_ap(apdev[0], params)
724 dev[0].request("SET sae_groups 19")
725 with fail_test(dev[0], 1, "hmac_sha256_vector;sae_derive_pwe_ecc"):
726 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
728 dev[0].request("REMOVE_NETWORK all")
729 dev[0].wait_disconnected()
730 with fail_test(dev[0], 1, "sae_test_pwd_seed_ecc"):
731 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
733 dev[0].request("REMOVE_NETWORK all")
734 dev[0].wait_disconnected()
736 dev[0].request("SET sae_groups 5")
737 with fail_test(dev[0], 1, "hmac_sha256_vector;sae_derive_pwe_ffc"):
738 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
740 dev[0].request("REMOVE_NETWORK all")
741 dev[0].wait_disconnected()
743 dev[0].request("SET sae_groups 5")
744 with fail_test(dev[0], 1, "sae_test_pwd_seed_ffc"):
745 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
747 dev[0].request("REMOVE_NETWORK all")
748 dev[0].wait_disconnected()
749 with fail_test(dev[0], 2, "sae_test_pwd_seed_ffc"):
750 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
752 dev[0].request("REMOVE_NETWORK all")
753 dev[0].wait_disconnected()
755 def test_sae_bignum_failure(dev, apdev):
756 """SAE and bignum failure"""
757 if "SAE" not in dev[0].get_capability("auth_alg"):
758 raise HwsimSkip("SAE not supported")
759 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
760 params['wpa_key_mgmt'] = 'SAE'
761 params['sae_groups'] = '19 5 22'
762 hapd = hostapd.add_ap(apdev[0], params)
764 dev[0].request("SET sae_groups 19")
765 tests = [ (1, "crypto_bignum_init_set;get_rand_1_to_p_1"),
766 (1, "crypto_bignum_init;is_quadratic_residue_blind"),
767 (1, "crypto_bignum_mulmod;is_quadratic_residue_blind"),
768 (2, "crypto_bignum_mulmod;is_quadratic_residue_blind"),
769 (3, "crypto_bignum_mulmod;is_quadratic_residue_blind"),
770 (1, "crypto_bignum_legendre;is_quadratic_residue_blind"),
771 (1, "crypto_bignum_init_set;sae_test_pwd_seed_ecc"),
772 (1, "crypto_ec_point_compute_y_sqr;sae_test_pwd_seed_ecc"),
773 (1, "crypto_bignum_init_set;get_random_qr_qnr"),
774 (1, "crypto_bignum_to_bin;sae_derive_pwe_ecc"),
775 (1, "crypto_ec_point_init;sae_derive_pwe_ecc"),
776 (1, "crypto_ec_point_solve_y_coord;sae_derive_pwe_ecc"),
777 (1, "crypto_ec_point_init;sae_derive_commit_element_ecc"),
778 (1, "crypto_ec_point_mul;sae_derive_commit_element_ecc"),
779 (1, "crypto_ec_point_invert;sae_derive_commit_element_ecc"),
780 (1, "crypto_bignum_init;=sae_derive_commit"),
781 (1, "crypto_ec_point_init;sae_derive_k_ecc"),
782 (1, "crypto_ec_point_mul;sae_derive_k_ecc"),
783 (1, "crypto_ec_point_add;sae_derive_k_ecc"),
784 (2, "crypto_ec_point_mul;sae_derive_k_ecc"),
785 (1, "crypto_ec_point_to_bin;sae_derive_k_ecc"),
786 (1, "crypto_bignum_legendre;get_random_qr_qnr"),
787 (1, "sha256_prf;sae_derive_keys"),
788 (1, "crypto_bignum_init;sae_derive_keys"),
789 (1, "crypto_bignum_init_set;sae_parse_commit_scalar"),
790 (1, "crypto_bignum_to_bin;sae_parse_commit_element_ecc"),
791 (1, "crypto_ec_point_from_bin;sae_parse_commit_element_ecc") ]
792 for count, func in tests:
793 with fail_test(dev[0], count, func):
794 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
795 scan_freq="2412", wait_connect=False)
796 wait_fail_trigger(dev[0], "GET_FAIL")
797 dev[0].request("REMOVE_NETWORK all")
799 dev[0].request("SET sae_groups 5")
800 tests = [ (1, "crypto_bignum_init_set;sae_set_group"),
801 (2, "crypto_bignum_init_set;sae_set_group"),
802 (1, "crypto_bignum_init_set;sae_get_rand"),
803 (1, "crypto_bignum_init_set;sae_test_pwd_seed_ffc"),
804 (1, "crypto_bignum_exptmod;sae_test_pwd_seed_ffc"),
805 (1, "crypto_bignum_init;sae_derive_pwe_ffc"),
806 (1, "crypto_bignum_init;sae_derive_commit_element_ffc"),
807 (1, "crypto_bignum_exptmod;sae_derive_commit_element_ffc"),
808 (1, "crypto_bignum_inverse;sae_derive_commit_element_ffc"),
809 (1, "crypto_bignum_init;sae_derive_k_ffc"),
810 (1, "crypto_bignum_exptmod;sae_derive_k_ffc"),
811 (1, "crypto_bignum_mulmod;sae_derive_k_ffc"),
812 (2, "crypto_bignum_exptmod;sae_derive_k_ffc"),
813 (1, "crypto_bignum_to_bin;sae_derive_k_ffc"),
814 (1, "crypto_bignum_init_set;sae_parse_commit_element_ffc"),
815 (1, "crypto_bignum_init;sae_parse_commit_element_ffc"),
816 (2, "crypto_bignum_init_set;sae_parse_commit_element_ffc"),
817 (1, "crypto_bignum_exptmod;sae_parse_commit_element_ffc") ]
818 for count, func in tests:
819 with fail_test(dev[0], count, func):
820 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
821 scan_freq="2412", wait_connect=False)
822 wait_fail_trigger(dev[0], "GET_FAIL")
823 dev[0].request("REMOVE_NETWORK all")
825 dev[0].request("SET sae_groups 22")
826 tests = [ (1, "crypto_bignum_init_set;sae_test_pwd_seed_ffc"),
827 (1, "crypto_bignum_sub;sae_test_pwd_seed_ffc"),
828 (1, "crypto_bignum_div;sae_test_pwd_seed_ffc") ]
829 for count, func in tests:
830 with fail_test(dev[0], count, func):
831 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
832 scan_freq="2412", wait_connect=False)
833 wait_fail_trigger(dev[0], "GET_FAIL")
834 dev[0].request("REMOVE_NETWORK all")