]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
AP MLD: Search MLD-level and per-link PMKSA caches
authorChenming Huang <quic_chenhuan@quicinc.com>
Wed, 26 Feb 2025 14:32:27 +0000 (20:02 +0530)
committerJouni Malinen <j@w1.fi>
Thu, 27 Feb 2025 10:13:30 +0000 (12:13 +0200)
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 <quic_chenhuan@quicinc.com>
src/ap/wpa_auth_ie.c

index 480d5bd8e5a79bf9de0bbf876cb08e98f0df7717..d56eeaa0590e5c93a8caa42bb66a6c0647f9383d 100644 (file)
@@ -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,