[PATCH 70/92] NAN: Derive and report ND-PMK after successful pairing
Andrei Otcheretianski
andrei.otcheretianski at intel.com
Wed Apr 22 05:24:01 PDT 2026
From: Avraham Stern <avraham.stern at intel.com>
After a successful pairing, derive the ND-PMK and report it in the
NAN-PAIRING_STATUS message.
Signed-off-by: Avraham Stern <avraham.stern at intel.com>
---
src/common/wpa_ctrl.h | 2 +-
src/nan/nan.h | 4 +-
src/nan/nan_pairing.c | 66 ++++++++++++++++++++++++++++++---
wpa_supplicant/nan_supplicant.c | 15 ++++++--
4 files changed, 76 insertions(+), 11 deletions(-)
diff --git a/src/common/wpa_ctrl.h b/src/common/wpa_ctrl.h
index 31ca1529cc..afb207b509 100644
--- a/src/common/wpa_ctrl.h
+++ b/src/common/wpa_ctrl.h
@@ -257,7 +257,7 @@ extern "C" {
#define NAN_NIK_RECEIVED "NAN-NIK-RECEIVED "
/* NAN Pairing status
- * <peer address> akmp=<SAE|PASN> cipher=<CCMP|GCMP-256> status=<success|failure>
+ * addr=<peer address> akmp=<SAE|PASN> cipher=<CCMP|GCMP-256> status=<success|failure> [nd_pmk=<hex>]
*/
#define NAN_PAIRING_STATUS "NAN-PAIRING-STATUS "
diff --git a/src/nan/nan.h b/src/nan/nan.h
index ab50545732..c1fe905b03 100644
--- a/src/nan/nan.h
+++ b/src/nan/nan.h
@@ -616,12 +616,14 @@ struct nan_config {
* @cipher: Cipher used in the pairing
* @status: Status of the pairing (WLAN_STATUS_* )
* @ptk: Derived PTK for the pairing (valid only if status is success)
+ * @nd_pmk: ND-PMK from the pairing (valid only if status is success)
* Returns: 0 if status is WLAN_STATUS_SUCCESS and the key was
* installed successfully or status is
* WLAN_STATUS_UNSPECIFIED_FAILURE, -1 otherwise
*/
int (*pairing_result_cb)(void *ctx, const u8 *peer_addr, int akmp,
- int cipher, u8 status, struct wpa_ptk *ptk);
+ int cipher, u8 status, struct wpa_ptk *ptk,
+ const u8 *nd_pmk);
/**
* update_pairing_credentials - Report received NIK and NPK for a peer
diff --git a/src/nan/nan_pairing.c b/src/nan/nan_pairing.c
index 0e2e87d039..8cdef0d727 100644
--- a/src/nan/nan_pairing.c
+++ b/src/nan/nan_pairing.c
@@ -786,6 +786,39 @@ static int nan_send_nik(struct nan_data *nan_data, struct nan_peer *peer)
return ret;
}
+static int nan_pairing_derive_nd_pmk(struct nan_data *nan_data,
+ struct nan_peer *peer, u8 *nd_pmk)
+{
+ struct pasn_data *pasn = peer->pairing.pasn;
+ int cipher = pasn_get_cipher(pasn);
+ enum nan_cipher_suite_id csid;
+ u8 *initiator_nmi, *responder_nmi;
+ int ret;
+
+ wpa_printf(MSG_DEBUG,
+ "NAN: Pairing: Derive ND-PMK after PASN pairing");
+
+ if (peer->pairing.self_pairing_role == NAN_PAIRING_ROLE_INITIATOR) {
+ initiator_nmi = nan_data->cfg->nmi_addr;
+ responder_nmi = peer->nmi_addr;
+ } else {
+ initiator_nmi = peer->nmi_addr;
+ responder_nmi = nan_data->cfg->nmi_addr;
+ }
+
+ csid = cipher == WPA_CIPHER_GCMP_256 ? NAN_CS_PK_PASN_256 :
+ NAN_CS_PK_PASN_128;
+
+ ret = nan_crypto_derive_nd_pmk_from_kdk(pasn->ptk.kdk,
+ pasn->ptk.kdk_len, csid,
+ initiator_nmi, responder_nmi,
+ nd_pmk);
+ if (ret)
+ wpa_printf(MSG_DEBUG,
+ "NAN: Pairing: Failed to derive ND PMK");
+ return ret;
+}
+
/*
* nan_pairing_pasn_auth_tx_status - Handle PASN authentication frame TX status
@@ -825,10 +858,22 @@ int nan_pairing_pasn_auth_tx_status(struct nan_data *nan, const u8 *data,
ret = wpa_pasn_auth_tx_status(pasn, data, data_len, acked);
if (ret == 1) {
+ u8 nd_pmk[PMK_LEN];
+
+ if (pasn->status == WLAN_STATUS_SUCCESS &&
+ nan_pairing_derive_nd_pmk(nan, peer, nd_pmk)) {
+ pasn->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ wpa_printf(MSG_DEBUG,
+ "NAN: Pairing: Failed to derive ND PMK");
+ }
+
ret = nan->cfg->pairing_result_cb(nan->cfg->cb_ctx,
- peer->nmi_addr,
- pasn->akmp, pasn->cipher,
- pasn->status, &pasn->ptk);
+ peer->nmi_addr, pasn->akmp,
+ pasn->cipher, pasn->status,
+ &pasn->ptk,
+ pasn->status ==
+ WLAN_STATUS_SUCCESS ? nd_pmk :
+ NULL);
if (pasn->status != WLAN_STATUS_SUCCESS || ret < 0) {
nan_pairing_deinit_peer(peer);
return -1;
@@ -1038,7 +1083,7 @@ static int nan_pairing_handle_auth_2(struct nan_data *nan_data,
peer->nmi_addr, pasn->akmp,
pasn->cipher,
WLAN_STATUS_UNSPECIFIED_FAILURE,
- NULL);
+ NULL, NULL);
nan_pairing_deinit_peer(peer);
return -1;
}
@@ -1055,18 +1100,27 @@ static int nan_pairing_handle_auth_3(struct nan_data *nan_data,
struct pasn_data *pasn = peer->pairing.pasn;
int ret;
u8 status = WLAN_STATUS_SUCCESS;
+ u8 nd_pmk[PMK_LEN];
ret = handle_auth_pasn_3(pasn, nan_data->cfg->nmi_addr, peer->nmi_addr,
mgmt, len);
if (ret < 0) {
status = WLAN_STATUS_UNSPECIFIED_FAILURE;
wpa_printf(MSG_DEBUG, "NAN: Pairing: Handle Auth3 failed");
+ } else {
+ if (nan_pairing_derive_nd_pmk(nan_data, peer, nd_pmk)) {
+ status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ wpa_printf(MSG_DEBUG,
+ "NAN: Pairing: Failed to derive ND PMK");
+ }
}
ret = nan_data->cfg->pairing_result_cb(nan_data->cfg->cb_ctx,
peer->nmi_addr, pasn->akmp,
pasn->cipher, status,
- &pasn->ptk);
+ &pasn->ptk,
+ status == WLAN_STATUS_SUCCESS ?
+ nd_pmk : NULL);
if (ret < 0 || status != WLAN_STATUS_SUCCESS)
nan_pairing_deinit_peer(peer);
else if (status == WLAN_STATUS_SUCCESS)
@@ -1161,7 +1215,7 @@ int nan_pairing_auth_rx(struct nan_data *nan_data,
nan_data->cfg->pairing_result_cb(nan_data->cfg->cb_ctx,
peer->nmi_addr, pasn->akmp,
pasn->cipher, status_code,
- NULL);
+ NULL, NULL);
nan_pairing_deinit_peer(peer);
wpa_printf(MSG_DEBUG,
"NAN: Pairing: Authentication rejected - status=%u",
diff --git a/wpa_supplicant/nan_supplicant.c b/wpa_supplicant/nan_supplicant.c
index d7e71c1457..072ce8229f 100644
--- a/wpa_supplicant/nan_supplicant.c
+++ b/wpa_supplicant/nan_supplicant.c
@@ -857,18 +857,27 @@ static int wpas_nan_pasn_send_cb(void *ctx, const u8 *data, size_t data_len)
static int wpas_nan_pasn_auth_status_cb(void *ctx, const u8 *peer_addr,
int akmp, int cipher, u8 status,
- struct wpa_ptk *ptk)
+ struct wpa_ptk *ptk, const u8 *nd_pmk)
{
struct wpa_supplicant *wpa_s = ctx;
enum wpa_alg alg;
u8 seq[6];
+ char nd_pmk_hex[2 * PMK_LEN + 1];
+
+ if (nd_pmk)
+ wpa_snprintf_hex(nd_pmk_hex, sizeof(nd_pmk_hex), nd_pmk,
+ PMK_LEN);
+ else
+ nd_pmk_hex[0] = '\0';
wpa_msg_global(wpa_s, MSG_INFO,
- NAN_PAIRING_STATUS MACSTR " akmp=%s cipher=%s status=%s",
+ NAN_PAIRING_STATUS "addr=" MACSTR " akmp=%s cipher=%s status=%s%s%s",
MAC2STR(peer_addr),
wpa_key_mgmt_txt(akmp, WPA_PROTO_RSN),
wpa_cipher_txt(cipher),
- status == WLAN_STATUS_SUCCESS ? "success" : "failure");
+ status == WLAN_STATUS_SUCCESS ? "success" : "failure",
+ nd_pmk ? " nd_pmk=" : "",
+ nd_pmk ? nd_pmk_hex : "");
if (status != WLAN_STATUS_SUCCESS)
return 0;
--
2.53.0
More information about the Hostap
mailing list