1# Test cases for SAE 2# Copyright (c) 2013-2020, 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 7from remotehost import remote_compatible 8import binascii 9import os 10import time 11import logging 12logger = logging.getLogger() 13import socket 14import struct 15import subprocess 16import tempfile 17 18import hwsim_utils 19import hostapd 20from wpasupplicant import WpaSupplicant 21from utils import * 22from test_ap_psk import find_wpas_process, read_process_memory, verify_not_present, get_key_locations 23 24@remote_compatible 25def test_sae(dev, apdev): 26 """SAE with default group""" 27 check_sae_capab(dev[0]) 28 params = hostapd.wpa2_params(ssid="test-sae", 29 passphrase="12345678") 30 params['wpa_key_mgmt'] = 'SAE' 31 hapd = hostapd.add_ap(apdev[0], params) 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) 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 hapd.wait_sta() 40 if dev[0].get_status_field('sae_group') != '19': 41 raise Exception("Expected default SAE group not used") 42 bss = dev[0].get_bss(apdev[0]['bssid']) 43 if 'flags' not in bss: 44 raise Exception("Could not get BSS flags from BSS table") 45 if "[WPA2-SAE-CCMP]" not in bss['flags']: 46 raise Exception("Unexpected BSS flags: " + bss['flags']) 47 48 res = hapd.request("STA-FIRST") 49 if "sae_group=19" not in res.splitlines(): 50 raise Exception("hostapd STA output did not specify SAE group") 51 52 pmk_h = hapd.request("GET_PMK " + dev[0].own_addr()) 53 pmk_w = dev[0].get_pmk(id) 54 if pmk_h != pmk_w: 55 raise Exception("Fetched PMK does not match: hostapd %s, wpa_supplicant %s" % (pmk_h, pmk_w)) 56 dev[0].request("DISCONNECT") 57 dev[0].wait_disconnected() 58 pmk_h2 = hapd.request("GET_PMK " + dev[0].own_addr()) 59 if pmk_h != pmk_h2: 60 raise Exception("Fetched PMK from PMKSA cache does not match: %s, %s" % (pmk_h, pmk_h2)) 61 if "FAIL" not in hapd.request("GET_PMK foo"): 62 raise Exception("Invalid GET_PMK did not return failure") 63 if "FAIL" not in hapd.request("GET_PMK 02:ff:ff:ff:ff:ff"): 64 raise Exception("GET_PMK for unknown STA did not return failure") 65 66@remote_compatible 67def test_sae_password_ecc(dev, apdev): 68 """SAE with number of different passwords (ECC)""" 69 check_sae_capab(dev[0]) 70 params = hostapd.wpa2_params(ssid="test-sae", 71 passphrase="12345678") 72 params['wpa_key_mgmt'] = 'SAE' 73 hapd = hostapd.add_ap(apdev[0], params) 74 75 dev[0].request("SET sae_groups 19") 76 77 for i in range(10): 78 password = "12345678-" + str(i) 79 hapd.set("wpa_passphrase", password) 80 dev[0].connect("test-sae", psk=password, key_mgmt="SAE", 81 scan_freq="2412") 82 dev[0].request("REMOVE_NETWORK all") 83 dev[0].wait_disconnected() 84 85@remote_compatible 86def test_sae_password_ffc(dev, apdev): 87 """SAE with number of different passwords (FFC)""" 88 check_sae_capab(dev[0]) 89 params = hostapd.wpa2_params(ssid="test-sae", 90 passphrase="12345678") 91 params['wpa_key_mgmt'] = 'SAE' 92 params['sae_groups'] = '15' 93 hapd = hostapd.add_ap(apdev[0], params) 94 95 dev[0].request("SET sae_groups 15") 96 97 for i in range(10): 98 password = "12345678-" + str(i) 99 hapd.set("wpa_passphrase", password) 100 dev[0].connect("test-sae", psk=password, key_mgmt="SAE", 101 scan_freq="2412") 102 dev[0].request("REMOVE_NETWORK all") 103 dev[0].wait_disconnected() 104 105@remote_compatible 106def test_sae_pmksa_caching(dev, apdev): 107 """SAE and PMKSA caching""" 108 run_sae_pmksa_caching(dev, apdev) 109 110@remote_compatible 111def test_sae_pmksa_caching_pmkid(dev, apdev): 112 """SAE and PMKSA caching (PMKID in AssocReq after SAE)""" 113 try: 114 dev[0].set("sae_pmkid_in_assoc", "1") 115 run_sae_pmksa_caching(dev, apdev) 116 finally: 117 dev[0].set("sae_pmkid_in_assoc", "0") 118 119def run_sae_pmksa_caching(dev, apdev): 120 check_sae_capab(dev[0]) 121 params = hostapd.wpa2_params(ssid="test-sae", 122 passphrase="12345678") 123 params['wpa_key_mgmt'] = 'SAE' 124 hapd = hostapd.add_ap(apdev[0], params) 125 126 dev[0].request("SET sae_groups ") 127 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 128 scan_freq="2412") 129 ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=5) 130 if ev is None: 131 raise Exception("No connection event received from hostapd") 132 sta0 = hapd.get_sta(dev[0].own_addr()) 133 if sta0['wpa'] != '2' or sta0['AKMSuiteSelector'] != '00-0f-ac-8': 134 raise Exception("SAE STA(0) AKM suite selector reported incorrectly") 135 dev[0].request("DISCONNECT") 136 dev[0].wait_disconnected() 137 dev[0].request("RECONNECT") 138 dev[0].wait_connected(timeout=15, error="Reconnect timed out") 139 val = dev[0].get_status_field('sae_group') 140 if val is not None: 141 raise Exception("SAE group claimed to have been used: " + val) 142 sta0 = hapd.get_sta(dev[0].own_addr()) 143 if sta0['wpa'] != '2' or sta0['AKMSuiteSelector'] != '00-0f-ac-8': 144 raise Exception("SAE STA(0) AKM suite selector reported incorrectly after PMKSA caching") 145 146@remote_compatible 147def test_sae_pmksa_caching_disabled(dev, apdev): 148 """SAE and PMKSA caching disabled""" 149 check_sae_capab(dev[0]) 150 params = hostapd.wpa2_params(ssid="test-sae", 151 passphrase="12345678") 152 params['wpa_key_mgmt'] = 'SAE' 153 params['disable_pmksa_caching'] = '1' 154 hapd = hostapd.add_ap(apdev[0], params) 155 156 dev[0].request("SET sae_groups ") 157 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 158 scan_freq="2412") 159 ev = hapd.wait_event(["AP-STA-CONNECTED"], timeout=5) 160 if ev is None: 161 raise Exception("No connection event received from hostapd") 162 dev[0].request("DISCONNECT") 163 dev[0].wait_disconnected() 164 dev[0].request("RECONNECT") 165 dev[0].wait_connected(timeout=15, error="Reconnect timed out") 166 if dev[0].get_status_field('sae_group') != '19': 167 raise Exception("Expected default SAE group not used") 168 169def test_sae_groups(dev, apdev): 170 """SAE with all supported groups""" 171 check_sae_capab(dev[0]) 172 # This is the full list of supported groups, but groups 14-16 (2048-4096 bit 173 # MODP) and group 21 (521-bit random ECP group) are a bit too slow on some 174 # VMs and can result in hitting the mac80211 authentication timeout, so 175 # allow them to fail and just report such failures in the debug log. 176 sae_groups = [19, 25, 26, 20, 21, 1, 2, 5, 14, 15, 16, 22, 23, 24] 177 tls = dev[0].request("GET tls_library") 178 if tls.startswith("OpenSSL") and "run=OpenSSL 1." in tls: 179 logger.info("Add Brainpool EC groups since OpenSSL is new enough") 180 sae_groups += [27, 28, 29, 30] 181 heavy_groups = [14, 15, 16] 182 suitable_groups = [15, 16, 17, 18, 19, 20, 21] 183 groups = [str(g) for g in sae_groups] 184 params = hostapd.wpa2_params(ssid="test-sae-groups", 185 passphrase="12345678") 186 params['wpa_key_mgmt'] = 'SAE' 187 params['sae_groups'] = ' '.join(groups) 188 hapd = hostapd.add_ap(apdev[0], params) 189 190 for g in groups: 191 logger.info("Testing SAE group " + g) 192 dev[0].request("SET sae_groups " + g) 193 id = dev[0].connect("test-sae-groups", psk="12345678", key_mgmt="SAE", 194 scan_freq="2412", wait_connect=False) 195 if int(g) in heavy_groups: 196 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=5) 197 if ev is None: 198 logger.info("No connection with heavy SAE group %s did not connect - likely hitting timeout in mac80211" % g) 199 dev[0].remove_network(id) 200 time.sleep(0.1) 201 dev[0].dump_monitor() 202 continue 203 logger.info("Connection with heavy SAE group " + g) 204 else: 205 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=10) 206 if ev is None: 207 if "BoringSSL" in tls and int(g) in [25]: 208 logger.info("Ignore connection failure with group " + g + " with BoringSSL") 209 dev[0].remove_network(id) 210 dev[0].dump_monitor() 211 continue 212 if int(g) not in suitable_groups: 213 logger.info("Ignore connection failure with unsuitable group " + g) 214 dev[0].remove_network(id) 215 dev[0].dump_monitor() 216 continue 217 raise Exception("Connection timed out with group " + g) 218 if dev[0].get_status_field('sae_group') != g: 219 raise Exception("Expected SAE group not used") 220 pmksa = dev[0].get_pmksa(hapd.own_addr()) 221 if not pmksa: 222 raise Exception("No PMKSA cache entry added") 223 if pmksa['pmkid'] == '00000000000000000000000000000000': 224 raise Exception("All zeros PMKID derived for group %s" % g) 225 dev[0].remove_network(id) 226 dev[0].wait_disconnected() 227 dev[0].dump_monitor() 228 229@remote_compatible 230def test_sae_group_nego(dev, apdev): 231 """SAE group negotiation""" 232 check_sae_capab(dev[0]) 233 params = hostapd.wpa2_params(ssid="test-sae-group-nego", 234 passphrase="12345678") 235 params['wpa_key_mgmt'] = 'SAE' 236 params['sae_groups'] = '19' 237 hostapd.add_ap(apdev[0], params) 238 239 dev[0].request("SET sae_groups 25 20 19") 240 dev[0].connect("test-sae-group-nego", psk="12345678", key_mgmt="SAE", 241 scan_freq="2412") 242 if dev[0].get_status_field('sae_group') != '19': 243 raise Exception("Expected SAE group not used") 244 245def test_sae_group_nego_no_match(dev, apdev): 246 """SAE group negotiation (no match)""" 247 check_sae_capab(dev[0]) 248 params = hostapd.wpa2_params(ssid="test-sae-group-nego", 249 passphrase="12345678") 250 params['wpa_key_mgmt'] = 'SAE' 251 # None-existing SAE group to force all attempts to be rejected 252 params['sae_groups'] = '0' 253 hostapd.add_ap(apdev[0], params) 254 255 dev[0].request("SET sae_groups ") 256 dev[0].connect("test-sae-group-nego", psk="12345678", key_mgmt="SAE", 257 scan_freq="2412", wait_connect=False) 258 ev = dev[0].wait_event(["CTRL-EVENT-SSID-TEMP-DISABLED"], timeout=10) 259 dev[0].request("REMOVE_NETWORK all") 260 if ev is None: 261 raise Exception("Network profile disabling not reported") 262 263@remote_compatible 264def test_sae_anti_clogging(dev, apdev): 265 """SAE anti clogging""" 266 check_sae_capab(dev[0]) 267 check_sae_capab(dev[1]) 268 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 269 params['wpa_key_mgmt'] = 'SAE' 270 params['sae_anti_clogging_threshold'] = '1' 271 hostapd.add_ap(apdev[0], params) 272 273 dev[0].request("SET sae_groups ") 274 dev[1].request("SET sae_groups ") 275 id = {} 276 for i in range(0, 2): 277 dev[i].scan(freq="2412") 278 id[i] = dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE", 279 scan_freq="2412", only_add_network=True) 280 for i in range(0, 2): 281 dev[i].select_network(id[i]) 282 for i in range(0, 2): 283 dev[i].wait_connected(timeout=10) 284 285def test_sae_forced_anti_clogging(dev, apdev): 286 """SAE anti clogging (forced)""" 287 check_sae_capab(dev[0]) 288 check_sae_capab(dev[1]) 289 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 290 params['wpa_key_mgmt'] = 'SAE WPA-PSK' 291 params['sae_anti_clogging_threshold'] = '0' 292 hostapd.add_ap(apdev[0], params) 293 dev[2].connect("test-sae", psk="12345678", scan_freq="2412") 294 for i in range(0, 2): 295 dev[i].request("SET sae_groups ") 296 dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE", 297 scan_freq="2412") 298 299def test_sae_mixed(dev, apdev): 300 """Mixed SAE and non-SAE network""" 301 check_sae_capab(dev[0]) 302 check_sae_capab(dev[1]) 303 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 304 params['wpa_key_mgmt'] = 'SAE WPA-PSK' 305 params['sae_anti_clogging_threshold'] = '0' 306 hapd = hostapd.add_ap(apdev[0], params) 307 308 dev[2].connect("test-sae", psk="12345678", scan_freq="2412") 309 for i in range(0, 2): 310 dev[i].request("SET sae_groups ") 311 dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE", 312 scan_freq="2412") 313 sta0 = hapd.get_sta(dev[0].own_addr()) 314 sta2 = hapd.get_sta(dev[2].own_addr()) 315 if sta0['wpa'] != '2' or sta0['AKMSuiteSelector'] != '00-0f-ac-8': 316 raise Exception("SAE STA(0) AKM suite selector reported incorrectly") 317 if sta2['wpa'] != '2' or sta2['AKMSuiteSelector'] != '00-0f-ac-2': 318 raise Exception("PSK STA(2) AKM suite selector reported incorrectly") 319 320def test_sae_and_psk(dev, apdev): 321 """SAE and PSK enabled in network profile""" 322 check_sae_capab(dev[0]) 323 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 324 params['wpa_key_mgmt'] = 'SAE' 325 hostapd.add_ap(apdev[0], params) 326 327 dev[0].request("SET sae_groups ") 328 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE WPA-PSK", 329 scan_freq="2412") 330 331def test_sae_and_psk2(dev, apdev): 332 """SAE and PSK enabled in network profile (use PSK)""" 333 check_sae_capab(dev[0]) 334 params = hostapd.wpa2_params(ssid="test-psk", passphrase="12345678") 335 hostapd.add_ap(apdev[0], params) 336 337 dev[0].request("SET sae_groups ") 338 dev[0].connect("test-psk", psk="12345678", key_mgmt="SAE WPA-PSK", 339 scan_freq="2412") 340 341def test_sae_wpa3_roam(dev, apdev): 342 """SAE and WPA3-Personal transition mode roaming""" 343 check_sae_capab(dev[0]) 344 345 # WPA3-Personal only AP 346 params = hostapd.wpa2_params(ssid="test", passphrase="12345678") 347 params['ieee80211w'] = '2' 348 params['wpa_key_mgmt'] = 'SAE' 349 hapd0 = hostapd.add_ap(apdev[0], params) 350 351 # WPA2-Personal only AP 352 params = hostapd.wpa2_params(ssid="test", passphrase="12345678") 353 hapd1 = hostapd.add_ap(apdev[1], params) 354 355 dev[0].set("sae_groups", "") 356 dev[0].connect("test", psk="12345678", key_mgmt="SAE WPA-PSK", 357 ieee80211w="1", scan_freq="2412") 358 bssid = dev[0].get_status_field('bssid') 359 360 # Disable the current AP to force roam to the other one 361 if bssid == apdev[0]['bssid']: 362 hapd0.disable() 363 else: 364 hapd1.disable() 365 dev[0].wait_connected() 366 367 # Disable the current AP to force roam to the other (previous) one 368 if bssid == apdev[0]['bssid']: 369 hapd0.enable() 370 hapd1.disable() 371 else: 372 hapd1.enable() 373 hapd0.disable() 374 dev[0].wait_connected() 375 376 # Force roam to an AP in WPA3-Personal transition mode 377 if bssid == apdev[0]['bssid']: 378 hapd1.set("ieee80211w", "1") 379 hapd1.set("sae_require_mfp", "1") 380 hapd1.set("wpa_key_mgmt", "SAE WPA-PSK") 381 hapd1.enable() 382 hapd0.disable() 383 else: 384 hapd0.set("ieee80211w", "1") 385 hapd0.set("sae_require_mfp", "1") 386 hapd0.set("wpa_key_mgmt", "SAE WPA-PSK") 387 hapd0.enable() 388 hapd1.disable() 389 dev[0].wait_connected() 390 status = dev[0].get_status() 391 if status['key_mgmt'] != "SAE": 392 raise Exception("Did not use SAE with WPA3-Personal transition mode AP") 393 if status['pmf'] != "1": 394 raise Exception("Did not use PMF with WPA3-Personal transition mode AP") 395 396def test_sae_mixed_mfp(dev, apdev): 397 """Mixed SAE and non-SAE network and MFP required with SAE""" 398 check_sae_capab(dev[0]) 399 check_sae_capab(dev[1]) 400 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 401 params['wpa_key_mgmt'] = 'SAE WPA-PSK' 402 params["ieee80211w"] = "1" 403 params['sae_require_mfp'] = '1' 404 hostapd.add_ap(apdev[0], params) 405 406 dev[0].request("SET sae_groups ") 407 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", ieee80211w="2", 408 scan_freq="2412") 409 dev[0].dump_monitor() 410 411 dev[1].request("SET sae_groups ") 412 dev[1].connect("test-sae", psk="12345678", key_mgmt="SAE", ieee80211w="0", 413 scan_freq="2412", wait_connect=False) 414 ev = dev[1].wait_event(["CTRL-EVENT-CONNECTED", 415 "CTRL-EVENT-ASSOC-REJECT"], timeout=10) 416 if ev is None: 417 raise Exception("No connection result reported") 418 if "CTRL-EVENT-ASSOC-REJECT" not in ev: 419 raise Exception("SAE connection without MFP was not rejected") 420 if "status_code=31" not in ev: 421 raise Exception("Unexpected status code in rejection: " + ev) 422 dev[1].request("DISCONNECT") 423 dev[1].dump_monitor() 424 425 dev[2].connect("test-sae", psk="12345678", ieee80211w="0", scan_freq="2412") 426 dev[2].dump_monitor() 427 428def _test_sae_mixed_check_mfp(dev, apdev): 429 """Mixed SAE and non-SAE network with the sae_check_mfp option""" 430 check_sae_capab(dev[0]) 431 check_sae_capab(dev[1]) 432 check_sae_capab(dev[2]) 433 434 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 435 params['wpa_key_mgmt'] = 'SAE WPA-PSK' 436 params["ieee80211w"] = "1" 437 hostapd.add_ap(apdev[0], params) 438 439 params = hostapd.wpa2_params(ssid="test-sae-no-mfp", passphrase="12345678") 440 params['wpa_key_mgmt'] = 'SAE WPA-PSK' 441 params["ieee80211w"] = "0" 442 hostapd.add_ap(apdev[1], params) 443 444 dev[0].set("sae_check_mfp", "0") 445 dev[0].set("sae_groups", "") 446 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE WPA-PSK", 447 ieee80211w="0", scan_freq="2412") 448 dev[0].dump_monitor() 449 status = dev[0].get_status() 450 if status['key_mgmt'] != "SAE": 451 raise Exception("SAE without sae_check_mfp was not allowed") 452 453 # Confirm SAE is used when sae_check_mfp is not set for non-PMF AP. 454 dev[2].set("sae_check_mfp", "0") 455 dev[2].set("sae_groups", "") 456 dev[2].connect("test-sae-no-mfp", psk="12345678", key_mgmt="SAE WPA-PSK", 457 ieee80211w="1", scan_freq="2412") 458 status = dev[2].get_status() 459 if status['key_mgmt'] != "SAE": 460 raise Exception("SAE without sae_check_mfp was not allowed") 461 dev[2].dump_monitor() 462 463 # Confirm SAE is not used with the PMF disabled network configuration. 464 dev[1].set("sae_check_mfp", "1") 465 dev[1].set("sae_groups", "") 466 dev[1].connect("test-sae", psk="12345678", key_mgmt="SAE WPA-PSK", 467 ieee80211w="0", scan_freq="2412") 468 status = dev[1].get_status() 469 dev[1].request("DISCONNECT") 470 dev[1].wait_disconnected() 471 dev[1].dump_monitor() 472 if status['key_mgmt'] != "WPA2-PSK": 473 raise Exception("SAE without MFP was allowed") 474 dev[1].request("REMOVE_NETWORK all") 475 476 # Confirm SAE is not used connecting to PMF disabled AP. 477 dev[1].set("sae_check_mfp", "1") 478 dev[1].set("sae_groups", "") 479 dev[1].connect("test-sae-no-mfp", psk="12345678", key_mgmt="SAE WPA-PSK", 480 ieee80211w="1", scan_freq="2412") 481 status = dev[1].get_status() 482 if status['key_mgmt'] != "WPA2-PSK": 483 raise Exception("SAE without MFP was allowed") 484 485def test_sae_mixed_check_mfp(dev, apdev): 486 """Mixed SAE and non-SAE network with the sae_check_mfp option""" 487 try: 488 _test_sae_mixed_check_mfp(dev, apdev) 489 finally: 490 dev[0].set("sae_check_mfp", "0") 491 dev[1].set("sae_check_mfp", "0") 492 dev[2].set("sae_check_mfp", "0") 493 494def test_sae_and_psk_transition_disable(dev, apdev): 495 """SAE and PSK transition disable indication""" 496 check_sae_capab(dev[0]) 497 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 498 params["ieee80211w"] = "1" 499 params['wpa_key_mgmt'] = 'SAE WPA-PSK' 500 params['transition_disable'] = '0x01' 501 hapd = hostapd.add_ap(apdev[0], params) 502 503 dev[0].request("SET sae_groups ") 504 id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE WPA-PSK", 505 ieee80211w="1", scan_freq="2412", wait_connect=False) 506 ev = dev[0].wait_event(["TRANSITION-DISABLE"], timeout=15) 507 if ev is None: 508 raise Exception("Transition disable not indicated") 509 if ev.split(' ')[1] != "01": 510 raise Exception("Unexpected transition disable bitmap: " + ev) 511 512 val = dev[0].get_network(id, "ieee80211w") 513 if val != "2": 514 raise Exception("Unexpected ieee80211w value: " + val) 515 val = dev[0].get_network(id, "key_mgmt") 516 if val != "SAE": 517 raise Exception("Unexpected key_mgmt value: " + val) 518 val = dev[0].get_network(id, "group") 519 if val != "CCMP": 520 raise Exception("Unexpected group value: " + val) 521 val = dev[0].get_network(id, "proto") 522 if val != "RSN": 523 raise Exception("Unexpected proto value: " + val) 524 525 dev[0].request("DISCONNECT") 526 dev[0].wait_disconnected() 527 dev[0].request("RECONNECT") 528 dev[0].wait_connected() 529 530def test_sae_mfp(dev, apdev): 531 """SAE and MFP enabled without sae_require_mfp""" 532 check_sae_capab(dev[0]) 533 check_sae_capab(dev[1]) 534 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 535 params['wpa_key_mgmt'] = 'SAE' 536 params["ieee80211w"] = "1" 537 hostapd.add_ap(apdev[0], params) 538 539 dev[0].request("SET sae_groups ") 540 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", ieee80211w="2", 541 scan_freq="2412") 542 543 dev[1].request("SET sae_groups ") 544 dev[1].connect("test-sae", psk="12345678", key_mgmt="SAE", ieee80211w="0", 545 scan_freq="2412") 546 547@remote_compatible 548def test_sae_missing_password(dev, apdev): 549 """SAE and missing password""" 550 check_sae_capab(dev[0]) 551 params = hostapd.wpa2_params(ssid="test-sae", 552 passphrase="12345678") 553 params['wpa_key_mgmt'] = 'SAE' 554 hapd = hostapd.add_ap(apdev[0], params) 555 556 dev[0].request("SET sae_groups ") 557 id = dev[0].connect("test-sae", 558 raw_psk="46b4a73b8a951ad53ebd2e0afdb9c5483257edd4c21d12b7710759da70945858", 559 key_mgmt="SAE", scan_freq="2412", wait_connect=False) 560 ev = dev[0].wait_event(['CTRL-EVENT-SSID-TEMP-DISABLED'], timeout=10) 561 if ev is None: 562 raise Exception("Invalid network not temporarily disabled") 563 564 565def test_sae_key_lifetime_in_memory(dev, apdev, params): 566 """SAE and key lifetime in memory""" 567 check_sae_capab(dev[0]) 568 password = "5ad144a7c1f5a5503baa6fa01dabc15b1843e8c01662d78d16b70b5cd23cf8b" 569 p = hostapd.wpa2_params(ssid="test-sae", passphrase=password) 570 p['wpa_key_mgmt'] = 'SAE' 571 hapd = hostapd.add_ap(apdev[0], p) 572 573 pid = find_wpas_process(dev[0]) 574 575 dev[0].request("SET sae_groups ") 576 id = dev[0].connect("test-sae", psk=password, key_mgmt="SAE", 577 scan_freq="2412") 578 579 # The decrypted copy of GTK is freed only after the CTRL-EVENT-CONNECTED 580 # event has been delivered, so verify that wpa_supplicant has returned to 581 # eloop before reading process memory. 582 time.sleep(1) 583 dev[0].ping() 584 password = password.encode() 585 buf = read_process_memory(pid, password) 586 587 dev[0].request("DISCONNECT") 588 dev[0].wait_disconnected() 589 590 dev[0].relog() 591 sae_k = None 592 sae_keyseed = None 593 sae_kck = None 594 pmk = None 595 ptk = None 596 gtk = None 597 with open(os.path.join(params['logdir'], 'log0'), 'r') as f: 598 for l in f.readlines(): 599 if "SAE: k - hexdump" in l: 600 val = l.strip().split(':')[3].replace(' ', '') 601 sae_k = binascii.unhexlify(val) 602 if "SAE: keyseed - hexdump" in l: 603 val = l.strip().split(':')[3].replace(' ', '') 604 sae_keyseed = binascii.unhexlify(val) 605 if "SAE: KCK - hexdump" in l: 606 val = l.strip().split(':')[3].replace(' ', '') 607 sae_kck = binascii.unhexlify(val) 608 if "SAE: PMK - hexdump" in l: 609 val = l.strip().split(':')[3].replace(' ', '') 610 pmk = binascii.unhexlify(val) 611 if "WPA: PTK - hexdump" in l: 612 val = l.strip().split(':')[3].replace(' ', '') 613 ptk = binascii.unhexlify(val) 614 if "WPA: Group Key - hexdump" in l: 615 val = l.strip().split(':')[3].replace(' ', '') 616 gtk = binascii.unhexlify(val) 617 if not sae_k or not sae_keyseed or not sae_kck or not pmk or not ptk or not gtk: 618 raise Exception("Could not find keys from debug log") 619 if len(gtk) != 16: 620 raise Exception("Unexpected GTK length") 621 622 kck = ptk[0:16] 623 kek = ptk[16:32] 624 tk = ptk[32:48] 625 626 fname = os.path.join(params['logdir'], 627 'sae_key_lifetime_in_memory.memctx-') 628 629 logger.info("Checking keys in memory while associated") 630 get_key_locations(buf, password, "Password") 631 get_key_locations(buf, pmk, "PMK") 632 if password not in buf: 633 raise HwsimSkip("Password not found while associated") 634 if pmk not in buf: 635 raise HwsimSkip("PMK not found while associated") 636 if kck not in buf: 637 raise Exception("KCK not found while associated") 638 if kek not in buf: 639 raise Exception("KEK not found while associated") 640 #if tk in buf: 641 # raise Exception("TK found from memory") 642 verify_not_present(buf, sae_k, fname, "SAE(k)") 643 verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)") 644 verify_not_present(buf, sae_kck, fname, "SAE(KCK)") 645 646 logger.info("Checking keys in memory after disassociation") 647 buf = read_process_memory(pid, password) 648 649 # Note: Password is still present in network configuration 650 # Note: PMK is in PMKSA cache 651 652 get_key_locations(buf, password, "Password") 653 get_key_locations(buf, pmk, "PMK") 654 verify_not_present(buf, kck, fname, "KCK") 655 verify_not_present(buf, kek, fname, "KEK") 656 verify_not_present(buf, tk, fname, "TK") 657 if gtk in buf: 658 get_key_locations(buf, gtk, "GTK") 659 verify_not_present(buf, gtk, fname, "GTK") 660 verify_not_present(buf, sae_k, fname, "SAE(k)") 661 verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)") 662 verify_not_present(buf, sae_kck, fname, "SAE(KCK)") 663 664 dev[0].request("PMKSA_FLUSH") 665 logger.info("Checking keys in memory after PMKSA cache flush") 666 buf = read_process_memory(pid, password) 667 get_key_locations(buf, password, "Password") 668 get_key_locations(buf, pmk, "PMK") 669 verify_not_present(buf, pmk, fname, "PMK") 670 671 dev[0].request("REMOVE_NETWORK all") 672 673 logger.info("Checking keys in memory after network profile removal") 674 buf = read_process_memory(pid, password) 675 676 get_key_locations(buf, password, "Password") 677 get_key_locations(buf, pmk, "PMK") 678 verify_not_present(buf, password, fname, "password") 679 verify_not_present(buf, pmk, fname, "PMK") 680 verify_not_present(buf, kck, fname, "KCK") 681 verify_not_present(buf, kek, fname, "KEK") 682 verify_not_present(buf, tk, fname, "TK") 683 verify_not_present(buf, gtk, fname, "GTK") 684 verify_not_present(buf, sae_k, fname, "SAE(k)") 685 verify_not_present(buf, sae_keyseed, fname, "SAE(keyseed)") 686 verify_not_present(buf, sae_kck, fname, "SAE(KCK)") 687 688@remote_compatible 689def test_sae_oom_wpas(dev, apdev): 690 """SAE and OOM in wpa_supplicant""" 691 check_sae_capab(dev[0]) 692 params = hostapd.wpa2_params(ssid="test-sae", 693 passphrase="12345678") 694 params['wpa_key_mgmt'] = 'SAE' 695 params['sae_groups'] = '19 25 26 20' 696 hapd = hostapd.add_ap(apdev[0], params) 697 698 dev[0].request("SET sae_groups 20") 699 with alloc_fail(dev[0], 1, "sae_set_group"): 700 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 701 scan_freq="2412") 702 dev[0].request("REMOVE_NETWORK all") 703 704 dev[0].request("SET sae_groups ") 705 with alloc_fail(dev[0], 2, "sae_set_group"): 706 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 707 scan_freq="2412") 708 dev[0].request("REMOVE_NETWORK all") 709 710 with alloc_fail(dev[0], 1, "wpabuf_alloc;sme_auth_build_sae_commit"): 711 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 712 scan_freq="2412") 713 dev[0].request("REMOVE_NETWORK all") 714 715 with alloc_fail(dev[0], 1, "wpabuf_alloc;sme_auth_build_sae_confirm"): 716 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 717 scan_freq="2412", wait_connect=False) 718 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL") 719 dev[0].request("REMOVE_NETWORK all") 720 721 with alloc_fail(dev[0], 1, "=sme_authenticate"): 722 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 723 scan_freq="2412", wait_connect=False) 724 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL") 725 dev[0].request("REMOVE_NETWORK all") 726 727 with alloc_fail(dev[0], 1, "radio_add_work;sme_authenticate"): 728 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 729 scan_freq="2412", wait_connect=False) 730 wait_fail_trigger(dev[0], "GET_ALLOC_FAIL") 731 dev[0].request("REMOVE_NETWORK all") 732 733@remote_compatible 734def test_sae_proto_ecc(dev, apdev): 735 """SAE protocol testing (ECC)""" 736 check_sae_capab(dev[0]) 737 params = hostapd.wpa2_params(ssid="test-sae", 738 passphrase="12345678") 739 params['wpa_key_mgmt'] = 'SAE' 740 hapd = hostapd.add_ap(apdev[0], params) 741 bssid = apdev[0]['bssid'] 742 743 dev[0].request("SET sae_groups 19") 744 745 tests = [("Confirm mismatch", 746 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8", 747 "0000800edebc3f260dc1fe7e0b20888af2b8a3316252ec37388a8504e25b73dc4240"), 748 ("Commit without even full cyclic group field", 749 "13", 750 None), 751 ("Too short commit", 752 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02", 753 None), 754 ("Invalid commit scalar (0)", 755 "1300" + "0000000000000000000000000000000000000000000000000000000000000000" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8", 756 None), 757 ("Invalid commit scalar (1)", 758 "1300" + "0000000000000000000000000000000000000000000000000000000000000001" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8", 759 None), 760 ("Invalid commit scalar (> r)", 761 "1300" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8", 762 None), 763 ("Commit element not on curve", 764 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728d0000000000000000000000000000000000000000000000000000000000000000", 765 None), 766 ("Invalid commit element (y coordinate > P)", 767 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 768 None), 769 ("Invalid commit element (x coordinate > P)", 770 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8", 771 None), 772 ("Different group in commit", 773 "1400" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8", 774 None), 775 ("Too short confirm", 776 "1300" + "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" + "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728dd3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8", 777 "0000800edebc3f260dc1fe7e0b20888af2b8a3316252ec37388a8504e25b73dc42")] 778 for (note, commit, confirm) in tests: 779 logger.info(note) 780 dev[0].scan_for_bss(bssid, freq=2412) 781 hapd.set("ext_mgmt_frame_handling", "1") 782 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 783 scan_freq="2412", wait_connect=False) 784 785 logger.info("Commit") 786 for i in range(0, 10): 787 req = hapd.mgmt_rx() 788 if req is None: 789 raise Exception("MGMT RX wait timed out (commit)") 790 if req['subtype'] == 11: 791 break 792 req = None 793 if not req: 794 raise Exception("Authentication frame (commit) not received") 795 796 hapd.dump_monitor() 797 resp = {} 798 resp['fc'] = req['fc'] 799 resp['da'] = req['sa'] 800 resp['sa'] = req['da'] 801 resp['bssid'] = req['bssid'] 802 resp['payload'] = binascii.unhexlify("030001000000" + commit) 803 hapd.mgmt_tx(resp) 804 805 if confirm: 806 logger.info("Confirm") 807 for i in range(0, 10): 808 req = hapd.mgmt_rx() 809 if req is None: 810 raise Exception("MGMT RX wait timed out (confirm)") 811 if req['subtype'] == 11: 812 break 813 req = None 814 if not req: 815 raise Exception("Authentication frame (confirm) not received") 816 817 hapd.dump_monitor() 818 resp = {} 819 resp['fc'] = req['fc'] 820 resp['da'] = req['sa'] 821 resp['sa'] = req['da'] 822 resp['bssid'] = req['bssid'] 823 resp['payload'] = binascii.unhexlify("030002000000" + confirm) 824 hapd.mgmt_tx(resp) 825 826 time.sleep(0.1) 827 dev[0].request("REMOVE_NETWORK all") 828 hapd.set("ext_mgmt_frame_handling", "0") 829 hapd.dump_monitor() 830 831@remote_compatible 832def test_sae_proto_ffc(dev, apdev): 833 """SAE protocol testing (FFC)""" 834 check_sae_capab(dev[0]) 835 params = hostapd.wpa2_params(ssid="test-sae", 836 passphrase="12345678") 837 params['wpa_key_mgmt'] = 'SAE' 838 hapd = hostapd.add_ap(apdev[0], params) 839 bssid = apdev[0]['bssid'] 840 841 dev[0].request("SET sae_groups 2") 842 843 tests = [("Confirm mismatch", 844 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "a8c00117493cdffa5dd671e934bc9cb1a69f39e25e9dd9cd9afd3aea2441a0f5491211c7ba50a753563f9ce943b043557cb71193b28e86ed9544f4289c471bf91b70af5c018cf4663e004165b0fd0bc1d8f3f78adf42eee92bcbc55246fd3ee9f107ab965dc7d4986f23eb71d616ebfe6bfe0a6c1ac5dc1718acee17c9a17486", 845 "0000f3116a9731f1259622e3eb55d4b3b50ba16f8c5f5565b28e609b180c51460251"), 846 ("Too short commit", 847 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "a8c00117493cdffa5dd671e934bc9cb1a69f39e25e9dd9cd9afd3aea2441a0f5491211c7ba50a753563f9ce943b043557cb71193b28e86ed9544f4289c471bf91b70af5c018cf4663e004165b0fd0bc1d8f3f78adf42eee92bcbc55246fd3ee9f107ab965dc7d4986f23eb71d616ebfe6bfe0a6c1ac5dc1718acee17c9a174", 848 None), 849 ("Invalid element (0) in commit", 850 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 851 None), 852 ("Invalid element (1) in commit", 853 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001", 854 None), 855 ("Invalid element (> P) in commit", 856 "0200" + "0c70519d874e3e4930a917cc5e17ea7a26028211159f217bab28b8d6c56691805e49f03249b2c6e22c7c9f86b30e04ccad2deedd5e5108ae07b737c00001c59cd0eb08b1dfc7f1b06a1542e2b6601a963c066e0c65940983a03917ae57a101ce84b5cbbc76ff33ebb990aac2e54aa0f0ab6ec0a58113d927683502b2cb2347d2" + "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 857 None)] 858 for (note, commit, confirm) in tests: 859 logger.info(note) 860 dev[0].scan_for_bss(bssid, freq=2412) 861 hapd.set("ext_mgmt_frame_handling", "1") 862 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 863 scan_freq="2412", wait_connect=False) 864 865 logger.info("Commit") 866 for i in range(0, 10): 867 req = hapd.mgmt_rx() 868 if req is None: 869 raise Exception("MGMT RX wait timed out (commit)") 870 if req['subtype'] == 11: 871 break 872 req = None 873 if not req: 874 raise Exception("Authentication frame (commit) not received") 875 876 hapd.dump_monitor() 877 resp = {} 878 resp['fc'] = req['fc'] 879 resp['da'] = req['sa'] 880 resp['sa'] = req['da'] 881 resp['bssid'] = req['bssid'] 882 resp['payload'] = binascii.unhexlify("030001000000" + commit) 883 hapd.mgmt_tx(resp) 884 885 if confirm: 886 logger.info("Confirm") 887 for i in range(0, 10): 888 req = hapd.mgmt_rx() 889 if req is None: 890 raise Exception("MGMT RX wait timed out (confirm)") 891 if req['subtype'] == 11: 892 break 893 req = None 894 if not req: 895 raise Exception("Authentication frame (confirm) not received") 896 897 hapd.dump_monitor() 898 resp = {} 899 resp['fc'] = req['fc'] 900 resp['da'] = req['sa'] 901 resp['sa'] = req['da'] 902 resp['bssid'] = req['bssid'] 903 resp['payload'] = binascii.unhexlify("030002000000" + confirm) 904 hapd.mgmt_tx(resp) 905 906 time.sleep(0.1) 907 dev[0].request("REMOVE_NETWORK all") 908 hapd.set("ext_mgmt_frame_handling", "0") 909 hapd.dump_monitor() 910 911 912def test_sae_proto_commit_delayed(dev, apdev): 913 """SAE protocol testing - Commit delayed""" 914 check_sae_capab(dev[0]) 915 params = hostapd.wpa2_params(ssid="test-sae", 916 passphrase="12345678") 917 params['wpa_key_mgmt'] = 'SAE' 918 hapd = hostapd.add_ap(apdev[0], params) 919 bssid = apdev[0]['bssid'] 920 921 dev[0].request("SET sae_groups 19") 922 923 dev[0].scan_for_bss(bssid, freq=2412) 924 hapd.set("ext_mgmt_frame_handling", "1") 925 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 926 scan_freq="2412", wait_connect=False) 927 928 logger.info("Commit") 929 for i in range(0, 10): 930 req = hapd.mgmt_rx() 931 if req is None: 932 raise Exception("MGMT RX wait timed out (commit)") 933 if req['subtype'] == 11: 934 break 935 req = None 936 if not req: 937 raise Exception("Authentication frame (commit) not received") 938 939 hapd.dump_monitor() 940 time.sleep(2.5) 941 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) 942 943 logger.info("Commit/Confirm") 944 for i in range(0, 10): 945 req = hapd.mgmt_rx() 946 if req is None: 947 raise Exception("MGMT RX wait timed out (confirm)") 948 if req['subtype'] == 11: 949 trans, = struct.unpack('<H', req['payload'][2:4]) 950 if trans == 1: 951 logger.info("Extra Commit") 952 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) 953 continue 954 break 955 req = None 956 if not req: 957 raise Exception("Authentication frame (confirm) not received") 958 959 hapd.dump_monitor() 960 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) 961 962 logger.info("Association Request") 963 for i in range(0, 10): 964 req = hapd.mgmt_rx() 965 if req is None: 966 raise Exception("MGMT RX wait timed out (AssocReq)") 967 if req['subtype'] == 0: 968 break 969 req = None 970 if not req: 971 raise Exception("Association Request frame not received") 972 973 hapd.dump_monitor() 974 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) 975 ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5) 976 if ev is None: 977 raise Exception("Management frame TX status not reported (1)") 978 if "stype=1 ok=1" not in ev: 979 raise Exception("Unexpected management frame TX status (1): " + ev) 980 cmd = "MGMT_TX_STATUS_PROCESS %s" % (" ".join(ev.split(' ')[1:4])) 981 if "OK" not in hapd.request(cmd): 982 raise Exception("MGMT_TX_STATUS_PROCESS failed") 983 984 hapd.set("ext_mgmt_frame_handling", "0") 985 986 dev[0].wait_connected() 987 988def test_sae_proto_commit_replay(dev, apdev): 989 """SAE protocol testing - Commit replay""" 990 check_sae_capab(dev[0]) 991 params = hostapd.wpa2_params(ssid="test-sae", 992 passphrase="12345678") 993 params['wpa_key_mgmt'] = 'SAE' 994 hapd = hostapd.add_ap(apdev[0], params) 995 bssid = apdev[0]['bssid'] 996 997 dev[0].request("SET sae_groups 19") 998 999 dev[0].scan_for_bss(bssid, freq=2412) 1000 hapd.set("ext_mgmt_frame_handling", "1") 1001 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 1002 scan_freq="2412", wait_connect=False) 1003 1004 logger.info("Commit") 1005 for i in range(0, 10): 1006 req = hapd.mgmt_rx() 1007 if req is None: 1008 raise Exception("MGMT RX wait timed out (commit)") 1009 if req['subtype'] == 11: 1010 break 1011 req = None 1012 if not req: 1013 raise Exception("Authentication frame (commit) not received") 1014 1015 hapd.dump_monitor() 1016 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) 1017 logger.info("Replay Commit") 1018 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) 1019 1020 logger.info("Confirm") 1021 for i in range(0, 10): 1022 req = hapd.mgmt_rx() 1023 if req is None: 1024 raise Exception("MGMT RX wait timed out (confirm)") 1025 if req['subtype'] == 11: 1026 trans, = struct.unpack('<H', req['payload'][2:4]) 1027 if trans == 1: 1028 logger.info("Extra Commit") 1029 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) 1030 continue 1031 break 1032 req = None 1033 if not req: 1034 raise Exception("Authentication frame (confirm) not received") 1035 1036 hapd.dump_monitor() 1037 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) 1038 1039 logger.info("Association Request") 1040 for i in range(0, 10): 1041 req = hapd.mgmt_rx() 1042 if req is None: 1043 raise Exception("MGMT RX wait timed out (AssocReq)") 1044 if req['subtype'] == 0: 1045 break 1046 req = None 1047 if not req: 1048 raise Exception("Association Request frame not received") 1049 1050 hapd.dump_monitor() 1051 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) 1052 for i in range(0, 10): 1053 ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5) 1054 if ev is None: 1055 raise Exception("Management frame TX status not reported (1)") 1056 if "stype=11 ok=1" in ev: 1057 continue 1058 if "stype=12 ok=1" in ev: 1059 continue 1060 if "stype=1 ok=1" not in ev: 1061 raise Exception("Unexpected management frame TX status (1): " + ev) 1062 cmd = "MGMT_TX_STATUS_PROCESS %s" % (" ".join(ev.split(' ')[1:4])) 1063 if "OK" not in hapd.request(cmd): 1064 raise Exception("MGMT_TX_STATUS_PROCESS failed") 1065 break 1066 1067 hapd.set("ext_mgmt_frame_handling", "0") 1068 1069 dev[0].wait_connected() 1070 1071def test_sae_proto_confirm_replay(dev, apdev): 1072 """SAE protocol testing - Confirm replay""" 1073 check_sae_capab(dev[0]) 1074 params = hostapd.wpa2_params(ssid="test-sae", 1075 passphrase="12345678") 1076 params['wpa_key_mgmt'] = 'SAE' 1077 hapd = hostapd.add_ap(apdev[0], params) 1078 bssid = apdev[0]['bssid'] 1079 1080 dev[0].request("SET sae_groups 19") 1081 1082 dev[0].scan_for_bss(bssid, freq=2412) 1083 hapd.set("ext_mgmt_frame_handling", "1") 1084 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 1085 scan_freq="2412", wait_connect=False) 1086 1087 logger.info("Commit") 1088 for i in range(0, 10): 1089 req = hapd.mgmt_rx() 1090 if req is None: 1091 raise Exception("MGMT RX wait timed out (commit)") 1092 if req['subtype'] == 11: 1093 break 1094 req = None 1095 if not req: 1096 raise Exception("Authentication frame (commit) not received") 1097 1098 hapd.dump_monitor() 1099 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) 1100 1101 logger.info("Confirm") 1102 for i in range(0, 10): 1103 req = hapd.mgmt_rx() 1104 if req is None: 1105 raise Exception("MGMT RX wait timed out (confirm)") 1106 if req['subtype'] == 11: 1107 break 1108 req = None 1109 if not req: 1110 raise Exception("Authentication frame (confirm) not received") 1111 1112 hapd.dump_monitor() 1113 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) 1114 1115 logger.info("Replay Confirm") 1116 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) 1117 1118 logger.info("Association Request") 1119 for i in range(0, 10): 1120 req = hapd.mgmt_rx() 1121 if req is None: 1122 raise Exception("MGMT RX wait timed out (AssocReq)") 1123 if req['subtype'] == 0: 1124 break 1125 req = None 1126 if not req: 1127 raise Exception("Association Request frame not received") 1128 1129 hapd.dump_monitor() 1130 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(req['frame']).decode()) 1131 ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5) 1132 if ev is None: 1133 raise Exception("Management frame TX status not reported (1)") 1134 if "stype=1 ok=1" not in ev: 1135 raise Exception("Unexpected management frame TX status (1): " + ev) 1136 cmd = "MGMT_TX_STATUS_PROCESS %s" % (" ".join(ev.split(' ')[1:4])) 1137 if "OK" not in hapd.request(cmd): 1138 raise Exception("MGMT_TX_STATUS_PROCESS failed") 1139 1140 hapd.set("ext_mgmt_frame_handling", "0") 1141 1142 dev[0].wait_connected() 1143 1144def test_sae_proto_hostapd(dev, apdev): 1145 """SAE protocol testing with hostapd""" 1146 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 1147 params['wpa_key_mgmt'] = 'SAE' 1148 params['sae_groups'] = "19 65535" 1149 hapd = hostapd.add_ap(apdev[0], params) 1150 hapd.set("ext_mgmt_frame_handling", "1") 1151 bssid = hapd.own_addr().replace(':', '') 1152 addr = "020000000000" 1153 addr2 = "020000000001" 1154 hdr = "b0003a01" + bssid + addr + bssid + "1000" 1155 hdr2 = "b0003a01" + bssid + addr2 + bssid + "1000" 1156 group = "1300" 1157 scalar = "f7df19f4a7fef1d3b895ea1de150b7c5a7a705c8ebb31a52b623e0057908bd93" 1158 element_x = "21931572027f2e953e2a49fab3d992944102cc95aa19515fc068b394fb25ae3c" 1159 element_y = "cb4eeb94d7b0b789abfdb73a67ab9d6d5efa94dd553e0e724a6289821cbce530" 1160 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030001000000" + group + scalar + element_x + element_y) 1161 # "SAE: Not enough data for scalar" 1162 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030001000000" + group + scalar[:-2]) 1163 # "SAE: Do not allow group to be changed" 1164 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030001000000" + "ffff" + scalar[:-2]) 1165 # "SAE: Unsupported Finite Cyclic Group 65535" 1166 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr2 + "030001000000" + "ffff" + scalar[:-2]) 1167 1168def test_sae_proto_hostapd_ecc(dev, apdev): 1169 """SAE protocol testing with hostapd (ECC)""" 1170 params = hostapd.wpa2_params(ssid="test-sae", passphrase="foofoofoo") 1171 params['wpa_key_mgmt'] = 'SAE' 1172 params['sae_groups'] = "19" 1173 hapd = hostapd.add_ap(apdev[0], params) 1174 hapd.set("ext_mgmt_frame_handling", "1") 1175 bssid = hapd.own_addr().replace(':', '') 1176 addr = "020000000000" 1177 addr2 = "020000000001" 1178 hdr = "b0003a01" + bssid + addr + bssid + "1000" 1179 hdr2 = "b0003a01" + bssid + addr2 + bssid + "1000" 1180 group = "1300" 1181 scalar = "9e9a959bf2dda875a4a29ce9b2afef46f2d83060930124cd9e39ddce798cd69a" 1182 element_x = "dfc55fd8622b91d362f4d1fc9646474d7fba0ff7cce6ca58b8e96a931e070220" 1183 element_y = "dac8a4e80724f167c1349cc9e1f9dd82a7c77b29d49789b63b72b4c849301a28" 1184 # sae_parse_commit_element_ecc() failure to parse peer element 1185 # (depending on crypto library, either crypto_ec_point_from_bin() failure 1186 # or crypto_ec_point_is_on_curve() returning 0) 1187 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030001000000" + group + scalar + element_x + element_y) 1188 # Unexpected continuation of the connection attempt with confirm 1189 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030002000000" + "0000" + "fd7b081ff4e8676f03612a4140eedcd3c179ab3a13b93863c6f7ca451340b9ae") 1190 1191def test_sae_proto_hostapd_ffc(dev, apdev): 1192 """SAE protocol testing with hostapd (FFC)""" 1193 params = hostapd.wpa2_params(ssid="test-sae", passphrase="foofoofoo") 1194 params['wpa_key_mgmt'] = 'SAE' 1195 params['sae_groups'] = "22" 1196 hapd = hostapd.add_ap(apdev[0], params) 1197 hapd.set("ext_mgmt_frame_handling", "1") 1198 bssid = hapd.own_addr().replace(':', '') 1199 addr = "020000000000" 1200 addr2 = "020000000001" 1201 hdr = "b0003a01" + bssid + addr + bssid + "1000" 1202 hdr2 = "b0003a01" + bssid + addr2 + bssid + "1000" 1203 group = "1600" 1204 scalar = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044cc46a73c07ef479dc66ec1f5e8ccf25131fa40" 1205 element = "0f1d67025e12fc874cf718c35b19d1ab2db858215623f1ce661cbd1d7b1d7a09ceda7dba46866cf37044259b5cac4db15e7feb778edc8098854b93a84347c1850c02ee4d7dac46db79c477c731085d5b39f56803cda1eeac4a2fbbccb9a546379e258c00ebe93dfdd0a34cf8ce5c55cf905a89564a590b7e159fb89198e9d5cd" 1206 # sae_parse_commit_element_ffc() failure to parse peer element 1207 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030001000000" + group + scalar + element) 1208 # Unexpected continuation of the connection attempt with confirm 1209 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030002000000" + "0000" + "fd7b081ff4e8676f03612a4140eedcd3c179ab3a13b93863c6f7ca451340b9ae") 1210 1211def sae_start_ap(apdev, sae_pwe): 1212 params = hostapd.wpa2_params(ssid="test-sae", passphrase="foofoofoo") 1213 params['wpa_key_mgmt'] = 'SAE' 1214 params['sae_groups'] = "19" 1215 params['sae_pwe'] = str(sae_pwe) 1216 return hostapd.add_ap(apdev, params) 1217 1218def check_commit_status(hapd, use_status, expect_status): 1219 hapd.set("ext_mgmt_frame_handling", "1") 1220 bssid = hapd.own_addr().replace(':', '') 1221 addr = "020000000000" 1222 addr2 = "020000000001" 1223 hdr = "b0003a01" + bssid + addr + bssid + "1000" 1224 hdr2 = "b0003a01" + bssid + addr2 + bssid + "1000" 1225 group = "1300" 1226 scalar = "033d3635b39666ed427fd4a3e7d37acec2810afeaf1687f746a14163ff0e6d03" 1227 element_x = "559cb8928db4ce4e3cbd6555e837591995e5ebe503ef36b503d9ca519d63728d" 1228 element_y = "d3c7c676b8e8081831b6bc3a64bdf136061a7de175e17d1965bfa41983ed02f8" 1229 status = binascii.hexlify(struct.pack('<H', use_status)).decode() 1230 hapd.dump_monitor() 1231 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "03000100" + status + group + scalar + element_x + element_y) 1232 ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5) 1233 if ev: 1234 msg = ev.split(' ')[3].split('=')[1] 1235 if not msg.startswith("b0"): 1236 ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5) 1237 if ev is None: 1238 raise Exception("MGMT-TX-STATUS not seen") 1239 msg = ev.split(' ')[3].split('=')[1] 1240 body = msg[2 * 24:] 1241 status, = struct.unpack('<H', binascii.unhexlify(body[8:12])) 1242 if status != expect_status: 1243 raise Exception("Unexpected status code: %d" % status) 1244 1245def test_sae_proto_hostapd_status_126(dev, apdev): 1246 """SAE protocol testing with hostapd (status code 126)""" 1247 hapd = sae_start_ap(apdev[0], 0) 1248 check_commit_status(hapd, 126, 1) 1249 check_commit_status(hapd, 0, 0) 1250 1251def test_sae_proto_hostapd_status_127(dev, apdev): 1252 """SAE protocol testing with hostapd (status code 127)""" 1253 hapd = sae_start_ap(apdev[0], 2) 1254 check_commit_status(hapd, 127, 1) 1255 check_commit_status(hapd, 0, 0) 1256 1257def test_sae_proto_hostapd_valid_commit_after_fail(dev, apdev): 1258 """SAE protocol testing with hostapd and valid commit after failed one""" 1259 params = hostapd.wpa2_params(ssid="test-sae", passphrase="foofoofoo") 1260 params['wpa_key_mgmt'] = 'SAE' 1261 params['sae_groups'] = "19" 1262 hapd = hostapd.add_ap(apdev[0], params) 1263 hapd.set("ext_mgmt_frame_handling", "1") 1264 bssid = hapd.own_addr().replace(':', '') 1265 addr = "020000000000" 1266 addr2 = "020000000001" 1267 hdr = "b0003a01" + bssid + addr + bssid + "1000" 1268 hdr2 = "b0003a01" + bssid + addr2 + bssid + "1000" 1269 group = "1300" 1270 scalar = "f7df19f4a7fef1d3b895ea1de150b7c5a7a705c8ebb31a52b623e0057908bd93" 1271 element_x = "21931572027f2e953e2a49fab3d992944102cc95aa19515fc068b394fb25ae3c" 1272 element_y = "cb4eeb94d7b0b789abfdb73a67ab9d6d5efa94dd553e0e724a6289821cbce530" 1273 pw_id = "ff022130" 1274 1275 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030001000000" + group + scalar + element_x + element_y + pw_id) 1276 ev = hapd.wait_event(['MGMT-TX-STATUS'], timeout=1) 1277 buf = ev.split(' ')[3].split('=')[1] 1278 # Check for status = Unknown Password ID 1279 if buf[48:] != '0300' + '0100' + '7b00': 1280 raise Exception("Unexpected response to SAE commit with unknown password id: " + buf) 1281 1282 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + hdr + "030001000000" + group + scalar + element_x + element_y) 1283 1284 ev = hapd.wait_event(['MGMT-TX-STATUS'], timeout=1) 1285 if ev is None: 1286 raise Exception("No response to valid SAE commit") 1287 buf = ev.split(' ')[3].split('=')[1] 1288 # Check for status = Success 1289 payload = buf[48:] 1290 if payload[8:12] != '0000': 1291 raise Exception("Unexpected Status Code for valid SAE commit: " + buf) 1292 1293@remote_compatible 1294def test_sae_no_ffc_by_default(dev, apdev): 1295 """SAE and default groups rejecting FFC""" 1296 check_sae_capab(dev[0]) 1297 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 1298 params['wpa_key_mgmt'] = 'SAE' 1299 hapd = hostapd.add_ap(apdev[0], params) 1300 1301 dev[0].request("SET sae_groups 15 16") 1302 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412", 1303 wait_connect=False) 1304 ev = dev[0].wait_event(["SME: Trying to authenticate"], timeout=3) 1305 if ev is None: 1306 raise Exception("Did not try to authenticate") 1307 ev = dev[0].wait_event(["SME: Trying to authenticate"], timeout=3) 1308 if ev is None: 1309 raise Exception("Did not try to authenticate (2)") 1310 dev[0].request("REMOVE_NETWORK all") 1311 1312def sae_reflection_attack(apdev, dev, group): 1313 check_sae_capab(dev) 1314 params = hostapd.wpa2_params(ssid="test-sae", 1315 passphrase="no-knowledge-of-passphrase") 1316 params['wpa_key_mgmt'] = 'SAE' 1317 hapd = hostapd.add_ap(apdev, params) 1318 bssid = apdev['bssid'] 1319 1320 dev.scan_for_bss(bssid, freq=2412) 1321 hapd.set("ext_mgmt_frame_handling", "1") 1322 1323 dev.request("SET sae_groups %d" % group) 1324 dev.connect("test-sae", psk="reflection-attack", key_mgmt="SAE", 1325 scan_freq="2412", wait_connect=False) 1326 1327 # Commit 1328 for i in range(0, 10): 1329 req = hapd.mgmt_rx() 1330 if req is None: 1331 raise Exception("MGMT RX wait timed out") 1332 if req['subtype'] == 11: 1333 break 1334 req = None 1335 if not req: 1336 raise Exception("Authentication frame not received") 1337 1338 resp = {} 1339 resp['fc'] = req['fc'] 1340 resp['da'] = req['sa'] 1341 resp['sa'] = req['da'] 1342 resp['bssid'] = req['bssid'] 1343 resp['payload'] = req['payload'] 1344 hapd.mgmt_tx(resp) 1345 1346 # Confirm 1347 req = hapd.mgmt_rx(timeout=0.5) 1348 if req is not None: 1349 if req['subtype'] == 11: 1350 raise Exception("Unexpected Authentication frame seen") 1351 1352@remote_compatible 1353def test_sae_reflection_attack_ecc(dev, apdev): 1354 """SAE reflection attack (ECC)""" 1355 sae_reflection_attack(apdev[0], dev[0], 19) 1356 1357@remote_compatible 1358def test_sae_reflection_attack_ffc(dev, apdev): 1359 """SAE reflection attack (FFC)""" 1360 sae_reflection_attack(apdev[0], dev[0], 15) 1361 1362def sae_reflection_attack_internal(apdev, dev, group): 1363 check_sae_capab(dev) 1364 params = hostapd.wpa2_params(ssid="test-sae", 1365 passphrase="no-knowledge-of-passphrase") 1366 params['wpa_key_mgmt'] = 'SAE' 1367 params['sae_reflection_attack'] = '1' 1368 hapd = hostapd.add_ap(apdev, params) 1369 bssid = apdev['bssid'] 1370 1371 dev.scan_for_bss(bssid, freq=2412) 1372 dev.request("SET sae_groups %d" % group) 1373 dev.connect("test-sae", psk="reflection-attack", key_mgmt="SAE", 1374 scan_freq="2412", wait_connect=False) 1375 ev = dev.wait_event(["SME: Trying to authenticate"], timeout=10) 1376 if ev is None: 1377 raise Exception("No authentication attempt seen") 1378 ev = dev.wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) 1379 if ev is not None: 1380 raise Exception("Unexpected connection") 1381 1382@remote_compatible 1383def test_sae_reflection_attack_ecc_internal(dev, apdev): 1384 """SAE reflection attack (ECC) - internal""" 1385 sae_reflection_attack_internal(apdev[0], dev[0], 19) 1386 1387@remote_compatible 1388def test_sae_reflection_attack_ffc_internal(dev, apdev): 1389 """SAE reflection attack (FFC) - internal""" 1390 sae_reflection_attack_internal(apdev[0], dev[0], 15) 1391 1392@remote_compatible 1393def test_sae_commit_override(dev, apdev): 1394 """SAE commit override (hostapd)""" 1395 check_sae_capab(dev[0]) 1396 params = hostapd.wpa2_params(ssid="test-sae", 1397 passphrase="12345678") 1398 params['wpa_key_mgmt'] = 'SAE' 1399 params['sae_commit_override'] = '13ffbad00d215867a7c5ff37d87bb9bdb7cb116e520f71e8d7a794ca2606d537ddc6c099c40e7a25372b80a8fd443cd7dd222c8ea21b8ef372d4b3e316c26a73fd999cc79ad483eb826e7b3893ea332da68fa13224bcdeb4fb18b0584dd100a2c514' 1400 hapd = hostapd.add_ap(apdev[0], params) 1401 dev[0].request("SET sae_groups ") 1402 dev[0].connect("test-sae", psk="test-sae", key_mgmt="SAE", 1403 scan_freq="2412", wait_connect=False) 1404 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) 1405 if ev is not None: 1406 raise Exception("Unexpected connection") 1407 1408@remote_compatible 1409def test_sae_commit_override2(dev, apdev): 1410 """SAE commit override (wpa_supplicant)""" 1411 check_sae_capab(dev[0]) 1412 params = hostapd.wpa2_params(ssid="test-sae", 1413 passphrase="12345678") 1414 params['wpa_key_mgmt'] = 'SAE' 1415 hapd = hostapd.add_ap(apdev[0], params) 1416 dev[0].request("SET sae_groups ") 1417 dev[0].set('sae_commit_override', '13ffbad00d215867a7c5ff37d87bb9bdb7cb116e520f71e8d7a794ca2606d537ddc6c099c40e7a25372b80a8fd443cd7dd222c8ea21b8ef372d4b3e316c26a73fd999cc79ad483eb826e7b3893ea332da68fa13224bcdeb4fb18b0584dd100a2c514') 1418 dev[0].connect("test-sae", psk="test-sae", key_mgmt="SAE", 1419 scan_freq="2412", wait_connect=False) 1420 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) 1421 if ev is not None: 1422 raise Exception("Unexpected connection") 1423 1424def test_sae_commit_invalid_scalar_element_ap(dev, apdev): 1425 """SAE commit invalid scalar/element from AP""" 1426 check_sae_capab(dev[0]) 1427 params = hostapd.wpa2_params(ssid="test-sae", 1428 passphrase="12345678") 1429 params['wpa_key_mgmt'] = 'SAE' 1430 params['sae_commit_override'] = '1300' + 96*'00' 1431 hapd = hostapd.add_ap(apdev[0], params) 1432 dev[0].request("SET sae_groups ") 1433 dev[0].connect("test-sae", psk="test-sae", key_mgmt="SAE", 1434 scan_freq="2412", wait_connect=False) 1435 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) 1436 if ev is not None: 1437 raise Exception("Unexpected connection") 1438 1439def test_sae_commit_invalid_element_ap(dev, apdev): 1440 """SAE commit invalid element from AP""" 1441 check_sae_capab(dev[0]) 1442 params = hostapd.wpa2_params(ssid="test-sae", 1443 passphrase="12345678") 1444 params['wpa_key_mgmt'] = 'SAE' 1445 params['sae_commit_override'] = '1300' + 31*'00' + '02' + 64*'00' 1446 hapd = hostapd.add_ap(apdev[0], params) 1447 dev[0].request("SET sae_groups ") 1448 dev[0].connect("test-sae", psk="test-sae", key_mgmt="SAE", 1449 scan_freq="2412", wait_connect=False) 1450 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) 1451 if ev is not None: 1452 raise Exception("Unexpected connection") 1453 1454def test_sae_commit_invalid_scalar_element_sta(dev, apdev): 1455 """SAE commit invalid scalar/element from STA""" 1456 check_sae_capab(dev[0]) 1457 params = hostapd.wpa2_params(ssid="test-sae", 1458 passphrase="12345678") 1459 params['wpa_key_mgmt'] = 'SAE' 1460 hapd = hostapd.add_ap(apdev[0], params) 1461 dev[0].request("SET sae_groups ") 1462 dev[0].set('sae_commit_override', '1300' + 96*'00') 1463 dev[0].connect("test-sae", psk="test-sae", key_mgmt="SAE", 1464 scan_freq="2412", wait_connect=False) 1465 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) 1466 if ev is not None: 1467 raise Exception("Unexpected connection") 1468 1469def test_sae_commit_invalid_element_sta(dev, apdev): 1470 """SAE commit invalid element from STA""" 1471 check_sae_capab(dev[0]) 1472 params = hostapd.wpa2_params(ssid="test-sae", 1473 passphrase="12345678") 1474 params['wpa_key_mgmt'] = 'SAE' 1475 hapd = hostapd.add_ap(apdev[0], params) 1476 dev[0].request("SET sae_groups ") 1477 dev[0].set('sae_commit_override', '1300' + 31*'00' + '02' + 64*'00') 1478 dev[0].connect("test-sae", psk="test-sae", key_mgmt="SAE", 1479 scan_freq="2412", wait_connect=False) 1480 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED"], timeout=1) 1481 if ev is not None: 1482 raise Exception("Unexpected connection") 1483 1484@remote_compatible 1485def test_sae_anti_clogging_proto(dev, apdev): 1486 """SAE anti clogging protocol testing""" 1487 check_sae_capab(dev[0]) 1488 params = hostapd.wpa2_params(ssid="test-sae", 1489 passphrase="no-knowledge-of-passphrase") 1490 params['wpa_key_mgmt'] = 'SAE' 1491 hapd = hostapd.add_ap(apdev[0], params) 1492 bssid = apdev[0]['bssid'] 1493 1494 dev[0].scan_for_bss(bssid, freq=2412) 1495 hapd.set("ext_mgmt_frame_handling", "1") 1496 1497 dev[0].request("SET sae_groups ") 1498 dev[0].connect("test-sae", psk="anti-cloggign", key_mgmt="SAE", 1499 scan_freq="2412", wait_connect=False) 1500 1501 # Commit 1502 for i in range(0, 10): 1503 req = hapd.mgmt_rx() 1504 if req is None: 1505 raise Exception("MGMT RX wait timed out") 1506 if req['subtype'] == 11: 1507 break 1508 req = None 1509 if not req: 1510 raise Exception("Authentication frame not received") 1511 1512 resp = {} 1513 resp['fc'] = req['fc'] 1514 resp['da'] = req['sa'] 1515 resp['sa'] = req['da'] 1516 resp['bssid'] = req['bssid'] 1517 resp['payload'] = binascii.unhexlify("030001004c00" + "ffff00") 1518 hapd.mgmt_tx(resp) 1519 1520 # Confirm (not received due to DH group being rejected) 1521 req = hapd.mgmt_rx(timeout=0.5) 1522 if req is not None: 1523 if req['subtype'] == 11: 1524 raise Exception("Unexpected Authentication frame seen") 1525 1526@remote_compatible 1527def test_sae_no_random(dev, apdev): 1528 """SAE and no random numbers available""" 1529 check_sae_capab(dev[0]) 1530 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 1531 params['wpa_key_mgmt'] = 'SAE' 1532 hapd = hostapd.add_ap(apdev[0], params) 1533 1534 dev[0].request("SET sae_groups ") 1535 tests = [(1, "os_get_random;sae_derive_pwe_ecc")] 1536 for count, func in tests: 1537 with fail_test(dev[0], count, func): 1538 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 1539 scan_freq="2412") 1540 dev[0].request("REMOVE_NETWORK all") 1541 dev[0].wait_disconnected() 1542 1543@remote_compatible 1544def test_sae_pwe_failure(dev, apdev): 1545 """SAE and pwe failure""" 1546 check_sae_capab(dev[0]) 1547 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 1548 params['wpa_key_mgmt'] = 'SAE' 1549 params['sae_groups'] = '19 15' 1550 hapd = hostapd.add_ap(apdev[0], params) 1551 1552 dev[0].request("SET sae_groups 19") 1553 with fail_test(dev[0], 1, "hmac_sha256_vector;sae_derive_pwe_ecc"): 1554 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 1555 scan_freq="2412") 1556 dev[0].request("REMOVE_NETWORK all") 1557 dev[0].wait_disconnected() 1558 with fail_test(dev[0], 1, "sae_test_pwd_seed_ecc"): 1559 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 1560 scan_freq="2412") 1561 dev[0].request("REMOVE_NETWORK all") 1562 dev[0].wait_disconnected() 1563 1564 dev[0].request("SET sae_groups 15") 1565 with fail_test(dev[0], 1, "hmac_sha256_vector;sae_derive_pwe_ffc"): 1566 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 1567 scan_freq="2412") 1568 dev[0].request("REMOVE_NETWORK all") 1569 dev[0].wait_disconnected() 1570 1571 dev[0].request("SET sae_groups 15") 1572 with fail_test(dev[0], 1, "sae_test_pwd_seed_ffc"): 1573 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 1574 scan_freq="2412") 1575 dev[0].request("REMOVE_NETWORK all") 1576 dev[0].wait_disconnected() 1577 with fail_test(dev[0], 2, "sae_test_pwd_seed_ffc"): 1578 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 1579 scan_freq="2412") 1580 dev[0].request("REMOVE_NETWORK all") 1581 dev[0].wait_disconnected() 1582 1583@remote_compatible 1584def test_sae_bignum_failure(dev, apdev): 1585 """SAE and bignum failure""" 1586 check_sae_capab(dev[0]) 1587 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 1588 params['wpa_key_mgmt'] = 'SAE' 1589 params['sae_groups'] = '19 15 22' 1590 hapd = hostapd.add_ap(apdev[0], params) 1591 1592 dev[0].request("SET sae_groups 19") 1593 tests = [(1, "crypto_bignum_init_set;dragonfly_get_rand_1_to_p_1"), 1594 (1, "crypto_bignum_init;dragonfly_is_quadratic_residue_blind"), 1595 (1, "crypto_bignum_mulmod;dragonfly_is_quadratic_residue_blind"), 1596 (2, "crypto_bignum_mulmod;dragonfly_is_quadratic_residue_blind"), 1597 (3, "crypto_bignum_mulmod;dragonfly_is_quadratic_residue_blind"), 1598 (1, "crypto_bignum_legendre;dragonfly_is_quadratic_residue_blind"), 1599 (1, "crypto_bignum_init_set;sae_test_pwd_seed_ecc"), 1600 (1, "crypto_ec_point_compute_y_sqr;sae_test_pwd_seed_ecc"), 1601 (1, "crypto_bignum_to_bin;sae_derive_pwe_ecc"), 1602 (1, "crypto_ec_point_compute_y_sqr;sae_derive_pwe_ecc"), 1603 (1, "crypto_ec_point_init;sae_derive_commit_element_ecc"), 1604 (1, "crypto_ec_point_mul;sae_derive_commit_element_ecc"), 1605 (1, "crypto_ec_point_invert;sae_derive_commit_element_ecc"), 1606 (1, "crypto_bignum_init;=sae_derive_commit"), 1607 (1, "crypto_ec_point_init;sae_derive_k_ecc"), 1608 (1, "crypto_ec_point_mul;sae_derive_k_ecc"), 1609 (1, "crypto_ec_point_add;sae_derive_k_ecc"), 1610 (2, "crypto_ec_point_mul;sae_derive_k_ecc"), 1611 (1, "crypto_ec_point_to_bin;sae_derive_k_ecc"), 1612 (1, "crypto_bignum_legendre;dragonfly_get_random_qr_qnr"), 1613 (1, "sha256_prf_bits;sae_derive_keys"), 1614 (1, "crypto_bignum_init;sae_derive_keys"), 1615 (1, "crypto_bignum_init_set;sae_parse_commit_scalar"), 1616 (1, "crypto_bignum_to_bin;sae_parse_commit_element_ecc"), 1617 (1, "crypto_ec_point_from_bin;sae_parse_commit_element_ecc")] 1618 for count, func in tests: 1619 with fail_test(dev[0], count, func): 1620 hapd.request("NOTE STA failure testing %d:%s" % (count, func)) 1621 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 1622 scan_freq="2412", wait_connect=False) 1623 wait_fail_trigger(dev[0], "GET_FAIL", timeout=0.1) 1624 dev[0].request("REMOVE_NETWORK all") 1625 dev[0].dump_monitor() 1626 hapd.dump_monitor() 1627 1628 dev[0].request("SET sae_groups 15") 1629 tests = [(1, "crypto_bignum_init_set;sae_set_group"), 1630 (2, "crypto_bignum_init_set;sae_set_group"), 1631 (1, "crypto_bignum_init;sae_derive_commit"), 1632 (2, "crypto_bignum_init;sae_derive_commit"), 1633 (1, "crypto_bignum_init_set;sae_test_pwd_seed_ffc"), 1634 (1, "crypto_bignum_exptmod;sae_test_pwd_seed_ffc"), 1635 (1, "crypto_bignum_init;sae_derive_pwe_ffc"), 1636 (1, "crypto_bignum_init;sae_derive_commit_element_ffc"), 1637 (1, "crypto_bignum_exptmod;sae_derive_commit_element_ffc"), 1638 (1, "crypto_bignum_inverse;sae_derive_commit_element_ffc"), 1639 (1, "crypto_bignum_init;sae_derive_k_ffc"), 1640 (1, "crypto_bignum_exptmod;sae_derive_k_ffc"), 1641 (1, "crypto_bignum_mulmod;sae_derive_k_ffc"), 1642 (2, "crypto_bignum_exptmod;sae_derive_k_ffc"), 1643 (1, "crypto_bignum_to_bin;sae_derive_k_ffc"), 1644 (1, "crypto_bignum_init_set;sae_parse_commit_element_ffc"), 1645 (1, "crypto_bignum_init;sae_parse_commit_element_ffc"), 1646 (2, "crypto_bignum_init_set;sae_parse_commit_element_ffc"), 1647 (1, "crypto_bignum_exptmod;sae_parse_commit_element_ffc")] 1648 for count, func in tests: 1649 with fail_test(dev[0], count, func): 1650 hapd.request("NOTE STA failure testing %d:%s" % (count, func)) 1651 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 1652 scan_freq="2412", wait_connect=False) 1653 wait_fail_trigger(dev[0], "GET_FAIL", timeout=0.1) 1654 dev[0].request("REMOVE_NETWORK all") 1655 dev[0].dump_monitor() 1656 hapd.dump_monitor() 1657 1658def test_sae_bignum_failure_unsafe_group(dev, apdev): 1659 """SAE and bignum failure unsafe group""" 1660 check_sae_capab(dev[0]) 1661 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 1662 params['wpa_key_mgmt'] = 'SAE' 1663 params['sae_groups'] = '22' 1664 hapd = hostapd.add_ap(apdev[0], params) 1665 1666 dev[0].request("SET sae_groups 22") 1667 tests = [(1, "crypto_bignum_init_set;sae_test_pwd_seed_ffc"), 1668 (1, "crypto_bignum_sub;sae_test_pwd_seed_ffc"), 1669 (1, "crypto_bignum_div;sae_test_pwd_seed_ffc")] 1670 for count, func in tests: 1671 with fail_test(dev[0], count, func): 1672 hapd.request("NOTE STA failure testing %d:%s" % (count, func)) 1673 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 1674 scan_freq="2412", wait_connect=False) 1675 wait_fail_trigger(dev[0], "GET_FAIL") 1676 dev[0].request("REMOVE_NETWORK all") 1677 dev[0].dump_monitor() 1678 hapd.dump_monitor() 1679 1680def test_sae_invalid_anti_clogging_token_req(dev, apdev): 1681 """SAE and invalid anti-clogging token request""" 1682 check_sae_capab(dev[0]) 1683 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 1684 params['wpa_key_mgmt'] = 'SAE' 1685 # Beacon more frequently since Probe Request frames are practically ignored 1686 # in this test setup (ext_mgmt_frame_handled=1 on hostapd side) and 1687 # wpa_supplicant scans may end up getting ignored if no new results are 1688 # available due to the missing Probe Response frames. 1689 params['beacon_int'] = '20' 1690 hapd = hostapd.add_ap(apdev[0], params) 1691 bssid = apdev[0]['bssid'] 1692 1693 dev[0].request("SET sae_groups 19") 1694 dev[0].scan_for_bss(bssid, freq=2412) 1695 hapd.set("ext_mgmt_frame_handling", "1") 1696 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 1697 scan_freq="2412", wait_connect=False) 1698 ev = dev[0].wait_event(["SME: Trying to authenticate"]) 1699 if ev is None: 1700 raise Exception("No authentication attempt seen (1)") 1701 dev[0].dump_monitor() 1702 1703 for i in range(0, 10): 1704 req = hapd.mgmt_rx() 1705 if req is None: 1706 raise Exception("MGMT RX wait timed out (commit)") 1707 if req['subtype'] == 11: 1708 break 1709 req = None 1710 if not req: 1711 raise Exception("Authentication frame (commit) not received") 1712 1713 hapd.dump_monitor() 1714 resp = {} 1715 resp['fc'] = req['fc'] 1716 resp['da'] = req['sa'] 1717 resp['sa'] = req['da'] 1718 resp['bssid'] = req['bssid'] 1719 resp['payload'] = binascii.unhexlify("030001004c0013") 1720 hapd.mgmt_tx(resp) 1721 ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5) 1722 if ev is None: 1723 raise Exception("Management frame TX status not reported (1)") 1724 if "stype=11 ok=1" not in ev: 1725 raise Exception("Unexpected management frame TX status (1): " + ev) 1726 1727 ev = dev[0].wait_event(["SME: Trying to authenticate"]) 1728 if ev is None: 1729 raise Exception("No authentication attempt seen (2)") 1730 dev[0].dump_monitor() 1731 1732 for i in range(0, 10): 1733 req = hapd.mgmt_rx() 1734 if req is None: 1735 raise Exception("MGMT RX wait timed out (commit) (2)") 1736 if req['subtype'] == 11: 1737 break 1738 req = None 1739 if not req: 1740 raise Exception("Authentication frame (commit) not received (2)") 1741 1742 hapd.dump_monitor() 1743 resp = {} 1744 resp['fc'] = req['fc'] 1745 resp['da'] = req['sa'] 1746 resp['sa'] = req['da'] 1747 resp['bssid'] = req['bssid'] 1748 resp['payload'] = binascii.unhexlify("030001000100") 1749 hapd.mgmt_tx(resp) 1750 ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5) 1751 if ev is None: 1752 raise Exception("Management frame TX status not reported (1)") 1753 if "stype=11 ok=1" not in ev: 1754 raise Exception("Unexpected management frame TX status (1): " + ev) 1755 1756 ev = dev[0].wait_event(["SME: Trying to authenticate"]) 1757 if ev is None: 1758 raise Exception("No authentication attempt seen (3)") 1759 dev[0].dump_monitor() 1760 1761 dev[0].request("DISCONNECT") 1762 1763def test_sae_password(dev, apdev): 1764 """SAE and sae_password in hostapd configuration""" 1765 check_sae_capab(dev[0]) 1766 params = hostapd.wpa2_params(ssid="test-sae", 1767 passphrase="12345678") 1768 params['wpa_key_mgmt'] = 'SAE WPA-PSK' 1769 params['sae_password'] = "sae-password" 1770 hapd = hostapd.add_ap(apdev[0], params) 1771 1772 dev[0].request("SET sae_groups ") 1773 dev[0].connect("test-sae", psk="sae-password", key_mgmt="SAE", 1774 scan_freq="2412") 1775 dev[1].connect("test-sae", psk="12345678", scan_freq="2412") 1776 dev[2].request("SET sae_groups ") 1777 dev[2].connect("test-sae", sae_password="sae-password", key_mgmt="SAE", 1778 scan_freq="2412") 1779 1780def test_sae_password_short(dev, apdev): 1781 """SAE and short password""" 1782 check_sae_capab(dev[0]) 1783 params = hostapd.wpa2_params(ssid="test-sae") 1784 params['wpa_key_mgmt'] = 'SAE' 1785 params['sae_password'] = "secret" 1786 hapd = hostapd.add_ap(apdev[0], params) 1787 1788 dev[0].request("SET sae_groups ") 1789 dev[0].connect("test-sae", sae_password="secret", key_mgmt="SAE", 1790 scan_freq="2412") 1791 1792def test_sae_password_long(dev, apdev): 1793 """SAE and long password""" 1794 check_sae_capab(dev[0]) 1795 params = hostapd.wpa2_params(ssid="test-sae") 1796 params['wpa_key_mgmt'] = 'SAE' 1797 params['sae_password'] = 100*"A" 1798 hapd = hostapd.add_ap(apdev[0], params) 1799 1800 dev[0].request("SET sae_groups ") 1801 dev[0].connect("test-sae", sae_password=100*"A", key_mgmt="SAE", 1802 scan_freq="2412") 1803 1804def test_sae_connect_cmd(dev, apdev): 1805 """SAE with connect command""" 1806 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 1807 wpas.interface_add("wlan5", drv_params="force_connect_cmd=1") 1808 check_sae_capab(wpas) 1809 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 1810 params['wpa_key_mgmt'] = 'SAE' 1811 hapd = hostapd.add_ap(apdev[0], params) 1812 1813 wpas.request("SET sae_groups ") 1814 wpas.connect("test-sae", psk="12345678", key_mgmt="SAE", 1815 scan_freq="2412", wait_connect=False) 1816 # mac80211_hwsim does not support SAE offload, so accept both a successful 1817 # connection and association rejection. 1818 ev = wpas.wait_event(["CTRL-EVENT-CONNECTED", "CTRL-EVENT-ASSOC-REJECT", 1819 "Association request to the driver failed"], 1820 timeout=15) 1821 if ev is None: 1822 raise Exception("No connection result reported") 1823 1824def run_sae_password_id(dev, apdev, groups=None): 1825 check_sae_capab(dev[0]) 1826 params = hostapd.wpa2_params(ssid="test-sae") 1827 params['wpa_key_mgmt'] = 'SAE' 1828 if groups: 1829 params['sae_groups'] = groups 1830 else: 1831 groups = "" 1832 params['sae_password'] = ['secret|mac=ff:ff:ff:ff:ff:ff|id=pw id', 1833 'foo|mac=02:02:02:02:02:02', 1834 'another secret|mac=ff:ff:ff:ff:ff:ff|id=' + 29*'A'] 1835 hapd = hostapd.add_ap(apdev[0], params) 1836 1837 dev[0].request("SET sae_groups " + groups) 1838 dev[0].connect("test-sae", sae_password="secret", sae_password_id="pw id", 1839 key_mgmt="SAE", scan_freq="2412") 1840 dev[0].request("REMOVE_NETWORK all") 1841 dev[0].wait_disconnected() 1842 1843 # SAE Password Identifier element with the exact same length as the 1844 # optional Anti-Clogging Token field 1845 dev[0].connect("test-sae", sae_password="another secret", 1846 sae_password_id=29*'A', 1847 key_mgmt="SAE", scan_freq="2412") 1848 dev[0].request("REMOVE_NETWORK all") 1849 dev[0].wait_disconnected() 1850 1851 dev[0].connect("test-sae", sae_password="secret", sae_password_id="unknown", 1852 key_mgmt="SAE", scan_freq="2412", wait_connect=False) 1853 1854 ev = dev[0].wait_event(["CTRL-EVENT-SAE-UNKNOWN-PASSWORD-IDENTIFIER"], 1855 timeout=10) 1856 if ev is None: 1857 raise Exception("Unknown password identifier not reported") 1858 dev[0].request("REMOVE_NETWORK all") 1859 1860def test_sae_password_id(dev, apdev): 1861 """SAE and password identifier""" 1862 run_sae_password_id(dev, apdev, "") 1863 1864def test_sae_password_id_ecc(dev, apdev): 1865 """SAE and password identifier (ECC)""" 1866 run_sae_password_id(dev, apdev, "19") 1867 1868def test_sae_password_id_ffc(dev, apdev): 1869 """SAE and password identifier (FFC)""" 1870 run_sae_password_id(dev, apdev, "15") 1871 1872def test_sae_password_id_only(dev, apdev): 1873 """SAE and password identifier (exclusively)""" 1874 check_sae_capab(dev[0]) 1875 params = hostapd.wpa2_params(ssid="test-sae") 1876 params['wpa_key_mgmt'] = 'SAE' 1877 params['sae_password'] = 'secret|id=pw id' 1878 hapd = hostapd.add_ap(apdev[0], params) 1879 1880 dev[0].request("SET sae_groups ") 1881 dev[0].connect("test-sae", sae_password="secret", sae_password_id="pw id", 1882 key_mgmt="SAE", scan_freq="2412") 1883 1884def test_sae_password_id_pwe_looping(dev, apdev): 1885 """SAE and password identifier with forced PWE looping""" 1886 check_sae_capab(dev[0]) 1887 params = hostapd.wpa2_params(ssid="test-sae") 1888 params['wpa_key_mgmt'] = 'SAE' 1889 params['sae_password'] = 'secret|id=pw id' 1890 params['sae_pwe'] = "3" 1891 hapd = hostapd.add_ap(apdev[0], params) 1892 1893 dev[0].request("SET sae_groups ") 1894 try: 1895 dev[0].set("sae_pwe", "3") 1896 dev[0].connect("test-sae", sae_password="secret", 1897 sae_password_id="pw id", 1898 key_mgmt="SAE", scan_freq="2412") 1899 if dev[0].get_status_field("ssid_verified") == "1": 1900 raise Exception("Unexpected ssid_verified=1 in STATUS") 1901 finally: 1902 dev[0].set("sae_pwe", "0") 1903 1904def test_sae_password_id_pwe_check_ap(dev, apdev): 1905 """SAE and password identifier with STA using unexpected PWE derivation""" 1906 check_sae_capab(dev[0]) 1907 params = hostapd.wpa2_params(ssid="test-sae") 1908 params['wpa_key_mgmt'] = 'SAE' 1909 params['sae_password'] = 'secret|id=pw id' 1910 hapd = hostapd.add_ap(apdev[0], params) 1911 1912 dev[0].request("SET sae_groups ") 1913 try: 1914 dev[0].set("sae_pwe", "3") 1915 dev[0].connect("test-sae", sae_password="secret", 1916 sae_password_id="pw id", 1917 key_mgmt="SAE", scan_freq="2412", wait_connect=False) 1918 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", 1919 "CTRL-EVENT-SSID-TEMP-DISABLED"], timeout=10) 1920 if ev is None or "CTRL-EVENT-SSID-TEMP-DISABLED" not in ev: 1921 raise Exception("Connection failure not reported") 1922 finally: 1923 dev[0].set("sae_pwe", "0") 1924 1925def test_sae_password_id_pwe_check_sta(dev, apdev): 1926 """SAE and password identifier with AP using unexpected PWE derivation""" 1927 check_sae_capab(dev[0]) 1928 params = hostapd.wpa2_params(ssid="test-sae") 1929 params['wpa_key_mgmt'] = 'SAE' 1930 params['sae_pwe'] = "3" 1931 params['sae_password'] = 'secret|id=pw id' 1932 hapd = hostapd.add_ap(apdev[0], params) 1933 1934 dev[0].request("SET sae_groups ") 1935 dev[0].connect("test-sae", sae_password="secret", 1936 sae_password_id="pw id", 1937 key_mgmt="SAE", scan_freq="2412", wait_connect=False) 1938 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", 1939 "CTRL-EVENT-NETWORK-NOT-FOUND"], timeout=10) 1940 if ev is None or "CTRL-EVENT-NETWORK-NOT-FOUND" not in ev: 1941 raise Exception("Connection failure not reported") 1942 1943def test_sae_forced_anti_clogging_pw_id(dev, apdev): 1944 """SAE anti clogging (forced and Password Identifier)""" 1945 check_sae_capab(dev[0]) 1946 params = hostapd.wpa2_params(ssid="test-sae") 1947 params['wpa_key_mgmt'] = 'SAE' 1948 params['sae_anti_clogging_threshold'] = '0' 1949 params['sae_password'] = 'secret|id=' + 29*'A' 1950 hostapd.add_ap(apdev[0], params) 1951 for i in range(0, 2): 1952 dev[i].request("SET sae_groups ") 1953 dev[i].connect("test-sae", sae_password="secret", 1954 sae_password_id=29*'A', key_mgmt="SAE", scan_freq="2412") 1955 1956def test_sae_reauth(dev, apdev): 1957 """SAE reauthentication""" 1958 check_sae_capab(dev[0]) 1959 params = hostapd.wpa2_params(ssid="test-sae", 1960 passphrase="12345678") 1961 params['wpa_key_mgmt'] = 'SAE' 1962 params["ieee80211w"] = "2" 1963 hapd = hostapd.add_ap(apdev[0], params) 1964 1965 dev[0].request("SET sae_groups ") 1966 id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 1967 ieee80211w="2", scan_freq="2412") 1968 1969 hapd.set("ext_mgmt_frame_handling", "1") 1970 dev[0].request("DISCONNECT") 1971 dev[0].wait_disconnected(timeout=10) 1972 hapd.set("ext_mgmt_frame_handling", "0") 1973 dev[0].request("PMKSA_FLUSH") 1974 dev[0].request("REASSOCIATE") 1975 dev[0].wait_connected(timeout=10, error="Timeout on re-connection") 1976 1977def test_sae_anti_clogging_during_attack(dev, apdev): 1978 """SAE anti clogging during an attack""" 1979 try: 1980 run_sae_anti_clogging_during_attack(dev, apdev) 1981 finally: 1982 stop_monitor(apdev[1]["ifname"]) 1983 1984def build_sae_commit(bssid, addr, group=21, token=None): 1985 if group == 19: 1986 scalar = binascii.unhexlify("7332d3ebff24804005ccd8c56141e3ed8d84f40638aa31cd2fac11d4d2e89e7b") 1987 element = binascii.unhexlify("954d0f4457066bff3168376a1d7174f4e66620d1792406f613055b98513a7f03a538c13dfbaf2029e2adc6aa96aa0ddcf08ac44887b02f004b7f29b9dbf4b7d9") 1988 elif group == 21: 1989 scalar = binascii.unhexlify("001eec673111b902f5c8a61c8cb4c1c4793031aeea8c8c319410903bc64bcbaea134ab01c4e016d51436f5b5426f7e2af635759a3033fb4031ea79f89a62a3e2f828") 1990 element = binascii.unhexlify("00580eb4b448ea600ea277d5e66e4ed37db82bb04ac90442e9c3727489f366ba4b82f0a472d02caf4cdd142e96baea5915d71374660ee23acbaca38cf3fe8c5fb94b01abbc5278121635d7c06911c5dad8f18d516e1fbe296c179b7c87a1dddfab393337d3d215ed333dd396da6d8f20f798c60d054f1093c24d9c2d98e15c030cc375f0") 1991 pass 1992 frame = binascii.unhexlify("b0003a01") 1993 frame += bssid + addr + bssid 1994 frame += binascii.unhexlify("1000") 1995 auth_alg = 3 1996 transact = 1 1997 status = 0 1998 frame += struct.pack("<HHHH", auth_alg, transact, status, group) 1999 if token: 2000 frame += token 2001 frame += scalar + element 2002 return frame 2003 2004def sae_rx_commit_token_req(sock, radiotap, send_two=False): 2005 msg = sock.recv(1500) 2006 ver, pad, length, present = struct.unpack('<BBHL', msg[0:8]) 2007 frame = msg[length:] 2008 if len(frame) < 4: 2009 return False 2010 fc, duration = struct.unpack('<HH', frame[0:4]) 2011 if fc != 0xb0: 2012 return False 2013 frame = frame[4:] 2014 da = frame[0:6] 2015 if da[0] != 0xf2: 2016 return False 2017 sa = frame[6:12] 2018 bssid = frame[12:18] 2019 body = frame[20:] 2020 2021 alg, seq, status, group = struct.unpack('<HHHH', body[0:8]) 2022 if alg != 3 or seq != 1 or status != 76: 2023 return False 2024 token = body[8:] 2025 2026 frame = build_sae_commit(bssid, da, token=token) 2027 sock.send(radiotap + frame) 2028 if send_two: 2029 sock.send(radiotap + frame) 2030 return True 2031 2032def run_sae_anti_clogging_during_attack(dev, apdev): 2033 check_sae_capab(dev[0]) 2034 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 2035 params['wpa_key_mgmt'] = 'SAE' 2036 params['sae_groups'] = '21' 2037 hapd = hostapd.add_ap(apdev[0], params) 2038 2039 dev[0].scan_for_bss(hapd.own_addr(), freq=2412) 2040 dev[0].request("SET sae_groups 21") 2041 dev[1].scan_for_bss(hapd.own_addr(), freq=2412) 2042 dev[1].request("SET sae_groups 21") 2043 2044 sock = start_monitor(apdev[1]["ifname"]) 2045 radiotap = radiotap_build() 2046 2047 bssid = binascii.unhexlify(hapd.own_addr().replace(':', '')) 2048 for i in range(16): 2049 addr = binascii.unhexlify("f2%010x" % i) 2050 frame = build_sae_commit(bssid, addr) 2051 sock.send(radiotap + frame) 2052 sock.send(radiotap + frame) 2053 2054 count = 0 2055 for i in range(150): 2056 if sae_rx_commit_token_req(sock, radiotap, send_two=True): 2057 count += 1 2058 logger.info("Number of token responses sent: %d" % count) 2059 if count < 10: 2060 raise Exception("Too few token responses seen: %d" % count) 2061 2062 for i in range(16): 2063 addr = binascii.unhexlify("f201%08x" % i) 2064 frame = build_sae_commit(bssid, addr) 2065 sock.send(radiotap + frame) 2066 2067 count = 0 2068 for i in range(150): 2069 if sae_rx_commit_token_req(sock, radiotap): 2070 count += 1 2071 if count == 10: 2072 break 2073 if count < 5: 2074 raise Exception("Too few token responses in second round: %d" % count) 2075 2076 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 2077 scan_freq="2412", wait_connect=False) 2078 dev[1].connect("test-sae", psk="12345678", key_mgmt="SAE", 2079 scan_freq="2412", wait_connect=False) 2080 2081 count = 0 2082 connected0 = False 2083 connected1 = False 2084 for i in range(1000): 2085 if sae_rx_commit_token_req(sock, radiotap): 2086 count += 1 2087 addr = binascii.unhexlify("f202%08x" % i) 2088 frame = build_sae_commit(bssid, addr) 2089 sock.send(radiotap + frame) 2090 while dev[0].mon.pending(): 2091 ev = dev[0].mon.recv() 2092 logger.debug("EV0: " + ev) 2093 if "CTRL-EVENT-CONNECTED" in ev: 2094 connected0 = True 2095 while dev[1].mon.pending(): 2096 ev = dev[1].mon.recv() 2097 logger.debug("EV1: " + ev) 2098 if "CTRL-EVENT-CONNECTED" in ev: 2099 connected1 = True 2100 if connected0 and connected1: 2101 break 2102 time.sleep(0.00000001) 2103 if not connected0: 2104 raise Exception("Real station(0) did not get connected") 2105 if not connected1: 2106 raise Exception("Real station(1) did not get connected") 2107 if count < 1: 2108 raise Exception("Too few token responses in third round: %d" % count) 2109 2110def test_sae_sync(dev, apdev): 2111 """SAE dot11RSNASAESync""" 2112 check_sae_capab(dev[0]) 2113 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 2114 params['wpa_key_mgmt'] = 'SAE' 2115 params['sae_sync'] = '1' 2116 hostapd.add_ap(apdev[0], params) 2117 2118 # TODO: More complete dot11RSNASAESync testing. For now, this is really only 2119 # checking that sae_sync config parameter is accepted. 2120 dev[0].request("SET sae_groups ") 2121 dev[1].request("SET sae_groups ") 2122 id = {} 2123 for i in range(0, 2): 2124 dev[i].scan(freq="2412") 2125 id[i] = dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE", 2126 scan_freq="2412", only_add_network=True) 2127 for i in range(0, 2): 2128 dev[i].select_network(id[i]) 2129 for i in range(0, 2): 2130 dev[i].wait_connected(timeout=10) 2131 2132def test_sae_confirm_immediate(dev, apdev): 2133 """SAE and AP sending Confirm message without waiting STA""" 2134 check_sae_capab(dev[0]) 2135 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 2136 params['wpa_key_mgmt'] = 'SAE' 2137 params['sae_confirm_immediate'] = '1' 2138 hapd = hostapd.add_ap(apdev[0], params) 2139 2140 dev[0].request("SET sae_groups ") 2141 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412") 2142 2143def test_sae_confirm_immediate2(dev, apdev): 2144 """SAE and AP sending Confirm message without waiting STA (2)""" 2145 check_sae_capab(dev[0]) 2146 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 2147 params['wpa_key_mgmt'] = 'SAE' 2148 params['sae_confirm_immediate'] = '2' 2149 hapd = hostapd.add_ap(apdev[0], params) 2150 2151 dev[0].request("SET sae_groups ") 2152 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", scan_freq="2412") 2153 2154def test_sae_pwe_group_19(dev, apdev): 2155 """SAE PWE derivation options with group 19""" 2156 run_sae_pwe_group(dev, apdev, 19) 2157 2158def test_sae_pwe_group_20(dev, apdev): 2159 """SAE PWE derivation options with group 20""" 2160 run_sae_pwe_group(dev, apdev, 20) 2161 2162def test_sae_pwe_group_21(dev, apdev): 2163 """SAE PWE derivation options with group 21""" 2164 run_sae_pwe_group(dev, apdev, 21) 2165 2166def test_sae_pwe_group_25(dev, apdev): 2167 """SAE PWE derivation options with group 25""" 2168 run_sae_pwe_group(dev, apdev, 25) 2169 2170def test_sae_pwe_group_28(dev, apdev): 2171 """SAE PWE derivation options with group 28""" 2172 run_sae_pwe_group(dev, apdev, 28) 2173 2174def test_sae_pwe_group_29(dev, apdev): 2175 """SAE PWE derivation options with group 29""" 2176 run_sae_pwe_group(dev, apdev, 29) 2177 2178def test_sae_pwe_group_30(dev, apdev): 2179 """SAE PWE derivation options with group 30""" 2180 run_sae_pwe_group(dev, apdev, 30) 2181 2182def test_sae_pwe_group_1(dev, apdev): 2183 """SAE PWE derivation options with group 1""" 2184 run_sae_pwe_group(dev, apdev, 1) 2185 2186def test_sae_pwe_group_2(dev, apdev): 2187 """SAE PWE derivation options with group 2""" 2188 run_sae_pwe_group(dev, apdev, 2) 2189 2190def test_sae_pwe_group_5(dev, apdev): 2191 """SAE PWE derivation options with group 5""" 2192 run_sae_pwe_group(dev, apdev, 5) 2193 2194def test_sae_pwe_group_14(dev, apdev): 2195 """SAE PWE derivation options with group 14""" 2196 run_sae_pwe_group(dev, apdev, 14) 2197 2198def test_sae_pwe_group_15(dev, apdev): 2199 """SAE PWE derivation options with group 15""" 2200 run_sae_pwe_group(dev, apdev, 15) 2201 2202def test_sae_pwe_group_16(dev, apdev): 2203 """SAE PWE derivation options with group 16""" 2204 run_sae_pwe_group(dev, apdev, 16) 2205 2206def test_sae_pwe_group_22(dev, apdev): 2207 """SAE PWE derivation options with group 22""" 2208 run_sae_pwe_group(dev, apdev, 22) 2209 2210def test_sae_pwe_group_23(dev, apdev): 2211 """SAE PWE derivation options with group 23""" 2212 run_sae_pwe_group(dev, apdev, 23) 2213 2214def test_sae_pwe_group_24(dev, apdev): 2215 """SAE PWE derivation options with group 24""" 2216 run_sae_pwe_group(dev, apdev, 24) 2217 2218def start_sae_pwe_ap(apdev, group, sae_pwe): 2219 params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678") 2220 params['wpa_key_mgmt'] = 'SAE' 2221 params['sae_groups'] = str(group) 2222 params['sae_pwe'] = str(sae_pwe) 2223 return hostapd.add_ap(apdev, params) 2224 2225def run_sae_pwe_group(dev, apdev, group): 2226 check_sae_capab(dev[0]) 2227 tls = dev[0].request("GET tls_library") 2228 if group == 25 and "run=BoringSSL" in tls: 2229 raise HwsimSkip("Group 15 not supported") 2230 if group in [27, 28, 29, 30]: 2231 if tls.startswith("OpenSSL") and ("run=OpenSSL 1." in tls or "run=OpenSSL 3." in tls): 2232 logger.info("Add Brainpool EC groups since OpenSSL is new enough") 2233 elif tls.startswith("wolfSSL"): 2234 logger.info("Make sure Brainpool EC groups were enabled when compiling wolfSSL") 2235 else: 2236 raise HwsimSkip("Brainpool curve not supported") 2237 start_sae_pwe_ap(apdev[0], group, 2) 2238 try: 2239 check_sae_pwe_group(dev[0], group, 0) 2240 check_sae_pwe_group(dev[0], group, 1) 2241 check_sae_pwe_group(dev[0], group, 2) 2242 finally: 2243 dev[0].set("sae_groups", "") 2244 dev[0].set("sae_pwe", "0") 2245 2246def check_sae_pwe_group(dev, group, sae_pwe, check_ssid=False): 2247 dev.set("sae_groups", str(group)) 2248 dev.set("sae_pwe", str(sae_pwe)) 2249 dev.connect("sae-pwe", psk="12345678", key_mgmt="SAE", scan_freq="2412") 2250 if check_ssid and dev.get_status_field("ssid_verified") != "1": 2251 raise Exception("ssid_verified=1 not in STATUS") 2252 dev.request("REMOVE_NETWORK all") 2253 dev.wait_disconnected() 2254 dev.dump_monitor() 2255 2256def test_sae_pwe_h2e_only_ap(dev, apdev): 2257 """SAE PWE derivation with H2E-only AP""" 2258 check_sae_capab(dev[0]) 2259 start_sae_pwe_ap(apdev[0], 19, 1) 2260 try: 2261 check_sae_pwe_group(dev[0], 19, 1, check_ssid=True) 2262 check_sae_pwe_group(dev[0], 19, 2, check_ssid=True) 2263 finally: 2264 dev[0].set("sae_groups", "") 2265 dev[0].set("sae_pwe", "0") 2266 2267 dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", scan_freq="2412", 2268 wait_connect=False) 2269 ev = dev[0].wait_event(["CTRL-EVENT-NETWORK-NOT-FOUND"], timeout=10) 2270 if ev is None: 2271 raise Exception("No indication of mismatching network seen") 2272 2273def test_sae_pwe_h2e_only_ap_sta_forcing_loop(dev, apdev): 2274 """SAE PWE derivation with H2E-only AP and STA forcing loop""" 2275 check_sae_capab(dev[0]) 2276 start_sae_pwe_ap(apdev[0], 19, 1) 2277 dev[0].set("ignore_sae_h2e_only", "1") 2278 dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", scan_freq="2412", 2279 wait_connect=False) 2280 ev = dev[0].wait_event(["CTRL-EVENT-SSID-TEMP-DISABLED"], timeout=10) 2281 dev[0].request("DISCONNECT") 2282 if ev is None: 2283 raise Exception("No indication of temporary disabled network seen") 2284 2285def test_sae_pwe_loop_only_ap(dev, apdev): 2286 """SAE PWE derivation with loop-only AP""" 2287 check_sae_capab(dev[0]) 2288 start_sae_pwe_ap(apdev[0], 19, 0) 2289 try: 2290 check_sae_pwe_group(dev[0], 19, 0) 2291 check_sae_pwe_group(dev[0], 19, 2) 2292 dev[0].set("sae_pwe", "1") 2293 dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", 2294 scan_freq="2412", wait_connect=False) 2295 ev = dev[0].wait_event(["CTRL-EVENT-NETWORK-NOT-FOUND"], timeout=10) 2296 if ev is None: 2297 raise Exception("No indication of mismatching network seen") 2298 finally: 2299 dev[0].set("sae_groups", "") 2300 dev[0].set("sae_pwe", "0") 2301 2302def test_sae_h2e_rejected_groups(dev, apdev): 2303 """SAE H2E and rejected groups indication""" 2304 check_sae_capab(dev[0]) 2305 params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678") 2306 params['wpa_key_mgmt'] = 'SAE' 2307 params['sae_groups'] = "19" 2308 params['sae_pwe'] = "1" 2309 hapd = hostapd.add_ap(apdev[0], params) 2310 try: 2311 dev[0].set("sae_groups", "21 20 19") 2312 dev[0].set("sae_pwe", "1") 2313 dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", 2314 scan_freq="2412") 2315 addr = dev[0].own_addr() 2316 hapd.wait_sta(addr) 2317 sta = hapd.get_sta(addr) 2318 if 'sae_rejected_groups' not in sta: 2319 raise Exception("No sae_rejected_groups") 2320 val = sta['sae_rejected_groups'] 2321 if val != "21 20": 2322 raise Exception("Unexpected sae_rejected_groups value: " + val) 2323 finally: 2324 dev[0].set("sae_groups", "") 2325 dev[0].set("sae_pwe", "0") 2326 2327def test_sae_h2e_rejected_groups_diff_ap(dev, apdev): 2328 """SAE H2E and rejected groups with different APs and different config""" 2329 check_sae_capab(dev[0]) 2330 2331 params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678") 2332 params['wpa_key_mgmt'] = 'SAE' 2333 params['sae_groups'] = "19" 2334 params['sae_pwe'] = "1" 2335 hapd = hostapd.add_ap(apdev[0], params) 2336 2337 try: 2338 dev[0].set("sae_groups", "21 20 19") 2339 dev[0].set("sae_pwe", "1") 2340 dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", 2341 scan_freq="2412") 2342 addr = dev[0].own_addr() 2343 hapd.wait_sta(addr) 2344 2345 params['sae_groups'] = "20" 2346 hapd2 = hostapd.add_ap(apdev[1], params) 2347 bssid2 = hapd2.own_addr() 2348 2349 dev[0].scan_for_bss(bssid2, freq=2412) 2350 dev[0].roam(bssid2) 2351 hapd2.wait_sta(addr) 2352 sta = hapd2.get_sta(addr) 2353 if 'sae_rejected_groups' not in sta: 2354 raise Exception("No sae_rejected_groups") 2355 val = sta['sae_rejected_groups'] 2356 if val != "21": 2357 raise Exception("Unexpected sae_rejected_groups value: " + val) 2358 finally: 2359 dev[0].set("sae_groups", "") 2360 dev[0].set("sae_pwe", "0") 2361 2362def test_sae_h2e_rejected_groups_unexpected(dev, apdev): 2363 """SAE H2E and rejected groups indication (unexpected group)""" 2364 check_sae_capab(dev[0]) 2365 params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678") 2366 params['wpa_key_mgmt'] = 'SAE' 2367 params['sae_groups'] = "19 20" 2368 params['sae_pwe'] = "1" 2369 hapd = hostapd.add_ap(apdev[0], params) 2370 try: 2371 dev[0].set("sae_groups", "21 19") 2372 dev[0].set("extra_sae_rejected_groups", "19") 2373 dev[0].set("sae_pwe", "1") 2374 dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", 2375 scan_freq="2412", wait_connect=False) 2376 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", 2377 "CTRL-EVENT-SSID-TEMP-DISABLED"], timeout=10) 2378 dev[0].request("DISCONNECT") 2379 if ev is None: 2380 raise Exception("No indication of temporary disabled network seen") 2381 if "CTRL-EVENT-CONNECTED" in ev: 2382 raise Exception("Unexpected connection") 2383 finally: 2384 dev[0].set("sae_groups", "") 2385 dev[0].set("sae_pwe", "0") 2386 2387def test_sae_h2e_rejected_groups_invalid(dev, apdev): 2388 """SAE protocol testing - Invalid Rejected Groups element""" 2389 check_sae_capab(dev[0]) 2390 params = hostapd.wpa2_params(ssid="test-sae", 2391 passphrase="12345678") 2392 params['wpa_key_mgmt'] = 'SAE' 2393 params['sae_groups'] = "19 20" 2394 params['sae_pwe'] = "1" 2395 hapd = hostapd.add_ap(apdev[0], params) 2396 2397 try: 2398 dev[0].set("sae_groups", "20 19") 2399 dev[0].set("sae_pwe", "1") 2400 run_sae_h2e_rejected_groups_invalid(dev[0], hapd) 2401 finally: 2402 dev[0].set("sae_groups", "") 2403 dev[0].set("sae_pwe", "0") 2404 2405def run_sae_h2e_rejected_groups_invalid(dev, hapd): 2406 addr = dev.own_addr() 2407 bssid = hapd.own_addr() 2408 2409 dev.scan_for_bss(bssid, freq=2412) 2410 hapd.set("ext_mgmt_frame_handling", "1") 2411 dev.connect("test-sae", psk="12345678", key_mgmt="SAE", 2412 scan_freq="2412", wait_connect=False) 2413 2414 logger.info("Commit (group 20)") 2415 for i in range(10): 2416 req = hapd.mgmt_rx() 2417 if req is None: 2418 raise Exception("MGMT RX wait timed out (commit)") 2419 if req['subtype'] == 11: 2420 break 2421 req = None 2422 if not req: 2423 raise Exception("Authentication frame (commit) not received") 2424 group, = struct.unpack('<H', req['payload'][6:8]) 2425 if group != 20: 2426 raise Exception("Unexpected group %d in SAE Commit" % group) 2427 hapd.dump_monitor() 2428 2429 # Discard this SAE Commit message without AP processing and instead, send 2430 # an unsupported group indication to the STA. 2431 resp = {} 2432 resp['fc'] = 0xb0 2433 resp['da'] = addr 2434 resp['sa'] = bssid 2435 resp['bssid'] = bssid 2436 resp['payload'] = binascii.unhexlify("030001004d001400") 2437 hapd.mgmt_tx(resp) 2438 2439 logger.info("Commit (group 19)") 2440 for i in range(10): 2441 req = hapd.mgmt_rx() 2442 if req is None: 2443 raise Exception("MGMT RX wait timed out (commit)") 2444 if req['subtype'] == 11: 2445 break 2446 req = None 2447 if not req: 2448 raise Exception("Authentication frame (commit) not received") 2449 group, = struct.unpack('<H', req['payload'][6:8]) 2450 if group != 19: 2451 raise Exception("Unexpected group %d in SAE Commit" % group) 2452 hapd.dump_monitor() 2453 2454 # Replace the Rejected Groups element with an invalid one and process the 2455 # modified SAE Commit message in hostapd. 2456 rej_groups = req['frame'][-5:] 2457 if rej_groups != binascii.unhexlify('ff035c1400'): 2458 raise Exception("No Rejected Groups element: " + binascii.hexlify(rej_groups).decode()) 2459 frame = req['frame'][:-5] + binascii.unhexlify('ff025c14') 2460 hapd.request("MGMT_RX_PROCESS freq=2412 datarate=0 ssi_signal=-30 frame=" + binascii.hexlify(frame).decode()) 2461 2462 ev = hapd.wait_event(["MGMT-TX-STATUS"], timeout=5) 2463 if ev is None: 2464 raise Exception("Management frame TX status not reported") 2465 if "stype=11 ok=1" not in ev: 2466 raise Exception("Unexpected Management frame TX status: " + ev) 2467 buf = ev.split(' ')[3].split('=')[1] 2468 payload = buf[48:] 2469 if payload != "030001000100": 2470 raise Exception("Unexpected AP response to SAE Commit with invalid Rejected Groups element: " + payload) 2471 2472 # Stop modifying frames and verify that connection is eventually established 2473 # with automatic retries. 2474 hapd.set("ext_mgmt_frame_handling", "0") 2475 dev.wait_connected(timeout=60) 2476 2477def test_sae_h2e_password_id(dev, apdev): 2478 """SAE H2E and password identifier""" 2479 check_sae_capab(dev[0]) 2480 params = hostapd.wpa2_params(ssid="test-sae") 2481 params['wpa_key_mgmt'] = 'SAE' 2482 params['sae_pwe'] = '1' 2483 params['sae_password'] = 'secret|id=pw id' 2484 hapd = hostapd.add_ap(apdev[0], params) 2485 2486 try: 2487 dev[0].request("SET sae_groups ") 2488 dev[0].set("sae_pwe", "1") 2489 dev[0].connect("test-sae", sae_password="secret", 2490 sae_password_id="pw id", 2491 key_mgmt="SAE", scan_freq="2412") 2492 finally: 2493 dev[0].set("sae_groups", "") 2494 dev[0].set("sae_pwe", "0") 2495 2496def test_sae_pwe_in_psk_ap(dev, apdev): 2497 """sae_pwe parameter in PSK-only-AP""" 2498 params = hostapd.wpa2_params(ssid="test-psk", passphrase="12345678") 2499 params['sae_pwe'] = '1' 2500 hapd = hostapd.add_ap(apdev[0], params) 2501 2502 dev[0].connect("test-psk", psk="12345678", scan_freq="2412") 2503 2504def test_sae_auth_restart(dev, apdev): 2505 """SAE and authentication restarts with H2E/looping""" 2506 check_sae_capab(dev[0]) 2507 params = hostapd.wpa2_params(ssid="test-sae") 2508 params['wpa_key_mgmt'] = 'SAE' 2509 params['sae_pwe'] = '2' 2510 params['sae_password'] = 'secret|id=pw id' 2511 hapd = hostapd.add_ap(apdev[0], params) 2512 2513 try: 2514 dev[0].request("SET sae_groups ") 2515 for pwe in [1, 0, 1]: 2516 dev[0].set("sae_pwe", str(pwe)) 2517 dev[0].connect("test-sae", sae_password="secret", 2518 sae_password_id="pw id", 2519 key_mgmt="SAE", scan_freq="2412") 2520 # Disconnect without hostapd removing the STA entry so that the 2521 # following SAE authentication instance starts with an existing 2522 # STA entry that has maintained some SAE state. 2523 hapd.set("ext_mgmt_frame_handling", "1") 2524 dev[0].request("REMOVE_NETWORK all") 2525 req = hapd.mgmt_rx() 2526 dev[0].wait_disconnected() 2527 dev[0].dump_monitor() 2528 hapd.set("ext_mgmt_frame_handling", "0") 2529 finally: 2530 dev[0].set("sae_groups", "") 2531 dev[0].set("sae_pwe", "0") 2532 2533def test_sae_rsne_mismatch(dev, apdev): 2534 """SAE and RSNE mismatch in EAPOL-Key msg 2/4""" 2535 check_sae_capab(dev[0]) 2536 dev[0].set("sae_groups", "") 2537 2538 params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678") 2539 params['wpa_key_mgmt'] = 'SAE' 2540 hapd = hostapd.add_ap(apdev[0], params) 2541 2542 # First, test with matching RSNE to confirm testing capability 2543 dev[0].set("rsne_override_eapol", 2544 "30140100000fac040100000fac040100000fac080c00") 2545 dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", 2546 scan_freq="2412") 2547 dev[0].request("REMOVE_NETWORK all") 2548 dev[0].wait_disconnected() 2549 dev[0].dump_monitor() 2550 2551 # Then, test with modified RSNE 2552 tests = ["30140100000fac040100000fac040100000fac080c10", "0000"] 2553 for ie in tests: 2554 dev[0].set("rsne_override_eapol", ie) 2555 dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", 2556 scan_freq="2412", wait_connect=False) 2557 ev = dev[0].wait_event(["Associated with"], timeout=10) 2558 if ev is None: 2559 raise Exception("No indication of association seen") 2560 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", 2561 "CTRL-EVENT-DISCONNECTED"], timeout=5) 2562 dev[0].request("REMOVE_NETWORK all") 2563 if ev is None: 2564 raise Exception("No disconnection seen") 2565 if "CTRL-EVENT-DISCONNECTED" not in ev: 2566 raise Exception("Unexpected connection") 2567 dev[0].dump_monitor() 2568 2569def test_sae_h2e_rsnxe_mismatch(dev, apdev): 2570 """SAE H2E and RSNXE mismatch in EAPOL-Key msg 2/4""" 2571 check_sae_capab(dev[0]) 2572 params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678") 2573 params['wpa_key_mgmt'] = 'SAE' 2574 params['sae_pwe'] = "1" 2575 hapd = hostapd.add_ap(apdev[0], params) 2576 try: 2577 dev[0].set("sae_groups", "19") 2578 dev[0].set("sae_pwe", "1") 2579 for rsnxe in ["F40100", "F400", ""]: 2580 dev[0].set("rsnxe_override_eapol", rsnxe) 2581 dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", 2582 scan_freq="2412", wait_connect=False) 2583 ev = dev[0].wait_event(["Associated with"], timeout=10) 2584 if ev is None: 2585 raise Exception("No indication of association seen") 2586 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", 2587 "CTRL-EVENT-DISCONNECTED"], timeout=5) 2588 dev[0].request("REMOVE_NETWORK all") 2589 if ev is None: 2590 raise Exception("No disconnection seen") 2591 if "CTRL-EVENT-DISCONNECTED" not in ev: 2592 raise Exception("Unexpected connection") 2593 dev[0].dump_monitor() 2594 finally: 2595 dev[0].set("sae_groups", "") 2596 dev[0].set("sae_pwe", "0") 2597 2598def test_sae_h2e_rsnxe_mismatch_retries(dev, apdev): 2599 """SAE H2E and RSNXE mismatch in EAPOL-Key msg 2/4 retries""" 2600 check_sae_capab(dev[0]) 2601 params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678") 2602 params['wpa_key_mgmt'] = 'SAE' 2603 params['sae_pwe'] = "1" 2604 hapd = hostapd.add_ap(apdev[0], params) 2605 try: 2606 dev[0].set("sae_groups", "19") 2607 dev[0].set("sae_pwe", "1") 2608 rsnxe = "F40100" 2609 dev[0].set("rsnxe_override_eapol", rsnxe) 2610 dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", 2611 scan_freq="2412", wait_connect=False) 2612 ev = dev[0].wait_event(["Associated with"], timeout=10) 2613 if ev is None: 2614 raise Exception("No indication of association seen") 2615 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", 2616 "CTRL-EVENT-DISCONNECTED"], timeout=5) 2617 if ev is None: 2618 raise Exception("No disconnection seen") 2619 if "CTRL-EVENT-DISCONNECTED" not in ev: 2620 raise Exception("Unexpected connection") 2621 2622 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", 2623 "CTRL-EVENT-DISCONNECTED"], timeout=10) 2624 if ev is None: 2625 raise Exception("No disconnection seen (2)") 2626 if "CTRL-EVENT-DISCONNECTED" not in ev: 2627 raise Exception("Unexpected connection (2)") 2628 2629 dev[0].dump_monitor() 2630 finally: 2631 dev[0].set("sae_groups", "") 2632 dev[0].set("sae_pwe", "0") 2633 2634def test_sae_h2e_rsnxe_mismatch_assoc(dev, apdev): 2635 """SAE H2E and RSNXE mismatch in EAPOL-Key msg 2/4 (assoc)""" 2636 check_sae_capab(dev[0]) 2637 params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678") 2638 params['wpa_key_mgmt'] = 'SAE' 2639 params['sae_pwe'] = "1" 2640 hapd = hostapd.add_ap(apdev[0], params) 2641 try: 2642 dev[0].set("sae_groups", "19") 2643 dev[0].set("sae_pwe", "1") 2644 for rsnxe in ["F40100", "F400", ""]: 2645 dev[0].set("rsnxe_override_assoc", rsnxe) 2646 dev[0].set("rsnxe_override_eapol", "F40120") 2647 dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", 2648 scan_freq="2412", wait_connect=False) 2649 ev = dev[0].wait_event(["Associated with"], timeout=10) 2650 if ev is None: 2651 raise Exception("No indication of association seen") 2652 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", 2653 "CTRL-EVENT-DISCONNECTED"], timeout=5) 2654 dev[0].request("REMOVE_NETWORK all") 2655 if ev is None: 2656 raise Exception("No disconnection seen") 2657 if "CTRL-EVENT-DISCONNECTED" not in ev: 2658 raise Exception("Unexpected connection") 2659 dev[0].dump_monitor() 2660 finally: 2661 dev[0].set("sae_groups", "") 2662 dev[0].set("sae_pwe", "0") 2663 2664def test_sae_h2e_rsnxe_mismatch_ap(dev, apdev): 2665 """SAE H2E and RSNXE mismatch in EAPOL-Key msg 3/4""" 2666 run_sae_h2e_rsnxe_mismatch_ap(dev, apdev, "F40100") 2667 2668def test_sae_h2e_rsnxe_mismatch_ap2(dev, apdev): 2669 """SAE H2E and RSNXE mismatch in EAPOL-Key msg 3/4""" 2670 run_sae_h2e_rsnxe_mismatch_ap(dev, apdev, "F400") 2671 2672def test_sae_h2e_rsnxe_mismatch_ap3(dev, apdev): 2673 """SAE H2E and RSNXE mismatch in EAPOL-Key msg 3/4""" 2674 run_sae_h2e_rsnxe_mismatch_ap(dev, apdev, "") 2675 2676def run_sae_h2e_rsnxe_mismatch_ap(dev, apdev, rsnxe): 2677 check_sae_capab(dev[0]) 2678 params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678") 2679 params['wpa_key_mgmt'] = 'SAE' 2680 params['sae_pwe'] = "1" 2681 params['rsnxe_override_eapol'] = rsnxe 2682 hapd = hostapd.add_ap(apdev[0], params) 2683 try: 2684 dev[0].set("sae_groups", "19") 2685 dev[0].set("sae_pwe", "1") 2686 dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE", 2687 scan_freq="2412", wait_connect=False) 2688 ev = dev[0].wait_event(["Associated with"], timeout=10) 2689 if ev is None: 2690 raise Exception("No indication of association seen") 2691 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", 2692 "CTRL-EVENT-DISCONNECTED"], timeout=5) 2693 dev[0].request("REMOVE_NETWORK all") 2694 if ev is None: 2695 raise Exception("No disconnection seen") 2696 if "CTRL-EVENT-DISCONNECTED" not in ev: 2697 raise Exception("Unexpected connection") 2698 finally: 2699 dev[0].set("sae_groups", "") 2700 dev[0].set("sae_pwe", "0") 2701 2702def test_sae_forced_anti_clogging_h2e(dev, apdev): 2703 """SAE anti clogging (forced, H2E)""" 2704 check_sae_capab(dev[0]) 2705 check_sae_capab(dev[1]) 2706 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 2707 params['wpa_key_mgmt'] = 'SAE WPA-PSK' 2708 params['sae_pwe'] = "1" 2709 params['sae_anti_clogging_threshold'] = '0' 2710 hostapd.add_ap(apdev[0], params) 2711 dev[2].connect("test-sae", psk="12345678", scan_freq="2412") 2712 try: 2713 for i in range(2): 2714 dev[i].request("SET sae_groups ") 2715 dev[i].set("sae_pwe", "1") 2716 dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE", 2717 scan_freq="2412") 2718 finally: 2719 for i in range(2): 2720 dev[i].set("sae_pwe", "0") 2721 2722def test_sae_forced_anti_clogging_h2e_loop(dev, apdev): 2723 """SAE anti clogging (forced, H2E + loop)""" 2724 check_sae_capab(dev[0]) 2725 check_sae_capab(dev[1]) 2726 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 2727 params['wpa_key_mgmt'] = 'SAE WPA-PSK' 2728 params['sae_pwe'] = "2" 2729 params['sae_anti_clogging_threshold'] = '0' 2730 hostapd.add_ap(apdev[0], params) 2731 dev[2].connect("test-sae", psk="12345678", scan_freq="2412") 2732 try: 2733 for i in range(2): 2734 dev[i].request("SET sae_groups ") 2735 dev[i].set("sae_pwe", "2") 2736 dev[i].connect("test-sae", psk="12345678", key_mgmt="SAE", 2737 scan_freq="2412") 2738 finally: 2739 for i in range(2): 2740 dev[i].set("sae_pwe", "0") 2741 2742def test_sae_okc(dev, apdev): 2743 """SAE and opportunistic key caching""" 2744 check_sae_capab(dev[0]) 2745 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 2746 params['wpa_key_mgmt'] = 'SAE' 2747 params['okc'] = '1' 2748 hapd = hostapd.add_ap(apdev[0], params) 2749 bssid = hapd.own_addr() 2750 2751 dev[0].flush_scan_cache() 2752 dev[0].set("sae_groups", "") 2753 id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 2754 okc=True, scan_freq="2412") 2755 dev[0].dump_monitor() 2756 hapd.wait_sta() 2757 if "sae_group" not in dev[0].get_status(): 2758 raise Exception("SAE authentication not used") 2759 2760 hapd2 = hostapd.add_ap(apdev[1], params) 2761 bssid2 = hapd2.own_addr() 2762 2763 dev[0].scan_for_bss(bssid2, freq=2412) 2764 dev[0].roam(bssid2) 2765 dev[0].dump_monitor() 2766 hapd2.wait_sta() 2767 if "sae_group" in dev[0].get_status(): 2768 raise Exception("SAE authentication used during roam to AP2") 2769 2770 dev[0].roam(bssid) 2771 dev[0].dump_monitor() 2772 hapd.wait_sta() 2773 if "sae_group" in dev[0].get_status(): 2774 raise Exception("SAE authentication used during roam to AP1") 2775 2776def test_sae_okc_sta_only(dev, apdev): 2777 """SAE and opportunistic key caching only on STA""" 2778 check_sae_capab(dev[0]) 2779 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 2780 params['wpa_key_mgmt'] = 'SAE' 2781 hapd = hostapd.add_ap(apdev[0], params) 2782 bssid = hapd.own_addr() 2783 2784 dev[0].flush_scan_cache() 2785 dev[0].set("sae_groups", "") 2786 id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 2787 okc=True, scan_freq="2412") 2788 dev[0].dump_monitor() 2789 hapd.wait_sta() 2790 if "sae_group" not in dev[0].get_status(): 2791 raise Exception("SAE authentication not used") 2792 2793 hapd2 = hostapd.add_ap(apdev[1], params) 2794 bssid2 = hapd2.own_addr() 2795 2796 dev[0].scan_for_bss(bssid2, freq=2412) 2797 dev[0].roam(bssid2, assoc_reject_ok=True) 2798 dev[0].dump_monitor() 2799 hapd2.wait_sta() 2800 if "sae_group" not in dev[0].get_status(): 2801 raise Exception("SAE authentication not used during roam to AP2") 2802 2803def test_sae_okc_pmk_lifetime(dev, apdev): 2804 """SAE and opportunistic key caching and PMK lifetime""" 2805 check_sae_capab(dev[0]) 2806 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 2807 params['wpa_key_mgmt'] = 'SAE' 2808 params['okc'] = '1' 2809 hapd = hostapd.add_ap(apdev[0], params) 2810 bssid = hapd.own_addr() 2811 2812 dev[0].flush_scan_cache() 2813 dev[0].set("sae_groups", "") 2814 dev[0].set("dot11RSNAConfigPMKLifetime", "10") 2815 dev[0].set("dot11RSNAConfigPMKReauthThreshold", "30") 2816 id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 2817 okc=True, scan_freq="2412") 2818 dev[0].dump_monitor() 2819 hapd.wait_sta() 2820 if "sae_group" not in dev[0].get_status(): 2821 raise Exception("SAE authentication not used") 2822 2823 hapd2 = hostapd.add_ap(apdev[1], params) 2824 bssid2 = hapd2.own_addr() 2825 2826 time.sleep(5) 2827 dev[0].scan_for_bss(bssid2, freq=2412) 2828 dev[0].roam(bssid2) 2829 dev[0].dump_monitor() 2830 hapd2.wait_sta() 2831 if "sae_group" not in dev[0].get_status(): 2832 raise Exception("SAE authentication not used during roam to AP2 after reauth threshold") 2833 2834def test_sae_pmk_lifetime(dev, apdev): 2835 """SAE and PMK lifetime""" 2836 check_sae_capab(dev[0]) 2837 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 2838 params['wpa_key_mgmt'] = 'SAE' 2839 hapd = hostapd.add_ap(apdev[0], params) 2840 bssid = hapd.own_addr() 2841 2842 dev[0].set("sae_groups", "") 2843 dev[0].set("dot11RSNAConfigPMKLifetime", "10") 2844 dev[0].set("dot11RSNAConfigPMKReauthThreshold", "50") 2845 id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 2846 scan_freq="2412") 2847 dev[0].dump_monitor() 2848 hapd.wait_sta() 2849 if "sae_group" not in dev[0].get_status(): 2850 raise Exception("SAE authentication not used") 2851 2852 hapd2 = hostapd.add_ap(apdev[1], params) 2853 bssid2 = hapd2.own_addr() 2854 2855 dev[0].flush_scan_cache() 2856 dev[0].scan_for_bss(bssid2, freq=2412) 2857 dev[0].roam(bssid2) 2858 dev[0].dump_monitor() 2859 hapd2.wait_sta() 2860 if "sae_group" not in dev[0].get_status(): 2861 raise Exception("SAE authentication not used during roam to AP2") 2862 2863 dev[0].roam(bssid) 2864 dev[0].dump_monitor() 2865 hapd.wait_sta() 2866 if "sae_group" in dev[0].get_status(): 2867 raise Exception("SAE authentication used during roam to AP1") 2868 2869 time.sleep(6) 2870 dev[0].scan_for_bss(bssid2, freq=2412) 2871 dev[0].roam(bssid2) 2872 dev[0].dump_monitor() 2873 hapd2.wait_sta() 2874 if "sae_group" not in dev[0].get_status(): 2875 raise Exception("SAE authentication not used during roam to AP2 after reauth threshold") 2876 2877 ev = dev[0].wait_event(["PMKSA-CACHE-REMOVED"], 11) 2878 if ev is None: 2879 raise Exception("PMKSA cache entry did not expire") 2880 if bssid2 in ev: 2881 raise Exception("Unexpected expiration of the current SAE PMKSA cache entry") 2882 2883def test_sae_and_psk_multiple_passwords(dev, apdev, params): 2884 """SAE and PSK with multiple passwords/passphrases""" 2885 check_sae_capab(dev[0]) 2886 check_sae_capab(dev[1]) 2887 addr0 = dev[0].own_addr() 2888 addr1 = dev[1].own_addr() 2889 psk_file = os.path.join(params['logdir'], 2890 'sae_and_psk_multiple_passwords.wpa_psk') 2891 with open(psk_file, 'w') as f: 2892 f.write(addr0 + ' passphrase0\n') 2893 f.write(addr1 + ' passphrase1\n') 2894 params = hostapd.wpa2_params(ssid="test-sae") 2895 params['wpa_key_mgmt'] = 'SAE WPA-PSK' 2896 params['sae_password'] = ['passphrase0|mac=' + addr0, 2897 'passphrase1|mac=' + addr1] 2898 params['wpa_psk_file'] = psk_file 2899 hapd = hostapd.add_ap(apdev[0], params) 2900 2901 dev[0].set("sae_groups", "") 2902 dev[0].connect("test-sae", sae_password="passphrase0", 2903 key_mgmt="SAE", scan_freq="2412") 2904 dev[0].request("REMOVE_NETWORK all") 2905 dev[0].wait_disconnected() 2906 2907 dev[0].connect("test-sae", psk="passphrase0", scan_freq="2412") 2908 dev[0].request("REMOVE_NETWORK all") 2909 dev[0].wait_disconnected() 2910 2911 dev[1].set("sae_groups", "") 2912 dev[1].connect("test-sae", sae_password="passphrase1", 2913 key_mgmt="SAE", scan_freq="2412") 2914 dev[1].request("REMOVE_NETWORK all") 2915 dev[1].wait_disconnected() 2916 2917 dev[1].connect("test-sae", psk="passphrase1", scan_freq="2412") 2918 dev[1].request("REMOVE_NETWORK all") 2919 dev[1].wait_disconnected() 2920 2921def test_sae_pmf_roam(dev, apdev): 2922 """SAE/PMF roam""" 2923 check_sae_capab(dev[0]) 2924 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 2925 params['wpa_key_mgmt'] = 'SAE' 2926 params['ieee80211w'] = '2' 2927 params['skip_prune_assoc'] = '1' 2928 hapd = hostapd.add_ap(apdev[0], params) 2929 bssid = hapd.own_addr() 2930 2931 dev[0].flush_scan_cache() 2932 dev[0].set("sae_groups", "") 2933 id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 2934 ieee80211w="2", scan_freq="2412") 2935 dev[0].dump_monitor() 2936 hapd.wait_sta() 2937 2938 hapd2 = hostapd.add_ap(apdev[1], params) 2939 bssid2 = hapd2.own_addr() 2940 2941 dev[0].scan_for_bss(bssid2, freq=2412) 2942 dev[0].roam(bssid2) 2943 dev[0].dump_monitor() 2944 hapd2.wait_sta() 2945 2946 dev[0].roam(bssid) 2947 dev[0].dump_monitor() 2948 2949def test_sae_ocv_pmk(dev, apdev): 2950 """SAE with OCV and fetching PMK (successful 4-way handshake)""" 2951 check_sae_capab(dev[0]) 2952 params = hostapd.wpa2_params(ssid="test-sae", 2953 passphrase="12345678") 2954 params['wpa_key_mgmt'] = 'SAE' 2955 params['ieee80211w'] = '2' 2956 params['ocv'] = '1' 2957 hapd = hostapd.add_ap(apdev[0], params) 2958 2959 dev[0].set("sae_groups", "") 2960 id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", ocv="1", 2961 ieee80211w="2", scan_freq="2412") 2962 hapd.wait_sta() 2963 2964 pmk_h = hapd.request("GET_PMK " + dev[0].own_addr()) 2965 if "FAIL" in pmk_h or len(pmk_h) == 0: 2966 raise Exception("Failed to fetch PMK from hostapd during a successful authentication") 2967 2968 pmk_w = dev[0].get_pmk(id) 2969 if pmk_h != pmk_w: 2970 raise Exception("Fetched PMK does not match: hostapd %s, wpa_supplicant %s" % (pmk_h, pmk_w)) 2971 2972def test_sae_ocv_pmk_failure(dev, apdev): 2973 """SAE with OCV and fetching PMK (failed 4-way handshake)""" 2974 check_sae_capab(dev[0]) 2975 params = hostapd.wpa2_params(ssid="test-sae", 2976 passphrase="12345678") 2977 params['wpa_key_mgmt'] = 'SAE' 2978 params['ieee80211w'] = '2' 2979 params['ocv'] = '1' 2980 hapd = hostapd.add_ap(apdev[0], params) 2981 2982 dev[0].set("sae_groups", "") 2983 dev[0].set("oci_freq_override_eapol", "2462") 2984 id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", ocv="1", 2985 ieee80211w="2", scan_freq="2412", wait_connect=False) 2986 ev = dev[0].wait_event(["CTRL-EVENT-CONNECTED", 2987 "CTRL-EVENT-DISCONNECTED"], timeout=15) 2988 if ev is None: 2989 raise Exception("No connection result reported") 2990 if "CTRL-EVENT-CONNECTED" in ev: 2991 raise Exception("Unexpected connection") 2992 2993 pmk_h = hapd.request("GET_PMK " + dev[0].own_addr()) 2994 if "FAIL" in pmk_h or len(pmk_h) == 0: 2995 raise Exception("Failed to fetch PMK from hostapd during a successful authentication") 2996 2997 res = dev[0].request("PMKSA_GET %d" % id) 2998 if not res.startswith(hapd.own_addr()): 2999 raise Exception("PMKSA from wpa_supplicant does not have matching BSSID") 3000 pmk_w = res.split(' ')[2] 3001 if pmk_h != pmk_w: 3002 raise Exception("Fetched PMK does not match: hostapd %s, wpa_supplicant %s" % (pmk_h, pmk_w)) 3003 3004 dev[0].request("DISCONNECT") 3005 time.sleep(0.1) 3006 pmk_h2 = hapd.request("GET_PMK " + dev[0].own_addr()) 3007 res = dev[0].request("PMKSA_GET %d" % id) 3008 pmk_w2 = res.split(' ')[2] 3009 if pmk_h2 != pmk_h: 3010 raise Exception("hostapd did not report correct PMK after disconnection") 3011 if pmk_w2 != pmk_w: 3012 raise Exception("wpa_supplicant did not report correct PMK after disconnection") 3013 3014def test_sae_reject(dev, apdev): 3015 """SAE and AP rejecting connection""" 3016 check_sae_capab(dev[0]) 3017 params = hostapd.wpa2_params(ssid="test-sae", 3018 passphrase="12345678") 3019 params['wpa_key_mgmt'] = 'SAE' 3020 params['max_num_sta'] = '0' 3021 hapd = hostapd.add_ap(apdev[0], params) 3022 dev[0].set("sae_groups", "") 3023 id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 3024 scan_freq="2412", wait_connect=False) 3025 if not dev[0].wait_event(["CTRL-EVENT-AUTH-REJECT"], timeout=10): 3026 raise Exception("Authentication rejection not reported") 3027 dev[0].request("REMOVE_NETWORK all") 3028 dev[0].dump_monitor() 3029 3030def test_sae_ext_key_19(dev, apdev): 3031 """SAE with extended key AKM (group 19)""" 3032 run_sae_ext_key(dev, apdev, 19) 3033 3034def test_sae_ext_key_20(dev, apdev): 3035 """SAE with extended key AKM (group 20)""" 3036 run_sae_ext_key(dev, apdev, 20) 3037 3038def test_sae_ext_key_21(dev, apdev): 3039 """SAE with extended key AKM (group 21)""" 3040 run_sae_ext_key(dev, apdev, 21) 3041 3042def test_sae_ext_key_19_gcmp256(dev, apdev): 3043 """SAE with extended key AKM (group 19) with GCMP256 pairwise cipher""" 3044 run_sae_ext_key(dev, apdev, 19, cipher="GCMP-256") 3045 3046def test_sae_ext_key_20_gcmp256(dev, apdev): 3047 """SAE with extended key AKM (group 20) with GCMP-256 pairwise cipher""" 3048 run_sae_ext_key(dev, apdev, 20, cipher="GCMP-256") 3049 3050def test_sae_ext_key_21_gcmp256(dev, apdev): 3051 """SAE with extended key AKM (group 21) with GCMP-256 pairwise cipher""" 3052 run_sae_ext_key(dev, apdev, 21, cipher="GCMP-256") 3053 3054def test_sae_ext_key_21_gcmp256_gcmp256(dev, apdev): 3055 """SAE with extended key AKM (group 21) with GCMP-256 pairwise and group cipher""" 3056 run_sae_ext_key(dev, apdev, 21, cipher="GCMP-256", group_cipher="GCMP-256") 3057 3058def run_sae_ext_key(dev, apdev, group, cipher="CCMP", group_cipher="CCMP"): 3059 check_sae_capab(dev[0]) 3060 3061 if cipher not in dev[0].get_capability("pairwise"): 3062 raise HwsimSkip("Cipher %s not supported" % cipher) 3063 if group_cipher not in dev[0].get_capability("group"): 3064 raise HwsimSkip("Cipher %s not supported" % group_cipher) 3065 3066 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 3067 params['wpa_key_mgmt'] = 'SAE-EXT-KEY' 3068 params['sae_groups'] = str(group) 3069 params['ieee80211w'] = '2' 3070 params['rsn_pairwise'] = cipher 3071 params['group_cipher'] = group_cipher 3072 3073 hapd = hostapd.add_ap(apdev[0], params) 3074 key_mgmt = hapd.get_config()['key_mgmt'] 3075 if key_mgmt.split(' ')[0] != "SAE-EXT-KEY": 3076 raise Exception("Unexpected GET_CONFIG(key_mgmt): " + key_mgmt) 3077 3078 dev[0].flush_scan_cache() 3079 dev[0].set("sae_groups", str(group)) 3080 id = dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE-EXT-KEY", 3081 pairwise=cipher, group=group_cipher, 3082 ieee80211w="2", scan_freq="2412") 3083 hapd.wait_sta() 3084 if dev[0].get_status_field('sae_group') != str(group): 3085 raise Exception("Expected SAE group not used") 3086 bss = dev[0].get_bss(apdev[0]['bssid']) 3087 if 'flags' not in bss: 3088 raise Exception("Could not get BSS flags from BSS table") 3089 if "[WPA2-SAE-EXT-KEY-" + cipher + "]" not in bss['flags']: 3090 raise Exception("Unexpected BSS flags: " + bss['flags']) 3091 3092 res = hapd.request("STA-FIRST") 3093 if ("sae_group=%d" % group) not in res.splitlines(): 3094 raise Exception("hostapd STA output did not specify SAE group") 3095 3096 sta0 = hapd.get_sta(dev[0].own_addr()) 3097 if sta0['wpa'] != '2' or sta0['AKMSuiteSelector'] != '00-0f-ac-24': 3098 raise Exception("SAE STA(0) AKM suite selector reported incorrectly") 3099 3100 pmk_h = hapd.request("GET_PMK " + dev[0].own_addr()) 3101 pmk_w = dev[0].get_pmk(id) 3102 if pmk_h != pmk_w: 3103 raise Exception("Fetched PMK does not match: hostapd %s, wpa_supplicant %s" % (pmk_h, pmk_w)) 3104 if group == 19: 3105 pmk_len = 32 3106 elif group == 20: 3107 pmk_len = 48 3108 elif group == 21: 3109 pmk_len = 64 3110 if len(pmk_h) != 2 * pmk_len: 3111 raise Exception("Unexpected SAE PMK length: %d" % (len(pmk_h) / 2)) 3112 dev[0].request("DISCONNECT") 3113 dev[0].wait_disconnected() 3114 pmk_h2 = hapd.request("GET_PMK " + dev[0].own_addr()) 3115 if pmk_h != pmk_h2: 3116 raise Exception("Fetched PMK from PMKSA cache does not match: %s, %s" % (pmk_h, pmk_h2)) 3117 3118 dev[0].request("RECONNECT") 3119 dev[0].wait_connected(timeout=15, error="Reconnect timed out") 3120 val = dev[0].get_status_field('sae_group') 3121 if val is not None: 3122 raise Exception("SAE group claimed to have been used: " + val) 3123 sta0 = hapd.get_sta(dev[0].own_addr()) 3124 if sta0['wpa'] != '2' or sta0['AKMSuiteSelector'] != '00-0f-ac-24': 3125 raise Exception("SAE STA(0) AKM suite selector reported incorrectly after PMKSA caching") 3126 3127def test_sae_akms(dev, apdev): 3128 """SAE with both AKMs)""" 3129 check_sae_capab(dev[0]) 3130 check_sae_capab(dev[1]) 3131 check_sae_capab(dev[2]) 3132 params = hostapd.wpa2_params(ssid="test-sae", passphrase="12345678") 3133 params['wpa_key_mgmt'] = 'SAE SAE-EXT-KEY' 3134 params['sae_groups'] = "19 20" 3135 params['ieee80211w'] = '2' 3136 hapd = hostapd.add_ap(apdev[0], params) 3137 3138 dev[0].set("sae_groups", "20") 3139 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE-EXT-KEY", 3140 ieee80211w="2", scan_freq="2412") 3141 3142 dev[1].set("sae_groups", "20") 3143 dev[1].connect("test-sae", psk="12345678", key_mgmt="SAE", 3144 ieee80211w="2", scan_freq="2412") 3145 3146 dev[2].set("sae_groups", "19") 3147 dev[2].connect("test-sae", psk="12345678", key_mgmt="SAE", 3148 ieee80211w="2", scan_freq="2412") 3149 3150def test_sae_ext_key_h2e_rejected_group(dev, apdev): 3151 """SAE-EXT-KEY, H2E, and rejected groups indication""" 3152 run_sae_ext_key_h2e_rejected_group(dev, apdev, "19", "20 19", "20") 3153 3154def test_sae_ext_key_h2e_rejected_group2(dev, apdev): 3155 """SAE-EXT-KEY, H2E, and rejected groups indication (2)""" 3156 run_sae_ext_key_h2e_rejected_group(dev, apdev, "20", "19 20", "19") 3157 3158def run_sae_ext_key_h2e_rejected_group(dev, apdev, ap_groups, sta_groups, 3159 rejected_groups): 3160 check_sae_capab(dev[0]) 3161 params = hostapd.wpa2_params(ssid="sae-pwe", passphrase="12345678") 3162 params['wpa_key_mgmt'] = 'SAE-EXT-KEY' 3163 params['sae_groups'] = ap_groups 3164 params['sae_pwe'] = "1" 3165 params['ieee80211w'] = "2" 3166 hapd = hostapd.add_ap(apdev[0], params) 3167 try: 3168 dev[0].set("sae_groups", sta_groups) 3169 dev[0].set("sae_pwe", "1") 3170 dev[0].connect("sae-pwe", psk="12345678", key_mgmt="SAE-EXT-KEY", 3171 ieee80211w="2", scan_freq="2412") 3172 addr = dev[0].own_addr() 3173 hapd.wait_sta(addr) 3174 sta = hapd.get_sta(addr) 3175 if 'sae_rejected_groups' not in sta: 3176 raise Exception("No sae_rejected_groups") 3177 val = sta['sae_rejected_groups'] 3178 if val != rejected_groups: 3179 raise Exception("Unexpected sae_rejected_groups value: " + val) 3180 finally: 3181 dev[0].set("sae_groups", "") 3182 dev[0].set("sae_pwe", "0") 3183 3184def test_sae_pref_ap_wrong_password(dev, apdev): 3185 """SAE and preferred AP using wrong password""" 3186 check_sae_capab(dev[0]) 3187 3188 params = hostapd.wpa3_params(ssid="test-sae", password="correct") 3189 params['ieee80211n'] = '0' 3190 hapd = hostapd.add_ap(apdev[0], params) 3191 3192 params = hostapd.wpa3_params(ssid="test-sae", password="wrong") 3193 hapd2 = hostapd.add_ap(apdev[1], params) 3194 3195 dev[0].scan_for_bss(hapd.own_addr(), freq=2412) 3196 dev[0].scan_for_bss(hapd2.own_addr(), freq=2412) 3197 3198 dev[0].set("sae_groups", "") 3199 dev[0].connect("test-sae", sae_password="correct", key_mgmt="SAE", 3200 ieee80211w="2", scan_freq="2412") 3201 3202def test_sae_pref_ap_wrong_password2(dev, apdev): 3203 """SAE and preferred AP using wrong password (2)""" 3204 check_sae_capab(dev[0]) 3205 3206 params = hostapd.wpa3_params(ssid="test-sae", password="wrong") 3207 hapd2 = hostapd.add_ap(apdev[1], params) 3208 3209 dev[0].scan_for_bss(hapd2.own_addr(), freq=2412) 3210 3211 dev[0].set("sae_groups", "") 3212 dev[0].connect("test-sae", sae_password="correct", key_mgmt="SAE", 3213 ieee80211w="2", scan_freq="2412", wait_connect=False) 3214 ev = dev[0].wait_event(["CTRL-EVENT-SSID-TEMP-DISABLED"], timeout=30) 3215 if ev is None: 3216 raise Exception("Temporary disabled of SSID not seen") 3217 3218 params = hostapd.wpa3_params(ssid="test-sae", password="correct") 3219 params['ieee80211n'] = '0' 3220 hapd = hostapd.add_ap(apdev[0], params) 3221 3222 dev[0].wait_connected(timeout=40) 3223 3224def test_sae_password_file(dev, apdev): 3225 """SAE and sae_password_file in hostapd configuration""" 3226 check_sae_capab(dev[0]) 3227 check_sae_capab(dev[1]) 3228 check_sae_capab(dev[2]) 3229 fd, fn = tempfile.mkstemp() 3230 try: 3231 f = os.fdopen(fd, 'w') 3232 f.write("pw1|id=id1\n") 3233 f.write("pw2|id=id2\n") 3234 f.write("pw3|id=id3\n") 3235 f.close() 3236 3237 params = hostapd.wpa2_params(ssid="test-sae", wpa_key_mgmt="SAE") 3238 params['sae_password_file'] = fn 3239 hapd = hostapd.add_ap(apdev[0], params) 3240 3241 dev[0].set("sae_groups", "") 3242 dev[0].connect("test-sae", sae_password="pw1", sae_password_id="id1", 3243 key_mgmt="SAE", scan_freq="2412") 3244 3245 dev[1].set("sae_groups", "") 3246 dev[1].connect("test-sae", sae_password="pw2", sae_password_id="id2", 3247 key_mgmt="SAE", scan_freq="2412") 3248 3249 dev[2].set("sae_groups", "") 3250 dev[2].connect("test-sae", sae_password="pw3", sae_password_id="id3", 3251 key_mgmt="SAE", scan_freq="2412") 3252 finally: 3253 os.unlink(fn) 3254 3255def test_sae_ssid_protection(dev, apdev): 3256 """SAE with SSID protection in 4-way handshake""" 3257 check_sae_capab(dev[0]) 3258 params = hostapd.wpa2_params(ssid="test-sae", 3259 passphrase="12345678") 3260 params['wpa_key_mgmt'] = 'SAE' 3261 params['ssid_protection'] = '1' 3262 hapd = hostapd.add_ap(apdev[0], params) 3263 3264 dev[0].set("sae_groups", "") 3265 dev[0].connect("test-sae", psk="12345678", key_mgmt="SAE", 3266 ssid_protection="1", 3267 scan_freq="2412", wait_connect=False) 3268 ev = dev[0].wait_event(["RSN: SSID matched expected value"], timeout=10) 3269 if ev is None: 3270 raise Exception("SSID protection event not seen") 3271 dev[0].wait_connected() 3272 hapd.wait_sta() 3273 3274 if dev[0].get_status_field("ssid_verified") != "1": 3275 raise Exception("ssid_verified=1 not in STATUS") 3276