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")
418 def test_sae_proto_ecc(dev, apdev):
419 """SAE protocol testing (ECC)"""
420 if "SAE" not in dev[0].get_capability("auth_alg"):
421 raise HwsimSkip("SAE not supported")
422 params = hostapd.wpa2_params(ssid="test-sae",
423 passphrase="12345678")
424 params['wpa_key_mgmt'] = 'SAE'
425 hapd = hostapd.add_ap(apdev[0], params)
426 bssid = apdev[0]['bssid']
428 dev[0].request("SET sae_groups 19")
430 tests = [ ("Confirm mismatch",
431 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
432 "0000800edebc3f260dc1fe7e0b20888af2b8a3316252ec37388a8504e25b73dc4240"),
433 ("Commit without even full cyclic group field",
437 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02",
439 ("Invalid commit scalar (0)",
440 "1300" + "0000000000000000000000000000000000000000000000000000000000000000" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
442 ("Invalid commit scalar (1)",
443 "1300" + "0000000000000000000000000000000000000000000000000000000000000001" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
445 ("Invalid commit scalar (> r)",
446 "1300" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
448 ("Commit element not on curve",
449 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728d0000000000000000000000000000000000000000000000000000000000000000",
451 ("Invalid commit element (y coordinate > P)",
452 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
454 ("Invalid commit element (x coordinate > P)",
455 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
457 ("Different group in commit",
458 "1400" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
460 ("Too short confirm",
461 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
462 "0000800edebc3f260dc1fe7e0b20888af2b8a3316252ec37388a8504e25b73dc42")]
463 for (note, commit, confirm) in tests:
465 dev[0].scan_for_bss(bssid, freq=2412)
466 hapd.set("ext_mgmt_frame_handling", "1")
467 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
468 scan_freq="2412", wait_connect=False)
470 logger.info("Commit")
471 for i in range(0, 10):
474 raise Exception("MGMT RX wait timed out (commit)")
475 if req['subtype'] == 11:
479 raise Exception("Authentication frame (commit) not received")
483 resp['fc'] = req['fc']
484 resp['da'] = req['sa']
485 resp['sa'] = req['da']
486 resp['bssid'] = req['bssid']
487 resp['payload'] = binascii.unhexlify("030001000000" + commit)
491 logger.info("Confirm")
492 for i in range(0, 10):
495 raise Exception("MGMT RX wait timed out (confirm)")
496 if req['subtype'] == 11:
500 raise Exception("Authentication frame (confirm) not received")
504 resp['fc'] = req['fc']
505 resp['da'] = req['sa']
506 resp['sa'] = req['da']
507 resp['bssid'] = req['bssid']
508 resp['payload'] = binascii.unhexlify("030002000000" + confirm)
512 dev[0].request("REMOVE_NETWORK all")
513 hapd.set("ext_mgmt_frame_handling", "0")
517 def test_sae_proto_ffc(dev, apdev):
518 """SAE protocol testing (FFC)"""
519 if "SAE" not in dev[0].get_capability("auth_alg"):
520 raise HwsimSkip("SAE not supported")
521 params = hostapd.wpa2_params(ssid="test-sae",
522 passphrase="12345678")
523 params['wpa_key_mgmt'] = 'SAE'
524 hapd = hostapd.add_ap(apdev[0], params)
525 bssid = apdev[0]['bssid']
527 dev[0].request("SET sae_groups 2")
529 tests = [ ("Confirm mismatch",
530 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "a8c00117493cdffa5dd671e934bc9cb1a69f39e25e9dd9cd9afd3aea2441a0f5491211c7ba50a753563f9ce943b043557cb71193b28e86ed9544f4289c471bf91b70af5c018cf4663e004165b0fd0bc1d8f3f78adf42eee92bcbc55246fd3ee9f107ab965dc7d4986f23eb71d616ebfe6bfe0a6c1ac5dc1718acee17c9a17486",
531 "0000f3116a9731f1259622e3eb55d4b3b50ba16f8c5f5565b28e609b180c51460251"),
533 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "a8c00117493cdffa5dd671e934bc9cb1a69f39e25e9dd9cd9afd3aea2441a0f5491211c7ba50a753563f9ce943b043557cb71193b28e86ed9544f4289c471bf91b70af5c018cf4663e004165b0fd0bc1d8f3f78adf42eee92bcbc55246fd3ee9f107ab965dc7d4986f23eb71d616ebfe6bfe0a6c1ac5dc1718acee17c9a174",
535 ("Invalid element (0) in commit",
536 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
538 ("Invalid element (1) in commit",
539 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
541 ("Invalid element (> P) in commit",
542 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
544 for (note, commit, confirm) in tests:
546 dev[0].scan_for_bss(bssid, freq=2412)
547 hapd.set("ext_mgmt_frame_handling", "1")
548 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
549 scan_freq="2412", wait_connect=False)
551 logger.info("Commit")
552 for i in range(0, 10):
555 raise Exception("MGMT RX wait timed out (commit)")
556 if req['subtype'] == 11:
560 raise Exception("Authentication frame (commit) not received")
564 resp['fc'] = req['fc']
565 resp['da'] = req['sa']
566 resp['sa'] = req['da']
567 resp['bssid'] = req['bssid']
568 resp['payload'] = binascii.unhexlify("030001000000" + commit)
572 logger.info("Confirm")
573 for i in range(0, 10):
576 raise Exception("MGMT RX wait timed out (confirm)")
577 if req['subtype'] == 11:
581 raise Exception("Authentication frame (confirm) not received")
585 resp['fc'] = req['fc']
586 resp['da'] = req['sa']
587 resp['sa'] = req['da']
588 resp['bssid'] = req['bssid']
589 resp['payload'] = binascii.unhexlify("030002000000" + confirm)
593 dev[0].request("REMOVE_NETWORK all")
594 hapd.set("ext_mgmt_frame_handling", "0")
598 def test_sae_no_ffc_by_default(dev, apdev):
599 """SAE and default groups rejecting FFC"""
600 if "SAE" not in dev[0].get_capability("auth_alg"):
601 raise HwsimSkip("SAE not supported")
602 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
603 params['wpa_key_mgmt'] = 'SAE'
604 hapd = hostapd.add_ap(apdev[0], params)
606 dev[0].request("SET sae_groups 5")
607 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412",
609 ev = dev[0].wait_event(["SME: Trying to authenticate"], timeout=3)
611 raise Exception("Did not try to authenticate")
612 ev = dev[0].wait_event(["SME: Trying to authenticate"], timeout=3)
614 raise Exception("Did not try to authenticate (2)")
615 dev[0].request("REMOVE_NETWORK all")
617 def sae_reflection_attack(apdev, dev, group):
618 if "SAE" not in dev.get_capability("auth_alg"):
619 raise HwsimSkip("SAE not supported")
620 params = hostapd.wpa2_params(ssid="test-sae",
621 passphrase="no-knowledge-of-passphrase")
622 params['wpa_key_mgmt'] = 'SAE'
623 hapd = hostapd.add_ap(apdev, params)
624 bssid = apdev['bssid']
626 dev.scan_for_bss(bssid, freq=2412)
627 hapd.set("ext_mgmt_frame_handling", "1")
629 dev.request("SET sae_groups %d" % group)
630 dev.connect("test-sae", psk="reflection-attack", key_mgmt="SAE",
631 scan_freq="2412", wait_connect=False)
634 for i in range(0, 10):
637 raise Exception("MGMT RX wait timed out")
638 if req['subtype'] == 11:
642 raise Exception("Authentication frame not received")
645 resp['fc'] = req['fc']
646 resp['da'] = req['sa']
647 resp['sa'] = req['da']
648 resp['bssid'] = req['bssid']
649 resp['payload'] = req['payload']
653 req = hapd.mgmt_rx(timeout=0.5)
655 if req['subtype'] == 11:
656 raise Exception("Unexpected Authentication frame seen")
659 def test_sae_reflection_attack_ecc(dev, apdev):
660 """SAE reflection attack (ECC)"""
661 sae_reflection_attack(apdev[0], dev[0], 19)
664 def test_sae_reflection_attack_ffc(dev, apdev):
665 """SAE reflection attack (FFC)"""
666 sae_reflection_attack(apdev[0], dev[0], 5)
669 def test_sae_anti_clogging_proto(dev, apdev):
670 """SAE anti clogging protocol testing"""
671 if "SAE" not in dev[0].get_capability("auth_alg"):
672 raise HwsimSkip("SAE not supported")
673 params = hostapd.wpa2_params(ssid="test-sae",
674 passphrase="no-knowledge-of-passphrase")
675 params['wpa_key_mgmt'] = 'SAE'
676 hapd = hostapd.add_ap(apdev[0], params)
677 bssid = apdev[0]['bssid']
679 dev[0].scan_for_bss(bssid, freq=2412)
680 hapd.set("ext_mgmt_frame_handling", "1")
682 dev[0].request("SET sae_groups ")
683 dev[0].connect("test-sae", psk="anti-cloggign", key_mgmt="SAE",
684 scan_freq="2412", wait_connect=False)
687 for i in range(0, 10):
690 raise Exception("MGMT RX wait timed out")
691 if req['subtype'] == 11:
695 raise Exception("Authentication frame not received")
698 resp['fc'] = req['fc']
699 resp['da'] = req['sa']
700 resp['sa'] = req['da']
701 resp['bssid'] = req['bssid']
702 resp['payload'] = binascii.unhexlify("030001004c00" + "ffff00")
705 # Confirm (not received due to DH group being rejected)
706 req = hapd.mgmt_rx(timeout=0.5)
708 if req['subtype'] == 11:
709 raise Exception("Unexpected Authentication frame seen")
712 def test_sae_no_random(dev, apdev):
713 """SAE and no random numbers available"""
714 if "SAE" not in dev[0].get_capability("auth_alg"):
715 raise HwsimSkip("SAE not supported")
716 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
717 params['wpa_key_mgmt'] = 'SAE'
718 hapd = hostapd.add_ap(apdev[0], params)
720 dev[0].request("SET sae_groups ")
721 tests = [ (1, "os_get_random;sae_get_rand"),
722 (1, "os_get_random;get_rand_1_to_p_1"),
723 (1, "os_get_random;get_random_qr_qnr"),
724 (1, "os_get_random;sae_derive_pwe_ecc") ]
725 for count, func in tests:
726 with fail_test(dev[0], count, func):
727 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
729 dev[0].request("REMOVE_NETWORK all")
730 dev[0].wait_disconnected()
733 def test_sae_pwe_failure(dev, apdev):
734 """SAE and pwe failure"""
735 if "SAE" not in dev[0].get_capability("auth_alg"):
736 raise HwsimSkip("SAE not supported")
737 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
738 params['wpa_key_mgmt'] = 'SAE'
739 params['sae_groups'] = '19 5'
740 hapd = hostapd.add_ap(apdev[0], params)
742 dev[0].request("SET sae_groups 19")
743 with fail_test(dev[0], 1, "hmac_sha256_vector;sae_derive_pwe_ecc"):
744 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
746 dev[0].request("REMOVE_NETWORK all")
747 dev[0].wait_disconnected()
748 with fail_test(dev[0], 1, "sae_test_pwd_seed_ecc"):
749 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
751 dev[0].request("REMOVE_NETWORK all")
752 dev[0].wait_disconnected()
754 dev[0].request("SET sae_groups 5")
755 with fail_test(dev[0], 1, "hmac_sha256_vector;sae_derive_pwe_ffc"):
756 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
758 dev[0].request("REMOVE_NETWORK all")
759 dev[0].wait_disconnected()
761 dev[0].request("SET sae_groups 5")
762 with fail_test(dev[0], 1, "sae_test_pwd_seed_ffc"):
763 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
765 dev[0].request("REMOVE_NETWORK all")
766 dev[0].wait_disconnected()
767 with fail_test(dev[0], 2, "sae_test_pwd_seed_ffc"):
768 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
770 dev[0].request("REMOVE_NETWORK all")
771 dev[0].wait_disconnected()
774 def test_sae_bignum_failure(dev, apdev):
775 """SAE and bignum failure"""
776 if "SAE" not in dev[0].get_capability("auth_alg"):
777 raise HwsimSkip("SAE not supported")
778 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
779 params['wpa_key_mgmt'] = 'SAE'
780 params['sae_groups'] = '19 5 22'
781 hapd = hostapd.add_ap(apdev[0], params)
783 dev[0].request("SET sae_groups 19")
784 tests = [ (1, "crypto_bignum_init_set;get_rand_1_to_p_1"),
785 (1, "crypto_bignum_init;is_quadratic_residue_blind"),
786 (1, "crypto_bignum_mulmod;is_quadratic_residue_blind"),
787 (2, "crypto_bignum_mulmod;is_quadratic_residue_blind"),
788 (3, "crypto_bignum_mulmod;is_quadratic_residue_blind"),
789 (1, "crypto_bignum_legendre;is_quadratic_residue_blind"),
790 (1, "crypto_bignum_init_set;sae_test_pwd_seed_ecc"),
791 (1, "crypto_ec_point_compute_y_sqr;sae_test_pwd_seed_ecc"),
792 (1, "crypto_bignum_init_set;get_random_qr_qnr"),
793 (1, "crypto_bignum_to_bin;sae_derive_pwe_ecc"),
794 (1, "crypto_ec_point_init;sae_derive_pwe_ecc"),
795 (1, "crypto_ec_point_solve_y_coord;sae_derive_pwe_ecc"),
796 (1, "crypto_ec_point_init;sae_derive_commit_element_ecc"),
797 (1, "crypto_ec_point_mul;sae_derive_commit_element_ecc"),
798 (1, "crypto_ec_point_invert;sae_derive_commit_element_ecc"),
799 (1, "crypto_bignum_init;=sae_derive_commit"),
800 (1, "crypto_ec_point_init;sae_derive_k_ecc"),
801 (1, "crypto_ec_point_mul;sae_derive_k_ecc"),
802 (1, "crypto_ec_point_add;sae_derive_k_ecc"),
803 (2, "crypto_ec_point_mul;sae_derive_k_ecc"),
804 (1, "crypto_ec_point_to_bin;sae_derive_k_ecc"),
805 (1, "crypto_bignum_legendre;get_random_qr_qnr"),
806 (1, "sha256_prf;sae_derive_keys"),
807 (1, "crypto_bignum_init;sae_derive_keys"),
808 (1, "crypto_bignum_init_set;sae_parse_commit_scalar"),
809 (1, "crypto_bignum_to_bin;sae_parse_commit_element_ecc"),
810 (1, "crypto_ec_point_from_bin;sae_parse_commit_element_ecc") ]
811 for count, func in tests:
812 with fail_test(dev[0], count, func):
813 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
814 scan_freq="2412", wait_connect=False)
815 wait_fail_trigger(dev[0], "GET_FAIL")
816 dev[0].request("REMOVE_NETWORK all")
818 dev[0].request("SET sae_groups 5")
819 tests = [ (1, "crypto_bignum_init_set;sae_set_group"),
820 (2, "crypto_bignum_init_set;sae_set_group"),
821 (1, "crypto_bignum_init_set;sae_get_rand"),
822 (1, "crypto_bignum_init_set;sae_test_pwd_seed_ffc"),
823 (1, "crypto_bignum_exptmod;sae_test_pwd_seed_ffc"),
824 (1, "crypto_bignum_init;sae_derive_pwe_ffc"),
825 (1, "crypto_bignum_init;sae_derive_commit_element_ffc"),
826 (1, "crypto_bignum_exptmod;sae_derive_commit_element_ffc"),
827 (1, "crypto_bignum_inverse;sae_derive_commit_element_ffc"),
828 (1, "crypto_bignum_init;sae_derive_k_ffc"),
829 (1, "crypto_bignum_exptmod;sae_derive_k_ffc"),
830 (1, "crypto_bignum_mulmod;sae_derive_k_ffc"),
831 (2, "crypto_bignum_exptmod;sae_derive_k_ffc"),
832 (1, "crypto_bignum_to_bin;sae_derive_k_ffc"),
833 (1, "crypto_bignum_init_set;sae_parse_commit_element_ffc"),
834 (1, "crypto_bignum_init;sae_parse_commit_element_ffc"),
835 (2, "crypto_bignum_init_set;sae_parse_commit_element_ffc"),
836 (1, "crypto_bignum_exptmod;sae_parse_commit_element_ffc") ]
837 for count, func in tests:
838 with fail_test(dev[0], count, func):
839 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
840 scan_freq="2412", wait_connect=False)
841 wait_fail_trigger(dev[0], "GET_FAIL")
842 dev[0].request("REMOVE_NETWORK all")
844 dev[0].request("SET sae_groups 22")
845 tests = [ (1, "crypto_bignum_init_set;sae_test_pwd_seed_ffc"),
846 (1, "crypto_bignum_sub;sae_test_pwd_seed_ffc"),
847 (1, "crypto_bignum_div;sae_test_pwd_seed_ffc") ]
848 for count, func in tests:
849 with fail_test(dev[0], count, func):
850 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
851 scan_freq="2412", wait_connect=False)
852 wait_fail_trigger(dev[0], "GET_FAIL")
853 dev[0].request("REMOVE_NETWORK all")