]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
MACsec: Add option to always include ICV Indicator
authorMartínek Petr <petr.martinek@elvac.eu>
Tue, 25 Feb 2025 08:18:06 +0000 (08:18 +0000)
committerJouni Malinen <j@w1.fi>
Sun, 2 Mar 2025 17:30:15 +0000 (19:30 +0200)
Some older MACsec switches incorrectly require ICV Indicator to be
present even when ICV has default length (Cisco C3560CX). To allow
communication with such devices option include-icv-indicator was added
to always include ICV Indicator.

Similar option is found in configuration of some other switches:

Cisco:
include-icv-indicator - this parameter configures inclusion of the
optional ICV Indicator as part of the transmitted MACsec Key Agreement
PDU (MKPDU). This configuration is necessary for MACsec to interoperate
with routers that run software prior to IOS XR version 6.1.3. This
configuration is also important in a service provider WAN setup where
MACsec interoperates with other vendor MACsec implementations that
expect ICV indicator to be present in the MKPDU.

fortiswitch:
include-mka-icv-ind: The MACsec Key Agreement (MKA) integrity check
value (ICV) indicator is always included. (enabled by default)

Signed-off-by: Petr Martínek <petr.martinek at elvac.eu>
hostapd/config_file.c
hostapd/hostapd.conf
src/ap/ap_config.h
src/ap/wpa_auth_kay.c
src/pae/ieee802_1x_kay.c
src/pae/ieee802_1x_kay.h
wpa_supplicant/config.c
wpa_supplicant/config_file.c
wpa_supplicant/config_ssid.h
wpa_supplicant/wpa_supplicant.conf
wpa_supplicant/wpas_kay.c

index c52adb8f2c2af17771afeccc08e99280ea352440..0e35730f9d2e4326e6eb5834b986bfb133abee83 100644 (file)
@@ -4791,6 +4791,16 @@ static int hostapd_config_fill(struct hostapd_config *conf,
                        return 1;
                }
                bss->macsec_csindex = macsec_csindex;
+       } else if (os_strcmp(buf, "macsec_icv_indicator") == 0) {
+               int macsec_icv_indicator = atoi(pos);
+
+               if (macsec_icv_indicator < 0 || macsec_icv_indicator > 1) {
+                       wpa_printf(MSG_ERROR,
+                                  "Line %d: invalid macsec_icv_indicator (%d): '%s'.",
+                                  line, macsec_icv_indicator, pos);
+                       return 1;
+               }
+               bss->macsec_icv_indicator = macsec_icv_indicator;
        } else if (os_strcmp(buf, "mka_cak") == 0) {
                size_t len = os_strlen(pos);
 
index 97a4dc38da10d45dca14c5cb68aa533c55f3fb49..338a16c82fb777d128ed1d9a1e009aebdfb7061c 100644 (file)
@@ -1219,6 +1219,10 @@ eapol_key_index_workaround=0
 # mka_priority (Priority of MKA Actor)
 # Range: 0..255 (default: 255)
 #
+# macsec_icv_indicator: Always include ICV indicator
+# 0 = ICV Indicator is not included when ICV has default length (default)
+# 1 = ICV Indicator is always included (compatibility mode)
+#
 # macsec_csindex: IEEE 802.1X/MACsec cipher suite
 # 0 = GCM-AES-128 (default)
 # 1 = GCM-AES-256 (default)
index 2b6cf4acfe3537e1a44e672027d45d0c1c7f5869..02eb4b6fb68d9fb265de5488af5f94e0dc26bd63 100644 (file)
@@ -891,6 +891,14 @@ struct hostapd_bss_config {
         */
        int macsec_csindex;
 
+       /**
+        * macsec_icv_indicator - Always include ICV Indicator
+        * (for compatibility with older MACsec switches)
+        *
+        * Range: 0-1 (default: 0)
+        */
+       int macsec_icv_indicator;
+
        /**
         * mka_ckn - MKA pre-shared CKN
         */
index 9902384b0d008b3c6c167e1d8cb649730d019014..20a5aaa10a56c60ada0d6091712187ad78483a3c 100644 (file)
@@ -331,6 +331,7 @@ int ieee802_1x_alloc_kay_sm_hapd(struct hostapd_data *hapd,
                                  hapd->conf->macsec_port,
                                  hapd->conf->mka_priority,
                                  hapd->conf->macsec_csindex,
+                                 hapd->conf->macsec_icv_indicator,
                                  hapd->conf->iface,
                                  hapd->own_addr);
        /* ieee802_1x_kay_init() frees kay_ctx on failure */
index 81f721af843d91977792f9a08fdb37a1ee782ab4..57b5e6064b5dd669f9cbb0e7d2e23fa6c1848f5a 100644 (file)
@@ -1871,7 +1871,7 @@ ieee802_1x_mka_get_icv_length(struct ieee802_1x_mka_participant *participant)
 
        /* Determine if we need space for the ICV Indicator */
        if (mka_alg_tbl[participant->kay->mka_algindex].icv_len !=
-           DEFAULT_ICV_LEN)
+           DEFAULT_ICV_LEN || participant->kay->include_icv_indicator)
                length = sizeof(struct ieee802_1x_mka_icv_body);
        else
                length = 0;
@@ -1894,7 +1894,7 @@ ieee802_1x_mka_encode_icv_body(struct ieee802_1x_mka_participant *participant,
 
        length = ieee802_1x_mka_get_icv_length(participant);
        if (mka_alg_tbl[participant->kay->mka_algindex].icv_len !=
-           DEFAULT_ICV_LEN)  {
+           DEFAULT_ICV_LEN || participant->kay->include_icv_indicator)  {
                wpa_printf(MSG_DEBUG, "KaY: ICV Indicator");
                body = wpabuf_put(buf, MKA_HDR_LEN);
                body->type = MKA_ICV_INDICATOR;
@@ -3495,7 +3495,8 @@ struct ieee802_1x_kay *
 ieee802_1x_kay_init(struct ieee802_1x_kay_ctx *ctx, enum macsec_policy policy,
                    bool macsec_replay_protect, u32 macsec_replay_window,
                    u8 macsec_offload, u16 port, u8 priority,
-                   u32 macsec_csindex, const char *ifname, const u8 *addr)
+                   u32 macsec_csindex, bool include_icv_indicator,
+                   const char *ifname, const u8 *addr)
 {
        struct ieee802_1x_kay *kay;
 
@@ -3533,6 +3534,7 @@ ieee802_1x_kay_init(struct ieee802_1x_kay_ctx *ctx, enum macsec_policy policy,
 
        kay->pn_exhaustion = PENDING_PN_EXHAUSTION;
        kay->macsec_csindex = macsec_csindex;
+       kay->include_icv_indicator = include_icv_indicator;
        kay->mka_algindex = DEFAULT_MKA_ALG_INDEX;
        kay->mka_version = MKA_VERSION_ID;
 
index 11464f7fc602e3fdf466cb506b7c3728c1bee363..d46f0b285a439c8db7a3b7e16d0019d384a06068 100644 (file)
@@ -206,6 +206,7 @@ struct ieee802_1x_kay {
        struct ieee802_1x_kay_ctx *ctx;
        bool is_key_server;
        bool is_obliged_key_server;
+       bool include_icv_indicator; /* Always include ICV Indicator */
        char if_name[IFNAMSIZ];
        u8 macsec_offload;
 
@@ -243,7 +244,8 @@ struct ieee802_1x_kay *
 ieee802_1x_kay_init(struct ieee802_1x_kay_ctx *ctx, enum macsec_policy policy,
                    bool macsec_replay_protect, u32 macsec_replay_window,
                    u8 macsec_offload, u16 port, u8 priority,
-                   u32 macsec_csindex, const char *ifname, const u8 *addr);
+                   u32 macsec_csindex, bool include_icv_indicator,
+                   const char *ifname, const u8 *addr);
 void ieee802_1x_kay_deinit(struct ieee802_1x_kay *kay);
 
 struct ieee802_1x_mka_participant *
index d958610b71ffe6be2b13c4f1f6fd9ad967e8084c..77eb9bf68cf235c1dda73bed5313000beb388055 100644 (file)
@@ -2726,6 +2726,7 @@ static const struct parse_data ssid_fields[] = {
        { INT_RANGE(macsec_port, 1, 65534) },
        { INT_RANGE(mka_priority, 0, 255) },
        { INT_RANGE(macsec_csindex, 0, 1) },
+       { INT_RANGE(macsec_icv_indicator, 0, 1) },
        { FUNC_KEY(mka_cak) },
        { FUNC_KEY(mka_ckn) },
 #endif /* CONFIG_MACSEC */
index 67cb144f1aa481e67613a28e464d8321cf79ce21..0f53753fa44dbde02ef510d7002411c708bdc582 100644 (file)
@@ -912,6 +912,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
        INT(macsec_port);
        INT_DEF(mka_priority, DEFAULT_PRIO_NOT_KEY_SERVER);
        INT(macsec_csindex);
+       INT(macsec_icv_indicator);
 #endif /* CONFIG_MACSEC */
 #ifdef CONFIG_HS20
        INT(update_identifier);
index 5f8a1f2ae3c4162573d6981af8a0f08821b6be1c..530b5e96385b7bbd69c976b9e47ce7dce832c696 100644 (file)
@@ -991,6 +991,14 @@ struct wpa_ssid {
         */
        int macsec_csindex;
 
+       /**
+        * macsec_icv_indicator - Always include ICV Indicator
+        * (for compatibility with older MACsec switches)
+        *
+        * Range: 0-1 (default: 0)
+        */
+       int macsec_icv_indicator;
+
        /**
         * mka_ckn - MKA pre-shared CKN
         */
index 40c5ff57db72fd3bb4f58881d01bcaa64a06ec2d..121ad38791cd40a4efd6e38286012f39e5492ae9 100644 (file)
@@ -1256,6 +1256,10 @@ fast_reauth=1
 # mka_priority (Priority of MKA Actor) is in 0..255 range with 255 being
 # default priority
 #
+# macsec_icv_indicator: Always include ICV indicator
+# 0 = ICV Indicator is not included when ICV has default length (default)
+# 1 = ICV Indicator is always included (compatibility mode)
+#
 # mixed_cell: This option can be used to configure whether so called mixed
 # cells, i.e., networks that use both plaintext and encryption in the same
 # SSID, are allowed when selecting a BSS from scan results.
index 600b3bc545277ae3614835d4681d692e2b678be3..7893a39bc387f4f662ef321fc65cd1186c0e2a75 100644 (file)
@@ -249,6 +249,7 @@ int ieee802_1x_alloc_kay_sm(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid)
                                  ssid->macsec_replay_window,
                                  ssid->macsec_offload, ssid->macsec_port,
                                  ssid->mka_priority, ssid->macsec_csindex,
+                                 ssid->macsec_icv_indicator,
                                  wpa_s->ifname, wpa_s->own_addr);
        /* ieee802_1x_kay_init() frees kay_ctx on failure */
        if (res == NULL)