]>
git.ipfire.org Git - thirdparty/hostap.git/blob - tests/hwsim/test_sae.py
2 # Copyright (c) 2013-2016, Jouni Malinen <j@w1.fi>
4 # This software may be distributed under the terms of the BSD license.
5 # See README for more details.
12 logger
= logging
.getLogger()
16 from utils
import HwsimSkip
, alloc_fail
, fail_test
, wait_fail_trigger
17 from test_ap_psk
import find_wpas_process
, read_process_memory
, verify_not_present
, get_key_locations
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], 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
)
31 dev
[0].request("SET sae_groups ")
32 id = dev
[0].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
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'])
42 def test_sae_password_ecc(dev
, apdev
):
43 """SAE with number of different passwords (ECC)"""
44 if "SAE" not in dev
[0].get_capability("auth_alg"):
45 raise HwsimSkip("SAE not supported")
46 params
= hostapd
.wpa2_params(ssid
="test-sae",
47 passphrase
="12345678")
48 params
['wpa_key_mgmt'] = 'SAE'
49 hapd
= hostapd
.add_ap(apdev
[0], params
)
51 dev
[0].request("SET sae_groups 19")
54 password
= "12345678-" + str(i
)
55 hapd
.set("wpa_passphrase", password
)
56 dev
[0].connect("test-sae", psk
=password
, key_mgmt
="SAE",
58 dev
[0].request("REMOVE_NETWORK all")
59 dev
[0].wait_disconnected()
61 def test_sae_password_ffc(dev
, apdev
):
62 """SAE with number of different passwords (FFC)"""
63 if "SAE" not in dev
[0].get_capability("auth_alg"):
64 raise HwsimSkip("SAE not supported")
65 params
= hostapd
.wpa2_params(ssid
="test-sae",
66 passphrase
="12345678")
67 params
['wpa_key_mgmt'] = 'SAE'
68 params
['sae_groups'] = '22'
69 hapd
= hostapd
.add_ap(apdev
[0], params
)
71 dev
[0].request("SET sae_groups 22")
74 password
= "12345678-" + str(i
)
75 hapd
.set("wpa_passphrase", password
)
76 dev
[0].connect("test-sae", psk
=password
, key_mgmt
="SAE",
78 dev
[0].request("REMOVE_NETWORK all")
79 dev
[0].wait_disconnected()
81 def test_sae_pmksa_caching(dev
, apdev
):
82 """SAE and PMKSA caching"""
83 if "SAE" not in dev
[0].get_capability("auth_alg"):
84 raise HwsimSkip("SAE not supported")
85 params
= hostapd
.wpa2_params(ssid
="test-sae",
86 passphrase
="12345678")
87 params
['wpa_key_mgmt'] = 'SAE'
88 hapd
= hostapd
.add_ap(apdev
[0], params
)
90 dev
[0].request("SET sae_groups ")
91 dev
[0].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
93 ev
= hapd
.wait_event([ "AP-STA-CONNECTED" ], timeout
=5)
95 raise Exception("No connection event received from hostapd")
96 dev
[0].request("DISCONNECT")
97 dev
[0].wait_disconnected()
98 dev
[0].request("RECONNECT")
99 dev
[0].wait_connected(timeout
=15, error
="Reconnect timed out")
100 if dev
[0].get_status_field('sae_group') is not None:
101 raise Exception("SAE group claimed to have been used")
103 def test_sae_pmksa_caching_disabled(dev
, apdev
):
104 """SAE and PMKSA caching disabled"""
105 if "SAE" not in dev
[0].get_capability("auth_alg"):
106 raise HwsimSkip("SAE not supported")
107 params
= hostapd
.wpa2_params(ssid
="test-sae",
108 passphrase
="12345678")
109 params
['wpa_key_mgmt'] = 'SAE'
110 params
['disable_pmksa_caching'] = '1'
111 hapd
= hostapd
.add_ap(apdev
[0], params
)
113 dev
[0].request("SET sae_groups ")
114 dev
[0].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
116 ev
= hapd
.wait_event([ "AP-STA-CONNECTED" ], timeout
=5)
118 raise Exception("No connection event received from hostapd")
119 dev
[0].request("DISCONNECT")
120 dev
[0].wait_disconnected()
121 dev
[0].request("RECONNECT")
122 dev
[0].wait_connected(timeout
=15, error
="Reconnect timed out")
123 if dev
[0].get_status_field('sae_group') != '19':
124 raise Exception("Expected default SAE group not used")
126 def test_sae_groups(dev
, apdev
):
127 """SAE with all supported groups"""
128 if "SAE" not in dev
[0].get_capability("auth_alg"):
129 raise HwsimSkip("SAE not supported")
130 # This is the full list of supported groups, but groups 14-16 (2048-4096 bit
131 # MODP) and group 21 (521-bit random ECP group) are a bit too slow on some
132 # VMs and can result in hitting the mac80211 authentication timeout, so
133 # allow them to fail and just report such failures in the debug log.
134 sae_groups
= [ 19, 25, 26, 20, 21, 2, 5, 14, 15, 16, 22, 23, 24 ]
135 tls
= dev
[0].request("GET tls_library")
136 if tls
.startswith("OpenSSL") and "build=OpenSSL 1.0.2" in tls
and "run=OpenSSL 1.0.2" in tls
:
137 logger
.info("Add Brainpool EC groups since OpenSSL is new enough")
138 sae_groups
+= [ 27, 28, 29, 30 ]
139 heavy_groups
= [ 14, 15, 16 ]
140 groups
= [str(g
) for g
in sae_groups
]
141 params
= hostapd
.wpa2_params(ssid
="test-sae-groups",
142 passphrase
="12345678")
143 params
['wpa_key_mgmt'] = 'SAE'
144 params
['sae_groups'] = ' '.join(groups
)
145 hostapd
.add_ap(apdev
[0], params
)
148 logger
.info("Testing SAE group " + g
)
149 dev
[0].request("SET sae_groups " + g
)
150 id = dev
[0].connect("test-sae-groups", psk
="12345678", key_mgmt
="SAE",
151 scan_freq
="2412", wait_connect
=False)
152 if int(g
) in heavy_groups
:
153 ev
= dev
[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout
=5)
155 logger
.info("No connection with heavy SAE group %s did not connect - likely hitting timeout in mac80211" % g
)
156 dev
[0].remove_network(id)
158 dev
[0].dump_monitor()
160 logger
.info("Connection with heavy SAE group " + g
)
162 ev
= dev
[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout
=10)
164 if "BoringSSL" in tls
and int(g
) in [ 25 ]:
165 logger
.info("Ignore connection failure with group " + g
+ " with BoringSSL")
166 dev
[0].remove_network(id)
167 dev
[0].dump_monitor()
169 raise Exception("Connection timed out with group " + g
)
170 if dev
[0].get_status_field('sae_group') != g
:
171 raise Exception("Expected SAE group not used")
172 dev
[0].remove_network(id)
173 dev
[0].wait_disconnected()
174 dev
[0].dump_monitor()
176 def test_sae_group_nego(dev
, apdev
):
177 """SAE group negotiation"""
178 if "SAE" not in dev
[0].get_capability("auth_alg"):
179 raise HwsimSkip("SAE not supported")
180 params
= hostapd
.wpa2_params(ssid
="test-sae-group-nego",
181 passphrase
="12345678")
182 params
['wpa_key_mgmt'] = 'SAE'
183 params
['sae_groups'] = '19'
184 hostapd
.add_ap(apdev
[0], params
)
186 dev
[0].request("SET sae_groups 25 26 20 19")
187 dev
[0].connect("test-sae-group-nego", psk
="12345678", key_mgmt
="SAE",
189 if dev
[0].get_status_field('sae_group') != '19':
190 raise Exception("Expected SAE group not used")
192 def test_sae_anti_clogging(dev
, apdev
):
193 """SAE anti clogging"""
194 if "SAE" not in dev
[0].get_capability("auth_alg"):
195 raise HwsimSkip("SAE not supported")
196 params
= hostapd
.wpa2_params(ssid
="test-sae", passphrase
="12345678")
197 params
['wpa_key_mgmt'] = 'SAE'
198 params
['sae_anti_clogging_threshold'] = '1'
199 hostapd
.add_ap(apdev
[0], params
)
201 dev
[0].request("SET sae_groups ")
202 dev
[1].request("SET sae_groups ")
204 for i
in range(0, 2):
205 dev
[i
].scan(freq
="2412")
206 id[i
] = dev
[i
].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
207 scan_freq
="2412", only_add_network
=True)
208 for i
in range(0, 2):
209 dev
[i
].select_network(id[i
])
210 for i
in range(0, 2):
211 dev
[i
].wait_connected(timeout
=10)
213 def test_sae_forced_anti_clogging(dev
, apdev
):
214 """SAE anti clogging (forced)"""
215 if "SAE" not in dev
[0].get_capability("auth_alg"):
216 raise HwsimSkip("SAE not supported")
217 params
= hostapd
.wpa2_params(ssid
="test-sae", passphrase
="12345678")
218 params
['wpa_key_mgmt'] = 'SAE WPA-PSK'
219 params
['sae_anti_clogging_threshold'] = '0'
220 hostapd
.add_ap(apdev
[0], params
)
221 dev
[2].connect("test-sae", psk
="12345678", scan_freq
="2412")
222 for i
in range(0, 2):
223 dev
[i
].request("SET sae_groups ")
224 dev
[i
].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
227 def test_sae_mixed(dev
, apdev
):
228 """Mixed SAE and non-SAE network"""
229 if "SAE" not in dev
[0].get_capability("auth_alg"):
230 raise HwsimSkip("SAE not supported")
231 params
= hostapd
.wpa2_params(ssid
="test-sae", passphrase
="12345678")
232 params
['wpa_key_mgmt'] = 'SAE WPA-PSK'
233 params
['sae_anti_clogging_threshold'] = '0'
234 hostapd
.add_ap(apdev
[0], params
)
236 dev
[2].connect("test-sae", psk
="12345678", scan_freq
="2412")
237 for i
in range(0, 2):
238 dev
[i
].request("SET sae_groups ")
239 dev
[i
].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
242 def test_sae_missing_password(dev
, apdev
):
243 """SAE and missing password"""
244 if "SAE" not in dev
[0].get_capability("auth_alg"):
245 raise HwsimSkip("SAE not supported")
246 params
= hostapd
.wpa2_params(ssid
="test-sae",
247 passphrase
="12345678")
248 params
['wpa_key_mgmt'] = 'SAE'
249 hapd
= hostapd
.add_ap(apdev
[0], params
)
251 dev
[0].request("SET sae_groups ")
252 id = dev
[0].connect("test-sae",
253 raw_psk
="46b4a73b8a951ad53ebd2e0afdb9c5483257edd4c21d12b7710759da70945858",
254 key_mgmt
="SAE", scan_freq
="2412", wait_connect
=False)
255 ev
= dev
[0].wait_event(['CTRL-EVENT-SSID-TEMP-DISABLED'], timeout
=10)
257 raise Exception("Invalid network not temporarily disabled")
260 def test_sae_key_lifetime_in_memory(dev
, apdev
, params
):
261 """SAE and key lifetime in memory"""
262 if "SAE" not in dev
[0].get_capability("auth_alg"):
263 raise HwsimSkip("SAE not supported")
264 password
= "5ad144a7c1f5a5503baa6fa01dabc15b1843e8c01662d78d16b70b5cd23cf8b"
265 p
= hostapd
.wpa2_params(ssid
="test-sae", passphrase
=password
)
266 p
['wpa_key_mgmt'] = 'SAE'
267 hapd
= hostapd
.add_ap(apdev
[0], p
)
269 pid
= find_wpas_process(dev
[0])
271 dev
[0].request("SET sae_groups ")
272 id = dev
[0].connect("test-sae", psk
=password
, key_mgmt
="SAE",
275 # The decrypted copy of GTK is freed only after the CTRL-EVENT-CONNECTED
276 # event has been delivered, so verify that wpa_supplicant has returned to
277 # eloop before reading process memory.
280 buf
= read_process_memory(pid
, password
)
282 dev
[0].request("DISCONNECT")
283 dev
[0].wait_disconnected()
292 with
open(os
.path
.join(params
['logdir'], 'log0'), 'r') as f
:
293 for l
in f
.readlines():
294 if "SAE: k - hexdump" in l
:
295 val
= l
.strip().split(':')[3].replace(' ', '')
296 sae_k
= binascii
.unhexlify(val
)
297 if "SAE: keyseed - hexdump" in l
:
298 val
= l
.strip().split(':')[3].replace(' ', '')
299 sae_keyseed
= binascii
.unhexlify(val
)
300 if "SAE: KCK - hexdump" in l
:
301 val
= l
.strip().split(':')[3].replace(' ', '')
302 sae_kck
= binascii
.unhexlify(val
)
303 if "SAE: PMK - hexdump" in l
:
304 val
= l
.strip().split(':')[3].replace(' ', '')
305 pmk
= binascii
.unhexlify(val
)
306 if "WPA: PTK - hexdump" in l
:
307 val
= l
.strip().split(':')[3].replace(' ', '')
308 ptk
= binascii
.unhexlify(val
)
309 if "WPA: Group Key - hexdump" in l
:
310 val
= l
.strip().split(':')[3].replace(' ', '')
311 gtk
= binascii
.unhexlify(val
)
312 if not sae_k
or not sae_keyseed
or not sae_kck
or not pmk
or not ptk
or not gtk
:
313 raise Exception("Could not find keys from debug log")
315 raise Exception("Unexpected GTK length")
321 fname
= os
.path
.join(params
['logdir'],
322 'sae_key_lifetime_in_memory.memctx-')
324 logger
.info("Checking keys in memory while associated")
325 get_key_locations(buf
, password
, "Password")
326 get_key_locations(buf
, pmk
, "PMK")
327 if password
not in buf
:
328 raise HwsimSkip("Password not found while associated")
330 raise HwsimSkip("PMK not found while associated")
332 raise Exception("KCK not found while associated")
334 raise Exception("KEK not found while associated")
336 raise Exception("TK found from memory")
338 get_key_locations(buf
, gtk
, "GTK")
339 raise Exception("GTK found from memory")
340 verify_not_present(buf
, sae_k
, fname
, "SAE(k)")
341 verify_not_present(buf
, sae_keyseed
, fname
, "SAE(keyseed)")
342 verify_not_present(buf
, sae_kck
, fname
, "SAE(KCK)")
344 logger
.info("Checking keys in memory after disassociation")
345 buf
= read_process_memory(pid
, password
)
347 # Note: Password is still present in network configuration
348 # Note: PMK is in PMKSA cache
350 get_key_locations(buf
, password
, "Password")
351 get_key_locations(buf
, pmk
, "PMK")
352 verify_not_present(buf
, kck
, fname
, "KCK")
353 verify_not_present(buf
, kek
, fname
, "KEK")
354 verify_not_present(buf
, tk
, fname
, "TK")
355 verify_not_present(buf
, gtk
, fname
, "GTK")
356 verify_not_present(buf
, sae_k
, fname
, "SAE(k)")
357 verify_not_present(buf
, sae_keyseed
, fname
, "SAE(keyseed)")
358 verify_not_present(buf
, sae_kck
, fname
, "SAE(KCK)")
360 dev
[0].request("PMKSA_FLUSH")
361 logger
.info("Checking keys in memory after PMKSA cache flush")
362 buf
= read_process_memory(pid
, password
)
363 get_key_locations(buf
, password
, "Password")
364 get_key_locations(buf
, pmk
, "PMK")
365 verify_not_present(buf
, pmk
, fname
, "PMK")
367 dev
[0].request("REMOVE_NETWORK all")
369 logger
.info("Checking keys in memory after network profile removal")
370 buf
= read_process_memory(pid
, password
)
372 get_key_locations(buf
, password
, "Password")
373 get_key_locations(buf
, pmk
, "PMK")
374 verify_not_present(buf
, password
, fname
, "password")
375 verify_not_present(buf
, pmk
, fname
, "PMK")
376 verify_not_present(buf
, kck
, fname
, "KCK")
377 verify_not_present(buf
, kek
, fname
, "KEK")
378 verify_not_present(buf
, tk
, fname
, "TK")
379 verify_not_present(buf
, gtk
, fname
, "GTK")
380 verify_not_present(buf
, sae_k
, fname
, "SAE(k)")
381 verify_not_present(buf
, sae_keyseed
, fname
, "SAE(keyseed)")
382 verify_not_present(buf
, sae_kck
, fname
, "SAE(KCK)")
384 def test_sae_oom_wpas(dev
, apdev
):
385 """SAE and OOM in wpa_supplicant"""
386 if "SAE" not in dev
[0].get_capability("auth_alg"):
387 raise HwsimSkip("SAE not supported")
388 params
= hostapd
.wpa2_params(ssid
="test-sae",
389 passphrase
="12345678")
390 params
['wpa_key_mgmt'] = 'SAE'
391 hapd
= hostapd
.add_ap(apdev
[0], params
)
393 dev
[0].request("SET sae_groups 25")
394 tls
= dev
[0].request("GET tls_library")
395 if "BoringSSL" in tls
:
396 dev
[0].request("SET sae_groups 26")
397 with
alloc_fail(dev
[0], 1, "sae_set_group"):
398 dev
[0].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
400 dev
[0].request("REMOVE_NETWORK all")
402 dev
[0].request("SET sae_groups ")
403 with
alloc_fail(dev
[0], 2, "sae_set_group"):
404 dev
[0].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
406 dev
[0].request("REMOVE_NETWORK all")
408 def test_sae_proto_ecc(dev
, apdev
):
409 """SAE protocol testing (ECC)"""
410 if "SAE" not in dev
[0].get_capability("auth_alg"):
411 raise HwsimSkip("SAE not supported")
412 params
= hostapd
.wpa2_params(ssid
="test-sae",
413 passphrase
="12345678")
414 params
['wpa_key_mgmt'] = 'SAE'
415 hapd
= hostapd
.add_ap(apdev
[0], params
)
416 bssid
= apdev
[0]['bssid']
418 dev
[0].request("SET sae_groups 19")
420 tests
= [ ("Confirm mismatch",
421 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
422 "0000800edebc3f260dc1fe7e0b20888af2b8a3316252ec37388a8504e25b73dc4240"),
423 ("Commit without even full cyclic group field",
427 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02",
429 ("Invalid commit scalar (0)",
430 "1300" + "0000000000000000000000000000000000000000000000000000000000000000" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
432 ("Invalid commit scalar (1)",
433 "1300" + "0000000000000000000000000000000000000000000000000000000000000001" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
435 ("Invalid commit scalar (> r)",
436 "1300" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
438 ("Commit element not on curve",
439 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728d0000000000000000000000000000000000000000000000000000000000000000",
441 ("Invalid commit element (y coordinate > P)",
442 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
444 ("Invalid commit element (x coordinate > P)",
445 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
447 ("Different group in commit",
448 "1400" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
450 ("Too short confirm",
451 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8",
452 "0000800edebc3f260dc1fe7e0b20888af2b8a3316252ec37388a8504e25b73dc42")]
453 for (note
, commit
, confirm
) in tests
:
455 dev
[0].scan_for_bss(bssid
, freq
=2412)
456 hapd
.set("ext_mgmt_frame_handling", "1")
457 dev
[0].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
458 scan_freq
="2412", wait_connect
=False)
460 logger
.info("Commit")
461 for i
in range(0, 10):
464 raise Exception("MGMT RX wait timed out (commit)")
465 if req
['subtype'] == 11:
469 raise Exception("Authentication frame (commit) not received")
473 resp
['fc'] = req
['fc']
474 resp
['da'] = req
['sa']
475 resp
['sa'] = req
['da']
476 resp
['bssid'] = req
['bssid']
477 resp
['payload'] = binascii
.unhexlify("030001000000" + commit
)
481 logger
.info("Confirm")
482 for i
in range(0, 10):
485 raise Exception("MGMT RX wait timed out (confirm)")
486 if req
['subtype'] == 11:
490 raise Exception("Authentication frame (confirm) not received")
494 resp
['fc'] = req
['fc']
495 resp
['da'] = req
['sa']
496 resp
['sa'] = req
['da']
497 resp
['bssid'] = req
['bssid']
498 resp
['payload'] = binascii
.unhexlify("030002000000" + confirm
)
502 dev
[0].request("REMOVE_NETWORK all")
503 hapd
.set("ext_mgmt_frame_handling", "0")
506 def test_sae_proto_ffc(dev
, apdev
):
507 """SAE protocol testing (FFC)"""
508 if "SAE" not in dev
[0].get_capability("auth_alg"):
509 raise HwsimSkip("SAE not supported")
510 params
= hostapd
.wpa2_params(ssid
="test-sae",
511 passphrase
="12345678")
512 params
['wpa_key_mgmt'] = 'SAE'
513 hapd
= hostapd
.add_ap(apdev
[0], params
)
514 bssid
= apdev
[0]['bssid']
516 dev
[0].request("SET sae_groups 2")
518 tests
= [ ("Confirm mismatch",
519 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "a8c00117493cdffa5dd671e934bc9cb1a69f39e25e9dd9cd9afd3aea2441a0f5491211c7ba50a753563f9ce943b043557cb71193b28e86ed9544f4289c471bf91b70af5c018cf4663e004165b0fd0bc1d8f3f78adf42eee92bcbc55246fd3ee9f107ab965dc7d4986f23eb71d616ebfe6bfe0a6c1ac5dc1718acee17c9a17486",
520 "0000f3116a9731f1259622e3eb55d4b3b50ba16f8c5f5565b28e609b180c51460251"),
522 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "a8c00117493cdffa5dd671e934bc9cb1a69f39e25e9dd9cd9afd3aea2441a0f5491211c7ba50a753563f9ce943b043557cb71193b28e86ed9544f4289c471bf91b70af5c018cf4663e004165b0fd0bc1d8f3f78adf42eee92bcbc55246fd3ee9f107ab965dc7d4986f23eb71d616ebfe6bfe0a6c1ac5dc1718acee17c9a174",
524 ("Invalid element (0) in commit",
525 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
527 ("Invalid element (1) in commit",
528 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
530 ("Invalid element (> P) in commit",
531 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
533 for (note
, commit
, confirm
) in tests
:
535 dev
[0].scan_for_bss(bssid
, freq
=2412)
536 hapd
.set("ext_mgmt_frame_handling", "1")
537 dev
[0].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
538 scan_freq
="2412", wait_connect
=False)
540 logger
.info("Commit")
541 for i
in range(0, 10):
544 raise Exception("MGMT RX wait timed out (commit)")
545 if req
['subtype'] == 11:
549 raise Exception("Authentication frame (commit) not received")
553 resp
['fc'] = req
['fc']
554 resp
['da'] = req
['sa']
555 resp
['sa'] = req
['da']
556 resp
['bssid'] = req
['bssid']
557 resp
['payload'] = binascii
.unhexlify("030001000000" + commit
)
561 logger
.info("Confirm")
562 for i
in range(0, 10):
565 raise Exception("MGMT RX wait timed out (confirm)")
566 if req
['subtype'] == 11:
570 raise Exception("Authentication frame (confirm) not received")
574 resp
['fc'] = req
['fc']
575 resp
['da'] = req
['sa']
576 resp
['sa'] = req
['da']
577 resp
['bssid'] = req
['bssid']
578 resp
['payload'] = binascii
.unhexlify("030002000000" + confirm
)
582 dev
[0].request("REMOVE_NETWORK all")
583 hapd
.set("ext_mgmt_frame_handling", "0")
586 def test_sae_no_ffc_by_default(dev
, apdev
):
587 """SAE and default groups rejecting FFC"""
588 if "SAE" not in dev
[0].get_capability("auth_alg"):
589 raise HwsimSkip("SAE not supported")
590 params
= hostapd
.wpa2_params(ssid
="test-sae", passphrase
="12345678")
591 params
['wpa_key_mgmt'] = 'SAE'
592 hapd
= hostapd
.add_ap(apdev
[0], params
)
594 dev
[0].request("SET sae_groups 5")
595 dev
[0].connect("test-sae", psk
="12345678", key_mgmt
="SAE", scan_freq
="2412",
597 ev
= dev
[0].wait_event(["SME: Trying to authenticate"], timeout
=3)
599 raise Exception("Did not try to authenticate")
600 ev
= dev
[0].wait_event(["SME: Trying to authenticate"], timeout
=3)
602 raise Exception("Did not try to authenticate (2)")
603 dev
[0].request("REMOVE_NETWORK all")
605 def sae_reflection_attack(apdev
, dev
, group
):
606 if "SAE" not in dev
.get_capability("auth_alg"):
607 raise HwsimSkip("SAE not supported")
608 params
= hostapd
.wpa2_params(ssid
="test-sae",
609 passphrase
="no-knowledge-of-passphrase")
610 params
['wpa_key_mgmt'] = 'SAE'
611 hapd
= hostapd
.add_ap(apdev
['ifname'], params
)
612 bssid
= apdev
['bssid']
614 dev
.scan_for_bss(bssid
, freq
=2412)
615 hapd
.set("ext_mgmt_frame_handling", "1")
617 dev
.request("SET sae_groups %d" % group
)
618 dev
.connect("test-sae", psk
="reflection-attack", key_mgmt
="SAE",
619 scan_freq
="2412", wait_connect
=False)
622 for i
in range(0, 10):
625 raise Exception("MGMT RX wait timed out")
626 if req
['subtype'] == 11:
630 raise Exception("Authentication frame not received")
633 resp
['fc'] = req
['fc']
634 resp
['da'] = req
['sa']
635 resp
['sa'] = req
['da']
636 resp
['bssid'] = req
['bssid']
637 resp
['payload'] = req
['payload']
641 req
= hapd
.mgmt_rx(timeout
=0.5)
643 if req
['subtype'] == 11:
644 raise Exception("Unexpected Authentication frame seen")
646 def test_sae_reflection_attack_ecc(dev
, apdev
):
647 """SAE reflection attack (ECC)"""
648 sae_reflection_attack(apdev
[0], dev
[0], 19)
650 def test_sae_reflection_attack_ffc(dev
, apdev
):
651 """SAE reflection attack (FFC)"""
652 sae_reflection_attack(apdev
[0], dev
[0], 5)
654 def test_sae_anti_clogging_proto(dev
, apdev
):
655 """SAE anti clogging protocol testing"""
656 if "SAE" not in dev
[0].get_capability("auth_alg"):
657 raise HwsimSkip("SAE not supported")
658 params
= hostapd
.wpa2_params(ssid
="test-sae",
659 passphrase
="no-knowledge-of-passphrase")
660 params
['wpa_key_mgmt'] = 'SAE'
661 hapd
= hostapd
.add_ap(apdev
[0], params
)
662 bssid
= apdev
[0]['bssid']
664 dev
[0].scan_for_bss(bssid
, freq
=2412)
665 hapd
.set("ext_mgmt_frame_handling", "1")
667 dev
[0].request("SET sae_groups ")
668 dev
[0].connect("test-sae", psk
="anti-cloggign", key_mgmt
="SAE",
669 scan_freq
="2412", wait_connect
=False)
672 for i
in range(0, 10):
675 raise Exception("MGMT RX wait timed out")
676 if req
['subtype'] == 11:
680 raise Exception("Authentication frame not received")
683 resp
['fc'] = req
['fc']
684 resp
['da'] = req
['sa']
685 resp
['sa'] = req
['da']
686 resp
['bssid'] = req
['bssid']
687 resp
['payload'] = binascii
.unhexlify("030001004c00" + "ffff00")
690 # Confirm (not received due to DH group being rejected)
691 req
= hapd
.mgmt_rx(timeout
=0.5)
693 if req
['subtype'] == 11:
694 raise Exception("Unexpected Authentication frame seen")
696 def test_sae_no_random(dev
, apdev
):
697 """SAE and no random numbers available"""
698 if "SAE" not in dev
[0].get_capability("auth_alg"):
699 raise HwsimSkip("SAE not supported")
700 params
= hostapd
.wpa2_params(ssid
="test-sae", passphrase
="12345678")
701 params
['wpa_key_mgmt'] = 'SAE'
702 hapd
= hostapd
.add_ap(apdev
[0], params
)
704 dev
[0].request("SET sae_groups ")
705 tests
= [ (1, "os_get_random;sae_get_rand"),
706 (1, "os_get_random;get_rand_1_to_p_1"),
707 (1, "os_get_random;get_random_qr_qnr"),
708 (1, "os_get_random;sae_derive_pwe_ecc") ]
709 for count
, func
in tests
:
710 with
fail_test(dev
[0], count
, func
):
711 dev
[0].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
713 dev
[0].request("REMOVE_NETWORK all")
714 dev
[0].wait_disconnected()
716 def test_sae_pwe_failure(dev
, apdev
):
717 """SAE and pwe failure"""
718 if "SAE" not in dev
[0].get_capability("auth_alg"):
719 raise HwsimSkip("SAE not supported")
720 params
= hostapd
.wpa2_params(ssid
="test-sae", passphrase
="12345678")
721 params
['wpa_key_mgmt'] = 'SAE'
722 params
['sae_groups'] = '19 5'
723 hapd
= hostapd
.add_ap(apdev
[0], params
)
725 dev
[0].request("SET sae_groups 19")
726 with
fail_test(dev
[0], 1, "hmac_sha256_vector;sae_derive_pwe_ecc"):
727 dev
[0].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
729 dev
[0].request("REMOVE_NETWORK all")
730 dev
[0].wait_disconnected()
731 with
fail_test(dev
[0], 1, "sae_test_pwd_seed_ecc"):
732 dev
[0].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
734 dev
[0].request("REMOVE_NETWORK all")
735 dev
[0].wait_disconnected()
737 dev
[0].request("SET sae_groups 5")
738 with
fail_test(dev
[0], 1, "hmac_sha256_vector;sae_derive_pwe_ffc"):
739 dev
[0].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
741 dev
[0].request("REMOVE_NETWORK all")
742 dev
[0].wait_disconnected()
744 dev
[0].request("SET sae_groups 5")
745 with
fail_test(dev
[0], 1, "sae_test_pwd_seed_ffc"):
746 dev
[0].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
748 dev
[0].request("REMOVE_NETWORK all")
749 dev
[0].wait_disconnected()
750 with
fail_test(dev
[0], 2, "sae_test_pwd_seed_ffc"):
751 dev
[0].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
753 dev
[0].request("REMOVE_NETWORK all")
754 dev
[0].wait_disconnected()
756 def test_sae_bignum_failure(dev
, apdev
):
757 """SAE and bignum failure"""
758 if "SAE" not in dev
[0].get_capability("auth_alg"):
759 raise HwsimSkip("SAE not supported")
760 params
= hostapd
.wpa2_params(ssid
="test-sae", passphrase
="12345678")
761 params
['wpa_key_mgmt'] = 'SAE'
762 params
['sae_groups'] = '19 5 22'
763 hapd
= hostapd
.add_ap(apdev
[0], params
)
765 dev
[0].request("SET sae_groups 19")
766 tests
= [ (1, "crypto_bignum_init_set;get_rand_1_to_p_1"),
767 (1, "crypto_bignum_init;is_quadratic_residue_blind"),
768 (1, "crypto_bignum_mulmod;is_quadratic_residue_blind"),
769 (2, "crypto_bignum_mulmod;is_quadratic_residue_blind"),
770 (3, "crypto_bignum_mulmod;is_quadratic_residue_blind"),
771 (1, "crypto_bignum_legendre;is_quadratic_residue_blind"),
772 (1, "crypto_bignum_init_set;sae_test_pwd_seed_ecc"),
773 (1, "crypto_ec_point_compute_y_sqr;sae_test_pwd_seed_ecc"),
774 (1, "crypto_bignum_init_set;get_random_qr_qnr"),
775 (1, "crypto_bignum_to_bin;sae_derive_pwe_ecc"),
776 (1, "crypto_ec_point_init;sae_derive_pwe_ecc"),
777 (1, "crypto_ec_point_solve_y_coord;sae_derive_pwe_ecc"),
778 (1, "crypto_ec_point_init;sae_derive_commit_element_ecc"),
779 (1, "crypto_ec_point_mul;sae_derive_commit_element_ecc"),
780 (1, "crypto_ec_point_invert;sae_derive_commit_element_ecc"),
781 (1, "crypto_bignum_init;=sae_derive_commit"),
782 (1, "crypto_ec_point_init;sae_derive_k_ecc"),
783 (1, "crypto_ec_point_mul;sae_derive_k_ecc"),
784 (1, "crypto_ec_point_add;sae_derive_k_ecc"),
785 (2, "crypto_ec_point_mul;sae_derive_k_ecc"),
786 (1, "crypto_ec_point_to_bin;sae_derive_k_ecc"),
787 (1, "crypto_bignum_legendre;get_random_qr_qnr"),
788 (1, "sha256_prf;sae_derive_keys"),
789 (1, "crypto_bignum_init;sae_derive_keys"),
790 (1, "crypto_bignum_init_set;sae_parse_commit_scalar"),
791 (1, "crypto_bignum_to_bin;sae_parse_commit_element_ecc"),
792 (1, "crypto_ec_point_from_bin;sae_parse_commit_element_ecc") ]
793 for count
, func
in tests
:
794 with
fail_test(dev
[0], count
, func
):
795 dev
[0].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
796 scan_freq
="2412", wait_connect
=False)
797 wait_fail_trigger(dev
[0], "GET_FAIL")
798 dev
[0].request("REMOVE_NETWORK all")
800 dev
[0].request("SET sae_groups 5")
801 tests
= [ (1, "crypto_bignum_init_set;sae_set_group"),
802 (2, "crypto_bignum_init_set;sae_set_group"),
803 (1, "crypto_bignum_init_set;sae_get_rand"),
804 (1, "crypto_bignum_init_set;sae_test_pwd_seed_ffc"),
805 (1, "crypto_bignum_exptmod;sae_test_pwd_seed_ffc"),
806 (1, "crypto_bignum_init;sae_derive_pwe_ffc"),
807 (1, "crypto_bignum_init;sae_derive_commit_element_ffc"),
808 (1, "crypto_bignum_exptmod;sae_derive_commit_element_ffc"),
809 (1, "crypto_bignum_inverse;sae_derive_commit_element_ffc"),
810 (1, "crypto_bignum_init;sae_derive_k_ffc"),
811 (1, "crypto_bignum_exptmod;sae_derive_k_ffc"),
812 (1, "crypto_bignum_mulmod;sae_derive_k_ffc"),
813 (2, "crypto_bignum_exptmod;sae_derive_k_ffc"),
814 (1, "crypto_bignum_to_bin;sae_derive_k_ffc"),
815 (1, "crypto_bignum_init_set;sae_parse_commit_element_ffc"),
816 (1, "crypto_bignum_init;sae_parse_commit_element_ffc"),
817 (2, "crypto_bignum_init_set;sae_parse_commit_element_ffc"),
818 (1, "crypto_bignum_exptmod;sae_parse_commit_element_ffc") ]
819 for count
, func
in tests
:
820 with
fail_test(dev
[0], count
, func
):
821 dev
[0].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
822 scan_freq
="2412", wait_connect
=False)
823 wait_fail_trigger(dev
[0], "GET_FAIL")
824 dev
[0].request("REMOVE_NETWORK all")
826 dev
[0].request("SET sae_groups 22")
827 tests
= [ (1, "crypto_bignum_init_set;sae_test_pwd_seed_ffc"),
828 (1, "crypto_bignum_sub;sae_test_pwd_seed_ffc"),
829 (1, "crypto_bignum_div;sae_test_pwd_seed_ffc") ]
830 for count
, func
in tests
:
831 with
fail_test(dev
[0], count
, func
):
832 dev
[0].connect("test-sae", psk
="12345678", key_mgmt
="SAE",
833 scan_freq
="2412", wait_connect
=False)
834 wait_fail_trigger(dev
[0], "GET_FAIL")
835 dev
[0].request("REMOVE_NETWORK all")