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