From: Peddolla Harshavardhan Reddy Date: Sat, 26 Apr 2025 20:38:47 +0000 (+0530) Subject: PR: Set password/PMK for PASN-SAE based on auth mode and configure RSNXE X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d5c51b2715c48b4bcc73d323f20e0067e51dadde;p=thirdparty%2Fhostap.git PR: Set password/PMK for PASN-SAE based on auth mode and configure RSNXE Set parameters such as password/PMK needed for PASN-SAE and configure the RSNXE for PASN negotiation for Proximity Ranging. Signed-off-by: Peddolla Harshavardhan Reddy --- diff --git a/src/common/proximity_ranging.c b/src/common/proximity_ranging.c index fea0c3dda..d4950a12d 100644 --- a/src/common/proximity_ranging.c +++ b/src/common/proximity_ranging.c @@ -100,6 +100,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; } @@ -132,6 +137,11 @@ void pr_deinit(struct pr_data *pr) pr_deinit_dev_iks(pr); +#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"); } @@ -1040,10 +1050,76 @@ 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; + + capab |= flen - 1; /* bit 0-3 = Field length (n - 1) */ + + wpa_printf(MSG_DEBUG, "PR: 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, 0, 0, 0 }; + size_t len; + + if (!passphrase) + return; + + len = os_strlen(passphrase); + + if ((pasn_type & (PR_PASN_DH20_UNAUTH | PR_PASN_DH20_AUTH)) && + (pasn_type & (PR_PASN_DH19_UNAUTH | PR_PASN_DH19_AUTH))) { + pasn_groups[0] = 20; + pasn_groups[1] = 19; + } else if (pasn_type & (PR_PASN_DH20_UNAUTH | PR_PASN_DH20_AUTH)) { + 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, - u8 ranging_type) + u8 ranging_type, const u8 *pmkid) { + struct wpabuf *rsnxe; struct pasn_data *pasn; if (dev->pasn) { @@ -1058,10 +1134,13 @@ static int pr_pasn_initialize(struct pr_data *pr, struct pr_device *dev, os_memcpy(pasn->own_addr, pr->cfg->dev_addr, ETH_ALEN); os_memcpy(pasn->peer_addr, addr, ETH_ALEN); - if (dev->pasn_role == PR_ROLE_PASN_INITIATOR) + if (dev->pasn_role == PR_ROLE_PASN_INITIATOR) { + pasn->pmksa = pr->initiator_pmksa; os_memcpy(pasn->bssid, pasn->peer_addr, ETH_ALEN); - else + } else { + pasn->pmksa = pr->responder_pmksa; os_memcpy(pasn->bssid, pasn->own_addr, ETH_ALEN); + } pasn->noauth = 1; @@ -1097,16 +1176,55 @@ static int pr_pasn_initialize(struct pr_data *pr, struct pr_device *dev, } wpa_printf(MSG_DEBUG, "PASN: kdk_len=%zu", pasn->kdk_len); - if (auth_mode == PR_PASN_AUTH_MODE_SAE) + 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_INFO, "PR PASN: Password not available"); + return -1; + } + } else if (auth_mode == PR_PASN_AUTH_MODE_PMK && dev->pmk_valid) { + if (!dev->pmk_valid) { + wpa_printf(MSG_INFO, "PR PASN: 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 + } else { pasn->akmp = WPA_KEY_MGMT_PASN; + } 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)); + wpabuf_free(rsnxe); + if (!pasn->rsnxe_ie) + return -1; + } + pasn->cb_ctx = pr->cfg->cb_ctx; pasn->send_mgmt = pr->cfg->pasn_send_mgmt; pasn->freq = freq; @@ -1121,6 +1239,7 @@ 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; + u8 pmkid[PMKID_LEN]; if (!addr) { wpa_printf(MSG_DEBUG, "PR PASN: Peer address NULL"); @@ -1138,7 +1257,12 @@ 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, ranging_type)) { + if (auth_mode == PR_PASN_AUTH_MODE_PMK && dev->pmk_valid && + os_get_random(pmkid, PMKID_LEN) < 0) + return -1; + + if (pr_pasn_initialize(pr, dev, addr, auth_mode, freq, ranging_type, + pmkid)) { wpa_printf(MSG_INFO, "PR PASN: Initialization failed"); return -1; } diff --git a/src/common/proximity_ranging.h b/src/common/proximity_ranging.h index 28f667422..d9b8568dd 100644 --- a/src/common/proximity_ranging.h +++ b/src/common/proximity_ranging.h @@ -424,6 +424,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; }; /* PR Device Identity Resolution Attribute parameters */