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