This page explains how to enable MACsec for Ethernet features.
Use MACsec to authenticate and encrypt the Ethernet communication used by in-vehicle infotainment (IVI) for different ECU units, protecting the data from tampering, replay, or information disclosure. Do this buy enabling MACsec IEEE 802.11AE for the Ethernet network.
Overview
To enable MACsec, wpa_supplicant
is used as the daemon for handling the
MACsec Key Agreement (MKA) handshake. A MACsec HAL is defined for storing the MACsec
pre-shared-key, called the connectivity association key (CAK) securely. The MACsec HAL
only supports CAK. This vendor-specific MACsec HAL stores the CAK securely in a tamper
resistant storage. Provisioning the key depends on the vendor implementation.
MACsec flow
Figure 1 illustrates the MACsec flow on the head unit.
Enable MACsec
To provide support for functionalities with the MACsec CAK key, MACsec for Ethernet must be explicitly enabled with a vendor-specific MACsec HAL.
To enable the feature, enable wpa_supplicant_macsec
and the vendor-specific
macsec-service
to PRODUCT_PACKAGES
and the configuration file
for wpa_supplicant_macsec
, init rc
script to
PRODUCT_COPY_FILES
.
For example, this [device-product].mk
file:
# MACSEC HAL # This is a mock MACsec HAL implementation with keys embedded in it. Replace with vendor specific HAL PRODUCT_PACKAGES += android.hardware.automotive.macsec-service # wpa_supplicant build with MACsec support PRODUCT_PACKAGES += wpa_supplicant_macsec # configuration file for wpa_supplicant with MACsec PRODUCT_COPY_FILES += \ $(LOCAL_PATH)/wpa_supplicant_macsec.conf:$(TARGET_COPY_OUT_VENDOR)/etc/wpa_supplicant_macsec.conf \ $(LOCAL_PATH)/wpa_supplicant_macsec.rc:$(TARGET_COPY_OUT_VENDOR)/etc/init/wpa_supplicant_macsec.rc
For example, wpa_supplicant_macsec.conf
.
# wpa_supplicant_macsec.conf eapol_version=3 ap_scan=0 fast_reauth=1 # Example configuration for MACsec with preshared key # mka_cak is not actual key but index for MACsec HAL to specify which key to use # and make_cak must be either 16 digits or 32 digits depends the actually CAK key length. network={ key_mgmt=NONE eapol_flags=0 macsec_policy=1 macsec_replay_protect=1 macsec_replay_window=0 mka_cak=00000000000000000000000000000001 mka_ckn=31323334 mka_priority=128 }
Sample wpa_supplicant_macsec.conf
on eth0
. When multiple network
interfaces need to be protected by MACsec, you can start multiple services.
# wpa_supplicant_macsec.rc service wpa_supplicant_macsec /vendor/bin/hw/wpa_supplicant_macsec \ -dd -i eth0 -Dmacsec_linux -c /vendor/etc/wpa_supplicant_macsec.conf oneshot
Start wpa_supplicant_macsec
after the Ethernet interface is ready. If the
system Ethernet is not ready, wpa_supplicant
immediately returns an error.
To avoid race conditions, a wait (default timeout is five (5) seconds) for
/sys//class/net/${eth_interface}
might be needed.
# init.target.rc on late-fs … wait /sys/class/net/eth0 start wpa_supplicant_macsec …
Configure the IP address for the MACsec interface
Configuration of the MACsec interface IP address can be done by the system connectivity manager once zygote starts. Here is an example overlay XML file for connectivity. If the IP address for MACsec interface needs to be ready before zygote starts, a vendor-specific daemon would need to listen for macsec0 interface and configure it instead since the system connectivity manager only starts after zygote starts.
# Example of com.google.android.connectivity.resources overlay config <?xml version="1.0" encoding="utf-8"?> <!-- Resources to configure the connectivity module based on each OEM's preference. --> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <!-- Whether the internal vehicle network should remain active even when no apps requested it. --> <bool name="config_vehicleInternalNetworkAlwaysRequested">true</bool> <string-array translatable="false" name="config_ethernet_interfaces"> <!-- Not metered, trusted, not vpn, vehicle, not vcn managed, restricted --> <item>macsec0;11,14,15,27,28;ip=10.10.10.2/24 gateway=10.10.10.1 dns=4.4.4.4,8.8.8.8</item> </string-array> <string translatable="false" name="config_ethernet_iface_regex">macsec\\d</string> </resources>
MACsec HAL
The MACsec vendor-specific HAL must implement the following functions to protect the CAK
key. All encryption and decryption with the key is done directly without exposing the key to
wpa_supplicant
.
/** * MACSEC pre-shared key plugin for wpa_applicant * * The goal of this service is to provide function for using the MACSEC CAK * */ @VintfStability interface IMacsecPSKPlugin { /** * For xTS test only, not called in production * * @param keyId is key id to add * @param CAK, CAK key to set * @param CKN, CKN to set * * @return ICV. */ void addTestKey(in byte[] keyId, in byte[] CAK, in byte[] CKN);
/** * Use ICV key do AES CMAC same as ieee802_1x_icv_aes_cmac in wpa_supplicant * * @param keyId is key id to be used for AES CMAC * @param data * * @return ICV. */ byte[] calcICV(in byte[] keyId, in byte[] data);
/** * KDF with CAK key to generate SAK key same as ieee802_1x_sak_aes_cmac in wpa_supplicant * * @param keyId is key id to be used for KDF * @param seed is key seed (random number) * @param sakLength generated SAK length (16 or 32) * * @return SAK key. */ byte[] generateSAK(in byte[] keyId, in byte[] data, in int sakLength);
/** * Encrypt using KEK key, this is same as aes_wrap with kek.key in wpa_supplicant * which used to wrap a SAK key * * @param keyId is key id to be used for encryption * @param sak is SAK key (16 or 32 bytes) to be wrapped. * * @return wrapped data using KEK key. */ byte[] wrapSAK(in byte[] keyId, in byte[] sak);
/** * Decrypt using KEK key, this is same as aes_unwrap with kek.key in wpa_supplicant * which used to unwrap a SAK key * * @param keyId is key id to be used for decryption * @param sak is wrapped SAK key. * * @return unwrapped data using KEK key. */ byte[] unwrapSAK(in byte[] keyId, in byte[] sak); }
Reference implementation
A reference implementation is provided in
hardware/interfaces/macsec/aidl/default
, which provides a software
implementation of the HAL with keys embedded inside. This implementation provides only
a functional reference to the HAL since the keys are not backed by tamper-resistant storage.
Test the MACsec HAL
A MACsec HAL test is provided in
hardware/interfaces/automotive/macsec/aidl/vts/functional
.
To run the test:
$ atest VtsHalMacsecPskPluginV1Test
This calls addTestKey
-- to insert a test key into the HAL and to verify against the
expected values for calcIcv
, generateSak
, wrapSak
and
unwrapSak
.
To confirm MACsec is working, for integration tests, ping between two machines in the MACsec interface:
# ping -I macsec0 10.10.10.1
To test Cuttlefish with host,
echo 8 > /sys/devices/virtual/net/cvd-ebr/bridge/group_fwd_mask
in host is
needed to allow passthrough the LLDP frames required for MACsec.