]> git.ipfire.org Git - thirdparty/hostap.git/blame - tests/hwsim/test_sae.py
SAE: Allow authentication restart on AP
[thirdparty/hostap.git] / tests / hwsim / test_sae.py
CommitLineData
1640a2e4 1# Test cases for SAE
4f6985de 2# Copyright (c) 2013-2016, 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
9fd6804d 7from remotehost import remote_compatible
5b3c40a6
JM
8import binascii
9import os
1640a2e4 10import time
1640a2e4
JM
11import logging
12logger = logging.getLogger()
13
14import hwsim_utils
15import hostapd
33822240 16from wpasupplicant import WpaSupplicant
51761ba2 17from utils import HwsimSkip, alloc_fail, fail_test, wait_fail_trigger
5b3c40a6 18from test_ap_psk import find_wpas_process, read_process_memory, verify_not_present, get_key_locations
1640a2e4 19
9fd6804d 20@remote_compatible
1640a2e4
JM
21def test_sae(dev, apdev):
22 """SAE with default group"""
b9749b6a
JM
23 if "SAE" not in dev[0].get_capability("auth_alg"):
24 raise HwsimSkip("SAE not supported")
1640a2e4
JM
25 params = hostapd.wpa2_params(ssid="test-sae",
26 passphrase="12345678")
27 params['wpa_key_mgmt'] = 'SAE'
8b8a1864 28 hapd = hostapd.add_ap(apdev[0], params)
65038313
JM
29 key_mgmt = hapd.get_config()['key_mgmt']
30 if key_mgmt.split(' ')[0] != "SAE":
31 raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt)
1640a2e4
JM
32
33 dev[0].request("SET sae_groups ")
34 id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
35 scan_freq="2412")
36 if dev[0].get_status_field('sae_group') != '19':
37 raise Exception("Expected default SAE group not used")
d463c556
JM
38 bss = dev[0].get_bss(apdev[0]['bssid'])
39 if 'flags' not in bss:
40 raise Exception("Could not get BSS flags from BSS table")
41 if "[WPA2-SAE-CCMP]" not in bss['flags']:
42 raise Exception("Unexpected BSS flags: " + bss['flags'])
1640a2e4 43
7b28c408
JM
44 res = hapd.request("STA-FIRST")
45 if "sae_group=19" not in res.splitlines():
46 raise Exception("hostapd STA output did not specify SAE group")
47
9fd6804d 48@remote_compatible
33dcced5
JM
49def test_sae_password_ecc(dev, apdev):
50 """SAE with number of different passwords (ECC)"""
51 if "SAE" not in dev[0].get_capability("auth_alg"):
52 raise HwsimSkip("SAE not supported")
53 params = hostapd.wpa2_params(ssid="test-sae",
54 passphrase="12345678")
55 params['wpa_key_mgmt'] = 'SAE'
8b8a1864 56 hapd = hostapd.add_ap(apdev[0], params)
33dcced5
JM
57
58 dev[0].request("SET sae_groups 19")
59
60 for i in range(10):
61 password = "12345678-" + str(i)
62 hapd.set("wpa_passphrase", password)
63 dev[0].connect("test-sae", psk=password, key_mgmt="SAE",
64 scan_freq="2412")
65 dev[0].request("REMOVE_NETWORK all")
66 dev[0].wait_disconnected()
67
9fd6804d 68@remote_compatible
33dcced5
JM
69def test_sae_password_ffc(dev, apdev):
70 """SAE with number of different passwords (FFC)"""
71 if "SAE" not in dev[0].get_capability("auth_alg"):
72 raise HwsimSkip("SAE not supported")
73 params = hostapd.wpa2_params(ssid="test-sae",
74 passphrase="12345678")
75 params['wpa_key_mgmt'] = 'SAE'
76 params['sae_groups'] = '22'
8b8a1864 77 hapd = hostapd.add_ap(apdev[0], params)
33dcced5
JM
78
79 dev[0].request("SET sae_groups 22")
80
81 for i in range(10):
82 password = "12345678-" + str(i)
83 hapd.set("wpa_passphrase", password)
84 dev[0].connect("test-sae", psk=password, key_mgmt="SAE",
85 scan_freq="2412")
86 dev[0].request("REMOVE_NETWORK all")
87 dev[0].wait_disconnected()
88
9fd6804d 89@remote_compatible
19d3a6e3
JM
90def test_sae_pmksa_caching(dev, apdev):
91 """SAE and PMKSA caching"""
b9749b6a
JM
92 if "SAE" not in dev[0].get_capability("auth_alg"):
93 raise HwsimSkip("SAE not supported")
19d3a6e3
JM
94 params = hostapd.wpa2_params(ssid="test-sae",
95 passphrase="12345678")
96 params['wpa_key_mgmt'] = 'SAE'
8b8a1864 97 hapd = hostapd.add_ap(apdev[0], params)
19d3a6e3
JM
98
99 dev[0].request("SET sae_groups ")
100 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
101 scan_freq="2412")
7cc9a81f
JM
102 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
103 if ev is None:
104 raise Exception("No connection event received from hostapd")
19d3a6e3 105 dev[0].request("DISCONNECT")
7cc9a81f 106 dev[0].wait_disconnected()
19d3a6e3 107 dev[0].request("RECONNECT")
5f35a5e2 108 dev[0].wait_connected(timeout=15, error="Reconnect timed out")
19d3a6e3
JM
109 if dev[0].get_status_field('sae_group') is not None:
110 raise Exception("SAE group claimed to have been used")
111
9fd6804d 112@remote_compatible
19d3a6e3
JM
113def test_sae_pmksa_caching_disabled(dev, apdev):
114 """SAE and PMKSA caching disabled"""
b9749b6a
JM
115 if "SAE" not in dev[0].get_capability("auth_alg"):
116 raise HwsimSkip("SAE not supported")
19d3a6e3
JM
117 params = hostapd.wpa2_params(ssid="test-sae",
118 passphrase="12345678")
119 params['wpa_key_mgmt'] = 'SAE'
120 params['disable_pmksa_caching'] = '1'
8b8a1864 121 hapd = hostapd.add_ap(apdev[0], params)
19d3a6e3
JM
122
123 dev[0].request("SET sae_groups ")
124 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
125 scan_freq="2412")
7cc9a81f
JM
126 ev = hapd.wait_event([ "AP-STA-CONNECTED" ], timeout=5)
127 if ev is None:
128 raise Exception("No connection event received from hostapd")
19d3a6e3 129 dev[0].request("DISCONNECT")
7cc9a81f 130 dev[0].wait_disconnected()
19d3a6e3 131 dev[0].request("RECONNECT")
5f35a5e2 132 dev[0].wait_connected(timeout=15, error="Reconnect timed out")
19d3a6e3
JM
133 if dev[0].get_status_field('sae_group') != '19':
134 raise Exception("Expected default SAE group not used")
135
1640a2e4
JM
136def test_sae_groups(dev, apdev):
137 """SAE with all supported groups"""
b9749b6a
JM
138 if "SAE" not in dev[0].get_capability("auth_alg"):
139 raise HwsimSkip("SAE not supported")
b1f487cb
JM
140 # This is the full list of supported groups, but groups 14-16 (2048-4096 bit
141 # MODP) and group 21 (521-bit random ECP group) are a bit too slow on some
142 # VMs and can result in hitting the mac80211 authentication timeout, so
143 # allow them to fail and just report such failures in the debug log.
144 sae_groups = [ 19, 25, 26, 20, 21, 2, 5, 14, 15, 16, 22, 23, 24 ]
9e286d5e
JM
145 tls = dev[0].request("GET tls_library")
146 if tls.startswith("OpenSSL") and "build=OpenSSL 1.0.2" in tls and "run=OpenSSL 1.0.2" in tls:
147 logger.info("Add Brainpool EC groups since OpenSSL is new enough")
148 sae_groups += [ 27, 28, 29, 30 ]
b1f487cb 149 heavy_groups = [ 14, 15, 16 ]
1640a2e4
JM
150 groups = [str(g) for g in sae_groups]
151 params = hostapd.wpa2_params(ssid="test-sae-groups",
152 passphrase="12345678")
153 params['wpa_key_mgmt'] = 'SAE'
154 params['sae_groups'] = ' '.join(groups)
8b8a1864 155 hostapd.add_ap(apdev[0], params)
1640a2e4
JM
156
157 for g in groups:
158 logger.info("Testing SAE group " + g)
159 dev[0].request("SET sae_groups " + g)
160 id = dev[0].connect("test-sae-groups", psk="12345678", key_mgmt="SAE",
b1f487cb
JM
161 scan_freq="2412", wait_connect=False)
162 if int(g) in heavy_groups:
163 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=5)
164 if ev is None:
165 logger.info("No connection with heavy SAE group %s did not connect - likely hitting timeout in mac80211" % g)
166 dev[0].remove_network(id)
167 time.sleep(0.1)
168 dev[0].dump_monitor()
169 continue
170 logger.info("Connection with heavy SAE group " + g)
171 else:
a68d1792
JM
172 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=10)
173 if ev is None:
174 if "BoringSSL" in tls and int(g) in [ 25 ]:
175 logger.info("Ignore connection failure with group " + g + " with BoringSSL")
176 dev[0].remove_network(id)
177 dev[0].dump_monitor()
178 continue
179 raise Exception("Connection timed out with group " + g)
1640a2e4
JM
180 if dev[0].get_status_field('sae_group') != g:
181 raise Exception("Expected SAE group not used")
182 dev[0].remove_network(id)
b1f487cb
JM
183 dev[0].wait_disconnected()
184 dev[0].dump_monitor()
1640a2e4 185
9fd6804d 186@remote_compatible
1640a2e4
JM
187def test_sae_group_nego(dev, apdev):
188 """SAE group negotiation"""
b9749b6a
JM
189 if "SAE" not in dev[0].get_capability("auth_alg"):
190 raise HwsimSkip("SAE not supported")
1640a2e4
JM
191 params = hostapd.wpa2_params(ssid="test-sae-group-nego",
192 passphrase="12345678")
193 params['wpa_key_mgmt'] = 'SAE'
194 params['sae_groups'] = '19'
8b8a1864 195 hostapd.add_ap(apdev[0], params)
1640a2e4
JM
196
197 dev[0].request("SET sae_groups 25 26 20 19")
198 dev[0].connect("test-sae-group-nego", psk="12345678", key_mgmt="SAE",
199 scan_freq="2412")
200 if dev[0].get_status_field('sae_group') != '19':
201 raise Exception("Expected SAE group not used")
a6cf5cd6 202
9fd6804d 203@remote_compatible
a6cf5cd6
JM
204def test_sae_anti_clogging(dev, apdev):
205 """SAE anti clogging"""
b9749b6a
JM
206 if "SAE" not in dev[0].get_capability("auth_alg"):
207 raise HwsimSkip("SAE not supported")
a6cf5cd6
JM
208 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
209 params['wpa_key_mgmt'] = 'SAE'
210 params['sae_anti_clogging_threshold'] = '1'
8b8a1864 211 hostapd.add_ap(apdev[0], params)
a6cf5cd6
JM
212
213 dev[0].request("SET sae_groups ")
214 dev[1].request("SET sae_groups ")
215 id = {}
216 for i in range(0, 2):
217 dev[i].scan(freq="2412")
218 id[i] = dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE",
219 scan_freq="2412", only_add_network=True)
220 for i in range(0, 2):
221 dev[i].select_network(id[i])
222 for i in range(0, 2):
5f35a5e2 223 dev[i].wait_connected(timeout=10)
d05ff960
JM
224
225def test_sae_forced_anti_clogging(dev, apdev):
226 """SAE anti clogging (forced)"""
b9749b6a
JM
227 if "SAE" not in dev[0].get_capability("auth_alg"):
228 raise HwsimSkip("SAE not supported")
d05ff960 229 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
fd4709ff 230 params['wpa_key_mgmt'] = 'SAE WPA-PSK'
d05ff960 231 params['sae_anti_clogging_threshold'] = '0'
8b8a1864 232 hostapd.add_ap(apdev[0], params)
fd4709ff 233 dev[2].connect("test-sae", psk="12345678", scan_freq="2412")
d05ff960
JM
234 for i in range(0, 2):
235 dev[i].request("SET sae_groups ")
236 dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE",
237 scan_freq="2412")
238
239def test_sae_mixed(dev, apdev):
240 """Mixed SAE and non-SAE network"""
b9749b6a
JM
241 if "SAE" not in dev[0].get_capability("auth_alg"):
242 raise HwsimSkip("SAE not supported")
d05ff960
JM
243 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
244 params['wpa_key_mgmt'] = 'SAE WPA-PSK'
245 params['sae_anti_clogging_threshold'] = '0'
8b8a1864 246 hostapd.add_ap(apdev[0], params)
d05ff960
JM
247
248 dev[2].connect("test-sae", psk="12345678", scan_freq="2412")
249 for i in range(0, 2):
250 dev[i].request("SET sae_groups ")
251 dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE",
252 scan_freq="2412")
acb63c75 253
fa617ee6
JM
254def test_sae_and_psk(dev, apdev):
255 """SAE and PSK enabled in network profile"""
256 if "SAE" not in dev[0].get_capability("auth_alg"):
257 raise HwsimSkip("SAE not supported")
258 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
259 params['wpa_key_mgmt'] = 'SAE'
260 hostapd.add_ap(apdev[0], params)
261
262 dev[0].request("SET sae_groups ")
263 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE WPA-PSK",
264 scan_freq="2412")
265
266def test_sae_and_psk2(dev, apdev):
267 """SAE and PSK enabled in network profile (use PSK)"""
268 if "SAE" not in dev[0].get_capability("auth_alg"):
269 raise HwsimSkip("SAE not supported")
270 params = hostapd.wpa2_params(ssid="test-psk", passphrase="12345678")
271 hostapd.add_ap(apdev[0], params)
272
273 dev[0].request("SET sae_groups ")
274 dev[0].connect("test-psk", psk="12345678", key_mgmt="SAE WPA-PSK",
275 scan_freq="2412")
276
5c8df74f
JM
277def test_sae_mixed_mfp(dev, apdev):
278 """Mixed SAE and non-SAE network and MFP required with SAE"""
279 if "SAE" not in dev[0].get_capability("auth_alg"):
280 raise HwsimSkip("SAE not supported")
281 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
282 params['wpa_key_mgmt'] = 'SAE WPA-PSK'
283 params["ieee80211w"] = "1"
284 params['sae_require_mfp'] = '1'
285 hostapd.add_ap(apdev[0], params)
286
287 dev[0].request("SET sae_groups ")
288 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", ieee80211w="2",
289 scan_freq="2412")
290 dev[0].dump_monitor()
291
292 dev[1].request("SET sae_groups ")
293 dev[1].connect("test-sae", psk="12345678", key_mgmt="SAE", ieee80211w="0",
294 scan_freq="2412", wait_connect=False)
295 ev = dev[1].wait_event(["CTRL-EVENT-CONNECTED",
296 "CTRL-EVENT-ASSOC-REJECT"], timeout=10)
297 if ev is None:
298 raise Exception("No connection result reported")
299 if "CTRL-EVENT-ASSOC-REJECT" not in ev:
300 raise Exception("SAE connection without MFP was not rejected")
301 if "status_code=31" not in ev:
302 raise Exception("Unexpected status code in rejection: " + ev)
303 dev[1].request("DISCONNECT")
304 dev[1].dump_monitor()
305
306 dev[2].connect("test-sae", psk="12345678", ieee80211w="0", scan_freq="2412")
307 dev[2].dump_monitor()
308
9fd6804d 309@remote_compatible
acb63c75
JM
310def test_sae_missing_password(dev, apdev):
311 """SAE and missing password"""
b9749b6a
JM
312 if "SAE" not in dev[0].get_capability("auth_alg"):
313 raise HwsimSkip("SAE not supported")
acb63c75
JM
314 params = hostapd.wpa2_params(ssid="test-sae",
315 passphrase="12345678")
316 params['wpa_key_mgmt'] = 'SAE'
8b8a1864 317 hapd = hostapd.add_ap(apdev[0], params)
acb63c75
JM
318
319 dev[0].request("SET sae_groups ")
320 id = dev[0].connect("test-sae",
321 raw_psk="46b4a73b8a951ad53ebd2e0afdb9c5483257edd4c21d12b7710759da70945858",
322 key_mgmt="SAE", scan_freq="2412", wait_connect=False)
323 ev = dev[0].wait_event(['CTRL-EVENT-SSID-TEMP-DISABLED'], timeout=10)
324 if ev is None:
325 raise Exception("Invalid network not temporarily disabled")
5b3c40a6
JM
326
327
328def test_sae_key_lifetime_in_memory(dev, apdev, params):
329 """SAE and key lifetime in memory"""
b9749b6a
JM
330 if "SAE" not in dev[0].get_capability("auth_alg"):
331 raise HwsimSkip("SAE not supported")
5b3c40a6
JM
332 password = "5ad144a7c1f5a5503baa6fa01dabc15b1843e8c01662d78d16b70b5cd23cf8b"
333 p = hostapd.wpa2_params(ssid="test-sae", passphrase=password)
334 p['wpa_key_mgmt'] = 'SAE'
8b8a1864 335 hapd = hostapd.add_ap(apdev[0], p)
5b3c40a6
JM
336
337 pid = find_wpas_process(dev[0])
338
339 dev[0].request("SET sae_groups ")
340 id = dev[0].connect("test-sae", psk=password, key_mgmt="SAE",
341 scan_freq="2412")
342
8e416cec
JM
343 # The decrypted copy of GTK is freed only after the CTRL-EVENT-CONNECTED
344 # event has been delivered, so verify that wpa_supplicant has returned to
345 # eloop before reading process memory.
54f2cae2 346 time.sleep(1)
8e416cec 347 dev[0].ping()
5b3c40a6
JM
348 buf = read_process_memory(pid, password)
349
350 dev[0].request("DISCONNECT")
351 dev[0].wait_disconnected()
352
353 dev[0].relog()
354 sae_k = None
355 sae_keyseed = None
356 sae_kck = None
357 pmk = None
358 ptk = None
359 gtk = None
360 with open(os.path.join(params['logdir'], 'log0'), 'r') as f:
361 for l in f.readlines():
362 if "SAE: k - hexdump" in l:
363 val = l.strip().split(':')[3].replace(' ', '')
364 sae_k = binascii.unhexlify(val)
365 if "SAE: keyseed - hexdump" in l:
366 val = l.strip().split(':')[3].replace(' ', '')
367 sae_keyseed = binascii.unhexlify(val)
368 if "SAE: KCK - hexdump" in l:
369 val = l.strip().split(':')[3].replace(' ', '')
370 sae_kck = binascii.unhexlify(val)
371 if "SAE: PMK - hexdump" in l:
372 val = l.strip().split(':')[3].replace(' ', '')
373 pmk = binascii.unhexlify(val)
374 if "WPA: PTK - hexdump" in l:
375 val = l.strip().split(':')[3].replace(' ', '')
376 ptk = binascii.unhexlify(val)
377 if "WPA: Group Key - hexdump" in l:
378 val = l.strip().split(':')[3].replace(' ', '')
379 gtk = binascii.unhexlify(val)
380 if not sae_k or not sae_keyseed or not sae_kck or not pmk or not ptk or not gtk:
381 raise Exception("Could not find keys from debug log")
382 if len(gtk) != 16:
383 raise Exception("Unexpected GTK length")
384
385 kck = ptk[0:16]
386 kek = ptk[16:32]
387 tk = ptk[32:48]
388
389 fname = os.path.join(params['logdir'],
390 'sae_key_lifetime_in_memory.memctx-')
391
392 logger.info("Checking keys in memory while associated")
393 get_key_locations(buf, password, "Password")
394 get_key_locations(buf, pmk, "PMK")
395 if password not in buf:
81e787b7 396 raise HwsimSkip("Password not found while associated")
5b3c40a6 397 if pmk not in buf:
81e787b7 398 raise HwsimSkip("PMK not found while associated")
5b3c40a6
JM
399 if kck not in buf:
400 raise Exception("KCK not found while associated")
401 if kek not in buf:
402 raise Exception("KEK not found while associated")
b74f82a4
JM
403 #if tk in buf:
404 # raise Exception("TK found from memory")
5b3c40a6
JM
405 verify_not_present(buf, sae_k, fname, "SAE(k)")
406 verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)")
407 verify_not_present(buf, sae_kck, fname, "SAE(KCK)")
408
409 logger.info("Checking keys in memory after disassociation")
410 buf = read_process_memory(pid, password)
411
412 # Note: Password is still present in network configuration
413 # Note: PMK is in PMKSA cache
414
415 get_key_locations(buf, password, "Password")
416 get_key_locations(buf, pmk, "PMK")
417 verify_not_present(buf, kck, fname, "KCK")
418 verify_not_present(buf, kek, fname, "KEK")
419 verify_not_present(buf, tk, fname, "TK")
6db556b2
JM
420 if gtk in buf:
421 get_key_locations(buf, gtk, "GTK")
5b3c40a6
JM
422 verify_not_present(buf, gtk, fname, "GTK")
423 verify_not_present(buf, sae_k, fname, "SAE(k)")
424 verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)")
425 verify_not_present(buf, sae_kck, fname, "SAE(KCK)")
426
427 dev[0].request("PMKSA_FLUSH")
428 logger.info("Checking keys in memory after PMKSA cache flush")
429 buf = read_process_memory(pid, password)
430 get_key_locations(buf, password, "Password")
431 get_key_locations(buf, pmk, "PMK")
432 verify_not_present(buf, pmk, fname, "PMK")
433
434 dev[0].request("REMOVE_NETWORK all")
435
436 logger.info("Checking keys in memory after network profile removal")
437 buf = read_process_memory(pid, password)
438
439 get_key_locations(buf, password, "Password")
440 get_key_locations(buf, pmk, "PMK")
441 verify_not_present(buf, password, fname, "password")
442 verify_not_present(buf, pmk, fname, "PMK")
443 verify_not_present(buf, kck, fname, "KCK")
444 verify_not_present(buf, kek, fname, "KEK")
445 verify_not_present(buf, tk, fname, "TK")
446 verify_not_present(buf, gtk, fname, "GTK")
447 verify_not_present(buf, sae_k, fname, "SAE(k)")
448 verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)")
449 verify_not_present(buf, sae_kck, fname, "SAE(KCK)")
eb6d3532 450
9fd6804d 451@remote_compatible
eb6d3532
JM
452def test_sae_oom_wpas(dev, apdev):
453 """SAE and OOM in wpa_supplicant"""
454 if "SAE" not in dev[0].get_capability("auth_alg"):
455 raise HwsimSkip("SAE not supported")
456 params = hostapd.wpa2_params(ssid="test-sae",
457 passphrase="12345678")
458 params['wpa_key_mgmt'] = 'SAE'
8b8a1864 459 hapd = hostapd.add_ap(apdev[0], params)
eb6d3532
JM
460
461 dev[0].request("SET sae_groups 25")
db036ed5
JM
462 tls = dev[0].request("GET tls_library")
463 if "BoringSSL" in tls:
464 dev[0].request("SET sae_groups 26")
eb6d3532
JM
465 with alloc_fail(dev[0], 1, "sae_set_group"):
466 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
467 scan_freq="2412")
468 dev[0].request("REMOVE_NETWORK all")
469
470 dev[0].request("SET sae_groups ")
471 with alloc_fail(dev[0], 2, "sae_set_group"):
472 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
473 scan_freq="2412")
474 dev[0].request("REMOVE_NETWORK all")
5527a391 475
2fd44db7
JM
476 with alloc_fail(dev[0], 1, "wpabuf_alloc;sme_auth_build_sae_commit"):
477 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
478 scan_freq="2412")
479 dev[0].request("REMOVE_NETWORK all")
480
481 with alloc_fail(dev[0], 1, "wpabuf_alloc;sme_auth_build_sae_confirm"):
482 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
483 scan_freq="2412", wait_connect=False)
484 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
485 dev[0].request("REMOVE_NETWORK all")
486
487 with alloc_fail(dev[0], 1, "=sme_authenticate"):
488 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
489 scan_freq="2412", wait_connect=False)
490 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
491 dev[0].request("REMOVE_NETWORK all")
492
493 with alloc_fail(dev[0], 1, "radio_add_work;sme_authenticate"):
494 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
495 scan_freq="2412", wait_connect=False)
496 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL")
497 dev[0].request("REMOVE_NETWORK all")
498
9fd6804d 499@remote_compatible
5527a391
JM
500def test_sae_proto_ecc(dev, apdev):
501 """SAE protocol testing (ECC)"""
502 if "SAE" not in dev[0].get_capability("auth_alg"):
503 raise HwsimSkip("SAE not supported")
504 params = hostapd.wpa2_params(ssid="test-sae",
505 passphrase="12345678")
506 params['wpa_key_mgmt'] = 'SAE'
8b8a1864 507 hapd = hostapd.add_ap(apdev[0], params)
5527a391
JM
508 bssid = apdev[0]['bssid']
509
510 dev[0].request("SET sae_groups 19")
511
512 tests = [ ("Confirm mismatch",
513 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
514 "0000800edebc3f260dc1fe7e0b20888af2b8a3316252ec37388a8504e25b73dc4240"),
515 ("Commit without even full cyclic group field",
516 "13",
517 None),
518 ("Too short commit",
519 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02",
520 None),
521 ("Invalid commit scalar (0)",
522 "1300" + "0000000000000000000000000000000000000000000000000000000000000000" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
523 None),
17ce7bb9
JM
524 ("Invalid commit scalar (1)",
525 "1300" + "0000000000000000000000000000000000000000000000000000000000000001" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
526 None),
5527a391
JM
527 ("Invalid commit scalar (> r)",
528 "1300" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
529 None),
530 ("Commit element not on curve",
531 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728d0000000000000000000000000000000000000000000000000000000000000000",
532 None),
533 ("Invalid commit element (y coordinate > P)",
534 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
535 None),
536 ("Invalid commit element (x coordinate > P)",
537 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
538 None),
539 ("Different group in commit",
540 "1400" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
541 None),
542 ("Too short confirm",
543 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
544 "0000800edebc3f260dc1fe7e0b20888af2b8a3316252ec37388a8504e25b73dc42")]
545 for (note, commit, confirm) in tests:
546 logger.info(note)
547 dev[0].scan_for_bss(bssid, freq=2412)
548 hapd.set("ext_mgmt_frame_handling", "1")
549 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
550 scan_freq="2412", wait_connect=False)
551
552 logger.info("Commit")
553 for i in range(0, 10):
554 req = hapd.mgmt_rx()
555 if req is None:
556 raise Exception("MGMT RX wait timed out (commit)")
557 if req['subtype'] == 11:
558 break
559 req = None
560 if not req:
561 raise Exception("Authentication frame (commit) not received")
562
563 hapd.dump_monitor()
564 resp = {}
565 resp['fc'] = req['fc']
566 resp['da'] = req['sa']
567 resp['sa'] = req['da']
568 resp['bssid'] = req['bssid']
569 resp['payload'] = binascii.unhexlify("030001000000" + commit)
570 hapd.mgmt_tx(resp)
571
572 if confirm:
573 logger.info("Confirm")
574 for i in range(0, 10):
575 req = hapd.mgmt_rx()
576 if req is None:
577 raise Exception("MGMT RX wait timed out (confirm)")
578 if req['subtype'] == 11:
579 break
580 req = None
581 if not req:
582 raise Exception("Authentication frame (confirm) not received")
583
584 hapd.dump_monitor()
585 resp = {}
586 resp['fc'] = req['fc']
587 resp['da'] = req['sa']
588 resp['sa'] = req['da']
589 resp['bssid'] = req['bssid']
590 resp['payload'] = binascii.unhexlify("030002000000" + confirm)
591 hapd.mgmt_tx(resp)
592
593 time.sleep(0.1)
594 dev[0].request("REMOVE_NETWORK all")
595 hapd.set("ext_mgmt_frame_handling", "0")
596 hapd.dump_monitor()
597
9fd6804d 598@remote_compatible
5527a391
JM
599def test_sae_proto_ffc(dev, apdev):
600 """SAE protocol testing (FFC)"""
601 if "SAE" not in dev[0].get_capability("auth_alg"):
602 raise HwsimSkip("SAE not supported")
603 params = hostapd.wpa2_params(ssid="test-sae",
604 passphrase="12345678")
605 params['wpa_key_mgmt'] = 'SAE'
8b8a1864 606 hapd = hostapd.add_ap(apdev[0], params)
5527a391
JM
607 bssid = apdev[0]['bssid']
608
609 dev[0].request("SET sae_groups 2")
610
611 tests = [ ("Confirm mismatch",
612 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "a8c00117493cdffa5dd671e934bc9cb1a69f39e25e9dd9cd9afd3aea2441a0f5491211c7ba50a753563f9ce943b043557cb71193b28e86ed9544f4289c471bf91b70af5c018cf4663e004165b0fd0bc1d8f3f78adf42eee92bcbc55246fd3ee9f107ab965dc7d4986f23eb71d616ebfe6bfe0a6c1ac5dc1718acee17c9a17486",
613 "0000f3116a9731f1259622e3eb55d4b3b50ba16f8c5f5565b28e609b180c51460251"),
614 ("Too short commit",
615 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "a8c00117493cdffa5dd671e934bc9cb1a69f39e25e9dd9cd9afd3aea2441a0f5491211c7ba50a753563f9ce943b043557cb71193b28e86ed9544f4289c471bf91b70af5c018cf4663e004165b0fd0bc1d8f3f78adf42eee92bcbc55246fd3ee9f107ab965dc7d4986f23eb71d616ebfe6bfe0a6c1ac5dc1718acee17c9a174",
616 None),
617 ("Invalid element (0) in commit",
618 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
619 None),
620 ("Invalid element (1) in commit",
621 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
622 None),
623 ("Invalid element (> P) in commit",
624 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
625 None) ]
626 for (note, commit, confirm) in tests:
627 logger.info(note)
628 dev[0].scan_for_bss(bssid, freq=2412)
629 hapd.set("ext_mgmt_frame_handling", "1")
630 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
631 scan_freq="2412", wait_connect=False)
632
633 logger.info("Commit")
634 for i in range(0, 10):
635 req = hapd.mgmt_rx()
636 if req is None:
637 raise Exception("MGMT RX wait timed out (commit)")
638 if req['subtype'] == 11:
639 break
640 req = None
641 if not req:
642 raise Exception("Authentication frame (commit) not received")
643
644 hapd.dump_monitor()
645 resp = {}
646 resp['fc'] = req['fc']
647 resp['da'] = req['sa']
648 resp['sa'] = req['da']
649 resp['bssid'] = req['bssid']
650 resp['payload'] = binascii.unhexlify("030001000000" + commit)
651 hapd.mgmt_tx(resp)
652
653 if confirm:
654 logger.info("Confirm")
655 for i in range(0, 10):
656 req = hapd.mgmt_rx()
657 if req is None:
658 raise Exception("MGMT RX wait timed out (confirm)")
659 if req['subtype'] == 11:
660 break
661 req = None
662 if not req:
663 raise Exception("Authentication frame (confirm) not received")
664
665 hapd.dump_monitor()
666 resp = {}
667 resp['fc'] = req['fc']
668 resp['da'] = req['sa']
669 resp['sa'] = req['da']
670 resp['bssid'] = req['bssid']
671 resp['payload'] = binascii.unhexlify("030002000000" + confirm)
672 hapd.mgmt_tx(resp)
673
674 time.sleep(0.1)
675 dev[0].request("REMOVE_NETWORK all")
676 hapd.set("ext_mgmt_frame_handling", "0")
677 hapd.dump_monitor()
678
2d0a04a8
JM
679def test_sae_proto_confirm_replay(dev, apdev):
680 """SAE protocol testing - Confirm replay"""
681 if "SAE" not in dev[0].get_capability("auth_alg"):
682 raise HwsimSkip("SAE not supported")
683 params = hostapd.wpa2_params(ssid="test-sae",
684 passphrase="12345678")
685 params['wpa_key_mgmt'] = 'SAE'
686 hapd = hostapd.add_ap(apdev[0], params)
687 bssid = apdev[0]['bssid']
688
689 dev[0].request("SET sae_groups 19")
690
691 dev[0].scan_for_bss(bssid, freq=2412)
692 hapd.set("ext_mgmt_frame_handling", "1")
693 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
694 scan_freq="2412", wait_connect=False)
695
696 logger.info("Commit")
697 for i in range(0, 10):
698 req = hapd.mgmt_rx()
699 if req is None:
700 raise Exception("MGMT RX wait timed out (commit)")
701 if req['subtype'] == 11:
702 break
703 req = None
704 if not req:
705 raise Exception("Authentication frame (commit) not received")
706
707 bssid = hapd.own_addr().replace(':', '')
708 addr = dev[0].own_addr().replace(':', '')
709 hdr = "b0003a01" + bssid + addr + bssid + "1000"
710
711 hapd.dump_monitor()
712 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + req['frame'].encode('hex'))
713
714 logger.info("Confirm")
715 for i in range(0, 10):
716 req = hapd.mgmt_rx()
717 if req is None:
718 raise Exception("MGMT RX wait timed out (confirm)")
719 if req['subtype'] == 11:
720 break
721 req = None
722 if not req:
723 raise Exception("Authentication frame (confirm) not received")
724
725 hapd.dump_monitor()
726 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + req['frame'].encode('hex'))
727
728 logger.info("Replay Confirm")
729 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + req['frame'].encode('hex'))
730
731 logger.info("Association Request")
732 for i in range(0, 10):
733 req = hapd.mgmt_rx()
734 if req is None:
735 raise Exception("MGMT RX wait timed out (AssocReq)")
736 if req['subtype'] == 0:
737 break
738 req = None
739 if not req:
740 raise Exception("Association Request frame not received")
741
742 hapd.dump_monitor()
743 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + req['frame'].encode('hex'))
744 ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5)
745 if ev is None:
746 raise Exception("Management frame TX status not reported (1)")
747 if "stype=1 ok=1" not in ev:
748 raise Exception("Unexpected management frame TX status (1): " + ev)
749 cmd = "MGMT_TX_STATUS_PROCESS %s" % (" ".join(ev.split(' ')[1:4]))
750 if "OK" not in hapd.request(cmd):
751 raise Exception("MGMT_TX_STATUS_PROCESS failed")
752
753 hapd.set("ext_mgmt_frame_handling", "0")
754
755 dev[0].wait_connected()
756
7a92dbd7
JM
757def test_sae_proto_hostapd(dev, apdev):
758 """SAE protocol testing with hostapd"""
759 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
760 params['wpa_key_mgmt'] = 'SAE'
761 params['sae_groups'] = "19 65535"
762 hapd = hostapd.add_ap(apdev[0], params)
763 hapd.set("ext_mgmt_frame_handling", "1")
764 bssid = hapd.own_addr().replace(':', '')
765 addr = "020000000000"
766 addr2 = "020000000001"
767 hdr = "b0003a01" + bssid + addr + bssid + "1000"
768 hdr2 = "b0003a01" + bssid + addr2 + bssid + "1000"
769 group = "1300"
770 scalar = "f7df19f4a7fef1d3b895ea1de150b7c5a7a705c8ebb31a52b623e0057908bd93"
771 element_x = "21931572027f2e953e2a49fab3d992944102cc95aa19515fc068b394fb25ae3c"
772 element_y = "cb4eeb94d7b0b789abfdb73a67ab9d6d5efa94dd553e0e724a6289821cbce530"
773 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030001000000" + group + scalar + element_x + element_y)
774 # "SAE: Not enough data for scalar"
775 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030001000000" + group + scalar[:-2])
776 # "SAE: Do not allow group to be changed"
777 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030001000000" + "ffff" + scalar[:-2])
778 # "SAE: Unsupported Finite Cyclic Group 65535"
779 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr2 + "030001000000" + "ffff" + scalar[:-2])
780
9fd6804d 781@remote_compatible
5527a391
JM
782def test_sae_no_ffc_by_default(dev, apdev):
783 """SAE and default groups rejecting FFC"""
784 if "SAE" not in dev[0].get_capability("auth_alg"):
785 raise HwsimSkip("SAE not supported")
786 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
787 params['wpa_key_mgmt'] = 'SAE'
8b8a1864 788 hapd = hostapd.add_ap(apdev[0], params)
5527a391
JM
789
790 dev[0].request("SET sae_groups 5")
791 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412",
792 wait_connect=False)
793 ev = dev[0].wait_event(["SME: Trying to authenticate"], timeout=3)
794 if ev is None:
795 raise Exception("Did not try to authenticate")
796 ev = dev[0].wait_event(["SME: Trying to authenticate"], timeout=3)
797 if ev is None:
798 raise Exception("Did not try to authenticate (2)")
799 dev[0].request("REMOVE_NETWORK all")
939527b5
JM
800
801def sae_reflection_attack(apdev, dev, group):
802 if "SAE" not in dev.get_capability("auth_alg"):
803 raise HwsimSkip("SAE not supported")
804 params = hostapd.wpa2_params(ssid="test-sae",
805 passphrase="no-knowledge-of-passphrase")
806 params['wpa_key_mgmt'] = 'SAE'
afc26df2 807 hapd = hostapd.add_ap(apdev, params)
939527b5
JM
808 bssid = apdev['bssid']
809
810 dev.scan_for_bss(bssid, freq=2412)
811 hapd.set("ext_mgmt_frame_handling", "1")
812
813 dev.request("SET sae_groups %d" % group)
814 dev.connect("test-sae", psk="reflection-attack", key_mgmt="SAE",
815 scan_freq="2412", wait_connect=False)
816
817 # Commit
818 for i in range(0, 10):
819 req = hapd.mgmt_rx()
820 if req is None:
821 raise Exception("MGMT RX wait timed out")
822 if req['subtype'] == 11:
823 break
824 req = None
825 if not req:
826 raise Exception("Authentication frame not received")
827
828 resp = {}
829 resp['fc'] = req['fc']
830 resp['da'] = req['sa']
831 resp['sa'] = req['da']
832 resp['bssid'] = req['bssid']
833 resp['payload'] = req['payload']
834 hapd.mgmt_tx(resp)
835
836 # Confirm
837 req = hapd.mgmt_rx(timeout=0.5)
838 if req is not None:
839 if req['subtype'] == 11:
840 raise Exception("Unexpected Authentication frame seen")
841
9fd6804d 842@remote_compatible
939527b5
JM
843def test_sae_reflection_attack_ecc(dev, apdev):
844 """SAE reflection attack (ECC)"""
845 sae_reflection_attack(apdev[0], dev[0], 19)
846
9fd6804d 847@remote_compatible
939527b5
JM
848def test_sae_reflection_attack_ffc(dev, apdev):
849 """SAE reflection attack (FFC)"""
850 sae_reflection_attack(apdev[0], dev[0], 5)
1965e196 851
1342c47a
JM
852def sae_reflection_attack_internal(apdev, dev, group):
853 if "SAE" not in dev.get_capability("auth_alg"):
854 raise HwsimSkip("SAE not supported")
855 params = hostapd.wpa2_params(ssid="test-sae",
856 passphrase="no-knowledge-of-passphrase")
857 params['wpa_key_mgmt'] = 'SAE'
858 params['sae_reflection_attack'] = '1'
859 hapd = hostapd.add_ap(apdev, params)
860 bssid = apdev['bssid']
861
862 dev.scan_for_bss(bssid, freq=2412)
863 dev.request("SET sae_groups %d" % group)
864 dev.connect("test-sae", psk="reflection-attack", key_mgmt="SAE",
865 scan_freq="2412", wait_connect=False)
866 ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
867 if ev is not None:
868 raise Exception("Unexpected connection")
869
870@remote_compatible
871def test_sae_reflection_attack_ecc_internal(dev, apdev):
872 """SAE reflection attack (ECC) - internal"""
873 sae_reflection_attack_internal(apdev[0], dev[0], 19)
874
875@remote_compatible
876def test_sae_reflection_attack_ffc_internal(dev, apdev):
877 """SAE reflection attack (FFC) - internal"""
878 sae_reflection_attack_internal(apdev[0], dev[0], 5)
879
cd06e266
JM
880@remote_compatible
881def test_sae_commit_override(dev, apdev):
882 """SAE commit override (hostapd)"""
883 if "SAE" not in dev[0].get_capability("auth_alg"):
884 raise HwsimSkip("SAE not supported")
885 params = hostapd.wpa2_params(ssid="test-sae",
886 passphrase="12345678")
887 params['wpa_key_mgmt'] = 'SAE'
888 params['sae_commit_override'] = '13ffbad00d215867a7c5ff37d87bb9bdb7cb116e520f71e8d7a794ca2606d537ddc6c099c40e7a25372b80a8fd443cd7dd222c8ea21b8ef372d4b3e316c26a73fd999cc79ad483eb826e7b3893ea332da68fa13224bcdeb4fb18b0584dd100a2c514'
889 hapd = hostapd.add_ap(apdev[0], params)
890 dev[0].request("SET sae_groups ")
891 dev[0].connect("test-sae", psk="test-sae", key_mgmt="SAE",
892 scan_freq="2412", wait_connect=False)
893 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
894 if ev is not None:
895 raise Exception("Unexpected connection")
896
eea62048
JM
897@remote_compatible
898def test_sae_commit_override2(dev, apdev):
899 """SAE commit override (wpa_supplicant)"""
900 if "SAE" not in dev[0].get_capability("auth_alg"):
901 raise HwsimSkip("SAE not supported")
902 params = hostapd.wpa2_params(ssid="test-sae",
903 passphrase="12345678")
904 params['wpa_key_mgmt'] = 'SAE'
905 hapd = hostapd.add_ap(apdev[0], params)
906 dev[0].request("SET sae_groups ")
907 dev[0].set('sae_commit_override', '13ffbad00d215867a7c5ff37d87bb9bdb7cb116e520f71e8d7a794ca2606d537ddc6c099c40e7a25372b80a8fd443cd7dd222c8ea21b8ef372d4b3e316c26a73fd999cc79ad483eb826e7b3893ea332da68fa13224bcdeb4fb18b0584dd100a2c514')
908 dev[0].connect("test-sae", psk="test-sae", key_mgmt="SAE",
909 scan_freq="2412", wait_connect=False)
910 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1)
911 if ev is not None:
912 raise Exception("Unexpected connection")
913
9fd6804d 914@remote_compatible
1965e196
JM
915def test_sae_anti_clogging_proto(dev, apdev):
916 """SAE anti clogging protocol testing"""
917 if "SAE" not in dev[0].get_capability("auth_alg"):
918 raise HwsimSkip("SAE not supported")
919 params = hostapd.wpa2_params(ssid="test-sae",
920 passphrase="no-knowledge-of-passphrase")
921 params['wpa_key_mgmt'] = 'SAE'
8b8a1864 922 hapd = hostapd.add_ap(apdev[0], params)
1965e196
JM
923 bssid = apdev[0]['bssid']
924
925 dev[0].scan_for_bss(bssid, freq=2412)
926 hapd.set("ext_mgmt_frame_handling", "1")
927
928 dev[0].request("SET sae_groups ")
929 dev[0].connect("test-sae", psk="anti-cloggign", key_mgmt="SAE",
930 scan_freq="2412", wait_connect=False)
931
932 # Commit
933 for i in range(0, 10):
934 req = hapd.mgmt_rx()
935 if req is None:
936 raise Exception("MGMT RX wait timed out")
937 if req['subtype'] == 11:
938 break
939 req = None
940 if not req:
941 raise Exception("Authentication frame not received")
942
943 resp = {}
944 resp['fc'] = req['fc']
945 resp['da'] = req['sa']
946 resp['sa'] = req['da']
947 resp['bssid'] = req['bssid']
948 resp['payload'] = binascii.unhexlify("030001004c00" + "ffff00")
949 hapd.mgmt_tx(resp)
950
951 # Confirm (not received due to DH group being rejected)
952 req = hapd.mgmt_rx(timeout=0.5)
953 if req is not None:
954 if req['subtype'] == 11:
955 raise Exception("Unexpected Authentication frame seen")
10ba4ae4 956
9fd6804d 957@remote_compatible
10ba4ae4
JM
958def test_sae_no_random(dev, apdev):
959 """SAE and no random numbers available"""
960 if "SAE" not in dev[0].get_capability("auth_alg"):
961 raise HwsimSkip("SAE not supported")
962 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
963 params['wpa_key_mgmt'] = 'SAE'
8b8a1864 964 hapd = hostapd.add_ap(apdev[0], params)
10ba4ae4
JM
965
966 dev[0].request("SET sae_groups ")
967 tests = [ (1, "os_get_random;sae_get_rand"),
968 (1, "os_get_random;get_rand_1_to_p_1"),
969 (1, "os_get_random;get_random_qr_qnr"),
970 (1, "os_get_random;sae_derive_pwe_ecc") ]
971 for count, func in tests:
972 with fail_test(dev[0], count, func):
973 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
974 scan_freq="2412")
975 dev[0].request("REMOVE_NETWORK all")
976 dev[0].wait_disconnected()
4f6985de 977
9fd6804d 978@remote_compatible
4f6985de
JM
979def test_sae_pwe_failure(dev, apdev):
980 """SAE and pwe failure"""
981 if "SAE" not in dev[0].get_capability("auth_alg"):
982 raise HwsimSkip("SAE not supported")
983 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
984 params['wpa_key_mgmt'] = 'SAE'
985 params['sae_groups'] = '19 5'
8b8a1864 986 hapd = hostapd.add_ap(apdev[0], params)
4f6985de
JM
987
988 dev[0].request("SET sae_groups 19")
989 with fail_test(dev[0], 1, "hmac_sha256_vector;sae_derive_pwe_ecc"):
990 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
991 scan_freq="2412")
992 dev[0].request("REMOVE_NETWORK all")
993 dev[0].wait_disconnected()
51761ba2
JM
994 with fail_test(dev[0], 1, "sae_test_pwd_seed_ecc"):
995 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
996 scan_freq="2412")
997 dev[0].request("REMOVE_NETWORK all")
998 dev[0].wait_disconnected()
4f6985de
JM
999
1000 dev[0].request("SET sae_groups 5")
1001 with fail_test(dev[0], 1, "hmac_sha256_vector;sae_derive_pwe_ffc"):
1002 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
1003 scan_freq="2412")
1004 dev[0].request("REMOVE_NETWORK all")
1005 dev[0].wait_disconnected()
1006
1007 dev[0].request("SET sae_groups 5")
1008 with fail_test(dev[0], 1, "sae_test_pwd_seed_ffc"):
1009 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
1010 scan_freq="2412")
1011 dev[0].request("REMOVE_NETWORK all")
1012 dev[0].wait_disconnected()
1013 with fail_test(dev[0], 2, "sae_test_pwd_seed_ffc"):
1014 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
1015 scan_freq="2412")
1016 dev[0].request("REMOVE_NETWORK all")
1017 dev[0].wait_disconnected()
51761ba2 1018
9fd6804d 1019@remote_compatible
51761ba2
JM
1020def test_sae_bignum_failure(dev, apdev):
1021 """SAE and bignum failure"""
1022 if "SAE" not in dev[0].get_capability("auth_alg"):
1023 raise HwsimSkip("SAE not supported")
1024 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
1025 params['wpa_key_mgmt'] = 'SAE'
1026 params['sae_groups'] = '19 5 22'
8b8a1864 1027 hapd = hostapd.add_ap(apdev[0], params)
51761ba2
JM
1028
1029 dev[0].request("SET sae_groups 19")
1030 tests = [ (1, "crypto_bignum_init_set;get_rand_1_to_p_1"),
1031 (1, "crypto_bignum_init;is_quadratic_residue_blind"),
1032 (1, "crypto_bignum_mulmod;is_quadratic_residue_blind"),
1033 (2, "crypto_bignum_mulmod;is_quadratic_residue_blind"),
1034 (3, "crypto_bignum_mulmod;is_quadratic_residue_blind"),
1035 (1, "crypto_bignum_legendre;is_quadratic_residue_blind"),
1036 (1, "crypto_bignum_init_set;sae_test_pwd_seed_ecc"),
1037 (1, "crypto_ec_point_compute_y_sqr;sae_test_pwd_seed_ecc"),
1038 (1, "crypto_bignum_init_set;get_random_qr_qnr"),
1039 (1, "crypto_bignum_to_bin;sae_derive_pwe_ecc"),
1040 (1, "crypto_ec_point_init;sae_derive_pwe_ecc"),
1041 (1, "crypto_ec_point_solve_y_coord;sae_derive_pwe_ecc"),
1042 (1, "crypto_ec_point_init;sae_derive_commit_element_ecc"),
1043 (1, "crypto_ec_point_mul;sae_derive_commit_element_ecc"),
1044 (1, "crypto_ec_point_invert;sae_derive_commit_element_ecc"),
1045 (1, "crypto_bignum_init;=sae_derive_commit"),
1046 (1, "crypto_ec_point_init;sae_derive_k_ecc"),
1047 (1, "crypto_ec_point_mul;sae_derive_k_ecc"),
1048 (1, "crypto_ec_point_add;sae_derive_k_ecc"),
1049 (2, "crypto_ec_point_mul;sae_derive_k_ecc"),
1050 (1, "crypto_ec_point_to_bin;sae_derive_k_ecc"),
1051 (1, "crypto_bignum_legendre;get_random_qr_qnr"),
1052 (1, "sha256_prf;sae_derive_keys"),
1053 (1, "crypto_bignum_init;sae_derive_keys"),
1054 (1, "crypto_bignum_init_set;sae_parse_commit_scalar"),
1055 (1, "crypto_bignum_to_bin;sae_parse_commit_element_ecc"),
1056 (1, "crypto_ec_point_from_bin;sae_parse_commit_element_ecc") ]
1057 for count, func in tests:
1058 with fail_test(dev[0], count, func):
1059 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
1060 scan_freq="2412", wait_connect=False)
1061 wait_fail_trigger(dev[0], "GET_FAIL")
1062 dev[0].request("REMOVE_NETWORK all")
1063
1064 dev[0].request("SET sae_groups 5")
1065 tests = [ (1, "crypto_bignum_init_set;sae_set_group"),
1066 (2, "crypto_bignum_init_set;sae_set_group"),
1067 (1, "crypto_bignum_init_set;sae_get_rand"),
1068 (1, "crypto_bignum_init_set;sae_test_pwd_seed_ffc"),
1069 (1, "crypto_bignum_exptmod;sae_test_pwd_seed_ffc"),
1070 (1, "crypto_bignum_init;sae_derive_pwe_ffc"),
1071 (1, "crypto_bignum_init;sae_derive_commit_element_ffc"),
1072 (1, "crypto_bignum_exptmod;sae_derive_commit_element_ffc"),
1073 (1, "crypto_bignum_inverse;sae_derive_commit_element_ffc"),
1074 (1, "crypto_bignum_init;sae_derive_k_ffc"),
1075 (1, "crypto_bignum_exptmod;sae_derive_k_ffc"),
1076 (1, "crypto_bignum_mulmod;sae_derive_k_ffc"),
1077 (2, "crypto_bignum_exptmod;sae_derive_k_ffc"),
1078 (1, "crypto_bignum_to_bin;sae_derive_k_ffc"),
1079 (1, "crypto_bignum_init_set;sae_parse_commit_element_ffc"),
1080 (1, "crypto_bignum_init;sae_parse_commit_element_ffc"),
1081 (2, "crypto_bignum_init_set;sae_parse_commit_element_ffc"),
1082 (1, "crypto_bignum_exptmod;sae_parse_commit_element_ffc") ]
1083 for count, func in tests:
1084 with fail_test(dev[0], count, func):
1085 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
1086 scan_freq="2412", wait_connect=False)
1087 wait_fail_trigger(dev[0], "GET_FAIL")
1088 dev[0].request("REMOVE_NETWORK all")
1089
1090 dev[0].request("SET sae_groups 22")
1091 tests = [ (1, "crypto_bignum_init_set;sae_test_pwd_seed_ffc"),
1092 (1, "crypto_bignum_sub;sae_test_pwd_seed_ffc"),
1093 (1, "crypto_bignum_div;sae_test_pwd_seed_ffc") ]
1094 for count, func in tests:
1095 with fail_test(dev[0], count, func):
1096 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
1097 scan_freq="2412", wait_connect=False)
1098 wait_fail_trigger(dev[0], "GET_FAIL")
1099 dev[0].request("REMOVE_NETWORK all")
28be769b
JM
1100
1101def test_sae_invalid_anti_clogging_token_req(dev, apdev):
1102 """SAE and invalid anti-clogging token request"""
1103 if "SAE" not in dev[0].get_capability("auth_alg"):
1104 raise HwsimSkip("SAE not supported")
1105 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
1106 params['wpa_key_mgmt'] = 'SAE'
77f52098
JM
1107 # Beacon more frequently since Probe Request frames are practically ignored
1108 # in this test setup (ext_mgmt_frame_handled=1 on hostapd side) and
1109 # wpa_supplicant scans may end up getting ignored if no new results are
1110 # available due to the missing Probe Response frames.
1111 params['beacon_int'] = '20'
28be769b
JM
1112 hapd = hostapd.add_ap(apdev[0], params)
1113 bssid = apdev[0]['bssid']
1114
1115 dev[0].request("SET sae_groups 19")
1116 dev[0].scan_for_bss(bssid, freq=2412)
1117 hapd.set("ext_mgmt_frame_handling", "1")
1118 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
1119 scan_freq="2412", wait_connect=False)
1120 ev = dev[0].wait_event(["SME: Trying to authenticate"])
1121 if ev is None:
77f52098 1122 raise Exception("No authentication attempt seen (1)")
28be769b
JM
1123 dev[0].dump_monitor()
1124
1125 for i in range(0, 10):
1126 req = hapd.mgmt_rx()
1127 if req is None:
1128 raise Exception("MGMT RX wait timed out (commit)")
1129 if req['subtype'] == 11:
1130 break
1131 req = None
1132 if not req:
1133 raise Exception("Authentication frame (commit) not received")
1134
1135 hapd.dump_monitor()
1136 resp = {}
1137 resp['fc'] = req['fc']
1138 resp['da'] = req['sa']
1139 resp['sa'] = req['da']
1140 resp['bssid'] = req['bssid']
1141 resp['payload'] = binascii.unhexlify("030001004c0013")
1142 hapd.mgmt_tx(resp)
77f52098
JM
1143 ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5)
1144 if ev is None:
1145 raise Exception("Management frame TX status not reported (1)")
1146 if "stype=11 ok=1" not in ev:
1147 raise Exception("Unexpected management frame TX status (1): " + ev)
28be769b
JM
1148
1149 ev = dev[0].wait_event(["SME: Trying to authenticate"])
1150 if ev is None:
77f52098 1151 raise Exception("No authentication attempt seen (2)")
28be769b
JM
1152 dev[0].dump_monitor()
1153
1154 for i in range(0, 10):
1155 req = hapd.mgmt_rx()
1156 if req is None:
1157 raise Exception("MGMT RX wait timed out (commit) (2)")
1158 if req['subtype'] == 11:
1159 break
1160 req = None
1161 if not req:
1162 raise Exception("Authentication frame (commit) not received (2)")
1163
1164 hapd.dump_monitor()
1165 resp = {}
1166 resp['fc'] = req['fc']
1167 resp['da'] = req['sa']
1168 resp['sa'] = req['da']
1169 resp['bssid'] = req['bssid']
1170 resp['payload'] = binascii.unhexlify("030001000100")
1171 hapd.mgmt_tx(resp)
77f52098
JM
1172 ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5)
1173 if ev is None:
1174 raise Exception("Management frame TX status not reported (1)")
1175 if "stype=11 ok=1" not in ev:
1176 raise Exception("Unexpected management frame TX status (1): " + ev)
28be769b
JM
1177
1178 ev = dev[0].wait_event(["SME: Trying to authenticate"])
1179 if ev is None:
77f52098 1180 raise Exception("No authentication attempt seen (3)")
28be769b
JM
1181 dev[0].dump_monitor()
1182
1183 dev[0].request("DISCONNECT")
606ef7d3
JM
1184
1185def test_sae_password(dev, apdev):
1186 """SAE and sae_password in hostapd configuration"""
1187 if "SAE" not in dev[0].get_capability("auth_alg"):
1188 raise HwsimSkip("SAE not supported")
1189 params = hostapd.wpa2_params(ssid="test-sae",
1190 passphrase="12345678")
1191 params['wpa_key_mgmt'] = 'SAE WPA-PSK'
1192 params['sae_password'] = "sae-password"
1193 hapd = hostapd.add_ap(apdev[0], params)
1194
1195 dev[0].request("SET sae_groups ")
1196 dev[0].connect("test-sae", psk="sae-password", key_mgmt="SAE",
1197 scan_freq="2412")
1198 dev[1].connect("test-sae", psk="12345678", scan_freq="2412")
1199 dev[2].request("SET sae_groups ")
1200 dev[2].connect("test-sae", sae_password="sae-password", key_mgmt="SAE",
1201 scan_freq="2412")
1202
1203def test_sae_password_short(dev, apdev):
1204 """SAE and short password"""
1205 if "SAE" not in dev[0].get_capability("auth_alg"):
1206 raise HwsimSkip("SAE not supported")
1207 params = hostapd.wpa2_params(ssid="test-sae")
1208 params['wpa_key_mgmt'] = 'SAE'
1209 params['sae_password'] = "secret"
1210 hapd = hostapd.add_ap(apdev[0], params)
1211
1212 dev[0].request("SET sae_groups ")
1213 dev[0].connect("test-sae", sae_password="secret", key_mgmt="SAE",
1214 scan_freq="2412")
1215
1216def test_sae_password_long(dev, apdev):
1217 """SAE and long password"""
1218 if "SAE" not in dev[0].get_capability("auth_alg"):
1219 raise HwsimSkip("SAE not supported")
1220 params = hostapd.wpa2_params(ssid="test-sae")
1221 params['wpa_key_mgmt'] = 'SAE'
1222 params['sae_password'] = 100*"A"
1223 hapd = hostapd.add_ap(apdev[0], params)
1224
1225 dev[0].request("SET sae_groups ")
1226 dev[0].connect("test-sae", sae_password=100*"A", key_mgmt="SAE",
1227 scan_freq="2412")
33822240
JM
1228
1229def test_sae_connect_cmd(dev, apdev):
1230 """SAE with connect command"""
1231 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5')
1232 wpas.interface_add("wlan5", drv_params="force_connect_cmd=1")
1233 if "SAE" not in wpas.get_capability("auth_alg"):
1234 raise HwsimSkip("SAE not supported")
1235 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678")
1236 params['wpa_key_mgmt'] = 'SAE'
1237 hapd = hostapd.add_ap(apdev[0], params)
1238
1239 wpas.request("SET sae_groups ")
1240 wpas.connect("test-sae", psk="12345678", key_mgmt="SAE",
1241 scan_freq="2412", wait_connect=False)
1242 # mac80211_hwsim does not support SAE offload, so accept both a successful
1243 # connection and association rejection.
1244 ev = wpas.wait_event(["CTRL-EVENT-CONNECTED", "CTRL-EVENT-ASSOC-REJECT",
1245 "Association request to the driver failed"],
1246 timeout=15)
1247 if ev is None:
1248 raise Exception("No connection result reported")
9a0ae89d
JM
1249
1250def test_sae_password_id(dev, apdev):
1251 """SAE and password identifier"""
1252 if "SAE" not in dev[0].get_capability("auth_alg"):
1253 raise HwsimSkip("SAE not supported")
1254 params = hostapd.wpa2_params(ssid="test-sae")
1255 params['wpa_key_mgmt'] = 'SAE'
1256 params['sae_password'] = [ 'secret|mac=ff:ff:ff:ff:ff:ff|id=pw id',
1257 'foo|mac=02:02:02:02:02:02',
1258 'another secret|mac=ff:ff:ff:ff:ff:ff|id=' + 29*'A' ]
1259 hapd = hostapd.add_ap(apdev[0], params)
1260
1261 dev[0].request("SET sae_groups ")
1262 dev[0].connect("test-sae", sae_password="secret", sae_password_id="pw id",
1263 key_mgmt="SAE", scan_freq="2412")
1264 dev[0].request("REMOVE_NETWORK all")
1265 dev[0].wait_disconnected()
1266
1267 # SAE Password Identifier element with the exact same length as the
1268 # optional Anti-Clogging Token field
1269 dev[0].connect("test-sae", sae_password="another secret",
1270 sae_password_id=29*'A',
1271 key_mgmt="SAE", scan_freq="2412")
1272 dev[0].request("REMOVE_NETWORK all")
1273 dev[0].wait_disconnected()
1274
1275 dev[0].connect("test-sae", sae_password="secret", sae_password_id="unknown",
1276 key_mgmt="SAE", scan_freq="2412", wait_connect=False)
1277
1278 ev = dev[0].wait_event(["CTRL-EVENT-SAE-UNKNOWN-PASSWORD-IDENTIFIER"],
1279 timeout=10)
1280 if ev is None:
1281 raise Exception("Unknown password identifier not reported")
1282 dev[0].request("REMOVE_NETWORK all")
1283
1284def test_sae_forced_anti_clogging_pw_id(dev, apdev):
1285 """SAE anti clogging (forced and Password Identifier)"""
1286 if "SAE" not in dev[0].get_capability("auth_alg"):
1287 raise HwsimSkip("SAE not supported")
1288 params = hostapd.wpa2_params(ssid="test-sae")
1289 params['wpa_key_mgmt'] = 'SAE'
1290 params['sae_anti_clogging_threshold'] = '0'
1291 params['sae_password'] = 'secret|id=' + 29*'A'
1292 hostapd.add_ap(apdev[0], params)
1293 for i in range(0, 2):
1294 dev[i].request("SET sae_groups ")
1295 dev[i].connect("test-sae", sae_password="secret",
1296 sae_password_id=29*'A', key_mgmt="SAE", scan_freq="2412")
fe102801
JM
1297
1298def test_sae_reauth(dev, apdev):
1299 """SAE reauthentication"""
1300 if "SAE" not in dev[0].get_capability("auth_alg"):
1301 raise HwsimSkip("SAE not supported")
1302 params = hostapd.wpa2_params(ssid="test-sae",
1303 passphrase="12345678")
1304 params['wpa_key_mgmt'] = 'SAE'
1305 params["ieee80211w"] = "2"
1306 hapd = hostapd.add_ap(apdev[0], params)
1307
1308 dev[0].request("SET sae_groups ")
1309 id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE",
1310 ieee80211w="2", scan_freq="2412")
1311
1312 hapd.set("ext_mgmt_frame_handling", "1")
1313 dev[0].request("DISCONNECT")
1314 dev[0].wait_disconnected(timeout=10)
1315 hapd.set("ext_mgmt_frame_handling", "0")
1316 dev[0].request("PMKSA_FLUSH")
1317 dev[0].request("REASSOCIATE")
1318 dev[0].wait_connected(timeout=10, error="Timeout on re-connection")