]> git.ipfire.org Git - thirdparty/hostap.git/blob - tests/hwsim/test_sae.py
tests: More SAE OOM coverage
[thirdparty/hostap.git] / tests / hwsim / test_sae.py
1 # Test cases for SAE
2 # Copyright (c) 2013-2016, Jouni Malinen <j@w1.fi>
3 #
4 # This software may be distributed under the terms of the BSD license.
5 # See README for more details.
6
7 from remotehost import remote_compatible
8 import binascii
9 import os
10 import time
11 import logging
12 logger = logging.getLogger()
13
14 import hwsim_utils
15 import hostapd
16 from 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
18
19 @remote_compatible
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)
31
32 dev[0].request("SET sae_groups ")
33 id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
34 scan_freq="2412")
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'])
42
43 @remote_compatible
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)
52
53 dev[0].request("SET sae_groups 19")
54
55 for i in range(10):
56 password = "12345678-" + str(i)
57 hapd.set("wpa_passphrase", password)
58 dev[0].connect("test-sae", psk=password, key_mgmt="SAE",
59 scan_freq="2412")
60 dev[0].request("REMOVE_NETWORK all")
61 dev[0].wait_disconnected()
62
63 @remote_compatible
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)
73
74 dev[0].request("SET sae_groups 22")
75
76 for i in range(10):
77 password = "12345678-" + str(i)
78 hapd.set("wpa_passphrase", password)
79 dev[0].connect("test-sae", psk=password, key_mgmt="SAE",
80 scan_freq="2412")
81 dev[0].request("REMOVE_NETWORK all")
82 dev[0].wait_disconnected()
83
84 @remote_compatible
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)
93
94 dev[0].request("SET sae_groups ")
95 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
96 scan_freq="2412")
97 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
98 if ev is None:
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")
106
107 @remote_compatible
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)
117
118 dev[0].request("SET sae_groups ")
119 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
120 scan_freq="2412")
121 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
122 if ev is None:
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")
130
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)
151
152 for g in groups:
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)
159 if ev is None:
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)
162 time.sleep(0.1)
163 dev[0].dump_monitor()
164 continue
165 logger.info("Connection with heavy SAE group " + g)
166 else:
167 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
168 if ev is None:
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()
173 continue
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()
180
181 @remote_compatible
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)
191
192 dev[0].request("SET sae_groups 25 26 20 19")
193 dev[0].connect("test-sae-group-nego", psk="12345678", key_mgmt="SAE",
194 scan_freq="2412")
195 if dev[0].get_status_field('sae_group') != '19':
196 raise Exception("Expected SAE group not used")
197
198 @remote_compatible
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)
207
208 dev[0].request("SET sae_groups ")
209 dev[1].request("SET sae_groups ")
210 id = {}
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)
219
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",
232 scan_freq="2412")
233
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)
242
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",
247 scan_freq="2412")
248
249 @remote_compatible
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)
258
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)
264 if ev is None:
265 raise Exception("Invalid network not temporarily disabled")
266
267
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)
276
277 pid = find_wpas_process(dev[0])
278
279 dev[0].request("SET sae_groups ")
280 id = dev[0].connect("test-sae", psk=password, key_mgmt="SAE",
281 scan_freq="2412")
282
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.
286 time.sleep(1)
287 dev[0].ping()
288 buf = read_process_memory(pid, password)
289
290 dev[0].request("DISCONNECT")
291 dev[0].wait_disconnected()
292
293 dev[0].relog()
294 sae_k = None
295 sae_keyseed = None
296 sae_kck = None
297 pmk = None
298 ptk = None
299 gtk = None
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")
322 if len(gtk) != 16:
323 raise Exception("Unexpected GTK length")
324
325 kck = ptk[0:16]
326 kek = ptk[16:32]
327 tk = ptk[32:48]
328
329 fname = os.path.join(params['logdir'],
330 'sae_key_lifetime_in_memory.memctx-')
331
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")
337 if pmk not in buf:
338 raise HwsimSkip("PMK not found while associated")
339 if kck not in buf:
340 raise Exception("KCK not found while associated")
341 if kek not in buf:
342 raise Exception("KEK not found while associated")
343 if tk in buf:
344 raise Exception("TK found from memory")
345 if gtk in buf:
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)")
351
352 logger.info("Checking keys in memory after disassociation")
353 buf = read_process_memory(pid, password)
354
355 # Note: Password is still present in network configuration
356 # Note: PMK is in PMKSA cache
357
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)")
367
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")
374
375 dev[0].request("REMOVE_NETWORK all")
376
377 logger.info("Checking keys in memory after network profile removal")
378 buf = read_process_memory(pid, password)
379
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)")
391
392 @remote_compatible
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)
401
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",
408 scan_freq="2412")
409 dev[0].request("REMOVE_NETWORK all")
410
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",
414 scan_freq="2412")
415 dev[0].request("REMOVE_NETWORK all")
416
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",
419 scan_freq="2412")
420 dev[0].request("REMOVE_NETWORK all")
421
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")
427
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")
433
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")
439
440 @remote_compatible
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']
450
451 dev[0].request("SET sae_groups 19")
452
453 tests = [ ("Confirm mismatch",
454 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
455 "0000800edebc3f260dc1fe7e0b20888af2b8a3316252ec37388a8504e25b73dc4240"),
456 ("Commit without even full cyclic group field",
457 "13",
458 None),
459 ("Too short commit",
460 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02",
461 None),
462 ("Invalid commit scalar (0)",
463 "1300" + "0000000000000000000000000000000000000000000000000000000000000000" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
464 None),
465 ("Invalid commit scalar (1)",
466 "1300" + "0000000000000000000000000000000000000000000000000000000000000001" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
467 None),
468 ("Invalid commit scalar (> r)",
469 "1300" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
470 None),
471 ("Commit element not on curve",
472 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728d0000000000000000000000000000000000000000000000000000000000000000",
473 None),
474 ("Invalid commit element (y coordinate > P)",
475 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
476 None),
477 ("Invalid commit element (x coordinate > P)",
478 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
479 None),
480 ("Different group in commit",
481 "1400" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
482 None),
483 ("Too short confirm",
484 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
485 "0000800edebc3f260dc1fe7e0b20888af2b8a3316252ec37388a8504e25b73dc42")]
486 for (note, commit, confirm) in tests:
487 logger.info(note)
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)
492
493 logger.info("Commit")
494 for i in range(0, 10):
495 req = hapd.mgmt_rx()
496 if req is None:
497 raise Exception("MGMT RX wait timed out (commit)")
498 if req['subtype'] == 11:
499 break
500 req = None
501 if not req:
502 raise Exception("Authentication frame (commit) not received")
503
504 hapd.dump_monitor()
505 resp = {}
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)
511 hapd.mgmt_tx(resp)
512
513 if confirm:
514 logger.info("Confirm")
515 for i in range(0, 10):
516 req = hapd.mgmt_rx()
517 if req is None:
518 raise Exception("MGMT RX wait timed out (confirm)")
519 if req['subtype'] == 11:
520 break
521 req = None
522 if not req:
523 raise Exception("Authentication frame (confirm) not received")
524
525 hapd.dump_monitor()
526 resp = {}
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)
532 hapd.mgmt_tx(resp)
533
534 time.sleep(0.1)
535 dev[0].request("REMOVE_NETWORK all")
536 hapd.set("ext_mgmt_frame_handling", "0")
537 hapd.dump_monitor()
538
539 @remote_compatible
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']
549
550 dev[0].request("SET sae_groups 2")
551
552 tests = [ ("Confirm mismatch",
553 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "a8c00117493cdffa5dd671e934bc9cb1a69f39e25e9dd9cd9afd3aea2441a0f5491211c7ba50a753563f9ce943b043557cb71193b28e86ed9544f4289c471bf91b70af5c018cf4663e004165b0fd0bc1d8f3f78adf42eee92bcbc55246fd3ee9f107ab965dc7d4986f23eb71d616ebfe6bfe0a6c1ac5dc1718acee17c9a17486",
554 "0000f3116a9731f1259622e3eb55d4b3b50ba16f8c5f5565b28e609b180c51460251"),
555 ("Too short commit",
556 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "a8c00117493cdffa5dd671e934bc9cb1a69f39e25e9dd9cd9afd3aea2441a0f5491211c7ba50a753563f9ce943b043557cb71193b28e86ed9544f4289c471bf91b70af5c018cf4663e004165b0fd0bc1d8f3f78adf42eee92bcbc55246fd3ee9f107ab965dc7d4986f23eb71d616ebfe6bfe0a6c1ac5dc1718acee17c9a174",
557 None),
558 ("Invalid element (0) in commit",
559 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
560 None),
561 ("Invalid element (1) in commit",
562 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
563 None),
564 ("Invalid element (> P) in commit",
565 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
566 None) ]
567 for (note, commit, confirm) in tests:
568 logger.info(note)
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)
573
574 logger.info("Commit")
575 for i in range(0, 10):
576 req = hapd.mgmt_rx()
577 if req is None:
578 raise Exception("MGMT RX wait timed out (commit)")
579 if req['subtype'] == 11:
580 break
581 req = None
582 if not req:
583 raise Exception("Authentication frame (commit) not received")
584
585 hapd.dump_monitor()
586 resp = {}
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)
592 hapd.mgmt_tx(resp)
593
594 if confirm:
595 logger.info("Confirm")
596 for i in range(0, 10):
597 req = hapd.mgmt_rx()
598 if req is None:
599 raise Exception("MGMT RX wait timed out (confirm)")
600 if req['subtype'] == 11:
601 break
602 req = None
603 if not req:
604 raise Exception("Authentication frame (confirm) not received")
605
606 hapd.dump_monitor()
607 resp = {}
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)
613 hapd.mgmt_tx(resp)
614
615 time.sleep(0.1)
616 dev[0].request("REMOVE_NETWORK all")
617 hapd.set("ext_mgmt_frame_handling", "0")
618 hapd.dump_monitor()
619
620 @remote_compatible
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)
628
629 dev[0].request("SET sae_groups 5")
630 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412",
631 wait_connect=False)
632 ev = dev[0].wait_event(["SME: Trying to authenticate"], timeout=3)
633 if ev is None:
634 raise Exception("Did not try to authenticate")
635 ev = dev[0].wait_event(["SME: Trying to authenticate"], timeout=3)
636 if ev is None:
637 raise Exception("Did not try to authenticate (2)")
638 dev[0].request("REMOVE_NETWORK all")
639
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']
648
649 dev.scan_for_bss(bssid, freq=2412)
650 hapd.set("ext_mgmt_frame_handling", "1")
651
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)
655
656 # Commit
657 for i in range(0, 10):
658 req = hapd.mgmt_rx()
659 if req is None:
660 raise Exception("MGMT RX wait timed out")
661 if req['subtype'] == 11:
662 break
663 req = None
664 if not req:
665 raise Exception("Authentication frame not received")
666
667 resp = {}
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']
673 hapd.mgmt_tx(resp)
674
675 # Confirm
676 req = hapd.mgmt_rx(timeout=0.5)
677 if req is not None:
678 if req['subtype'] == 11:
679 raise Exception("Unexpected Authentication frame seen")
680
681 @remote_compatible
682 def test_sae_reflection_attack_ecc(dev, apdev):
683 """SAE reflection attack (ECC)"""
684 sae_reflection_attack(apdev[0], dev[0], 19)
685
686 @remote_compatible
687 def test_sae_reflection_attack_ffc(dev, apdev):
688 """SAE reflection attack (FFC)"""
689 sae_reflection_attack(apdev[0], dev[0], 5)
690
691 @remote_compatible
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']
701
702 dev[0].scan_for_bss(bssid, freq=2412)
703 hapd.set("ext_mgmt_frame_handling", "1")
704
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)
708
709 # Commit
710 for i in range(0, 10):
711 req = hapd.mgmt_rx()
712 if req is None:
713 raise Exception("MGMT RX wait timed out")
714 if req['subtype'] == 11:
715 break
716 req = None
717 if not req:
718 raise Exception("Authentication frame not received")
719
720 resp = {}
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")
726 hapd.mgmt_tx(resp)
727
728 # Confirm (not received due to DH group being rejected)
729 req = hapd.mgmt_rx(timeout=0.5)
730 if req is not None:
731 if req['subtype'] == 11:
732 raise Exception("Unexpected Authentication frame seen")
733
734 @remote_compatible
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)
742
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",
751 scan_freq="2412")
752 dev[0].request("REMOVE_NETWORK all")
753 dev[0].wait_disconnected()
754
755 @remote_compatible
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)
764
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",
768 scan_freq="2412")
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",
773 scan_freq="2412")
774 dev[0].request("REMOVE_NETWORK all")
775 dev[0].wait_disconnected()
776
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",
780 scan_freq="2412")
781 dev[0].request("REMOVE_NETWORK all")
782 dev[0].wait_disconnected()
783
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",
787 scan_freq="2412")
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",
792 scan_freq="2412")
793 dev[0].request("REMOVE_NETWORK all")
794 dev[0].wait_disconnected()
795
796 @remote_compatible
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)
805
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")
840
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")
866
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")