MACsec (802.1AE) with 802.1X (EAPOL) key management with wpa_supplicant

I'd like to use MACsec (802.1AE) to secure the Ethernet connection of an OpenWRT wifi access point.

I've benchmarked MACsec on the hardware (Zyxel NWA50AX Pro) and it outperforms Wireguard by about 30% (presumably because the SoC includes AES extensions which Linux's MACsec implementation is using, whereas Wireguard's chacha20 encryption runs a slower SIMD algorithm).

Using MACsec also keeps things simpler in some ways because it's a layer 2 option, so I don't have to implement workarounds for zeroconf etc. and wifi roaming works in a straightforward way (something like GRETAP over Wireguard would be a lower performance alternative option for this particular hardware).

Although I won't be using it in this particular scenario, some "business/enterprise" oriented rack-mount switches commonly implement MACsec in hardware, which sometimes makes it a good option for those type of environments. The Linux kernel also now has MACsec hardware offload support, and I believe MACsec offload is includes in various silicon including "Enterprise" PCIe NICs, QCA hardware, and a few Ethernet PHYs (e.g. Aquantia, Realtek, and Microchip all have offerings).

It is possible to set up MACsec with a set of static keys using ip from the OpenWRT ip-full package, but this alone isn't a viable solution because unless you implement some custom solution for manual key rotation, the link "stops" after 2^32 packets (at this point 802.1AE requires key rotation to prevent replay attacks).

The normal way of implementing 802.1AE on Linux is to use wpa_supplicant to manage the keys - it uses an extension to 802.1X (as used for "WPA2-Enterprise") to set up a MACsec link (both "enterprise-style" user+password and also preshared key options are support). This Red Hat article gives a good intro, including a demo of an "ad-hoc" key management setup: https://developers.redhat.com/blog/2017/06/28/whats-new-in-macsec-setting-up-macsec-using-wpa_supplicant-and-optionally-networkmanager

Unfortunately (despite the name), the OpenWRT wpad "full" packages don't compile in MACsec support. 802.1X on wired Ethernet devices is included, but without the MACsec extensions, this is vulnerable to eavesdropping and MITM attacks.

As a PoC, I've recompiled the OpenWRT package to include MACsec, but doing-so requires it to be linked against libnl instead of libnl-tiny.

Here are some options for adding MACsec support to wpa_supplicant (and hostapd) in OpenWRT permanently:

Have the "full" wpad package include MACsec and require libnl (I assume this is a non-starter because the additional storage and possibly runtime RAM requirements would make this unusable on some supported hardware).

Add a "fuller" wpad package config to include MACsec and require libnl. Name TBC.

I've only had a quick look at the code, but I don't think adapting the hostapd MACsec support to build with libnl-tiny would be a viable alternative.

Any thoughts?

@nbd ?

3 Likes

I'm running into the same issue.

How did you recompile the package to include MACsec?

wpad-full-macsec?

1 Like

I've pushed my (very rough WiP tree) here: https://github.com/tim-seoss/openwrt/tree/wpad-macsec-23-05-3 It adds a package named wpad-macsec-mbedtls. The MACsec support works (I've used it to setup a test macsec layer2 with a Debian box on top of a gretap tunnel), but you can't use the same package to do wireless networks (yet) because the ucode-mod-nl80211 package (which the OpenWRT patches hostapd and wpa_supplicant to integrate with) then fails to function (presumably because it's built against libnl-tiny). There is (as-yet) no OpenWRT network configuration integration at all, so wpa_supplicant is started with:

# cat /etc/hotplug.d/iface/99-macsec 
[ ifup = "$ACTION" ] && {
        if [ "$DEVICE" == "gre4t-tap" ]; then
                if [ -x /root/wpa_supplicant ]; then
                        /root/wpa_supplicant -i "$DEVICE" -Dmacsec_linux -c /etc/config/wpa_supplicant_macsec.conf
                fi
        fi
}

... where /root/wpa_supplicant is a copy of the wpa_supplicant binary from the macsec package manually copied out, so that the non-macsec wpad package can be installed and manage the wifi network as usual. This is in /etc/config/wpa_supplicant_macsec.conf:

ctrl_interface=/tmp/wpa_supplicant_macsec
eapol_version=3
ap_scan=0
fast_reauth=1

network={
        key_mgmt=NONE
        eapol_flags=0
        macsec_policy=1

        # Don't use group address because these are blocked by procurves
        #use_pae_group_addr=0

        mka_cak=124... # 16 bytes hexadecimal
        mka_ckn=718... # 32 bytes hexadecimal
}

Hack hack hack :slight_smile:

1 Like

[edited 22/04 to add more detailed notes and explanations]

I've modified my test environment slightly - it's still using a ZyXEL NWA50AX Pro (medium spec wifi 6 access point with a Mediatek chipset including dual core 1.3GHz Cortex A53 with AES CPU instructions), but without the GRETAP tunnel. The underlying device is a VLAN on the Ethernet port (unbridged). MTU size on the VLAN is adjusted up to 1532 bytes, so that the resulting macsec device can still have a 1500 byte MTU (and so can be bridged to other Ethernet networks and wifi networks easily).

The original 802.1x and 802.1ae standards specified that the MACsec connection setup is carried out using "EAPOL" packets which are Ethernet packets which have a destination mac address which is the "IEEE Std 802.1X PAE address" of 01:80:C2:00:00:03, and this is what hostapd and wpa_supplicant currently do, without any configuration option to change this.

The IEEE specs for bridges (which include Ethernet switches) mandate that mac addresses 01:80:c2:00:00:00 to 01:80:c2:00:00:0f should be processed locally by bridges and not passed on. This has the effect of forcing MACsec encryption setup by 802.1X to only span between a device and the nearest switch that it is connected to. As well as not being desirable in many situations (e.g. intermediate switch is owned by a third party provider), that would make MACsec configured with 801.1X impossible if the nearest switch lacks MACsec support.

Because the IEEE standards made decisions which considerably limit the practical use of MACsec for quite a few applications which they'd otherwise be quite useful for, some switch manufacturers have settings in their managed switches to allow users to make them not conform to these requirements e.g. to instead passthrough the EAPOL packets with the 01:80:c2:00:00:03 destination mad address (e.g. Cisco's dot1x eapol-relay), or to use a different mac addresses entirely for their EAPOL packets (e.g. Cisco's eapol destination-address, HP Procurve eapol-destination-mac, and Juniper's eapol-address settings). Cisco has also gone further and offers other options with their "WAN MACSEC" features and protocol extensions.

The standards themselves have more recently been expanded to add options to traverse switches (e.g. 802.1ae-2018 defines other multicast mac addresses e.g. 01:80:c2:00:00:1f which can be used for "Ethernet Data Encryption devices" where you want to encrypt a "customer" VLAN which is implemented inside of a service provider VLAN - for nested vlans also known as "Q in Q" and specified in 802.1.ad), and other recent changes have added more encryption algorithm options, and provide mac address privacy for the inner packets.

So... I was originally using a GRETAP tunnel as a way of getting the (traditional 01:80:c2:00:00:03 destination mac address) EAPOL packets through intermediate switches. Because the GRETAP tunnel adds a chunk of processing and bandwidth overhead (and I was having trouble with getting it to operate with the MTUs that I wanted - leading to packets being fragmented and reassembled), instead I've removed GRETAP from the test setup, and instead I've temporarily modified the wpa_supplicant daemons on both devices to use a different MAC address for EAPOL packets which isn't blocked by intermediate switches. I'll try and extend the upstream hostapd/wpa_supplicant to make that a proper configuration setting. For the time being, instead of using 01:80:c2:00:00:03 (the 802.1X PAE address) for wpa_supplicant's EAPOL packets, my temporary change hard-codes 01:80:c2:00:00:1f (the newer 802.1X EDE-CC PEP Address) - but I plan to make that fully configurable (like some Juniper, HP Procurve, and Cisco switches already do as detailed above).

In the new test setup, running an iperf3 server on the OpenWrt AP, and an iperf3 client elsewhere on the network gives 800 Mbit throughput for the macsec interface. The same device gets about 500 Mbit throughput for wireguard. It was previously getting about 650 Mbit when the GRETAP tunnel was used with MACsec.

git branch with this additional mac dest address change is here: https://github.com/tim-seoss/openwrt/tree/wpad-macsec-23-05-with-eapol-dest-addr-hack