From: Chenming Huang Date: Wed, 26 Feb 2025 14:32:27 +0000 (+0530) Subject: AP MLD: Search MLD-level and per-link PMKSA caches X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4c1ae91015e34ba83bc892e83739445e0cb4a9f9;p=thirdparty%2Fhostap.git AP MLD: Search MLD-level and per-link PMKSA caches There are cases where non-AP MLD first associates with MLO but reassociates with non-MLO using PMKSA caching. Since the standard does not explicity disallow such cases, it makes sense to have additional code to check the MLD level PMKSA cache as well even when processing non-ML associations. Same would apply in the other direction, i.e., ML association with PMKSA caching should search all affiliated APs of the AP MLD for a PMKID match. Check both the MLD-level and per-link PMKSA caches when trying to find a match for an PMKID in (Re)Association Request frame. Signed-off-by: Chenming Huang --- diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c index 480d5bd8e..d56eeaa05 100644 --- a/src/ap/wpa_auth_ie.c +++ b/src/ap/wpa_auth_ie.c @@ -791,6 +791,32 @@ static int wpa_auth_okc_iter(struct wpa_authenticator *a, void *ctx) } +#ifdef CONFIG_IEEE80211BE + +struct wpa_auth_link_iter_data { + struct wpa_authenticator *wpa_auth; + struct rsn_pmksa_cache_entry *pmksa; + const u8 *spa; + const u8 *pmkid; +}; + +static int wpa_auth_pmksa_iter(struct wpa_authenticator *a, void *ctx) +{ + struct wpa_auth_link_iter_data *data = ctx; + + if (a == data->wpa_auth || + !ether_addr_equal(a->mld_addr, data->wpa_auth->mld_addr)) + return 0; + + data->pmksa = pmksa_cache_auth_get(a->pmksa, data->spa, data->pmkid); + if (data->pmksa) + return 1; + return 0; +} + +#endif /* CONFIG_IEEE80211BE */ + + enum wpa_validate_result wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, struct wpa_state_machine *sm, int freq, @@ -1194,6 +1220,25 @@ wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, #endif /* CONFIG_IEEE80211BE */ sm->pmksa = pmksa_cache_auth_get(pmksa, sm->addr, &data.pmkid[i * PMKID_LEN]); +#ifdef CONFIG_IEEE80211BE + if (!sm->pmksa && !is_ml && wpa_auth->is_ml) + sm->pmksa = pmksa_cache_auth_get( + wpa_auth->ml_pmksa, sm->addr, + &data.pmkid[i * PMKID_LEN]); + if (!sm->pmksa && is_ml) { + struct wpa_auth_link_iter_data idata; + + idata.wpa_auth = wpa_auth; + idata.pmksa = NULL; + idata.spa = sm->addr; + idata.pmkid = &data.pmkid[i * PMKID_LEN]; + wpa_auth_for_each_auth(wpa_auth, + wpa_auth_pmksa_iter, + &idata); + if (idata.pmksa) + sm->pmksa = idata.pmksa; + } +#endif /* CONFIG_IEEE80211BE */ if (!sm->pmksa && !is_zero_ether_addr(sm->p2p_dev_addr)) sm->pmksa = pmksa_cache_auth_get( wpa_auth->pmksa, sm->p2p_dev_addr,