1# Test cases for MACsec/MKA 2# Copyright (c) 2018-2019, 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 7import logging 8logger = logging.getLogger() 9import binascii 10import os 11import signal 12import subprocess 13import time 14 15import hostapd 16from wpasupplicant import WpaSupplicant 17import hwsim_utils 18from utils import HwsimSkip, alloc_fail, fail_test, wait_fail_trigger 19from wlantest import WlantestCapture 20 21def cleanup_macsec(): 22 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5', monitor=False) 23 wpas.interface_remove("veth0") 24 wpas.interface_remove("veth1") 25 del wpas 26 subprocess.call(["ip", "link", "del", "veth0"], 27 stderr=open('/dev/null', 'w')) 28 29def test_macsec_psk(dev, apdev, params): 30 """MACsec PSK""" 31 try: 32 run_macsec_psk(dev, apdev, params, "macsec_psk") 33 finally: 34 cleanup_macsec() 35 36def test_macsec_psk_mka_life_time(dev, apdev, params): 37 """MACsec PSK - MKA life time""" 38 try: 39 run_macsec_psk(dev, apdev, params, "macsec_psk_mka_life_time") 40 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5', monitor=False) 41 wpas.interface_remove("veth1") 42 del wpas 43 # Wait for live peer to be removed on veth0 44 time.sleep(6.1) 45 finally: 46 cleanup_macsec() 47 48def test_macsec_psk_integ_only(dev, apdev, params): 49 """MACsec PSK (integrity only)""" 50 try: 51 run_macsec_psk(dev, apdev, params, "macsec_psk_integ_only", 52 integ_only=True) 53 finally: 54 cleanup_macsec() 55 56def test_macsec_psk_port(dev, apdev, params): 57 """MACsec PSK (port)""" 58 try: 59 run_macsec_psk(dev, apdev, params, "macsec_psk_port", 60 port0=65534, port1=65534) 61 finally: 62 cleanup_macsec() 63 64def test_macsec_psk_different_ports(dev, apdev, params): 65 """MACsec PSK (different ports)""" 66 try: 67 run_macsec_psk(dev, apdev, params, "macsec_psk_different_ports", 68 port0=2, port1=3) 69 finally: 70 cleanup_macsec() 71 72def test_macsec_psk_shorter_ckn(dev, apdev, params): 73 """MACsec PSK (shorter CKN)""" 74 try: 75 ckn = "11223344" 76 run_macsec_psk(dev, apdev, params, "macsec_psk_shorter_ckn", 77 ckn0=ckn, ckn1=ckn) 78 finally: 79 cleanup_macsec() 80 81def test_macsec_psk_shorter_ckn2(dev, apdev, params): 82 """MACsec PSK (shorter CKN, unaligned)""" 83 try: 84 ckn = "112233" 85 run_macsec_psk(dev, apdev, params, "macsec_psk_shorter_ckn2", 86 ckn0=ckn, ckn1=ckn) 87 finally: 88 cleanup_macsec() 89 90def test_macsec_psk_ckn_mismatch(dev, apdev, params): 91 """MACsec PSK (CKN mismatch)""" 92 try: 93 ckn0 = "11223344" 94 ckn1 = "1122334455667788" 95 run_macsec_psk(dev, apdev, params, "macsec_psk_ckn_mismatch", 96 ckn0=ckn0, ckn1=ckn1, expect_failure=True) 97 finally: 98 cleanup_macsec() 99 100def test_macsec_psk_cak_mismatch(dev, apdev, params): 101 """MACsec PSK (CAK mismatch)""" 102 try: 103 cak0 = 16*"11" 104 cak1 = 16*"22" 105 run_macsec_psk(dev, apdev, params, "macsec_psk_cak_mismatch", 106 cak0=cak0, cak1=cak1, expect_failure=True) 107 finally: 108 cleanup_macsec() 109 110def test_macsec_psk_256(dev, apdev, params): 111 """MACsec PSK with 256-bit keys""" 112 try: 113 cak = "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" 114 run_macsec_psk(dev, apdev, params, "macsec_psk_256", cak0=cak, cak1=cak) 115 finally: 116 cleanup_macsec() 117 118def test_macsec_gcm_aes_256(dev, apdev, params): 119 """MACsec PSK with GCM-AES-256""" 120 try: 121 cak = "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" 122 run_macsec_psk(dev, apdev, params, "macsec_gcm_aes_256", 123 cak0=cak, cak1=cak, csindex=1) 124 finally: 125 cleanup_macsec() 126 127def set_mka_psk_config(dev, mka_priority=None, integ_only=False, port=None, 128 ckn=None, cak=None, csindex=None): 129 dev.set("eapol_version", "3") 130 dev.set("ap_scan", "0") 131 dev.set("fast_reauth", "1") 132 133 id = dev.add_network() 134 dev.set_network(id, "key_mgmt", "NONE") 135 if cak is None: 136 cak = "000102030405060708090a0b0c0d0e0f" 137 dev.set_network(id, "mka_cak", cak) 138 if ckn is None: 139 ckn = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" 140 dev.set_network(id, "mka_ckn", ckn) 141 dev.set_network(id, "eapol_flags", "0") 142 dev.set_network(id, "macsec_policy", "1") 143 if integ_only: 144 dev.set_network(id, "macsec_integ_only", "1") 145 if mka_priority is not None: 146 dev.set_network(id, "mka_priority", str(mka_priority)) 147 if port is not None: 148 dev.set_network(id, "macsec_port", str(port)) 149 if csindex is not None: 150 dev.set_network(id, "macsec_csindex", str(csindex)) 151 152 dev.select_network(id) 153 154def set_mka_eap_config(dev, mka_priority=None, integ_only=False, port=None, 155 eap_psk=False): 156 dev.set("eapol_version", "3") 157 dev.set("ap_scan", "0") 158 dev.set("fast_reauth", "1") 159 160 id = dev.add_network() 161 dev.set_network(id, "key_mgmt", "NONE") 162 dev.set_network(id, "eapol_flags", "0") 163 dev.set_network(id, "macsec_policy", "1") 164 if integ_only: 165 dev.set_network(id, "macsec_integ_only", "1") 166 if mka_priority is not None: 167 dev.set_network(id, "mka_priority", str(mka_priority)) 168 if port is not None: 169 dev.set_network(id, "macsec_port", str(port)) 170 171 dev.set_network(id, "key_mgmt", "IEEE8021X") 172 if eap_psk: 173 dev.set_network(id, "eap", "PSK") 174 dev.set_network_quoted(id, "identity", "psk.user@example.com") 175 dev.set_network(id, "password", "0123456789abcdef0123456789abcdef") 176 else: 177 dev.set_network(id, "eap", "TTLS") 178 dev.set_network_quoted(id, "ca_cert", "auth_serv/ca.pem") 179 dev.set_network_quoted(id, "phase2", "auth=MSCHAPV2") 180 dev.set_network_quoted(id, "anonymous_identity", "ttls") 181 dev.set_network_quoted(id, "identity", "DOMAIN\mschapv2 user") 182 dev.set_network_quoted(id, "password", "password") 183 184 dev.select_network(id) 185 186def log_ip_macsec(): 187 cmd = subprocess.Popen(["ip", "macsec", "show"], 188 stdout=subprocess.PIPE, 189 stderr=open('/dev/null', 'w')) 190 res = cmd.stdout.read().decode() 191 cmd.stdout.close() 192 logger.info("ip macsec:\n" + res) 193 194def log_ip_link(): 195 cmd = subprocess.Popen(["ip", "link", "show"], 196 stdout=subprocess.PIPE) 197 res = cmd.stdout.read().decode() 198 cmd.stdout.close() 199 logger.info("ip link:\n" + res) 200 201def add_veth(): 202 try: 203 subprocess.check_call(["ip", "link", "add", "veth0", "type", "veth", 204 "peer", "name", "veth1"]) 205 except subprocess.CalledProcessError: 206 raise HwsimSkip("veth not supported (kernel CONFIG_VETH)") 207 208def add_wpas_interfaces(count=2): 209 wpa = [] 210 try: 211 for i in range(count): 212 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5') 213 wpas.interface_add("veth%d" % i, driver="macsec_linux") 214 wpa.append(wpas) 215 except Exception as e: 216 if "Failed to add a dynamic wpa_supplicant interface" in str(e): 217 raise HwsimSkip("macsec supported (wpa_supplicant CONFIG_MACSEC, CONFIG_DRIVER_MACSEC_LINUX; kernel CONFIG_MACSEC)") 218 raise 219 220 return wpa 221 222def lower_addr(addr1, addr2): 223 a1 = addr1.split(':') 224 a2 = addr2.split(':') 225 for i in range(6): 226 if binascii.unhexlify(a1[i]) < binascii.unhexlify(a2[i]): 227 return True 228 if binascii.unhexlify(a1[i]) > binascii.unhexlify(a2[i]): 229 return False 230 return False 231 232def wait_mka_done(wpa, expect_failure=False, hostapd=False): 233 max_iter = 14 if expect_failure else 40 234 for i in range(max_iter): 235 done = True 236 for w in wpa: 237 secured = w.get_status_field("Secured") 238 live_peers = w.get_status_field("live_peers") 239 peers = int(live_peers) if live_peers else 0 240 if expect_failure and (secured == "Yes" or peers > 0): 241 raise Exception("MKA completed unexpectedly") 242 expect_peers = len(wpa) - 1 243 if hostapd: 244 expect_peers += 1 245 if peers != expect_peers or secured != "Yes": 246 done = False 247 break 248 w.dump_monitor() 249 if done: 250 break 251 time.sleep(0.5) 252 253 if expect_failure: 254 return 255 256 if not done: 257 raise Exception("MKA not completed successfully") 258 259 if hostapd: 260 # TODO: check that hostapd is the key server 261 return 262 263 key_server = None 264 ks_prio = 999 265 for w in wpa: 266 logger.info("%s STATUS:\n%s" % (w.ifname, w.request("STATUS"))) 267 addr = w.get_status_field("address") 268 prio = int(w.get_status_field("Actor Priority")) 269 if key_server is None or prio < ks_prio or \ 270 (prio == ks_prio and lower_addr(addr, ks_addr)): 271 key_server = w 272 ks_addr = addr 273 ks_prio = prio 274 275 logger.info("Expected key server: " + key_server.ifname) 276 if key_server.get_status_field("is_key_server") != "Yes": 277 raise Exception("Expected key server was not elected") 278 for w in wpa: 279 if w != key_server and w.get_status_field("is_key_server") == "Yes": 280 raise Exception("Unexpected key server") 281 282def run_macsec_psk(dev, apdev, params, prefix, integ_only=False, port0=None, 283 port1=None, ckn0=None, ckn1=None, cak0=None, cak1=None, 284 csindex=None, expect_failure=False): 285 add_veth() 286 287 cap_veth0 = os.path.join(params['logdir'], prefix + ".veth0.pcap") 288 cap_veth1 = os.path.join(params['logdir'], prefix + ".veth1.pcap") 289 cap_macsec0 = os.path.join(params['logdir'], prefix + ".macsec0.pcap") 290 cap_macsec1 = os.path.join(params['logdir'], prefix + ".macsec1.pcap") 291 292 for i in range(2): 293 subprocess.check_call(["ip", "link", "set", "dev", "veth%d" % i, "up"]) 294 295 cmd = {} 296 cmd[0] = WlantestCapture('veth0', cap_veth0) 297 cmd[1] = WlantestCapture('veth1', cap_veth1) 298 299 wpa = add_wpas_interfaces() 300 wpas0 = wpa[0] 301 wpas1 = wpa[1] 302 303 set_mka_psk_config(wpas0, integ_only=integ_only, port=port0, ckn=ckn0, 304 cak=cak0, csindex=csindex) 305 set_mka_psk_config(wpas1, mka_priority=100, integ_only=integ_only, 306 port=port1, ckn=ckn1, cak=cak1, csindex=csindex) 307 308 log_ip_macsec() 309 log_ip_link() 310 311 logger.info("wpas0 STATUS:\n" + wpas0.request("STATUS")) 312 logger.info("wpas1 STATUS:\n" + wpas1.request("STATUS")) 313 logger.info("wpas0 STATUS-DRIVER:\n" + wpas0.request("STATUS-DRIVER")) 314 logger.info("wpas1 STATUS-DRIVER:\n" + wpas1.request("STATUS-DRIVER")) 315 macsec_ifname0 = wpas0.get_driver_status_field("parent_ifname") 316 macsec_ifname1 = wpas1.get_driver_status_field("parent_ifname") 317 318 wait_mka_done(wpa, expect_failure=expect_failure) 319 320 if expect_failure: 321 for i in range(len(cmd)): 322 cmd[i].close() 323 return 324 325 cmd[2] = WlantestCapture(macsec_ifname0, cap_macsec0) 326 cmd[3] = WlantestCapture(macsec_ifname1, cap_macsec1) 327 time.sleep(0.5) 328 329 mi0 = wpas0.get_status_field("mi") 330 mi1 = wpas1.get_status_field("mi") 331 sci0 = wpas0.get_status_field("actor_sci") 332 sci1 = wpas1.get_status_field("actor_sci") 333 logger.info("wpas0 MIB:\n" + wpas0.request("MIB")) 334 logger.info("wpas1 MIB:\n" + wpas1.request("MIB")) 335 mib0 = wpas0.get_mib() 336 mib1 = wpas1.get_mib() 337 338 if mib0['ieee8021XKayMkaPeerListMI'] != mi1: 339 raise Exception("Unexpected ieee8021XKayMkaPeerListMI value (0)") 340 if mib0['ieee8021XKayMkaPeerListType'] != "1": 341 raise Exception("Unexpected ieee8021XKayMkaPeerListType value (0)") 342 if mib0['ieee8021XKayMkaPeerListSCI'] != sci1: 343 raise Exception("Unexpected ieee8021XKayMkaPeerListSCI value (0)") 344 if mib1['ieee8021XKayMkaPeerListMI'] != mi0: 345 raise Exception("Unexpected ieee8021XKayMkaPeerListMI value (1)") 346 if mib1['ieee8021XKayMkaPeerListType'] != "1": 347 raise Exception("Unexpected ieee8021XKayMkaPeerListType value (1)") 348 if mib1['ieee8021XKayMkaPeerListSCI'] != sci0: 349 raise Exception("Unexpected ieee8021XKayMkaPeerListSCI value (1)") 350 351 logger.info("wpas0 STATUS:\n" + wpas0.request("STATUS")) 352 logger.info("wpas1 STATUS:\n" + wpas1.request("STATUS")) 353 log_ip_macsec() 354 hwsim_utils.test_connectivity(wpas0, wpas1, 355 ifname1=macsec_ifname0, 356 ifname2=macsec_ifname1, 357 send_len=1400) 358 log_ip_macsec() 359 360 time.sleep(1) 361 for i in range(len(cmd)): 362 cmd[i].close() 363 364def cleanup_macsec_br(count): 365 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5', monitor=False) 366 for i in range(count): 367 wpas.interface_remove("veth%d" % i) 368 subprocess.call(["ip", "link", "del", "veth%d" % i], 369 stderr=open('/dev/null', 'w')) 370 del wpas 371 subprocess.call(["ip", "link", "set", "brveth", "down"]) 372 subprocess.call(["brctl", "delbr", "brveth"]) 373 374def test_macsec_psk_br2(dev, apdev): 375 """MACsec PSK (bridge; 2 devices)""" 376 try: 377 run_macsec_psk_br(dev, apdev, 2, [10, 20]) 378 finally: 379 cleanup_macsec_br(count=2) 380 381def test_macsec_psk_br2_same_prio(dev, apdev): 382 """MACsec PSK (bridge; 2 devices, same mka_priority)""" 383 try: 384 run_macsec_psk_br(dev, apdev, 2, [None, None]) 385 finally: 386 cleanup_macsec_br(count=2) 387 388def test_macsec_psk_br3(dev, apdev): 389 """MACsec PSK (bridge; 3 devices)""" 390 try: 391 run_macsec_psk_br(dev, apdev, 3, [10, 20, 30]) 392 finally: 393 cleanup_macsec_br(count=3) 394 395def test_macsec_psk_br3_same_prio(dev, apdev): 396 """MACsec PSK (bridge; 3 devices, same mka_priority)""" 397 try: 398 run_macsec_psk_br(dev, apdev, 3, [None, None, None]) 399 finally: 400 cleanup_macsec_br(count=3) 401 402def run_macsec_psk_br(dev, apdev, count, mka_priority): 403 subprocess.check_call(["brctl", "addbr", "brveth"]) 404 subprocess.call(["echo 8 > /sys/devices/virtual/net/brveth/bridge/group_fwd_mask"], 405 shell=True) 406 407 try: 408 for i in range(count): 409 subprocess.check_call(["ip", "link", "add", "veth%d" % i, 410 "type", "veth", 411 "peer", "name", "vethbr%d" % i]) 412 subprocess.check_call(["ip", "link", "set", "vethbr%d" % i, "up"]) 413 subprocess.check_call(["brctl", "addif", "brveth", 414 "vethbr%d" % i]) 415 except subprocess.CalledProcessError: 416 raise HwsimSkip("veth not supported (kernel CONFIG_VETH)") 417 418 subprocess.check_call(["ip", "link", "set", "brveth", "up"]) 419 420 log_ip_link() 421 422 wpa = add_wpas_interfaces(count=count) 423 for i in range(count): 424 set_mka_psk_config(wpa[i], mka_priority=mka_priority[i]) 425 wpa[i].dump_monitor() 426 wait_mka_done(wpa) 427 428 macsec_ifname = [] 429 for i in range(count): 430 macsec_ifname.append(wpa[i].get_driver_status_field("parent_ifname")) 431 432 timeout = 2 433 max_tries = 2 if count > 2 else 1 434 success_seen = False 435 failure_seen = False 436 for i in range(1, count): 437 try: 438 hwsim_utils.test_connectivity(wpa[0], wpa[i], 439 ifname1=macsec_ifname[0], 440 ifname2=macsec_ifname[i], 441 send_len=1400, 442 timeout=timeout, max_tries=max_tries) 443 success_seen = True 444 logger.info("Traffic test %d<->%d success" % (0, i)) 445 except: 446 failure_seen = True 447 logger.info("Traffic test %d<->%d failure" % (0, i)) 448 for i in range(2, count): 449 try: 450 hwsim_utils.test_connectivity(wpa[1], wpa[i], 451 ifname1=macsec_ifname[1], 452 ifname2=macsec_ifname[i], 453 send_len=1400, 454 timeout=timeout, max_tries=max_tries) 455 success_seen = True 456 logger.info("Traffic test %d<->%d success" % (1, i)) 457 except: 458 failure_seen = True 459 logger.info("Traffic test %d<->%d failure" % (1, i)) 460 461 if not success_seen: 462 raise Exception("None of the data traffic tests succeeded") 463 464 # Something seems to be failing with three device tests semi-regularly, so 465 # do not report this as a failed test case until the real reason behind 466 # those failures have been determined. 467 if failure_seen: 468 if count < 3: 469 raise Exception("Data traffic test failed") 470 else: 471 logger.info("Data traffic test failed - ignore for now for >= 3 device cases") 472 473 for i in range(count): 474 wpa[i].close_monitor() 475 for i in range(count): 476 wpa[0].close_control() 477 del wpa[0] 478 479def test_macsec_psk_ns(dev, apdev, params): 480 """MACsec PSK (netns)""" 481 try: 482 run_macsec_psk_ns(dev, apdev, params) 483 finally: 484 prefix = "macsec_psk_ns" 485 pidfile = os.path.join(params['logdir'], prefix + ".pid") 486 for i in range(2): 487 was_running = False 488 if os.path.exists(pidfile + str(i)): 489 with open(pidfile + str(i), 'r') as f: 490 pid = int(f.read().strip()) 491 logger.info("wpa_supplicant for wpas%d still running with pid %d - kill it" % (i, pid)) 492 was_running = True 493 os.kill(pid, signal.SIGTERM) 494 if was_running: 495 time.sleep(1) 496 497 subprocess.call(["ip", "netns", "exec", "ns0", 498 "ip", "link", "del", "veth0"], 499 stderr=open('/dev/null', 'w')) 500 subprocess.call(["ip", "link", "del", "veth0"], 501 stderr=open('/dev/null', 'w')) 502 log_ip_link_ns() 503 subprocess.call(["ip", "netns", "delete", "ns0"], 504 stderr=open('/dev/null', 'w')) 505 subprocess.call(["ip", "netns", "delete", "ns1"], 506 stderr=open('/dev/null', 'w')) 507 508def log_ip_macsec_ns(): 509 cmd = subprocess.Popen(["ip", "macsec", "show"], 510 stdout=subprocess.PIPE, 511 stderr=open('/dev/null', 'w')) 512 res = cmd.stdout.read().decode() 513 cmd.stdout.close() 514 logger.info("ip macsec show:\n" + res) 515 516 cmd = subprocess.Popen(["ip", "netns", "exec", "ns0", 517 "ip", "macsec", "show"], 518 stdout=subprocess.PIPE, 519 stderr=open('/dev/null', 'w')) 520 res = cmd.stdout.read().decode() 521 cmd.stdout.close() 522 logger.info("ip macsec show (ns0):\n" + res) 523 524 cmd = subprocess.Popen(["ip", "netns", "exec", "ns1", 525 "ip", "macsec", "show"], 526 stdout=subprocess.PIPE, 527 stderr=open('/dev/null', 'w')) 528 res = cmd.stdout.read().decode() 529 cmd.stdout.close() 530 logger.info("ip macsec show (ns1):\n" + res) 531 532def log_ip_link_ns(): 533 cmd = subprocess.Popen(["ip", "link", "show"], 534 stdout=subprocess.PIPE) 535 res = cmd.stdout.read().decode() 536 cmd.stdout.close() 537 logger.info("ip link:\n" + res) 538 539 cmd = subprocess.Popen(["ip", "netns", "exec", "ns0", 540 "ip", "link", "show"], 541 stdout=subprocess.PIPE, 542 stderr=open('/dev/null', 'w')) 543 res = cmd.stdout.read().decode() 544 cmd.stdout.close() 545 logger.info("ip link show (ns0):\n" + res) 546 547 cmd = subprocess.Popen(["ip", "netns", "exec", "ns1", 548 "ip", "link", "show"], 549 stdout=subprocess.PIPE, 550 stderr=open('/dev/null', 'w')) 551 res = cmd.stdout.read().decode() 552 cmd.stdout.close() 553 logger.info("ip link show (ns1):\n" + res) 554 555def write_conf(conffile, mka_priority=None): 556 with open(conffile, 'w') as f: 557 f.write("ctrl_interface=DIR=/var/run/wpa_supplicant\n") 558 f.write("eapol_version=3\n") 559 f.write("ap_scan=0\n") 560 f.write("fast_reauth=1\n") 561 f.write("network={\n") 562 f.write(" key_mgmt=NONE\n") 563 f.write(" mka_cak=000102030405060708090a0b0c0d0e0f\n") 564 f.write(" mka_ckn=000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f\n") 565 if mka_priority is not None: 566 f.write(" mka_priority=%d\n" % mka_priority) 567 f.write(" eapol_flags=0\n") 568 f.write(" macsec_policy=1\n") 569 f.write("}\n") 570 571def run_macsec_psk_ns(dev, apdev, params): 572 try: 573 subprocess.check_call(["ip", "link", "add", "veth0", "type", "veth", 574 "peer", "name", "veth1"]) 575 except subprocess.CalledProcessError: 576 raise HwsimSkip("veth not supported (kernel CONFIG_VETH)") 577 578 prefix = "macsec_psk_ns" 579 conffile = os.path.join(params['logdir'], prefix + ".conf") 580 pidfile = os.path.join(params['logdir'], prefix + ".pid") 581 logfile0 = os.path.join(params['logdir'], prefix + ".veth0.log") 582 logfile1 = os.path.join(params['logdir'], prefix + ".veth1.log") 583 cap_veth0 = os.path.join(params['logdir'], prefix + ".veth0.pcap") 584 cap_veth1 = os.path.join(params['logdir'], prefix + ".veth1.pcap") 585 cap_macsec0 = os.path.join(params['logdir'], prefix + ".macsec0.pcap") 586 cap_macsec1 = os.path.join(params['logdir'], prefix + ".macsec1.pcap") 587 588 for i in range(2): 589 try: 590 subprocess.check_call(["ip", "netns", "add", "ns%d" % i]) 591 except subprocess.CalledProcessError: 592 raise HwsimSkip("network namespace not supported (kernel CONFIG_NAMESPACES, CONFIG_NET_NS)") 593 subprocess.check_call(["ip", "link", "set", "veth%d" % i, 594 "netns", "ns%d" %i]) 595 subprocess.check_call(["ip", "netns", "exec", "ns%d" % i, 596 "ip", "link", "set", "dev", "veth%d" % i, 597 "up"]) 598 599 cmd = {} 600 cmd[0] = WlantestCapture('veth0', cap_veth0, netns='ns0') 601 cmd[1] = WlantestCapture('veth1', cap_veth1, netns='ns1') 602 603 write_conf(conffile + '0') 604 write_conf(conffile + '1', mka_priority=100) 605 606 prg = os.path.join(params['logdir'], 607 'alt-wpa_supplicant/wpa_supplicant/wpa_supplicant') 608 if not os.path.exists(prg): 609 prg = '../../wpa_supplicant/wpa_supplicant' 610 611 arg = ["ip", "netns", "exec", "ns0", 612 prg, '-BdddtKW', '-P', pidfile + '0', '-f', logfile0, 613 '-g', '/tmp/wpas-veth0', 614 '-Dmacsec_linux', '-c', conffile + '0', '-i', "veth0"] 615 logger.info("Start wpa_supplicant: " + str(arg)) 616 try: 617 subprocess.check_call(arg) 618 except subprocess.CalledProcessError: 619 raise HwsimSkip("macsec supported (wpa_supplicant CONFIG_MACSEC, CONFIG_DRIVER_MACSEC_LINUX; kernel CONFIG_MACSEC)") 620 621 if os.path.exists("wpa_supplicant-macsec2"): 622 logger.info("Use alternative wpa_supplicant binary for one of the macsec devices") 623 prg = "wpa_supplicant-macsec2" 624 625 arg = ["ip", "netns", "exec", "ns1", 626 prg, '-BdddtKW', '-P', pidfile + '1', '-f', logfile1, 627 '-g', '/tmp/wpas-veth1', 628 '-Dmacsec_linux', '-c', conffile + '1', '-i', "veth1"] 629 logger.info("Start wpa_supplicant: " + str(arg)) 630 subprocess.check_call(arg) 631 632 wpas0 = WpaSupplicant('veth0', '/tmp/wpas-veth0') 633 wpas1 = WpaSupplicant('veth1', '/tmp/wpas-veth1') 634 635 log_ip_macsec_ns() 636 log_ip_link_ns() 637 638 logger.info("wpas0 STATUS:\n" + wpas0.request("STATUS")) 639 logger.info("wpas1 STATUS:\n" + wpas1.request("STATUS")) 640 logger.info("wpas0 STATUS-DRIVER:\n" + wpas0.request("STATUS-DRIVER")) 641 logger.info("wpas1 STATUS-DRIVER:\n" + wpas1.request("STATUS-DRIVER")) 642 643 for i in range(10): 644 macsec_ifname0 = wpas0.get_driver_status_field("parent_ifname") 645 macsec_ifname1 = wpas1.get_driver_status_field("parent_ifname") 646 if "Number of Keys" in wpas0.request("STATUS"): 647 key_tx0 = int(wpas0.get_status_field("Number of Keys Distributed")) 648 key_rx0 = int(wpas0.get_status_field("Number of Keys Received")) 649 else: 650 key_tx0 = 0 651 key_rx0 = 0 652 if "Number of Keys" in wpas1.request("STATUS"): 653 key_tx1 = int(wpas1.get_status_field("Number of Keys Distributed")) 654 key_rx1 = int(wpas1.get_status_field("Number of Keys Received")) 655 else: 656 key_tx1 = 0 657 key_rx1 = 0 658 if key_rx0 > 0 and key_tx1 > 0: 659 break 660 time.sleep(1) 661 662 cmd[2] = WlantestCapture(macsec_ifname0, cap_macsec0, netns='ns0') 663 cmd[3] = WlantestCapture(macsec_ifname1, cap_macsec1, netns='ns0') 664 time.sleep(0.5) 665 666 logger.info("wpas0 STATUS:\n" + wpas0.request("STATUS")) 667 logger.info("wpas1 STATUS:\n" + wpas1.request("STATUS")) 668 log_ip_macsec_ns() 669 hwsim_utils.test_connectivity(wpas0, wpas1, 670 ifname1=macsec_ifname0, 671 ifname2=macsec_ifname1, 672 send_len=1400) 673 log_ip_macsec_ns() 674 675 subprocess.check_call(['ip', 'netns', 'exec', 'ns0', 676 'ip', 'addr', 'add', '192.168.248.17/30', 677 'dev', macsec_ifname0]) 678 subprocess.check_call(['ip', 'netns', 'exec', 'ns1', 679 'ip', 'addr', 'add', '192.168.248.18/30', 680 'dev', macsec_ifname1]) 681 c = subprocess.Popen(['ip', 'netns', 'exec', 'ns0', 682 'ping', '-c', '2', '192.168.248.18'], 683 stdout=subprocess.PIPE) 684 res = c.stdout.read().decode() 685 c.stdout.close() 686 logger.info("ping:\n" + res) 687 if "2 packets transmitted, 2 received" not in res: 688 raise Exception("ping did not work") 689 690 wpas0.close_monitor() 691 wpas0.request("TERMINATE") 692 wpas0.close_control() 693 del wpas0 694 wpas1.close_monitor() 695 wpas1.request("TERMINATE") 696 wpas1.close_control() 697 del wpas1 698 699 time.sleep(1) 700 for i in range(len(cmd)): 701 cmd[i].close() 702 703def test_macsec_psk_fail_cp(dev, apdev): 704 """MACsec PSK local failures in CP state machine""" 705 try: 706 add_veth() 707 wpa = add_wpas_interfaces() 708 set_mka_psk_config(wpa[0]) 709 with alloc_fail(wpa[0], 1, "sm_CP_RECEIVE_Enter"): 710 set_mka_psk_config(wpa[1]) 711 wait_fail_trigger(wpa[0], "GET_ALLOC_FAIL", max_iter=100) 712 713 wait_mka_done(wpa) 714 finally: 715 cleanup_macsec() 716 717def test_macsec_psk_fail_cp2(dev, apdev): 718 """MACsec PSK local failures in CP state machine (2)""" 719 try: 720 add_veth() 721 wpa = add_wpas_interfaces() 722 set_mka_psk_config(wpa[0]) 723 with alloc_fail(wpa[1], 1, "ieee802_1x_cp_sm_init"): 724 set_mka_psk_config(wpa[1]) 725 wait_fail_trigger(wpa[1], "GET_ALLOC_FAIL", max_iter=100) 726 727 wait_mka_done(wpa) 728 finally: 729 cleanup_macsec() 730 731def cleanup_macsec_hostapd(): 732 wpas = WpaSupplicant(global_iface='/tmp/wpas-wlan5', monitor=False) 733 wpas.interface_remove("veth0") 734 del wpas 735 hapd = hostapd.HostapdGlobal() 736 hapd.remove('veth1') 737 subprocess.call(["ip", "link", "del", "veth0"], 738 stderr=open('/dev/null', 'w')) 739 log_ip_link() 740 741def test_macsec_hostapd_psk(dev, apdev, params): 742 """MACsec PSK with hostapd""" 743 try: 744 run_macsec_hostapd_psk(dev, apdev, params, "macsec_hostapd_psk") 745 finally: 746 cleanup_macsec_hostapd() 747 748def run_macsec_hostapd_psk(dev, apdev, params, prefix, integ_only=False, 749 port0=None, port1=None, ckn0=None, ckn1=None, 750 cak0=None, cak1=None, expect_failure=False): 751 add_veth() 752 753 cap_veth0 = os.path.join(params['logdir'], prefix + ".veth0.pcap") 754 cap_veth1 = os.path.join(params['logdir'], prefix + ".veth1.pcap") 755 cap_macsec0 = os.path.join(params['logdir'], prefix + ".macsec0.pcap") 756 cap_macsec1 = os.path.join(params['logdir'], prefix + ".macsec1.pcap") 757 758 for i in range(2): 759 subprocess.check_call(["ip", "link", "set", "dev", "veth%d" % i, "up"]) 760 761 cmd = {} 762 cmd[0] = WlantestCapture('veth0', cap_veth0) 763 cmd[1] = WlantestCapture('veth1', cap_veth1) 764 765 wpa = add_wpas_interfaces(count=1) 766 wpas0 = wpa[0] 767 768 set_mka_psk_config(wpas0, integ_only=integ_only, port=port0, ckn=ckn0, 769 cak=cak0, mka_priority=100) 770 771 if cak1 is None: 772 cak1 = "000102030405060708090a0b0c0d0e0f" 773 if ckn1 is None: 774 ckn1 = "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" 775 params = {"driver": "macsec_linux", 776 "interface": "veth1", 777 "eapol_version": "3", 778 "mka_cak": cak1, 779 "mka_ckn": ckn1, 780 "macsec_policy": "1", 781 "mka_priority": "1"} 782 if integ_only: 783 params["macsec_integ_only"] = "1" 784 if port1 is not None: 785 params["macsec_port"] = str(port1) 786 apdev = {'ifname': 'veth1'} 787 try: 788 hapd = hostapd.add_ap(apdev, params, driver="macsec_linux") 789 except: 790 raise HwsimSkip("No CONFIG_MACSEC=y in hostapd") 791 792 log_ip_macsec() 793 log_ip_link() 794 795 logger.info("wpas0 STATUS:\n" + wpas0.request("STATUS")) 796 logger.info("wpas0 STATUS-DRIVER:\n" + wpas0.request("STATUS-DRIVER")) 797 798 wait_mka_done(wpa, expect_failure=expect_failure, hostapd=True) 799 log_ip_link() 800 801 if expect_failure: 802 for i in range(len(cmd)): 803 cmd[i].close() 804 return 805 806 macsec_ifname0 = wpas0.get_driver_status_field("parent_ifname") 807 macsec_ifname1 = hapd.get_driver_status_field("parent_ifname") 808 809 cmd[2] = WlantestCapture(macsec_ifname0, cap_macsec0) 810 cmd[3] = WlantestCapture(macsec_ifname1, cap_macsec1) 811 time.sleep(0.5) 812 813 logger.info("wpas0 MIB:\n" + wpas0.request("MIB")) 814 logger.info("wpas0 STATUS:\n" + wpas0.request("STATUS")) 815 log_ip_macsec() 816 hwsim_utils.test_connectivity(wpas0, hapd, 817 ifname1=macsec_ifname0, 818 ifname2=macsec_ifname1, 819 send_len=1400) 820 log_ip_macsec() 821 822 time.sleep(1) 823 for i in range(len(cmd)): 824 cmd[i].close() 825 826def test_macsec_hostapd_eap(dev, apdev, params): 827 """MACsec EAP with hostapd""" 828 try: 829 run_macsec_hostapd_eap(dev, apdev, params, "macsec_hostapd_eap") 830 finally: 831 cleanup_macsec_hostapd() 832 833def test_macsec_hostapd_eap_psk(dev, apdev, params): 834 """MACsec EAP-PSK with hostapd""" 835 try: 836 run_macsec_hostapd_eap(dev, apdev, params, "macsec_hostapd_eap_psk", 837 eap_psk=True) 838 finally: 839 cleanup_macsec_hostapd() 840 841def run_macsec_hostapd_eap(dev, apdev, params, prefix, integ_only=False, 842 port0=None, port1=None, expect_failure=False, 843 eap_psk=False): 844 add_veth() 845 846 cap_veth0 = os.path.join(params['logdir'], prefix + ".veth0.pcap") 847 cap_veth1 = os.path.join(params['logdir'], prefix + ".veth1.pcap") 848 cap_macsec0 = os.path.join(params['logdir'], prefix + ".macsec0.pcap") 849 cap_macsec1 = os.path.join(params['logdir'], prefix + ".macsec1.pcap") 850 851 for i in range(2): 852 subprocess.check_call(["ip", "link", "set", "dev", "veth%d" % i, "up"]) 853 854 cmd = {} 855 cmd[0] = WlantestCapture('veth0', cap_veth0) 856 cmd[1] = WlantestCapture('veth1', cap_veth1) 857 858 wpa = add_wpas_interfaces(count=1) 859 wpas0 = wpa[0] 860 861 set_mka_eap_config(wpas0, integ_only=integ_only, port=port0, 862 mka_priority=100, eap_psk=eap_psk) 863 864 params = {"driver": "macsec_linux", 865 "interface": "veth1", 866 "eapol_version": "3", 867 "macsec_policy": "1", 868 "mka_priority": "1", 869 "ieee8021x": "1", 870 "auth_server_addr": "127.0.0.1", 871 "auth_server_port": "1812", 872 "auth_server_shared_secret": "radius", 873 "nas_identifier": "nas.w1.fi"} 874 if integ_only: 875 params["macsec_integ_only"] = "1" 876 if port1 is not None: 877 params["macsec_port"] = str(port1) 878 apdev = {'ifname': 'veth1'} 879 try: 880 hapd = hostapd.add_ap(apdev, params, driver="macsec_linux") 881 except: 882 raise HwsimSkip("No CONFIG_MACSEC=y in hostapd") 883 884 log_ip_macsec() 885 log_ip_link() 886 887 logger.info("wpas0 STATUS:\n" + wpas0.request("STATUS")) 888 logger.info("wpas0 STATUS-DRIVER:\n" + wpas0.request("STATUS-DRIVER")) 889 890 wait_mka_done(wpa, expect_failure=expect_failure, hostapd=True) 891 log_ip_link() 892 893 if expect_failure: 894 for i in range(len(cmd)): 895 cmd[i].close() 896 return 897 898 macsec_ifname0 = wpas0.get_driver_status_field("parent_ifname") 899 macsec_ifname1 = hapd.get_driver_status_field("parent_ifname") 900 901 cmd[2] = WlantestCapture(macsec_ifname0, cap_macsec0) 902 cmd[3] = WlantestCapture(macsec_ifname1, cap_macsec1) 903 time.sleep(0.5) 904 905 logger.info("wpas0 MIB:\n" + wpas0.request("MIB")) 906 logger.info("wpas0 STATUS:\n" + wpas0.request("STATUS")) 907 log_ip_macsec() 908 hwsim_utils.test_connectivity(wpas0, hapd, 909 ifname1=macsec_ifname0, 910 ifname2=macsec_ifname1, 911 send_len=1400) 912 log_ip_macsec() 913 914 time.sleep(1) 915 for i in range(len(cmd)): 916 cmd[i].close() 917