From bd545de69714a98d1b4ea16a72c4a3d655083add Mon Sep 17 00:00:00 2001 From: Aditi Date: Thu, 10 Sep 2026 11:27:53 +0530 Subject: [PATCH] feat(wpa_supplicant): Match SPA when searching PMKSA cache Store the supplicant address (SPA) in PMKSA cache entries and match it when looking up the PMKSA cache. (partially picked from commit 18cbdbf2b1998c374b7ef0c00eec4bf708ff6056) --- .../wpa_supplicant/src/rsn_supp/pmksa_cache.c | 16 ++++++++++------ .../wpa_supplicant/src/rsn_supp/pmksa_cache.h | 8 +++++--- components/wpa_supplicant/src/rsn_supp/wpa.c | 9 +++++---- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/components/wpa_supplicant/src/rsn_supp/pmksa_cache.c b/components/wpa_supplicant/src/rsn_supp/pmksa_cache.c index 87f8b6871da..f54ce3fa12b 100644 --- a/components/wpa_supplicant/src/rsn_supp/pmksa_cache.c +++ b/components/wpa_supplicant/src/rsn_supp/pmksa_cache.c @@ -136,6 +136,7 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, entry->reauth_time = now.sec + dot11RSNAConfigPMKLifetime / 100 * dot11RSNAConfigPMKReauthThreshold; entry->akmp = akmp; os_memcpy(entry->aa, aa, ETH_ALEN); + os_memcpy(entry->spa, spa, ETH_ALEN); entry->network_ctx = network_ctx; return pmksa_cache_add_entry(pmksa, entry); @@ -306,17 +307,20 @@ void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa) * pmksa_cache_get - Fetch a PMKSA cache entry * @pmksa: Pointer to PMKSA cache data from pmksa_cache_init() * @aa: Authenticator address or %NULL to match any + * @spa: Supplicant address or %NULL to skip SPA matching (not recommended) * @pmkid: PMKID or %NULL to match any * @network_ctx: Network context or %NULL to match any * Returns: Pointer to PMKSA cache entry or %NULL if no match was found */ struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa, - const u8 *aa, const u8 *pmkid, + const u8 *aa, const u8 *spa, const u8 *pmkid, const void *network_ctx) { struct rsn_pmksa_cache_entry *entry = pmksa->pmksa; while (entry) { if ((aa == NULL || os_memcmp(entry->aa, aa, ETH_ALEN) == 0) && + (spa == NULL || + os_memcmp(entry->spa, spa, ETH_ALEN) == 0) && (pmkid == NULL || os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0) && (network_ctx == NULL || network_ctx == entry->network_ctx)) @@ -435,10 +439,10 @@ int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid, sm->cur_pmksa = NULL; if (pmkid) - sm->cur_pmksa = pmksa_cache_get(pmksa, NULL, pmkid, + sm->cur_pmksa = pmksa_cache_get(pmksa, NULL, sm->own_addr, pmkid, network_ctx); if (sm->cur_pmksa == NULL && bssid) - sm->cur_pmksa = pmksa_cache_get(pmksa, bssid, NULL, + sm->cur_pmksa = pmksa_cache_get(pmksa, bssid, sm->own_addr, NULL, network_ctx); if (sm->cur_pmksa == NULL && try_opportunistic && bssid) sm->cur_pmksa = pmksa_cache_get_opportunistic(pmksa, @@ -471,7 +475,7 @@ int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len) struct rsn_pmksa_cache_entry *entry; struct os_reltime now; ret = os_snprintf(pos, buf + len - pos, - "Index / AA / PMKID / expiration (in seconds) / " + "Index / AA / SPA / PMKID / expiration (in seconds) / " "opportunistic\n"); if (os_snprintf_error(buf + len - pos, ret)) return pos - buf; @@ -481,8 +485,8 @@ int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len) os_get_reltime(&now); while (entry) { i++; - ret = os_snprintf(pos, buf + len - pos, "%d " MACSTR " ", - i, MAC2STR(entry->aa)); + ret = os_snprintf(pos, buf + len - pos, "%d " MACSTR " " MACSTR " ", + i, MAC2STR(entry->aa), MAC2STR(entry->spa)); if (os_snprintf_error(buf + len - pos, ret)) return pos - buf; pos += ret; diff --git a/components/wpa_supplicant/src/rsn_supp/pmksa_cache.h b/components/wpa_supplicant/src/rsn_supp/pmksa_cache.h index 2bdf3d4d156..8954f97f4c0 100644 --- a/components/wpa_supplicant/src/rsn_supp/pmksa_cache.h +++ b/components/wpa_supplicant/src/rsn_supp/pmksa_cache.h @@ -20,6 +20,8 @@ struct rsn_pmksa_cache_entry { os_time_t expiration; int akmp; /* WPA_KEY_MGMT_* */ u8 aa[ETH_ALEN]; + /** Supplicant MAC (SPA) this PMKSA was created for; used when matching cache */ + u8 spa[ETH_ALEN]; os_time_t reauth_time; @@ -52,7 +54,7 @@ pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, void *ctx, struct wpa_sm *sm); void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa); struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa, - const u8 *aa, const u8 *pmkid, + const u8 *aa, const u8 *spa, const u8 *pmkid, const void *network_ctx); int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len); struct rsn_pmksa_cache_entry * @@ -88,8 +90,8 @@ static inline void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa) } static inline struct rsn_pmksa_cache_entry * -pmksa_cache_get(struct rsn_pmksa_cache *pmksa, const u8 *aa, const u8 *pmkid, - const void *network_ctx) +pmksa_cache_get(struct rsn_pmksa_cache *pmksa, const u8 *aa, const u8 *spa, + const u8 *pmkid, const void *network_ctx) { return NULL; } diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index e8f413f41c3..e0967f3f177 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa.c @@ -404,8 +404,8 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm, * not have enough time to get the association information * event before receiving this 1/4 message, so try to find a * matching PMKSA cache entry here. */ - sm->cur_pmksa = pmksa_cache_get(sm->pmksa, src_addr, pmkid, - NULL); + sm->cur_pmksa = pmksa_cache_get(sm->pmksa, src_addr, sm->own_addr, + pmkid, NULL); if (sm->cur_pmksa) { wpa_printf(MSG_DEBUG, "RSN: found matching PMKID from PMKSA cache"); @@ -474,7 +474,7 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm, sm->network_ctx, sm->key_mgmt); } if (!sm->cur_pmksa && pmkid && - pmksa_cache_get(sm->pmksa, src_addr, pmkid, NULL)) + pmksa_cache_get(sm->pmksa, src_addr, sm->own_addr, pmkid, NULL)) { wpa_printf( MSG_DEBUG, "RSN: the new PMK matches with the " @@ -2687,7 +2687,8 @@ int wpa_set_bss(uint8_t *macddr, uint8_t *bssid, uint8_t pairwise_cipher, uint8_ struct rsn_pmksa_cache_entry *pmksa = NULL; if (use_pmk_cache) { - pmksa = pmksa_cache_get(sm->pmksa, (const u8 *)bssid, NULL, NULL); + pmksa = pmksa_cache_get(sm->pmksa, (const u8 *)bssid, sm->own_addr, + NULL, NULL); if (pmksa && (pmksa->akmp != sm->key_mgmt)) { use_pmk_cache = false; }