]> git.ipfire.org Git - thirdparty/hostap.git/blame - tests/hwsim/test_sae.py
tests: Write GTK locations into debug log in key_lifetime_in_memory
[thirdparty/hostap.git] / tests / hwsim / test_sae.py
CommitLineData
1640a2e4 1# Test cases for SAE
10ba4ae4 2# Copyright (c) 2013-2015, Jouni Malinen <j@w1.fi>
1640a2e4
JM
3#
4# This software may be distributed under the terms of the BSD license.
5# See README for more details.
6
5b3c40a6
JM
7import binascii
8import os
1640a2e4
JM
9import time
10import subprocess
11import logging
12logger = logging.getLogger()
13
14import hwsim_utils
15import hostapd
10ba4ae4 16from utils import HwsimSkip, alloc_fail, fail_test
5b3c40a6 17from test_ap_psk import find_wpas_process, read_process_memory, verify_not_present, get_key_locations
1640a2e4
JM
18
19def test_sae(dev, apdev):
20 """SAE with default group"""
b9749b6a
JM
21 if "SAE" not in dev[0].get_capability("auth_alg"):
22 raise HwsimSkip("SAE not supported")
1640a2e4
JM
23 params = hostapd.wpa2_params(ssid="test-sae",
24 passphrase="12345678")
25 params['wpa_key_mgmt'] = 'SAE'
65038313
JM
26 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
27 key_mgmt = hapd.get_config()['key_mgmt']
28 if key_mgmt.split(' ')[0] != "SAE":
29 raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
1640a2e4
JM
30
31 dev[0].request("SET sae_groups ")
32 id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
33 scan_freq="2412")
34 if dev[0].get_status_field('sae_group') != '19':
35 raise Exception("Expected default SAE group not used")
d463c556
JM
36 bss = dev[0].get_bss(apdev[0]['bssid'])
37 if 'flags' not in bss:
38 raise Exception("Could not get BSS flags from BSS table")
39 if "[WPA2-SAE-CCMP]" not in bss['flags']:
40 raise Exception("Unexpected BSS flags: " + bss['flags'])
1640a2e4 41
33dcced5
JM
42def test_sae_password_ecc(dev, apdev):
43 """SAE with number of different passwords (ECC)"""
44 if "SAE" not in dev[0].get_capability("auth_alg"):
45 raise HwsimSkip("SAE not supported")
46 params = hostapd.wpa2_params(ssid="test-sae",
47 passphrase="12345678")
48 params['wpa_key_mgmt'] = 'SAE'
49 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
50
51 dev[0].request("SET sae_groups 19")
52
53 for i in range(10):
54 password = "12345678-" + str(i)
55 hapd.set("wpa_passphrase", password)
56 dev[0].connect("test-sae", psk=password, key_mgmt="SAE",
57 scan_freq="2412")
58 dev[0].request("REMOVE_NETWORK all")
59 dev[0].wait_disconnected()
60
61def test_sae_password_ffc(dev, apdev):
62 """SAE with number of different passwords (FFC)"""
63 if "SAE" not in dev[0].get_capability("auth_alg"):
64 raise HwsimSkip("SAE not supported")
65 params = hostapd.wpa2_params(ssid="test-sae",
66 passphrase="12345678")
67 params['wpa_key_mgmt'] = 'SAE'
68 params['sae_groups'] = '22'
69 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
70
71 dev[0].request("SET sae_groups 22")
72
73 for i in range(10):
74 password = "12345678-" + str(i)
75 hapd.set("wpa_passphrase", password)
76 dev[0].connect("test-sae", psk=password, key_mgmt="SAE",
77 scan_freq="2412")
78 dev[0].request("REMOVE_NETWORK all")
79 dev[0].wait_disconnected()
80
19d3a6e3
JM
81def test_sae_pmksa_caching(dev, apdev):
82 """SAE and PMKSA caching"""
b9749b6a
JM
83 if "SAE" not in dev[0].get_capability("auth_alg"):
84 raise HwsimSkip("SAE not supported")
19d3a6e3
JM
85 params = hostapd.wpa2_params(ssid="test-sae",
86 passphrase="12345678")
87 params['wpa_key_mgmt'] = 'SAE'
88 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
89
90 dev[0].request("SET sae_groups ")
91 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
92 scan_freq="2412")
7cc9a81f
JM
93 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
94 if ev is None:
95 raise Exception("No connection event received from hostapd")
19d3a6e3 96 dev[0].request("DISCONNECT")
7cc9a81f 97 dev[0].wait_disconnected()
19d3a6e3 98 dev[0].request("RECONNECT")
5f35a5e2 99 dev[0].wait_connected(timeout=15, error="Reconnect timed out")
19d3a6e3
JM
100 if dev[0].get_status_field('sae_group') is not None:
101 raise Exception("SAE group claimed to have been used")
102
103def test_sae_pmksa_caching_disabled(dev, apdev):
104 """SAE and PMKSA caching disabled"""
b9749b6a
JM
105 if "SAE" not in dev[0].get_capability("auth_alg"):
106 raise HwsimSkip("SAE not supported")
19d3a6e3
JM
107 params = hostapd.wpa2_params(ssid="test-sae",
108 passphrase="12345678")
109 params['wpa_key_mgmt'] = 'SAE'
110 params['disable_pmksa_caching'] = '1'
111 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
112
113 dev[0].request("SET sae_groups ")
114 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
115 scan_freq="2412")
7cc9a81f
JM
116 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
117 if ev is None:
118 raise Exception("No connection event received from hostapd")
19d3a6e3 119 dev[0].request("DISCONNECT")
7cc9a81f 120 dev[0].wait_disconnected()
19d3a6e3 121 dev[0].request("RECONNECT")
5f35a5e2 122 dev[0].wait_connected(timeout=15, error="Reconnect timed out")
19d3a6e3
JM
123 if dev[0].get_status_field('sae_group') != '19':
124 raise Exception("Expected default SAE group not used")
125
1640a2e4
JM
126def test_sae_groups(dev, apdev):
127 """SAE with all supported groups"""
b9749b6a
JM
128 if "SAE" not in dev[0].get_capability("auth_alg"):
129 raise HwsimSkip("SAE not supported")
b1f487cb
JM
130 # This is the full list of supported groups, but groups 14-16 (2048-4096 bit
131 # MODP) and group 21 (521-bit random ECP group) are a bit too slow on some
132 # VMs and can result in hitting the mac80211 authentication timeout, so
133 # allow them to fail and just report such failures in the debug log.
134 sae_groups = [ 19, 25, 26, 20, 21, 2, 5, 14, 15, 16, 22, 23, 24 ]
9e286d5e
JM
135 tls = dev[0].request("GET tls_library")
136 if tls.startswith("OpenSSL") and "build=OpenSSL 1.0.2" in tls and "run=OpenSSL 1.0.2" in tls:
137 logger.info("Add Brainpool EC groups since OpenSSL is new enough")
138 sae_groups += [ 27, 28, 29, 30 ]
b1f487cb 139 heavy_groups = [ 14, 15, 16 ]
1640a2e4
JM
140 groups = [str(g) for g in sae_groups]
141 params = hostapd.wpa2_params(ssid="test-sae-groups",
142 passphrase="12345678")
143 params['wpa_key_mgmt'] = 'SAE'
144 params['sae_groups'] = ' '.join(groups)
145 hostapd.add_ap(apdev[0]['ifname'], params)
146
147 for g in groups:
148 logger.info("Testing SAE group " + g)
149 dev[0].request("SET sae_groups " + g)
150 id = dev[0].connect("test-sae-groups", psk="12345678", key_mgmt="SAE",
b1f487cb
JM
151 scan_freq="2412", wait_connect=False)
152 if int(g) in heavy_groups:
153 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=5)
154 if ev is None:
155 logger.info("No connection with heavy SAE group %s did not connect - likely hitting timeout in mac80211" % g)
156 dev[0].remove_network(id)
157 time.sleep(0.1)
158 dev[0].dump_monitor()
159 continue
160 logger.info("Connection with heavy SAE group " + g)
161 else:
a68d1792
JM
162 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
163 if ev is None:
164 if "BoringSSL" in tls and int(g) in [ 25 ]:
165 logger.info("Ignore connection failure with group " + g + " with BoringSSL")
166 dev[0].remove_network(id)
167 dev[0].dump_monitor()
168 continue
169 raise Exception("Connection timed out with group " + g)
1640a2e4
JM
170 if dev[0].get_status_field('sae_group') != g:
171 raise Exception("Expected SAE group not used")
172 dev[0].remove_network(id)
b1f487cb
JM
173 dev[0].wait_disconnected()
174 dev[0].dump_monitor()
1640a2e4
JM
175
176def test_sae_group_nego(dev, apdev):
177 """SAE group negotiation"""
b9749b6a
JM
178 if "SAE" not in dev[0].get_capability("auth_alg"):
179 raise HwsimSkip("SAE not supported")
1640a2e4
JM
180 params = hostapd.wpa2_params(ssid="test-sae-group-nego",
181 passphrase="12345678")
182 params['wpa_key_mgmt'] = 'SAE'
183 params['sae_groups'] = '19'
184 hostapd.add_ap(apdev[0]['ifname'], params)
185
186 dev[0].request("SET sae_groups 25 26 20 19")
187 dev[0].connect("test-sae-group-nego", psk="12345678", key_mgmt="SAE",
188 scan_freq="2412")
189 if dev[0].get_status_field('sae_group') != '19':
190 raise Exception("Expected SAE group not used")
a6cf5cd6
JM
191
192def test_sae_anti_clogging(dev, apdev):
193 """SAE anti clogging"""
b9749b6a
JM
194 if "SAE" not in dev[0].get_capability("auth_alg"):
195 raise HwsimSkip("SAE not supported")
a6cf5cd6
JM
196 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
197 params['wpa_key_mgmt'] = 'SAE'
198 params['sae_anti_clogging_threshold'] = '1'
199 hostapd.add_ap(apdev[0]['ifname'], params)
200
201 dev[0].request("SET sae_groups ")
202 dev[1].request("SET sae_groups ")
203 id = {}
204 for i in range(0, 2):
205 dev[i].scan(freq="2412")
206 id[i] = dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE",
207 scan_freq="2412", only_add_network=True)
208 for i in range(0, 2):
209 dev[i].select_network(id[i])
210 for i in range(0, 2):
5f35a5e2 211 dev[i].wait_connected(timeout=10)
d05ff960
JM
212
213def test_sae_forced_anti_clogging(dev, apdev):
214 """SAE anti clogging (forced)"""
b9749b6a
JM
215 if "SAE" not in dev[0].get_capability("auth_alg"):
216 raise HwsimSkip("SAE not supported")
d05ff960 217 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
fd4709ff 218 params['wpa_key_mgmt'] = 'SAE WPA-PSK'
d05ff960
JM
219 params['sae_anti_clogging_threshold'] = '0'
220 hostapd.add_ap(apdev[0]['ifname'], params)
fd4709ff 221 dev[2].connect("test-sae", psk="12345678", scan_freq="2412")
d05ff960
JM
222 for i in range(0, 2):
223 dev[i].request("SET sae_groups ")
224 dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE",
225 scan_freq="2412")
226
227def test_sae_mixed(dev, apdev):
228 """Mixed SAE and non-SAE network"""
b9749b6a
JM
229 if "SAE" not in dev[0].get_capability("auth_alg"):
230 raise HwsimSkip("SAE not supported")
d05ff960
JM
231 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
232 params['wpa_key_mgmt'] = 'SAE WPA-PSK'
233 params['sae_anti_clogging_threshold'] = '0'
234 hostapd.add_ap(apdev[0]['ifname'], params)
235
236 dev[2].connect("test-sae", psk="12345678", scan_freq="2412")
237 for i in range(0, 2):
238 dev[i].request("SET sae_groups ")
239 dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE",
240 scan_freq="2412")
acb63c75
JM
241
242def test_sae_missing_password(dev, apdev):
243 """SAE and missing password"""
b9749b6a
JM
244 if "SAE" not in dev[0].get_capability("auth_alg"):
245 raise HwsimSkip("SAE not supported")
acb63c75
JM
246 params = hostapd.wpa2_params(ssid="test-sae",
247 passphrase="12345678")
248 params['wpa_key_mgmt'] = 'SAE'
249 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
250
251 dev[0].request("SET sae_groups ")
252 id = dev[0].connect("test-sae",
253 raw_psk="46b4a73b8a951ad53ebd2e0afdb9c5483257edd4c21d12b7710759da70945858",
254 key_mgmt="SAE", scan_freq="2412", wait_connect=False)
255 ev = dev[0].wait_event(['CTRL-EVENT-SSID-TEMP-DISABLED'], timeout=10)
256 if ev is None:
257 raise Exception("Invalid network not temporarily disabled")
5b3c40a6
JM
258
259
260def test_sae_key_lifetime_in_memory(dev, apdev, params):
261 """SAE and key lifetime in memory"""
b9749b6a
JM
262 if "SAE" not in dev[0].get_capability("auth_alg"):
263 raise HwsimSkip("SAE not supported")
5b3c40a6
JM
264 password = "5ad144a7c1f5a5503baa6fa01dabc15b1843e8c01662d78d16b70b5cd23cf8b"
265 p = hostapd.wpa2_params(ssid="test-sae", passphrase=password)
266 p['wpa_key_mgmt'] = 'SAE'
267 hapd = hostapd.add_ap(apdev[0]['ifname'], p)
268
269 pid = find_wpas_process(dev[0])
270
271 dev[0].request("SET sae_groups ")
272 id = dev[0].connect("test-sae", psk=password, key_mgmt="SAE",
273 scan_freq="2412")
274
54f2cae2 275 time.sleep(1)
5b3c40a6
JM
276 buf = read_process_memory(pid, password)
277
278 dev[0].request("DISCONNECT")
279 dev[0].wait_disconnected()
280
281 dev[0].relog()
282 sae_k = None
283 sae_keyseed = None
284 sae_kck = None
285 pmk = None
286 ptk = None
287 gtk = None
288 with open(os.path.join(params['logdir'], 'log0'), 'r') as f:
289 for l in f.readlines():
290 if "SAE: k - hexdump" in l:
291 val = l.strip().split(':')[3].replace(' ', '')
292 sae_k = binascii.unhexlify(val)
293 if "SAE: keyseed - hexdump" in l:
294 val = l.strip().split(':')[3].replace(' ', '')
295 sae_keyseed = binascii.unhexlify(val)
296 if "SAE: KCK - hexdump" in l:
297 val = l.strip().split(':')[3].replace(' ', '')
298 sae_kck = binascii.unhexlify(val)
299 if "SAE: PMK - hexdump" in l:
300 val = l.strip().split(':')[3].replace(' ', '')
301 pmk = binascii.unhexlify(val)
302 if "WPA: PTK - hexdump" in l:
303 val = l.strip().split(':')[3].replace(' ', '')
304 ptk = binascii.unhexlify(val)
305 if "WPA: Group Key - hexdump" in l:
306 val = l.strip().split(':')[3].replace(' ', '')
307 gtk = binascii.unhexlify(val)
308 if not sae_k or not sae_keyseed or not sae_kck or not pmk or not ptk or not gtk:
309 raise Exception("Could not find keys from debug log")
310 if len(gtk) != 16:
311 raise Exception("Unexpected GTK length")
312
313 kck = ptk[0:16]
314 kek = ptk[16:32]
315 tk = ptk[32:48]
316
317 fname = os.path.join(params['logdir'],
318 'sae_key_lifetime_in_memory.memctx-')
319
320 logger.info("Checking keys in memory while associated")
321 get_key_locations(buf, password, "Password")
322 get_key_locations(buf, pmk, "PMK")
323 if password not in buf:
81e787b7 324 raise HwsimSkip("Password not found while associated")
5b3c40a6 325 if pmk not in buf:
81e787b7 326 raise HwsimSkip("PMK not found while associated")
5b3c40a6
JM
327 if kck not in buf:
328 raise Exception("KCK not found while associated")
329 if kek not in buf:
330 raise Exception("KEK not found while associated")
331 if tk in buf:
332 raise Exception("TK found from memory")
333 if gtk in buf:
8eb45bde 334 get_key_locations(buf, gtk, "GTK")
5b3c40a6
JM
335 raise Exception("GTK found from memory")
336 verify_not_present(buf, sae_k, fname, "SAE(k)")
337 verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)")
338 verify_not_present(buf, sae_kck, fname, "SAE(KCK)")
339
340 logger.info("Checking keys in memory after disassociation")
341 buf = read_process_memory(pid, password)
342
343 # Note: Password is still present in network configuration
344 # Note: PMK is in PMKSA cache
345
346 get_key_locations(buf, password, "Password")
347 get_key_locations(buf, pmk, "PMK")
348 verify_not_present(buf, kck, fname, "KCK")
349 verify_not_present(buf, kek, fname, "KEK")
350 verify_not_present(buf, tk, fname, "TK")
351 verify_not_present(buf, gtk, fname, "GTK")
352 verify_not_present(buf, sae_k, fname, "SAE(k)")
353 verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)")
354 verify_not_present(buf, sae_kck, fname, "SAE(KCK)")
355
356 dev[0].request("PMKSA_FLUSH")
357 logger.info("Checking keys in memory after PMKSA cache flush")
358 buf = read_process_memory(pid, password)
359 get_key_locations(buf, password, "Password")
360 get_key_locations(buf, pmk, "PMK")
361 verify_not_present(buf, pmk, fname, "PMK")
362
363 dev[0].request("REMOVE_NETWORK all")
364
365 logger.info("Checking keys in memory after network profile removal")
366 buf = read_process_memory(pid, password)
367
368 get_key_locations(buf, password, "Password")
369 get_key_locations(buf, pmk, "PMK")
370 verify_not_present(buf, password, fname, "password")
371 verify_not_present(buf, pmk, fname, "PMK")
372 verify_not_present(buf, kck, fname, "KCK")
373 verify_not_present(buf, kek, fname, "KEK")
374 verify_not_present(buf, tk, fname, "TK")
375 verify_not_present(buf, gtk, fname, "GTK")
376 verify_not_present(buf, sae_k, fname, "SAE(k)")
377 verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)")
378 verify_not_present(buf, sae_kck, fname, "SAE(KCK)")
eb6d3532
JM
379
380def test_sae_oom_wpas(dev, apdev):
381 """SAE and OOM in wpa_supplicant"""
382 if "SAE" not in dev[0].get_capability("auth_alg"):
383 raise HwsimSkip("SAE not supported")
384 params = hostapd.wpa2_params(ssid="test-sae",
385 passphrase="12345678")
386 params['wpa_key_mgmt'] = 'SAE'
387 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
388
389 dev[0].request("SET sae_groups 25")
db036ed5
JM
390 tls = dev[0].request("GET tls_library")
391 if "BoringSSL" in tls:
392 dev[0].request("SET sae_groups 26")
eb6d3532
JM
393 with alloc_fail(dev[0], 1, "sae_set_group"):
394 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
395 scan_freq="2412")
396 dev[0].request("REMOVE_NETWORK all")
397
398 dev[0].request("SET sae_groups ")
399 with alloc_fail(dev[0], 2, "sae_set_group"):
400 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
401 scan_freq="2412")
402 dev[0].request("REMOVE_NETWORK all")
5527a391
JM
403
404def test_sae_proto_ecc(dev, apdev):
405 """SAE protocol testing (ECC)"""
406 if "SAE" not in dev[0].get_capability("auth_alg"):
407 raise HwsimSkip("SAE not supported")
408 params = hostapd.wpa2_params(ssid="test-sae",
409 passphrase="12345678")
410 params['wpa_key_mgmt'] = 'SAE'
411 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
412 bssid = apdev[0]['bssid']
413
414 dev[0].request("SET sae_groups 19")
415
416 tests = [ ("Confirm mismatch",
417 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
418 "0000800edebc3f260dc1fe7e0b20888af2b8a3316252ec37388a8504e25b73dc4240"),
419 ("Commit without even full cyclic group field",
420 "13",
421 None),
422 ("Too short commit",
423 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02",
424 None),
425 ("Invalid commit scalar (0)",
426 "1300" + "0000000000000000000000000000000000000000000000000000000000000000" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
427 None),
17ce7bb9
JM
428 ("Invalid commit scalar (1)",
429 "1300" + "0000000000000000000000000000000000000000000000000000000000000001" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
430 None),
5527a391
JM
431 ("Invalid commit scalar (> r)",
432 "1300" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
433 None),
434 ("Commit element not on curve",
435 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728d0000000000000000000000000000000000000000000000000000000000000000",
436 None),
437 ("Invalid commit element (y coordinate > P)",
438 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
439 None),
440 ("Invalid commit element (x coordinate > P)",
441 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
442 None),
443 ("Different group in commit",
444 "1400" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
445 None),
446 ("Too short confirm",
447 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
448 "0000800edebc3f260dc1fe7e0b20888af2b8a3316252ec37388a8504e25b73dc42")]
449 for (note, commit, confirm) in tests:
450 logger.info(note)
451 dev[0].scan_for_bss(bssid, freq=2412)
452 hapd.set("ext_mgmt_frame_handling", "1")
453 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
454 scan_freq="2412", wait_connect=False)
455
456 logger.info("Commit")
457 for i in range(0, 10):
458 req = hapd.mgmt_rx()
459 if req is None:
460 raise Exception("MGMT RX wait timed out (commit)")
461 if req['subtype'] == 11:
462 break
463 req = None
464 if not req:
465 raise Exception("Authentication frame (commit) not received")
466
467 hapd.dump_monitor()
468 resp = {}
469 resp['fc'] = req['fc']
470 resp['da'] = req['sa']
471 resp['sa'] = req['da']
472 resp['bssid'] = req['bssid']
473 resp['payload'] = binascii.unhexlify("030001000000" + commit)
474 hapd.mgmt_tx(resp)
475
476 if confirm:
477 logger.info("Confirm")
478 for i in range(0, 10):
479 req = hapd.mgmt_rx()
480 if req is None:
481 raise Exception("MGMT RX wait timed out (confirm)")
482 if req['subtype'] == 11:
483 break
484 req = None
485 if not req:
486 raise Exception("Authentication frame (confirm) not received")
487
488 hapd.dump_monitor()
489 resp = {}
490 resp['fc'] = req['fc']
491 resp['da'] = req['sa']
492 resp['sa'] = req['da']
493 resp['bssid'] = req['bssid']
494 resp['payload'] = binascii.unhexlify("030002000000" + confirm)
495 hapd.mgmt_tx(resp)
496
497 time.sleep(0.1)
498 dev[0].request("REMOVE_NETWORK all")
499 hapd.set("ext_mgmt_frame_handling", "0")
500 hapd.dump_monitor()
501
502def test_sae_proto_ffc(dev, apdev):
503 """SAE protocol testing (FFC)"""
504 if "SAE" not in dev[0].get_capability("auth_alg"):
505 raise HwsimSkip("SAE not supported")
506 params = hostapd.wpa2_params(ssid="test-sae",
507 passphrase="12345678")
508 params['wpa_key_mgmt'] = 'SAE'
509 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
510 bssid = apdev[0]['bssid']
511
512 dev[0].request("SET sae_groups 2")
513
514 tests = [ ("Confirm mismatch",
515 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "a8c00117493cdffa5dd671e934bc9cb1a69f39e25e9dd9cd9afd3aea2441a0f5491211c7ba50a753563f9ce943b043557cb71193b28e86ed9544f4289c471bf91b70af5c018cf4663e004165b0fd0bc1d8f3f78adf42eee92bcbc55246fd3ee9f107ab965dc7d4986f23eb71d616ebfe6bfe0a6c1ac5dc1718acee17c9a17486",
516 "0000f3116a9731f1259622e3eb55d4b3b50ba16f8c5f5565b28e609b180c51460251"),
517 ("Too short commit",
518 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "a8c00117493cdffa5dd671e934bc9cb1a69f39e25e9dd9cd9afd3aea2441a0f5491211c7ba50a753563f9ce943b043557cb71193b28e86ed9544f4289c471bf91b70af5c018cf4663e004165b0fd0bc1d8f3f78adf42eee92bcbc55246fd3ee9f107ab965dc7d4986f23eb71d616ebfe6bfe0a6c1ac5dc1718acee17c9a174",
519 None),
520 ("Invalid element (0) in commit",
521 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
522 None),
523 ("Invalid element (1) in commit",
524 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
525 None),
526 ("Invalid element (> P) in commit",
527 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
528 None) ]
529 for (note, commit, confirm) in tests:
530 logger.info(note)
531 dev[0].scan_for_bss(bssid, freq=2412)
532 hapd.set("ext_mgmt_frame_handling", "1")
533 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
534 scan_freq="2412", wait_connect=False)
535
536 logger.info("Commit")
537 for i in range(0, 10):
538 req = hapd.mgmt_rx()
539 if req is None:
540 raise Exception("MGMT RX wait timed out (commit)")
541 if req['subtype'] == 11:
542 break
543 req = None
544 if not req:
545 raise Exception("Authentication frame (commit) not received")
546
547 hapd.dump_monitor()
548 resp = {}
549 resp['fc'] = req['fc']
550 resp['da'] = req['sa']
551 resp['sa'] = req['da']
552 resp['bssid'] = req['bssid']
553 resp['payload'] = binascii.unhexlify("030001000000" + commit)
554 hapd.mgmt_tx(resp)
555
556 if confirm:
557 logger.info("Confirm")
558 for i in range(0, 10):
559 req = hapd.mgmt_rx()
560 if req is None:
561 raise Exception("MGMT RX wait timed out (confirm)")
562 if req['subtype'] == 11:
563 break
564 req = None
565 if not req:
566 raise Exception("Authentication frame (confirm) not received")
567
568 hapd.dump_monitor()
569 resp = {}
570 resp['fc'] = req['fc']
571 resp['da'] = req['sa']
572 resp['sa'] = req['da']
573 resp['bssid'] = req['bssid']
574 resp['payload'] = binascii.unhexlify("030002000000" + confirm)
575 hapd.mgmt_tx(resp)
576
577 time.sleep(0.1)
578 dev[0].request("REMOVE_NETWORK all")
579 hapd.set("ext_mgmt_frame_handling", "0")
580 hapd.dump_monitor()
581
582def test_sae_no_ffc_by_default(dev, apdev):
583 """SAE and default groups rejecting FFC"""
584 if "SAE" not in dev[0].get_capability("auth_alg"):
585 raise HwsimSkip("SAE not supported")
586 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
587 params['wpa_key_mgmt'] = 'SAE'
588 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
589
590 dev[0].request("SET sae_groups 5")
591 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412",
592 wait_connect=False)
593 ev = dev[0].wait_event(["SME: Trying to authenticate"], timeout=3)
594 if ev is None:
595 raise Exception("Did not try to authenticate")
596 ev = dev[0].wait_event(["SME: Trying to authenticate"], timeout=3)
597 if ev is None:
598 raise Exception("Did not try to authenticate (2)")
599 dev[0].request("REMOVE_NETWORK all")
939527b5
JM
600
601def sae_reflection_attack(apdev, dev, group):
602 if "SAE" not in dev.get_capability("auth_alg"):
603 raise HwsimSkip("SAE not supported")
604 params = hostapd.wpa2_params(ssid="test-sae",
605 passphrase="no-knowledge-of-passphrase")
606 params['wpa_key_mgmt'] = 'SAE'
607 hapd = hostapd.add_ap(apdev['ifname'], params)
608 bssid = apdev['bssid']
609
610 dev.scan_for_bss(bssid, freq=2412)
611 hapd.set("ext_mgmt_frame_handling", "1")
612
613 dev.request("SET sae_groups %d" % group)
614 dev.connect("test-sae", psk="reflection-attack", key_mgmt="SAE",
615 scan_freq="2412", wait_connect=False)
616
617 # Commit
618 for i in range(0, 10):
619 req = hapd.mgmt_rx()
620 if req is None:
621 raise Exception("MGMT RX wait timed out")
622 if req['subtype'] == 11:
623 break
624 req = None
625 if not req:
626 raise Exception("Authentication frame not received")
627
628 resp = {}
629 resp['fc'] = req['fc']
630 resp['da'] = req['sa']
631 resp['sa'] = req['da']
632 resp['bssid'] = req['bssid']
633 resp['payload'] = req['payload']
634 hapd.mgmt_tx(resp)
635
636 # Confirm
637 req = hapd.mgmt_rx(timeout=0.5)
638 if req is not None:
639 if req['subtype'] == 11:
640 raise Exception("Unexpected Authentication frame seen")
641
642def test_sae_reflection_attack_ecc(dev, apdev):
643 """SAE reflection attack (ECC)"""
644 sae_reflection_attack(apdev[0], dev[0], 19)
645
646def test_sae_reflection_attack_ffc(dev, apdev):
647 """SAE reflection attack (FFC)"""
648 sae_reflection_attack(apdev[0], dev[0], 5)
1965e196
JM
649
650def test_sae_anti_clogging_proto(dev, apdev):
651 """SAE anti clogging protocol testing"""
652 if "SAE" not in dev[0].get_capability("auth_alg"):
653 raise HwsimSkip("SAE not supported")
654 params = hostapd.wpa2_params(ssid="test-sae",
655 passphrase="no-knowledge-of-passphrase")
656 params['wpa_key_mgmt'] = 'SAE'
657 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
658 bssid = apdev[0]['bssid']
659
660 dev[0].scan_for_bss(bssid, freq=2412)
661 hapd.set("ext_mgmt_frame_handling", "1")
662
663 dev[0].request("SET sae_groups ")
664 dev[0].connect("test-sae", psk="anti-cloggign", key_mgmt="SAE",
665 scan_freq="2412", wait_connect=False)
666
667 # Commit
668 for i in range(0, 10):
669 req = hapd.mgmt_rx()
670 if req is None:
671 raise Exception("MGMT RX wait timed out")
672 if req['subtype'] == 11:
673 break
674 req = None
675 if not req:
676 raise Exception("Authentication frame not received")
677
678 resp = {}
679 resp['fc'] = req['fc']
680 resp['da'] = req['sa']
681 resp['sa'] = req['da']
682 resp['bssid'] = req['bssid']
683 resp['payload'] = binascii.unhexlify("030001004c00" + "ffff00")
684 hapd.mgmt_tx(resp)
685
686 # Confirm (not received due to DH group being rejected)
687 req = hapd.mgmt_rx(timeout=0.5)
688 if req is not None:
689 if req['subtype'] == 11:
690 raise Exception("Unexpected Authentication frame seen")
10ba4ae4
JM
691
692def test_sae_no_random(dev, apdev):
693 """SAE and no random numbers available"""
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", passphrase="12345678")
697 params['wpa_key_mgmt'] = 'SAE'
698 hapd = hostapd.add_ap(apdev[0]['ifname'], params)
699
700 dev[0].request("SET sae_groups ")
701 tests = [ (1, "os_get_random;sae_get_rand"),
702 (1, "os_get_random;get_rand_1_to_p_1"),
703 (1, "os_get_random;get_random_qr_qnr"),
704 (1, "os_get_random;sae_derive_pwe_ecc") ]
705 for count, func in tests:
706 with fail_test(dev[0], count, func):
707 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
708 scan_freq="2412")
709 dev[0].request("REMOVE_NETWORK all")
710 dev[0].wait_disconnected()