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