[PATCH] NAN: Set security required bit in SDEA

Andrei Otcheretianski andrei.otcheretianski at intel.com
Thu Jun 4 00:02:37 PDT 2026


If the security is mandatory, publish SDFs should advertise
security_required bit in SDEA. Set this bit by default when CSIDs are
specified in NAN_PUBLISH command.
In addition, add an explicit configuration parameter to allow open
NDP connections even when CSIDs are configured for a service.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski at intel.com>
---
 src/common/nan_de.c             | 13 ++++++++-
 src/common/nan_de.h             |  3 +++
 wpa_supplicant/ctrl_iface.c     | 11 ++++++++
 wpa_supplicant/nan_supplicant.c | 48 ++++++++++++++++-----------------
 4 files changed, 50 insertions(+), 25 deletions(-)

diff --git a/src/common/nan_de.c b/src/common/nan_de.c
index 6cac62b690..42a61c49bc 100644
--- a/src/common/nan_de.c
+++ b/src/common/nan_de.c
@@ -86,6 +86,7 @@ struct nan_de_service {
 	bool close_proximity;
 	bool gtk_required;
 	bool data_path;
+	bool security_required;
 
 	/* Bootstrapping methods */
 	u16 pbm;
@@ -598,8 +599,12 @@ static void nan_de_tx_sdf(struct nan_de *de, struct nan_de_service *srv,
 				sdea_ctrl |= NAN_SDEA_CTRL_FSD_GAS;
 			if (srv->gtk_required)
 				sdea_ctrl |= NAN_SDEA_CTRL_GTK_REQ;
-			if (srv->data_path)
+			if (srv->data_path) {
 				sdea_ctrl |= NAN_SDEA_CTRL_DATA_PATH_REQ;
+				if (srv->cipher_suites_list &&
+				    srv->security_required)
+					sdea_ctrl |= NAN_SDEA_CTRL_SECURITY_REQ;
+			}
 		}
 
 		if (sdea_ctrl || ssi) {
@@ -1726,6 +1731,7 @@ send_event:
 	res.fsd = !!(sdea_control & NAN_SDEA_CTRL_FSD_REQ);
 	res.fsd_gas = !!(sdea_control & NAN_SDEA_CTRL_FSD_GAS);
 	res.data_path = !!(sdea_control & NAN_SDEA_CTRL_DATA_PATH_REQ);
+	res.security_required = !!(sdea_control & NAN_SDEA_CTRL_SECURITY_REQ);
 	res.cipher_suites = cipher_suite_count > 0 ? cipher_suites : NULL;
 	res.n_cipher_suites = cipher_suite_count;
 	res.pmkid_list = pmkid_count > 0 ? pmkid_list : NULL;
@@ -2318,6 +2324,7 @@ int nan_de_publish(struct nan_de *de, const char *service_name,
 	srv->pbm = params->pbm;
 	srv->gtk_required = params->gtk_required;
 	srv->data_path = params->data_path;
+	srv->security_required = params->security_required;
 
 	nan_de_add_srv(de, srv);
 	nan_de_run_timer(de);
@@ -2813,6 +2820,10 @@ bool nan_de_service_supports_csid(struct nan_de *de, int handle, int csid)
 	if (!srv->cipher_suites_list)
 		return true;
 
+	/* Open is allowed only if security is not required */
+	if (csid == NAN_CS_NONE)
+		return !srv->security_required;
+
 	/* Check if the CSID is in the service's cipher suite list */
 	return int_array_includes(srv->cipher_suites_list, csid);
 }
diff --git a/src/common/nan_de.h b/src/common/nan_de.h
index 1e05608cae..0599a808ef 100644
--- a/src/common/nan_de.h
+++ b/src/common/nan_de.h
@@ -34,6 +34,7 @@ struct nan_discovery_result {
 	bool fsd;
 	bool fsd_gas;
 	bool data_path;
+	bool security_required;
 	const u8 *pmkid_list;
 	unsigned int pmkid_count;
 	const u8 *cipher_suites;
@@ -182,6 +183,8 @@ struct nan_publish_params {
 
 	/* Request NAN Data Path */
 	bool data_path;
+
+	bool security_required;
 };
 
 /* Returns -1 on failure or >0 publish_id */
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index bd08d2c77a..c2c0cb6472 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -12895,6 +12895,7 @@ static int wpas_ctrl_nan_publish(struct wpa_supplicant *wpa_s, char *cmd,
 	u8 nd_pmk[PMK_LEN];
 	bool p2p = false;
 	u8 forced_addr[ETH_ALEN];
+	bool security_required_set = false;
 
 	os_memset(&params, 0, sizeof(params));
 	/* USD shall use both solicited and unsolicited transmissions */
@@ -13056,11 +13057,21 @@ static int wpas_ctrl_nan_publish(struct wpa_supplicant *wpa_s, char *cmd,
 			continue;
 		}
 
+		if (os_strcmp(token, "security_required=0") == 0) {
+			params.security_required = false;
+			security_required_set = true;
+			continue;
+		}
+
 		wpa_printf(MSG_INFO, "CTRL: Invalid NAN_PUBLISH parameter: %s",
 			   token);
 		goto fail;
 	}
 
+	/* Default security_required to true when cipher suites are specified */
+	if (params.cipher_suites_list && !security_required_set)
+		params.security_required = true;
+
 	if (params.gtk_required &&
 	    !wpas_nan_gtk_cs_supported(params.cipher_suites_list)) {
 		wpa_printf(MSG_INFO,
diff --git a/wpa_supplicant/nan_supplicant.c b/wpa_supplicant/nan_supplicant.c
index 47a83560d5..ab9713b455 100644
--- a/wpa_supplicant/nan_supplicant.c
+++ b/wpa_supplicant/nan_supplicant.c
@@ -2722,27 +2722,6 @@ static int wpas_nan_fill_nd_pmk(struct wpa_supplicant *wpa_s,
 		return -1;
 	}
 
-	if (ndp->sec.csid == NAN_CS_NONE)
-		return 0;
-
-	/* Security parameters are not needed in confirmation */
-	if (ndp->type == NAN_NDP_ACTION_CONF)
-		return 0;
-
-	if (!(wpa_s->nan_supported_csids & BIT(ndp->sec.csid))) {
-			wpa_printf(MSG_INFO,
-				   "NAN: Requested CSID %d not supported",
-				   ndp->sec.csid);
-			return -1;
-	}
-
-	if ((!pwd || os_strlen(pwd) == 0) && (!pmk || os_strlen(pmk) == 0)) {
-		wpa_printf(MSG_INFO,
-			   "NAN: Password/PMK required for CSID %d",
-			   ndp->sec.csid);
-		return -1;
-	}
-
 	/*
 	 * Get service ID from the local handle (subscribe on
 	 * requester and publish on responder)
@@ -2757,14 +2736,35 @@ static int wpas_nan_fill_nd_pmk(struct wpa_supplicant *wpa_s,
 	}
 
 	/*
-	 * For NDP response (publisher side), check if the requested CSID is in
-	 * the service's advertised cipher suite list.
+	 * For NDP response (publisher side), check if the requested CSID
+	 * is supported by the service (including open/NAN_CS_NONE).
 	 */
 	if (ndp->type == NAN_NDP_ACTION_RESP &&
 	    !nan_de_service_supports_csid(wpa_s->nan_de, handle,
 					  ndp->sec.csid)) {
 		wpa_printf(MSG_DEBUG,
-			   "NAN: Requested CSID %d not advertised by service",
+			   "NAN: CSID %d not supported by service",
+			   ndp->sec.csid);
+		return -1;
+	}
+
+	if (ndp->sec.csid == NAN_CS_NONE)
+		return 0;
+
+	/* Security parameters are not needed in confirmation */
+	if (ndp->type == NAN_NDP_ACTION_CONF)
+		return 0;
+
+	if (!(wpa_s->nan_supported_csids & BIT(ndp->sec.csid))) {
+			wpa_printf(MSG_INFO,
+				   "NAN: Requested CSID %d not supported",
+				   ndp->sec.csid);
+			return -1;
+	}
+
+	if ((!pwd || os_strlen(pwd) == 0) && (!pmk || os_strlen(pmk) == 0)) {
+		wpa_printf(MSG_INFO,
+			   "NAN: Password/PMK required for CSID %d",
 			   ndp->sec.csid);
 		return -1;
 	}
-- 
2.53.0




More information about the Hostap mailing list