[PATCH v4 20/20] PR: use USD source address for DIRA tag computation

Kavita Kavita kavita.kavita at oss.qualcomm.com
Fri May 22 18:23:52 PDT 2026


From: Peddolla Harshavardhan Reddy <peddolla.reddy at oss.qualcomm.com>

Currently when a USD publish or subscribe session is started with a
forced (random) PR MAC address, pr_prepare_usd_elems() calls
pr_derive_dira() which uses pr->cfg->dev_addr (the regular interface
MAC) to compute the DIRA tag. The USD SDF is transmitted with the
forced address as the source, so the receiving peer uses that address
in pr_validate_dira(). The two addresses differ, causing the HMAC
to never match and DIRA verification to always fail.

To address this issue, add a src_addr parameter to pr_derive_dira()
and pr_prepare_usd_elems() so the caller can supply the address that
will appear as the SDF source on air. Thread this through
wpas_pr_usd_elems() and use params->forced_addr (falling back to
wpa_s->own_addr when no forced address is set) at the two call sites
in wpas_nan_publish() and wpas_nan_subscribe(). The PASN path in
pr_prepare_pasn_pr_elem() is unchanged and continues to pass
pr->cfg->dev_addr, which is already set to the PD wdev address
before any PASN DIRA computation occurs.

Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy at oss.qualcomm.com>
---
 src/common/proximity_ranging.c  | 11 ++++++-----
 src/common/proximity_ranging.h  |  2 +-
 wpa_supplicant/nan_supplicant.c |  8 ++++++--
 wpa_supplicant/pr_supplicant.c  |  5 +++--
 wpa_supplicant/pr_supplicant.h  |  6 ++++--
 5 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/src/common/proximity_ranging.c b/src/common/proximity_ranging.c
index a9fc9c0c1..44289d523 100644
--- a/src/common/proximity_ranging.c
+++ b/src/common/proximity_ranging.c
@@ -388,7 +388,8 @@ static void pr_get_ntb_capabilities(struct pr_data *pr,
 }
 
 
-static int pr_derive_dira(struct pr_data *pr, struct pr_dira *dira)
+static int pr_derive_dira(struct pr_data *pr, const u8 *src_addr,
+			  struct pr_dira *dira)
 {
 	u8 nonce[DEVICE_IDENTITY_NONCE_LEN];
 	u8 tag[DEVICE_MAX_HASH_LEN];
@@ -417,7 +418,7 @@ static int pr_derive_dira(struct pr_data *pr, struct pr_dira *dira)
 	 *                                Nonce))
 	 */
 	os_memcpy(data, "DIR", DIR_STR_LEN);
-	os_memcpy(&data[DIR_STR_LEN], pr->cfg->dev_addr, ETH_ALEN);
+	os_memcpy(&data[DIR_STR_LEN], src_addr, ETH_ALEN);
 	os_memcpy(&data[DIR_STR_LEN + ETH_ALEN], nonce,
 		  DEVICE_IDENTITY_NONCE_LEN);
 
@@ -746,7 +747,7 @@ static void pr_buf_add_dira(struct wpabuf *buf, const struct pr_dira *dira)
 }
 
 
-struct wpabuf * pr_prepare_usd_elems(struct pr_data *pr)
+struct wpabuf * pr_prepare_usd_elems(struct pr_data *pr, const u8 *src_addr)
 {
 	u32 ie_type;
 	struct wpabuf *buf, *buf2;
@@ -774,7 +775,7 @@ struct wpabuf * pr_prepare_usd_elems(struct pr_data *pr)
 		pr_buf_add_ntb_capa_info(buf, &ntb_caps);
 	}
 
-	if (!pr_derive_dira(pr, &dira))
+	if (!pr_derive_dira(pr, src_addr, &dira))
 		pr_buf_add_dira(buf, &dira);
 
 	ie_type = (OUI_WFA << 8) | PR_OUI_TYPE;
@@ -1685,7 +1686,7 @@ static int pr_prepare_pasn_pr_elem(struct pr_data *pr, struct wpabuf *extra_ies,
 	pr_buf_add_operation_mode(buf, &op_mode);
 
 	/* PR Device Identity Resolution attribute */
-	if (!pr_derive_dira(pr, &dira))
+	if (!pr_derive_dira(pr, pr->cfg->dev_addr, &dira))
 		pr_buf_add_dira(buf, &dira);
 
 	ie_type = (OUI_WFA << 8) | PR_OUI_TYPE;
diff --git a/src/common/proximity_ranging.h b/src/common/proximity_ranging.h
index e06c327a1..c7a60c0cb 100644
--- a/src/common/proximity_ranging.h
+++ b/src/common/proximity_ranging.h
@@ -653,7 +653,7 @@ void pr_add_dev_ik(struct pr_data *pr, const u8 *dik, const char *password,
 void pr_set_peer_credentials(struct pr_data *pr, const u8 *addr,
 			     const u8 *pmk, size_t pmk_len,
 			     const char *password);
-struct wpabuf * pr_prepare_usd_elems(struct pr_data *pr);
+struct wpabuf * pr_prepare_usd_elems(struct pr_data *pr, const u8 *src_addr);
 void pr_process_usd_elems(struct pr_data *pr, const u8 *ies, u16 ies_len,
 			  const u8 *peer_addr, unsigned int freq);
 int pr_ensure_oob_peer(struct pr_data *pr, const u8 *addr, int freq);
diff --git a/wpa_supplicant/nan_supplicant.c b/wpa_supplicant/nan_supplicant.c
index e17fbfda6..3f491ca27 100644
--- a/wpa_supplicant/nan_supplicant.c
+++ b/wpa_supplicant/nan_supplicant.c
@@ -4525,7 +4525,9 @@ int wpas_nan_publish(struct wpa_supplicant *wpa_s, const char *service_name,
 		elems = wpas_p2p_usd_elems(wpa_s, service_name);
 		addr = wpa_s->global->p2p_dev_addr;
 	} else if (params->proximity_ranging) {
-		elems = wpas_pr_usd_elems(wpa_s);
+		const u8 *src = params->forced_addr ?
+					params->forced_addr : wpa_s->own_addr;
+		elems = wpas_pr_usd_elems(wpa_s, src);
 	}
 
 	if (params->forced_addr) {
@@ -4685,7 +4687,9 @@ int wpas_nan_subscribe(struct wpa_supplicant *wpa_s,
 		elems = wpas_p2p_usd_elems(wpa_s, service_name);
 		addr = wpa_s->global->p2p_dev_addr;
 	} else if (params->proximity_ranging) {
-		elems = wpas_pr_usd_elems(wpa_s);
+		const u8 *src = params->forced_addr ?
+					params->forced_addr : wpa_s->own_addr;
+		elems = wpas_pr_usd_elems(wpa_s, src);
 	}
 
 	if (params->forced_addr) {
diff --git a/wpa_supplicant/pr_supplicant.c b/wpa_supplicant/pr_supplicant.c
index ed265fb09..1e6f03d53 100644
--- a/wpa_supplicant/pr_supplicant.c
+++ b/wpa_supplicant/pr_supplicant.c
@@ -600,12 +600,13 @@ static void wpas_pr_pasn_clear_keys(void *ctx, const u8 *own_addr,
 }
 
 
-struct wpabuf * wpas_pr_usd_elems(struct wpa_supplicant *wpa_s)
+struct wpabuf * wpas_pr_usd_elems(struct wpa_supplicant *wpa_s,
+				  const u8 *src_addr)
 {
 	if (!wpa_s->global->pr)
 		return NULL;
 
-	return pr_prepare_usd_elems(wpa_s->global->pr);
+	return pr_prepare_usd_elems(wpa_s->global->pr, src_addr);
 }
 
 
diff --git a/wpa_supplicant/pr_supplicant.h b/wpa_supplicant/pr_supplicant.h
index b83782e51..8141cba57 100644
--- a/wpa_supplicant/pr_supplicant.h
+++ b/wpa_supplicant/pr_supplicant.h
@@ -23,7 +23,8 @@ void wpas_pr_clear_dev_iks(struct wpa_supplicant *wpa_s);
 void wpas_pr_set_dev_ik(struct wpa_supplicant *wpa_s, const u8 *dik,
 			const char *password, const u8 *pmk, size_t pmk_len,
 			bool own);
-struct wpabuf * wpas_pr_usd_elems(struct wpa_supplicant *wpa_s);
+struct wpabuf * wpas_pr_usd_elems(struct wpa_supplicant *wpa_s,
+				  const u8 *src_addr);
 void wpas_pr_process_usd_elems(struct wpa_supplicant *wpa_s, const u8 *buf,
 			       u16 buf_len, const u8 *peer_addr,
 			       unsigned int freq);
@@ -82,7 +83,8 @@ static inline void wpas_pr_set_dev_ik(struct wpa_supplicant *wpa_s,
 {
 }
 
-static inline struct wpabuf * wpas_pr_usd_elems(struct wpa_supplicant *wpa_s)
+static inline struct wpabuf * wpas_pr_usd_elems(struct wpa_supplicant *wpa_s,
+						const u8 *src_addr)
 {
 	return NULL;
 }
-- 
2.34.1




More information about the Hostap mailing list