[PATCH 83/92] NAN: Add API to retrieve peer pairing configuration

Andrei Otcheretianski andrei.otcheretianski at intel.com
Wed Apr 22 05:24:14 PDT 2026


Add nan_peer_get_pairing_cfg() API that returns a const pointer to a
peer's NAN pairing configuration. This allows retrieving the pairing
setup, NPK caching, pairing verification, and cipher suites settings
from peer->pairing.pairing_cfg. In addition this function returns peer's
tag and nonce.

Also add support for the "pairing" option in wpas_nan_peer_info() to
query pairing configuration for a NAN peer. Use the tag/nonce values to
find the corresponding identity and dump peer's NPK/NIK.

Signed-off-by: Andrei Otcheretianski <andrei.otcheretianski at intel.com>
---
 src/nan/nan.c                   |  27 +++++++++
 src/nan/nan.h                   |   4 ++
 wpa_supplicant/nan_supplicant.c | 102 +++++++++++++++++++++++++++-----
 3 files changed, 119 insertions(+), 14 deletions(-)

diff --git a/src/nan/nan.c b/src/nan/nan.c
index e8556f3638..38006f349f 100644
--- a/src/nan/nan.c
+++ b/src/nan/nan.c
@@ -2092,6 +2092,33 @@ int nan_peer_get_tk(struct nan_data *nan, const u8 *addr,
 }
 
 
+const struct nan_pairing_cfg * nan_peer_get_pairing_cfg(struct nan_data *nan,
+							const u8 *addr,
+							const u8 **nonce,
+							const u8 **tag)
+{
+	struct nan_peer *peer;
+
+	if (!nan || !addr || !nonce || !tag)
+		return NULL;
+
+	peer = nan_get_peer(nan, addr);
+	if (!peer)
+		return NULL;
+
+	/* Return nonce and tag pointers if valid, NULL otherwise */
+	if (peer->pairing.nonce_tag_valid) {
+		*nonce = peer->pairing.nonce;
+		*tag = peer->pairing.tag;
+	} else {
+		*nonce = NULL;
+		*tag = NULL;
+	}
+
+	return &peer->pairing.pairing_cfg;
+}
+
+
 static bool
 nan_peer_channel_in_local_sched(const struct nan_data *nan,
 				int peer_ctrl_freq,
diff --git a/src/nan/nan.h b/src/nan/nan.h
index 36b9b4acfc..c66b6a3b5a 100644
--- a/src/nan/nan.h
+++ b/src/nan/nan.h
@@ -718,6 +718,10 @@ int nan_peer_get_pot_avail(struct nan_data *nan, const u8 *addr,
 			   struct nan_peer_potential_avail *pot_avail);
 int nan_peer_dump_pot_avail_to_buf(struct nan_peer_potential_avail *pot_avail,
 				   char *buf, size_t buflen);
+const struct nan_pairing_cfg * nan_peer_get_pairing_cfg(struct nan_data *nan,
+							const u8 *addr,
+							const u8 **nonce,
+							const u8 **tag);
 int nan_convert_sched_to_avail_attrs(struct nan_data *nan, u8 sequence_id,
 				     u32 map_ids_bitmap,
 				     size_t n_chans,
diff --git a/wpa_supplicant/nan_supplicant.c b/wpa_supplicant/nan_supplicant.c
index acebae9157..8a24937137 100644
--- a/wpa_supplicant/nan_supplicant.c
+++ b/wpa_supplicant/nan_supplicant.c
@@ -943,29 +943,21 @@ fail:
 }
 
 
-static const struct wpabuf *wpas_nan_get_npk_akmp_cb(void *ctx,
-						     const u8 *peer_nmi,
-						     const u8 *nonce,
-						     const u8 *tag, int *akmp)
+static const struct wpa_dev_ik *
+wpas_nan_find_ik_by_nonce_tag(struct wpa_supplicant *wpa_s, const u8 *peer_nmi,
+			      const u8 *nonce, const u8 *tag)
 {
-	struct wpa_supplicant *wpa_s = ctx;
 	struct wpa_dev_ik *ik;
 	struct wpabuf *derived_tag;
 
-	if (!akmp) {
-		wpa_printf(MSG_DEBUG, "NAN: Invalid akmp pointer");
-		return NULL;
-	}
-
 	if (!nonce || !tag) {
 		wpa_printf(MSG_DEBUG, "NAN: Invalid nonce or tag");
 		return NULL;
 	}
 
-	wpa_hexdump(MSG_DEBUG, "NAN: Looking up NPK and AKMP for nonce",
-		    nonce, NAN_NIRA_NONCE_LEN);
-	wpa_hexdump(MSG_DEBUG, "NAN: Looking up NPK and AKMP for tag",
-		    tag, NAN_NIRA_TAG_LEN);
+	wpa_printf(MSG_DEBUG, "NAN: Looking up device identity:");
+	wpa_hexdump(MSG_DEBUG, "NONCE", nonce, NAN_NIRA_NONCE_LEN);
+	wpa_hexdump(MSG_DEBUG, "TAG", tag, NAN_NIRA_TAG_LEN);
 
 	/* Iterate over all saved NIKs (stored as device identities) */
 	for (ik = wpa_s->conf->identity; ik; ik = ik->next) {
@@ -1001,7 +993,28 @@ static const struct wpabuf *wpas_nan_get_npk_akmp_cb(void *ctx,
 			   "NAN: NIRA validation succeeded with NIK id=%d",
 			   ik->id);
 		wpabuf_free(derived_tag);
+		return ik;
+	}
+
+	return NULL;
+}
+
+
+static const struct wpabuf *wpas_nan_get_npk_akmp_cb(void *ctx,
+						     const u8 *peer_nmi,
+						     const u8 *nonce,
+						     const u8 *tag, int *akmp)
+{
+	struct wpa_supplicant *wpa_s = ctx;
+	const struct wpa_dev_ik *ik;
+
+	if (!akmp) {
+		wpa_printf(MSG_DEBUG, "NAN: Invalid akmp pointer");
+		return NULL;
+	}
 
+	ik = wpas_nan_find_ik_by_nonce_tag(wpa_s, peer_nmi, nonce, tag);
+	if (ik) {
 		*akmp = ik->akmp;
 		wpa_printf(MSG_DEBUG, "NAN: Found NPK for NIK id=%d, akmp=%d",
 			   ik->id, *akmp);
@@ -2573,6 +2586,33 @@ int wpas_nan_ndp_terminate(struct wpa_supplicant *wpa_s, char *cmd)
 }
 
 
+static int wpas_nan_append_ik_info(char *reply, size_t reply_size,
+				   const struct wpa_dev_ik *ik)
+{
+	char *pos = reply;
+	char *end = reply + reply_size;
+
+	pos += wpa_scnprintf(pos, end - pos, "nik_cipher=%d\n",
+			     ik->dik_cipher);
+	pos += wpa_scnprintf(pos, end - pos, "nik=");
+	pos += wpa_snprintf_hex(pos, end - pos, wpabuf_head(ik->dik),
+				wpabuf_len(ik->dik));
+	pos += wpa_scnprintf(pos, end - pos, "\n");
+
+	if (ik->pmk) {
+		pos += wpa_scnprintf(pos, end - pos, "akmp=%s\n",
+				     wpa_key_mgmt_txt(ik->akmp,
+						      WPA_PROTO_RSN));
+		pos += wpa_scnprintf(pos, end - pos, "npk=");
+		pos += wpa_snprintf_hex(pos, end - pos, wpabuf_head(ik->pmk),
+					wpabuf_len(ik->pmk));
+		pos += wpa_scnprintf(pos, end - pos, "\n");
+	}
+
+	return pos - reply;
+}
+
+
 /* Format: NAN_PEER_INFO <addr> <schedule|potential|capa> [map_id] */
 int wpas_nan_peer_info(struct wpa_supplicant *wpa_s, const char *cmd,
 		       char *reply, size_t reply_size)
@@ -2668,6 +2708,40 @@ int wpas_nan_peer_info(struct wpa_supplicant *wpa_s, const char *cmd,
 		ret = wpa_scnprintf(reply, reply_size,
 				    "supported_methods=0x%04x\n",
 				    supported_methods);
+	} else if (os_strncmp(pos + 1, "pairing", 7) == 0) {
+		const struct nan_pairing_cfg *pairing_cfg;
+		const struct wpa_dev_ik *ik = NULL;
+		const u8 *nonce = NULL;
+		const u8 *tag = NULL;
+
+		pairing_cfg = nan_peer_get_pairing_cfg(wpa_s->nan, addr,
+						       &nonce, &tag);
+		if (!pairing_cfg) {
+			wpa_printf(MSG_DEBUG,
+				   "NAN: Failed to get pairing config for peer "
+				   MACSTR, MAC2STR(addr));
+			return -1;
+		}
+
+		ret = wpa_scnprintf(reply, reply_size,
+				    "pairing_setup=%d\n"
+				    "npk_caching=%d\n"
+				    "pairing_verification=%d\n"
+				    "cipher_suites=0x%08x\n",
+				    pairing_cfg->pairing_setup,
+				    pairing_cfg->npk_caching,
+				    pairing_cfg->pairing_verification,
+				    pairing_cfg->cipher_suites);
+
+		/* Try to find matching NIK if nonce and tag are available */
+		if (nonce && tag)
+			ik = wpas_nan_find_ik_by_nonce_tag(wpa_s, addr, nonce,
+							   tag);
+
+		if (ik)
+			ret += wpas_nan_append_ik_info(reply + ret,
+						       reply_size - ret, ik);
+
 	} else {
 		wpa_printf(MSG_INFO, "NAN: Unknown info type: %s", pos + 1);
 		ret = -1;
-- 
2.53.0




More information about the Hostap mailing list