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