Add PMKSA entries with both AP MLD address and AP link addresse for MLO connection. Per-BSSID PMKSA entries could be used in case the station wants to associate with one of the BSSs without enabling MLO capability later. Signed-off-by: Veerendranath Jakkam <quic_vjakkam@xxxxxxxxxxx> --- src/rsn_supp/wpa.c | 46 ++++++++++++++++++++++++++++----- src/rsn_supp/wpa.h | 4 +-- wpa_supplicant/events.c | 7 +++-- wpa_supplicant/sme.c | 26 ++++++++++++++++--- wpa_supplicant/wpa_supplicant.c | 6 ++++- 5 files changed, 75 insertions(+), 14 deletions(-) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 2b8d95f1c..fd3d5c8da 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -2232,6 +2232,25 @@ static int wpa_validate_mlo_ieee80211w_kdes(struct wpa_sm *sm, } +static void mlo_links_pmksa_cache_add(struct wpa_sm *sm, const u8 *pmk, + size_t pmk_len, const u8 *pmkid, + const u8 *kck, size_t kck_len, + void *network_ctx, int akmp, + const u8 *cache_id) +{ + int i; + + for (i = 0; i < MAX_NUM_MLO_LINKS; i++) { + if (!(sm->mlo.valid_links & BIT(i))) + continue; + + pmksa_cache_add(sm->pmksa, pmk, pmk_len, pmkid, kck, kck_len, + sm->mlo.links[i].bssid, sm->own_addr, + network_ctx, akmp, cache_id); + } +} + + static void wpa_supplicant_process_mlo_3_of_4(struct wpa_sm *sm, const struct wpa_eapol_key *key, u16 ver, const u8 *key_data, @@ -2373,6 +2392,10 @@ static void wpa_supplicant_process_mlo_3_of_4(struct wpa_sm *sm, sm->network_ctx, sm->key_mgmt, NULL); if (!sm->cur_pmksa) sm->cur_pmksa = sa; + + mlo_links_pmksa_cache_add(sm, sm->pmk, sm->pmk_len, NULL, + sm->ptk.kck, sm->ptk.kck_len, + sm->network_ctx, sm->key_mgmt, NULL); } if (ie.transition_disable) @@ -3959,12 +3982,12 @@ void wpa_sm_notify_disassoc(struct wpa_sm *sm) * @pmk: The new PMK * @pmk_len: The length of the new PMK in bytes * @pmkid: Calculated PMKID - * @bssid: AA to add into PMKSA cache or %NULL to not cache the PMK + * @auth_addr: AA to add into PMKSA cache or %NULL to not cache the PMK * * Configure the PMK for WPA state machine. */ void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len, - const u8 *pmkid, const u8 *bssid) + const u8 *pmkid, const u8 *auth_addr) { if (sm == NULL) return; @@ -3980,12 +4003,17 @@ void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len, os_memcpy(sm->xxkey, pmk, pmk_len); #endif /* CONFIG_IEEE80211R */ - if (bssid) { + if (auth_addr) { sm->cur_pmksa = pmksa_cache_add(sm->pmksa, pmk, pmk_len, - pmkid, NULL, 0, bssid, + pmkid, NULL, 0, auth_addr, sm->own_addr, sm->network_ctx, sm->key_mgmt, NULL); + if (sm->mlo.valid_links && + os_memcmp(auth_addr, sm->mlo.ap_mld_addr, ETH_ALEN) == 0) + mlo_links_pmksa_cache_add(sm, pmk, pmk_len, pmkid, NULL, + 0, sm->network_ctx, + sm->key_mgmt, NULL); } } @@ -6020,7 +6048,7 @@ fail: } -int owe_process_assoc_resp(struct wpa_sm *sm, const u8 *bssid, +int owe_process_assoc_resp(struct wpa_sm *sm, const u8 *auth_addr, const u8 *resp_ies, size_t resp_ies_len) { struct ieee802_11_elems elems; @@ -6171,9 +6199,15 @@ int owe_process_assoc_resp(struct wpa_sm *sm, const u8 *bssid, wpa_hexdump_key(MSG_DEBUG, "OWE: PMK", sm->pmk, sm->pmk_len); wpa_hexdump(MSG_DEBUG, "OWE: PMKID", pmkid, PMKID_LEN); pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len, pmkid, NULL, 0, - bssid, sm->own_addr, sm->network_ctx, sm->key_mgmt, + auth_addr, sm->own_addr, sm->network_ctx, sm->key_mgmt, NULL); + if (sm->mlo.valid_links && + os_memcmp(auth_addr, sm->mlo.ap_mld_addr, ETH_ALEN) == 0) + mlo_links_pmksa_cache_add(sm, sm->pmk, sm->pmk_len, pmkid, NULL, + 0, sm->network_ctx, sm->key_mgmt, + NULL); + return 0; } diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index b97edd551..287864e5a 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -153,7 +153,7 @@ void wpa_sm_deinit(struct wpa_sm *sm); void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid); void wpa_sm_notify_disassoc(struct wpa_sm *sm); void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len, - const u8 *pmkid, const u8 *bssid); + const u8 *pmkid, const u8 *auth_addr); void wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm); void wpa_sm_set_fast_reauth(struct wpa_sm *sm, int fast_reauth); void wpa_sm_set_scard_ctx(struct wpa_sm *sm, void *scard_ctx); @@ -568,7 +568,7 @@ struct wpabuf * fils_build_assoc_req(struct wpa_sm *sm, const u8 **kek, int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len); struct wpabuf * owe_build_assoc_req(struct wpa_sm *sm, u16 group); -int owe_process_assoc_resp(struct wpa_sm *sm, const u8 *bssid, +int owe_process_assoc_resp(struct wpa_sm *sm, const u8 *auth_addr, const u8 *resp_ies, size_t resp_ies_len); void wpa_sm_set_reset_fils_completed(struct wpa_sm *sm, int set); diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 4840c82fc..e714ac489 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -3113,7 +3113,8 @@ static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s, #ifdef CONFIG_OWE if (wpa_s->key_mgmt == WPA_KEY_MGMT_OWE && (!bssid_known || - owe_process_assoc_resp(wpa_s->wpa, bssid, + owe_process_assoc_resp(wpa_s->wpa, + wpa_s->valid_links ? wpa_s->ap_mld_addr : bssid, data->assoc_info.resp_ies, data->assoc_info.resp_ies_len) < 0)) { wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_UNSPECIFIED); @@ -5036,7 +5037,9 @@ static void wpa_supplicant_event_assoc_auth(struct wpa_supplicant *wpa_s, data->assoc_info.fils_pmk, data->assoc_info.fils_pmk_len, data->assoc_info.fils_pmkid, - wpa_s->bssid, fils_cache_id); + wpa_s->valid_links ? + wpa_s->ap_mld_addr : wpa_s->bssid, + fils_cache_id); } else if (data->assoc_info.fils_pmkid) { /* Update the current PMKSA used for this connection */ pmksa_cache_set_current(wpa_s->wpa, diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index e6e39c4c3..83269968b 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -1548,12 +1548,12 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction, } -static int sme_sae_set_pmk(struct wpa_supplicant *wpa_s, const u8 *bssid) +static int sme_sae_set_pmk(struct wpa_supplicant *wpa_s, const u8 *auth_addr) { wpa_printf(MSG_DEBUG, "SME: SAE completed - setting PMK for 4-way handshake"); wpa_sm_set_pmk(wpa_s->wpa, wpa_s->sme.sae.pmk, wpa_s->sme.sae.pmk_len, - wpa_s->sme.sae.pmkid, bssid); + wpa_s->sme.sae.pmkid, auth_addr); if (wpa_s->conf->sae_pmkid_in_assoc) { /* Update the own RSNE contents now that we have set the PMK * and added a PMKSA cache entry based on the successfully @@ -1597,6 +1597,8 @@ void sme_external_auth_mgmt_rx(struct wpa_supplicant *wpa_s, if (le_to_host16(header->u.auth.auth_alg) == WLAN_AUTH_SAE) { int res; + struct wpa_bss *bss; + const u8 *auth_addr; res = sme_sae_auth( wpa_s, le_to_host16(header->u.auth.auth_transaction), @@ -1615,7 +1617,25 @@ void sme_external_auth_mgmt_rx(struct wpa_supplicant *wpa_s, if (res != 1) return; - if (sme_sae_set_pmk(wpa_s, wpa_s->sme.ext_auth_bssid) < 0) + auth_addr = wpa_s->sme.ext_auth_bssid; + if (wpa_s->sme.ext_ml_auth) { + bss = wpa_bss_get_bssid_latest( + wpa_s, wpa_s->sme.ext_auth_bssid); + if (!bss) { + wpa_printf(MSG_INFO, + "MLO SAE: BSS not available, update scan result to get BSS"); + wpa_supplicant_update_scan_results(wpa_s); + bss = wpa_bss_get_bssid_latest( + wpa_s, wpa_s->sme.ext_auth_bssid); + } + if (bss && !is_zero_ether_addr(bss->mld_addr)) + auth_addr = bss->mld_addr; + else + wpa_printf(MSG_INFO, + "MLO SAE: AP MLD address fetch failed"); + } + + if (sme_sae_set_pmk(wpa_s, auth_addr) < 0) return; } } diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 4f010ef40..547c00187 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -3101,6 +3101,10 @@ static u8 * wpas_populate_assoc_ies( wpa_key_mgmt_wpa(ssid->key_mgmt)) { int try_opportunistic; const u8 *cache_id = NULL; + const u8 *auth_addr = bss->bssid; + + if (!is_zero_ether_addr(bss->mld_addr)) + auth_addr = bss->mld_addr; try_opportunistic = (ssid->proactive_key_caching < 0 ? wpa_s->conf->okc : @@ -3110,7 +3114,7 @@ static u8 * wpas_populate_assoc_ies( if (wpa_key_mgmt_fils(ssid->key_mgmt)) cache_id = wpa_bss_get_fils_cache_id(bss); #endif /* CONFIG_FILS */ - if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, + if (pmksa_cache_set_current(wpa_s->wpa, NULL, auth_addr, ssid, try_opportunistic, cache_id, 0) == 0) { eapol_sm_notify_pmkid_attempt(wpa_s->eapol); -- 2.25.1 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap