[RFC PATCH 17/34] Set password/PMK based on auth mode and configure rsnxe

Peddolla Harshavardhan Reddy peddolla at qti.qualcomm.com
Thu May 15 00:17:40 PDT 2025


Signed-off-by: Peddolla Harshavardhan Reddy <peddolla at qti.qualcomm.com>
---
 src/common/proximity_ranging.c | 142 ++++++++++++++++++++++++++++++++-
 src/common/proximity_ranging.h |   4 +
 2 files changed, 143 insertions(+), 3 deletions(-)

diff --git a/src/common/proximity_ranging.c b/src/common/proximity_ranging.c
index 2bd7ee9fe..f136fe06f 100644
--- a/src/common/proximity_ranging.c
+++ b/src/common/proximity_ranging.c
@@ -98,6 +98,11 @@ struct pr_data * pr_init(const struct pr_config *cfg)
 	dl_list_init(&pr->devices);
 	dl_list_init(&pr->dev_iks);
 
+#ifdef CONFIG_PASN
+	pr->initiator_pmksa = pasn_initiator_pmksa_cache_init();
+	pr->responder_pmksa = pasn_responder_pmksa_cache_init();
+#endif /* CONFIG_PASN */
+
 	return pr;
 }
 
@@ -122,6 +127,11 @@ void pr_deinit(struct pr_data *pr)
 		os_free(dev_ik);
 	}
 
+#ifdef CONFIG_PASN
+	pasn_initiator_pmksa_cache_deinit(pr->initiator_pmksa);
+	pasn_responder_pmksa_cache_deinit(pr->responder_pmksa);
+#endif /* CONFIG_PASN */
+
 	os_free(pr);
 	wpa_printf(MSG_DEBUG, "PR: Deinit done");
 }
@@ -985,9 +995,81 @@ void pr_process_usd_elems(struct pr_data *pr, const u8 *ies, u16 ies_len,
 
 #ifdef CONFIG_PASN
 
+
+
+static struct wpabuf * pr_pasn_generate_rsnxe(struct pr_data *pr, int akmp)
+{
+	u32 capab;
+	size_t flen = 0;
+	struct wpabuf *buf;
+
+	capab = BIT(WLAN_RSNX_CAPAB_KEK_IN_PASN);
+
+	if (wpa_key_mgmt_sae(akmp))
+		capab |= BIT(WLAN_RSNX_CAPAB_SAE_H2E);
+	if (pr->cfg->secure_he_ltf)
+		capab |= BIT(WLAN_RSNX_CAPAB_SECURE_LTF);
+
+	while (capab >> flen * 8)
+		flen++;
+
+	buf = wpabuf_alloc(2 + flen);
+	if (!buf)
+		return NULL;
+
+	if (wpabuf_tailroom(buf) < 2 + flen) {
+		wpa_printf(MSG_ERROR, "wpabuf tail room too small");
+		wpabuf_free(buf);
+		return NULL;
+	}
+	capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */
+
+	wpa_printf(MSG_ERROR, "RSNXE capabilities: %04x", capab);
+	wpabuf_put_u8(buf, WLAN_EID_RSNX);
+	wpabuf_put_u8(buf, flen);
+	while (flen--) {
+		wpabuf_put_u8(buf, (capab & 0xff));
+		capab = capab >> 8;
+	}
+	return buf;
+}
+
+
+/* SSID used for deriving SAE pt for PR security */
+#define PR_PASN_SSID "516F9A010000"
+
+static void pr_pasn_set_password(struct pasn_data *pasn, u8 pasn_type,
+				 const char *passphrase)
+{
+	int pasn_groups[4] = { 0 };
+	size_t len;
+
+	if (!passphrase)
+		return;
+
+	len = os_strlen(passphrase);
+
+	if (pasn_type & 0xc && pasn_type & 0x3) {
+		pasn_groups[0] = 20;
+		pasn_groups[1] = 19;
+	} else if (pasn_type & 0xc) {
+		pasn_groups[0] = 20;
+	} else {
+		pasn_groups[0] = 19;
+	}
+	pasn->pt = sae_derive_pt(pasn_groups, (const u8 *) PR_PASN_SSID,
+				 os_strlen(PR_PASN_SSID),
+				 (const u8 *) passphrase, len, NULL);
+	/* Set passphrase for PASN responder to validate Auth 1 frame */
+	pasn->password = passphrase;
+}
+
+
 static int pr_pasn_initialize(struct pr_data *pr, struct pr_device *dev,
-			      const u8 *addr, u8 auth_mode, int freq)
+			      const u8 *addr, u8 auth_mode, int freq,
+			      const u8 *pmkid)
 {
+	struct wpabuf *rsnxe;
 	struct pasn_data *pasn;
 
 	if (!pr || !dev)
@@ -1006,8 +1088,10 @@ static int pr_pasn_initialize(struct pr_data *pr, struct pr_device *dev,
 	os_memcpy(pasn->peer_addr, addr, ETH_ALEN);
 
 	if (dev->pasn_role == PR_ROLE_PASN_INITIATOR) {
+		pasn->pmksa = pr->initiator_pmksa;
 		os_memcpy(pasn->bssid, pasn->peer_addr, ETH_ALEN);
 	} else {
+		pasn->pmksa = pr->responder_pmksa;
 		os_memcpy(pasn->bssid, pasn->own_addr, ETH_ALEN);
 	}
 
@@ -1034,7 +1118,41 @@ static int pr_pasn_initialize(struct pr_data *pr, struct pr_device *dev,
 
 	if (auth_mode == PR_PASN_AUTH_MODE_SAE) {
 		pasn->akmp = WPA_KEY_MGMT_SAE;
-	} else if (auth_mode == PR_PASN_AUTH_MODE_PMK) {
+		if (dev->password_valid) {
+			pr_pasn_set_password(pasn, pr->cfg->pasn_type,
+					     dev->password);
+		} else if (pr->cfg->global_password_valid) {
+			pr_pasn_set_password(pasn, pr->cfg->pasn_type,
+					     pr->cfg->global_password);
+		} else {
+			wpa_printf(MSG_ERROR, "PASN init: Password not available");
+			return -1;
+		}
+#ifdef CONFIG_TESTING_OPTIONS
+		if (dev->pasn_role == PR_ROLE_PASN_INITIATOR)
+			pasn_initiator_pmksa_cache_flush(pr->initiator_pmksa);
+		else
+			pasn_responder_pmksa_cache_flush(pr->responder_pmksa);
+#endif /* CONFIG_TESTING_OPTIONS */
+	} else if (auth_mode == PR_PASN_AUTH_MODE_PMK && dev->pmk_valid) {
+		if (!dev->pmk_valid) {
+			wpa_printf(MSG_ERROR, "PASN init: PMK not available");
+			return -1;
+		}
+		if (dev->pasn_role == PR_ROLE_PASN_INITIATOR)
+			pasn_initiator_pmksa_cache_add(pr->initiator_pmksa,
+						       pasn->own_addr,
+						       pasn->peer_addr,
+						       dev->pmk,
+						       WPA_PASN_PMK_LEN,
+						       pmkid);
+		else
+			pasn_responder_pmksa_cache_add(pr->responder_pmksa,
+						       pasn->own_addr,
+						       pasn->peer_addr,
+						       dev->pmk,
+						       WPA_PASN_PMK_LEN,
+						       pmkid);
 		pasn->akmp = WPA_KEY_MGMT_SAE;
 	} else {
 		pasn->akmp = WPA_KEY_MGMT_PASN;
@@ -1043,6 +1161,18 @@ static int pr_pasn_initialize(struct pr_data *pr, struct pr_device *dev,
 	pasn->rsn_pairwise = pasn->cipher;
 	pasn->wpa_key_mgmt = pasn->akmp;
 
+	rsnxe = pr_pasn_generate_rsnxe(pr, pasn->akmp);
+	if (rsnxe) {
+		os_free(pasn->rsnxe_ie);
+		pasn->rsnxe_ie = os_memdup(wpabuf_head_u8(rsnxe),
+					   wpabuf_len(rsnxe));
+		if (!pasn->rsnxe_ie) {
+			wpabuf_free(rsnxe);
+			return -1;
+		}
+		wpabuf_free(rsnxe);
+	}
+
 	pasn->cb_ctx = pr->cfg->cb_ctx;
 	pasn->send_mgmt = pr->cfg->pasn_send_mgmt;
 	pasn->freq = freq;
@@ -1057,6 +1187,8 @@ int pr_initiate_pasn_auth(struct pr_data *pr, const u8 *addr, int freq,
 	int ret = 0;
 	struct pasn_data *pasn;
 	struct pr_device *dev;
+	struct wpabuf *extra_ies;
+	u8 pmkid[PMKID_LEN];
 
 	if (!addr) {
 		wpa_printf(MSG_DEBUG, "Peer address NULL");
@@ -1074,7 +1206,11 @@ int pr_initiate_pasn_auth(struct pr_data *pr, const u8 *addr, int freq,
 
 	dev->pasn_role = PR_ROLE_PASN_INITIATOR;
 
-	if (pr_pasn_initialize(pr, dev, addr, auth_mode, freq)) {
+	if (auth_mode == PR_PASN_AUTH_MODE_PMK && dev->pmk_valid) {
+		if (os_get_random(pmkid, PMKID_LEN) < 0)
+			return -1;
+	}
+	if (pr_pasn_initialize(pr, dev, addr, auth_mode, freq, pmkid)) {
 		wpa_printf(MSG_ERROR, "PR PASN: Initialize failed");
 		return -1;
 	}
diff --git a/src/common/proximity_ranging.h b/src/common/proximity_ranging.h
index 16ebaabd7..780df8033 100644
--- a/src/common/proximity_ranging.h
+++ b/src/common/proximity_ranging.h
@@ -361,6 +361,10 @@ struct pr_data {
 	struct dl_list devices;
 
 	struct dl_list dev_iks;
+
+	/* PMKSA cache for PASN-PMK authentication */
+	struct rsn_pmksa_cache *initiator_pmksa;
+	struct rsn_pmksa_cache *responder_pmksa;
 };
 
 
-- 
2.34.1




More information about the Hostap mailing list