Add changes to set parameters such as password/PMK needed for PASN-SAE and configure rsnxe for PASN negotiation for Proximity Ranging. Signed-off-by: Peddolla Harshavardhan Reddy <peddolla@xxxxxxxxxxxxxxxx> --- src/common/proximity_ranging.c | 157 ++++++++++++++++++++++++++++++--- src/common/proximity_ranging.h | 4 + 2 files changed, 151 insertions(+), 10 deletions(-) diff --git a/src/common/proximity_ranging.c b/src/common/proximity_ranging.c index a80a36c6e..ea3182c8e 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"); } @@ -983,9 +993,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) @@ -1003,10 +1085,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; @@ -1029,16 +1114,63 @@ static int pr_pasn_initialize(struct pr_data *pr, struct pr_device *dev, if (pr->cfg->secure_he_ltf) pasn->secure_ltf = true; - if (auth_mode == PR_PASN_AUTH_MODE_SAE) - pasn->akmp = WPA_KEY_MGMT_SAE; - else if (auth_mode == PR_PASN_AUTH_MODE_PMK) - pasn->akmp = WPA_KEY_MGMT_SAE; - else - pasn->akmp = WPA_KEY_MGMT_PASN; + if (auth_mode == PR_PASN_AUTH_MODE_SAE) { + pasn->akmp = WPA_KEY_MGMT_SAE; + 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; + } 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; @@ -1053,6 +1185,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, "Peer address NULL"); @@ -1070,7 +1203,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 3cc4a3fd8..e422253e7 100644 --- a/src/common/proximity_ranging.h +++ b/src/common/proximity_ranging.h @@ -415,6 +415,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 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap