[PATCH 16/21] AP: Add CIP support

Benjamin Berg benjamin at sipsolutions.net
Tue Oct 27 06:17:02 PDT 2026


From: Benjamin Berg <benjamin.berg at intel.com>

Final commit to add CIP support to the AP. This adds the configuration
option, RSNXE handling and enabling CIP in the WPA state machine when
both the AP and the client supports it. It also adds the code to clear
the key on shutdown as that depends on the configuration option to be
present.

Signed-off-by: Benjamin Berg <benjamin.berg at intel.com>
Reviewed-by: Andrei Otcheretianski <andrei.otcheretianski at intel.com>
---
 hostapd/config_file.c      |  2 ++
 hostapd/main.c             |  8 ++++++++
 src/ap/ap_config.c         |  5 +++++
 src/ap/beacon.c            |  4 ++++
 src/ap/hostapd.c           | 11 +++++++++++
 src/ap/ieee802_11_shared.c |  3 +++
 src/ap/wpa_auth_glue.c     |  2 ++
 src/ap/wpa_auth_ie.c       | 10 ++++++++++
 8 files changed, 45 insertions(+)

diff --git a/hostapd/config_file.c b/hostapd/config_file.c
index 396d145b5e..8a02828c6e 100644
--- a/hostapd/config_file.c
+++ b/hostapd/config_file.c
@@ -3672,6 +3672,8 @@ static int hostapd_config_fill(struct hostapd_config *conf,
 		bss->rsn_override_mfp_2 = atoi(pos);
 	} else if (os_strcmp(buf, "spp_amsdu") == 0) {
 		bss->spp_amsdu = !!atoi(pos);
+	} else if (os_strcmp(buf, "cip") == 0) {
+		bss->cip = !!atoi(pos);
 	} else if (os_strcmp(buf, "group_mgmt_cipher") == 0) {
 		if (os_strcmp(pos, "AES-128-CMAC") == 0) {
 			bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC;
diff --git a/hostapd/main.c b/hostapd/main.c
index c508010e26..71569e7530 100644
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -396,6 +396,14 @@ setup_mld:
 	}
 #endif /* CONFIG_IEEE80211BE */
 
+	if (hapd->conf->cip) {
+		if (!iface->cip_supported) {
+			wpa_printf(MSG_INFO,
+				   "CIP: Not supported on the interface");
+			return -1;
+		}
+	}
+
 	return 0;
 }
 
diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
index 57b92c45c8..2c155a56b7 100644
--- a/src/ap/ap_config.c
+++ b/src/ap/ap_config.c
@@ -1595,6 +1595,11 @@ static int hostapd_config_check_bss(struct hostapd_bss_config *bss,
 				   WPA_CIPHER_GCMP_256 | WPA_CIPHER_GCMP)))
 		bss->spp_amsdu = false;
 
+	/* Do not advertise CIP if not using GCMP-256 */
+	if (full_config && bss->cip &&
+	    !(bss->wpa && bss->rsn_pairwise & WPA_CIPHER_GCMP_256))
+		bss->cip = false;
+
 	if (bss->wmm_override && hostapd_config_check_bss_wmm_params(bss))
 		return -1;
 
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index be8e1153d6..0d125a9121 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -837,6 +837,8 @@ static size_t hostapd_probe_resp_elems_len(struct hostapd_data *hapd,
 	}
 #endif /* CONFIG_IEEE80211BE */
 
+	buflen += hostapd_eid_cip_capab_len(hapd);
+
 	buflen += hostapd_eid_mbssid_len(hapd_probed, WLAN_FC_STYPE_PROBE_RESP,
 					 NULL,
 					 params->known_bss,
@@ -1018,6 +1020,8 @@ static u8 * hostapd_probe_resp_fill_elems(struct hostapd_data *hapd,
 	}
 #endif /* CONFIG_IEEE80211BE */
 
+	pos = hostapd_eid_cip_capab(hapd, pos);
+
 #ifdef CONFIG_IEEE80211BN
 	if (hostapd_is_uhr_enabled(hapd)) {
 		pos = hostapd_eid_uhr_capab(hapd, pos, IEEE80211_MODE_AP);
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index a4394f73d9..2731dfe0b4 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -410,6 +410,17 @@ static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd,
 			}
 		}
 	}
+	if (hapd->conf->cip) {
+		for (i = 0; i < 2; i++) {
+			if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE,
+						NULL, i, 0, 0, NULL,
+						0, NULL, 0, KEY_FLAG_CIGTK)) {
+				wpa_printf(MSG_DEBUG,
+					   "Failed to clear default control protection keys (ifname=%s keyidx=%d)",
+					   ifname, i);
+			}
+		}
+	}
 }
 
 
diff --git a/src/ap/ieee802_11_shared.c b/src/ap/ieee802_11_shared.c
index cc7d72f9e3..ddd87c05f3 100644
--- a/src/ap/ieee802_11_shared.c
+++ b/src/ap/ieee802_11_shared.c
@@ -1186,6 +1186,9 @@ u8 * hostapd_eid_rsnxe(struct hostapd_data *hapd, u8 *eid, size_t len,
 		capab |= BIT_ULL(WLAN_RSNX_CAPAB_UNAUTH_EPPKE);
 #endif /* CONFIG_ENC_ASSOC */
 
+	if (hapd->conf->cip)
+		capab |= BIT_ULL(WLAN_RSNX_CAPAB_CIP);
+
 	capab &= capab_mask;
 
 	if (!capab)
diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
index 9208b57d86..32591a96bb 100644
--- a/src/ap/wpa_auth_glue.c
+++ b/src/ap/wpa_auth_glue.c
@@ -81,6 +81,7 @@ static void hostapd_wpa_auth_config_update(struct hostapd_data *hapd,
 	_conf->prot_range_neg =
 		!!(hapd->iface->drv_flags2 &
 		   WPA_DRIVER_FLAGS2_PROT_RANGE_NEG_AP);
+	_conf->cip = hapd->conf->cip;
 
 #ifdef CONFIG_ENC_ASSOC
 	if (!(hapd->iface->drv_flags2 &
@@ -363,6 +364,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_iface *iface,
 	wconf->rsn_override_mlo_compat = conf->rsn_override_mlo_compat;
 	wconf->spp_amsdu = conf->spp_amsdu &&
 		(iface->drv_flags2 & WPA_DRIVER_FLAGS2_SPP_AMSDU);
+	wconf->cip = conf->cip;
 
 	if (conf->sae_pw_id_num && conf->sae_pw_id_key &&
 	    wpabuf_len(conf->sae_pw_id_key) == sizeof(wconf->sae_pw_id_key)) {
diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c
index 0cc319ec77..c83faac6ed 100644
--- a/src/ap/wpa_auth_ie.c
+++ b/src/ap/wpa_auth_ie.c
@@ -602,6 +602,9 @@ static u64 rsnxe_capab(struct wpa_auth_config *conf, int key_mgmt)
 		capab |= BIT_ULL(WLAN_RSNX_CAPAB_UNAUTH_EPPKE);
 #endif /* CONFIG_ENC_ASSOC */
 
+	if (conf->cip)
+		capab |= BIT_ULL(WLAN_RSNX_CAPAB_CIP);
+
 	return capab;
 }
 
@@ -1328,6 +1331,13 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth,
 	if (sm->pairwise < 0)
 		return WPA_INVALID_PAIRWISE;
 
+	if (wpa_auth->conf.cip &&
+	    ieee802_11_rsnx_capab(rsnxe, WLAN_RSNX_CAPAB_CIP) &&
+	    (sm->pairwise == WPA_CIPHER_GCMP_256))
+		sm->cip = 1;
+	else
+		sm->cip = 0;
+
 	/* TODO: clear WPA/WPA2 state if STA changes from one to another */
 	if (wpa_ie[0] == WLAN_EID_RSN)
 		sm->wpa = WPA_VERSION_WPA2;
-- 
2.56.0




More information about the Hostap mailing list