[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