[PATCH 22/92] NAN: Handle pairing PASN auth frame 1

Andrei Otcheretianski andrei.otcheretianski at intel.com
Wed Apr 22 05:23:13 PDT 2026


From: Avraham Stern <avraham.stern at intel.com>

Add handling for NAN pairing PASN auth frame 1.

Signed-off-by: Avraham Stern <avraham.stern at intel.com>
---
 src/nan/nan.c         |   6 +-
 src/nan/nan.h         |   9 ++
 src/nan/nan_i.h       |   2 +
 src/nan/nan_pairing.c | 264 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 277 insertions(+), 4 deletions(-)

diff --git a/src/nan/nan.c b/src/nan/nan.c
index 6904b12815..30dcf6a614 100644
--- a/src/nan/nan.c
+++ b/src/nan/nan.c
@@ -975,10 +975,8 @@ static void nan_parse_peer_elem_container(struct nan_data *nan,
 		nan_parse_peer_elem_container_attr(nan, peer, attr);
 }
 
-
-static void nan_parse_peer_dev_capa_ext(struct nan_data *nan,
-					struct nan_peer *peer,
-					struct nan_attrs *attrs)
+void nan_parse_peer_dev_capa_ext(struct nan_data *nan, struct nan_peer *peer,
+				 struct nan_attrs *attrs)
 {
 	if (!attrs->dev_capa_ext || attrs->dev_capa_ext_len <= 1)
 		return;
diff --git a/src/nan/nan.h b/src/nan/nan.h
index 90ada88959..65075c1508 100644
--- a/src/nan/nan.h
+++ b/src/nan/nan.h
@@ -700,6 +700,8 @@ int nan_pairing_initiate_pasn_auth(struct nan_data *nan_data, const u8 *addr,
 				   const char *password);
 int nan_pairing_pasn_auth_tx_status(struct nan_data *nan, const u8 *data,
 				    size_t data_len, bool acked);
+int nan_pairing_auth_rx(struct nan_data *nan_data,
+			const struct ieee80211_mgmt *mgmt, size_t len);
 #else
 static inline int nan_pairing_add_attrs(struct nan_data *nan_data,
 					struct wpabuf *buf)
@@ -722,6 +724,13 @@ static inline int nan_pairing_pasn_auth_tx_status(struct nan_data *nan,
 {
 	return -1;
 }
+
+static inline int nan_pairing_auth_rx(struct nan_data *nan_data,
+				      const struct ieee80211_mgmt *mgmt,
+				      size_t len)
+{
+	return -1;
+}
 #endif /* CONFIG_PASN */
 
 #endif /* NAN_H */
diff --git a/src/nan/nan_i.h b/src/nan/nan_i.h
index d0bf37a290..e48f4136da 100644
--- a/src/nan/nan_i.h
+++ b/src/nan/nan_i.h
@@ -742,6 +742,8 @@ bool nan_bootstrap_handle_rx(struct nan_data *nan, const u8 *peer_nmi,
 			     int handle, u8 req_instance_id);
 int nan_add_nira_attr(struct wpabuf *buf, const u8 *nira_tag,
 		      const u8 *nira_nonce);
+void nan_parse_peer_dev_capa_ext(struct nan_data *nan, struct nan_peer *peer,
+				 struct nan_attrs *attrs);
 #ifdef CONFIG_PASN
 int nan_nira_get_tag_nonce(const struct nan_config *nan, u8 *nira_nonce,
 			   u8 *nira_tag);
diff --git a/src/nan/nan_pairing.c b/src/nan/nan_pairing.c
index c3a7d44245..bb2c5ec51a 100644
--- a/src/nan/nan_pairing.c
+++ b/src/nan/nan_pairing.c
@@ -10,6 +10,7 @@
 #include "common.h"
 #include "nan/nan_i.h"
 #include "pasn/pasn_common.h"
+#include "common/ieee802_11_common.h"
 
 /*
  * nan_nira_get_tag_nonce - Generate NIRA nonce and compute NIRA tag
@@ -491,3 +492,266 @@ int nan_pairing_pasn_auth_tx_status(struct nan_data *nan, const u8 *data,
 
 	return 0;
 }
+
+
+/*
+ * nan_parse_csia - Parse NAN Cipher Suite Info Attribute
+ *
+ * @csia: Pointer to the CSIA data buffer
+ * @len: Length of the CSIA data buffer
+ * @cs: Pointer to nan_cipher_suite structure to store parsed information
+ *
+ * Parses the NAN Cipher Suite Info Attribute (CSIA) and extracts the cipher
+ * suite ID (csid) and instance ID from the attribute. It is assumed that only
+ * one cipher suite is present in the attribute (which is the case for NAN
+ * pairing).
+ *
+ * Returns: 0 on success, -1 on failure
+ */
+static int nan_parse_csia(const u8 *csia, size_t len,
+			  struct nan_cipher_suite *cs)
+{
+	/* Capabilities (1) + Cipher Suite list (2) */
+	if (len != sizeof(struct nan_cipher_suite_info) +
+		   sizeof(struct nan_cipher_suite)) {
+		wpa_printf(MSG_DEBUG, "NAN: Pairing: CSIA too short");
+		return -1;
+	}
+
+	cs->csid = csia[1];
+	cs->instance_id = csia[2];
+
+	if (cs->csid != NAN_CS_PK_PASN_128 && cs->csid != NAN_CS_PK_PASN_256) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: Pairing: Unsupported cipher suite in CSIA: %u",
+			   cs->csid);
+		return -1;
+	}
+
+	return 0;
+}
+
+
+/*
+ * nan_pairing_process_elems - Process NAN pairing information elements
+ *
+ * @nan_data: NAN state data
+ * @peer: NAN peer information structure
+ * @mgmt: PASN authentication frame
+ * @len: Length of the PASN authentication frame
+ * @cs: Output cipher suite structure to be filled
+ *
+ * This function processes NAN pairing information elements from a PASN
+ * authentication frame. It extracts the selected cipher suite and intance ID.
+ *
+ * Returns: 0 on success, -1 on failure
+ */
+static int nan_pairing_process_elems(struct nan_data *nan_data,
+				     struct nan_peer *peer,
+				     const struct ieee80211_mgmt *mgmt,
+				     size_t len, struct nan_cipher_suite *cs)
+{
+	const u8 *ies;
+	size_t ies_len;
+	const u8 *buf;
+	struct wpabuf *ie_buf;
+	struct nan_attrs attrs;
+	int ret = -1;
+
+	if (len < offsetof(struct ieee80211_mgmt, u.auth.variable)) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: Pairing: PASN frame too short for NAN IEs");
+		return -1;
+	}
+
+	ies = mgmt->u.auth.variable;
+	ies_len = len - offsetof(struct ieee80211_mgmt, u.auth.variable);
+
+	buf = get_vendor_ie(ies, ies_len, NAN_IE_VENDOR_TYPE);
+	if (!buf)
+		return -1;
+
+	ie_buf = ieee802_11_defrag(buf + 2, buf[1], false);
+	if (!ie_buf)
+		return -1;
+
+	buf = wpabuf_head(ie_buf);
+	ret = nan_parse_attrs(nan_data, &buf[4], wpabuf_len(ie_buf) - 4,
+			      &attrs);
+	if (ret)
+		goto fail;
+
+	nan_parse_peer_dev_capa_ext(nan_data, peer, &attrs);
+
+	if (!attrs.cipher_suite_info || !attrs.cipher_suite_info_len ||
+	    nan_parse_csia(attrs.cipher_suite_info, attrs.cipher_suite_info_len,
+			   cs) < 0) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: Pairing: CSIA attribute missing or invalid");
+		ret = -1;
+	}
+
+
+	nan_attrs_clear(nan_data, &attrs);
+fail:
+	wpabuf_free(ie_buf);
+	return ret;
+}
+
+
+/*
+ * nan_pairing_handle_auth_1 - Handle the first PASN frame in NAN pairing
+ *
+ * @nan_data: Pointer to NAN data structure
+ * @own_addr: Own MAC address
+ * @peer: Pointer to NAN peer structure
+ * @mgmt: Pointer to the received PASN frame
+ * @len: Length of the PASN frame
+ *
+ * This function processes the first PASN authentication frame during NAN
+ * pairing as a responder. It initializes the PASN data structure, prepares
+ * the necessary information elements, and delegates to the PASN module to
+ * handle the authentication.
+ *
+ * Returns: 0 on success, -1 on failure
+ */
+static int nan_pairing_handle_auth_1(struct nan_data *nan_data, u8 *own_addr,
+				     struct nan_peer *peer,
+				     const struct ieee80211_mgmt *mgmt,
+				     size_t len)
+{
+	struct nan_cipher_suite cs;
+	struct pasn_data *pasn;
+	int cipher;
+
+	if (peer->pairing.self_pairing_role != NAN_PAIRING_ROLE_RESPONDER) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: Pairing: Unexpected Auth1 frame");
+		return -1;
+	}
+
+	pasn = peer->pairing.pasn;
+
+	if (nan_pairing_process_elems(nan_data, peer, mgmt, len, &cs)) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: Pairing: Handle Auth1 NAN attributes failed");
+		return -1;
+	}
+
+	cipher = cs.csid == NAN_CS_PK_PASN_256 ? WPA_CIPHER_GCMP_256 :
+						 WPA_CIPHER_CCMP;
+
+	if (cipher != pasn->cipher) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: Pairing: Cipher suite mismatch (CSIA: %s, PASN: %s)",
+			   wpa_cipher_txt(cipher),
+			   wpa_cipher_txt(pasn->cipher));
+		return -1;
+	}
+
+	if (handle_auth_pasn_1(pasn, own_addr, peer->nmi_addr, mgmt, len,
+			       false) < 0) {
+		wpa_printf(MSG_DEBUG, "NAN: Pairing: Handle Auth1 failed");
+		return -1;
+	}
+
+	return 0;
+}
+
+
+/*
+ * nan_pairing_auth_rx - Handle received NAN pairing authentication frames
+ *
+ * @nan_data: Pointer to NAN data structure
+ * @mgmt: Pointer to the PASN authentication frame
+ * @len: Length of the PASN authentication frame in bytes
+ *
+ * Returns: 0 on success, -1 on failure
+ */
+int nan_pairing_auth_rx(struct nan_data *nan_data,
+			const struct ieee80211_mgmt *mgmt, size_t len)
+{
+	struct nan_peer *peer;
+	u16 auth_alg, auth_transaction, status_code;
+	int ret;
+	struct wpabuf *nan_ie;
+	const u8 *buf;
+
+	if (len < offsetof(struct ieee80211_mgmt, u.auth.variable))
+		return -1;
+
+	if (os_memcmp(mgmt->da, nan_data->cfg->nmi_addr, ETH_ALEN) != 0) {
+		wpa_printf(MSG_DEBUG, "NAN: Pairing: Not our frame");
+		return -1;
+	}
+
+	auth_alg = le_to_host16(mgmt->u.auth.auth_alg);
+	auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction);
+	status_code = le_to_host16(mgmt->u.auth.status_code);
+
+	if (auth_alg != WLAN_AUTH_PASN) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: Pairing: Not a PASN frame, auth_alg=%d",
+			   auth_alg);
+		return -1;
+	}
+
+	buf = get_vendor_ie(mgmt->u.auth.variable,
+			    len - offsetof(struct ieee80211_mgmt,
+					   u.auth.variable),
+			    NAN_IE_VENDOR_TYPE);
+	if (!buf)
+		return -1;
+
+	nan_ie = ieee802_11_defrag(buf + 2, buf[1], false);
+	if (!nan_ie) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: Pairing: No NAN IE in PASN authentication frame");
+		return -1;
+	}
+
+	ret = nan_add_peer(nan_data, mgmt->sa, wpabuf_head_u8(nan_ie) + 4,
+			   wpabuf_len(nan_ie) - 4);
+	if (ret) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: Pairing: Failed to add peer from PASN");
+		wpabuf_free(nan_ie);
+		return -1;
+	}
+
+	wpabuf_free(nan_ie);
+
+	peer = nan_get_peer(nan_data, mgmt->sa);
+	if (!peer) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: Pairing: Failed to get a peer that was just added");
+		return -1;
+	}
+
+	if (!peer->pairing.pasn) {
+		wpa_printf(MSG_DEBUG,
+			   "NAN: Pairing: PASN data not initialized for peer");
+		return -1;
+	}
+
+	if (status_code != WLAN_STATUS_SUCCESS) {
+		struct pasn_data *pasn = peer->pairing.pasn;
+
+		nan_data->cfg->pairing_result_cb(nan_data->cfg->cb_ctx,
+						 peer->nmi_addr, pasn->akmp,
+						 pasn->cipher, status_code,
+						 NULL);
+		nan_pairing_deinit_peer(peer);
+		wpa_printf(MSG_DEBUG,
+			   "NAN: Pairing: Authentication rejected - status=%u",
+			   status_code);
+		return -1;
+	}
+
+	if (auth_transaction == 1)
+		return nan_pairing_handle_auth_1(nan_data,
+						 nan_data->cfg->nmi_addr, peer,
+						 mgmt, len);
+
+	return -1;
+}
-- 
2.53.0




More information about the Hostap mailing list