[PATCH v2] wpa_supplicant: Add network option to disable PMKSA caching
Jason Huang
Jason.Huang2 at infineon.com
Tue Jun 30 20:41:31 PDT 2026
From: Darren Li <Darren.Li at infineon.com>
Some certification-oriented test setups need to disable PMKSA
caching on the STA side. Using a very short dot11RSNAConfigPMKLifetime
value for this purpose lets a PMKSA entry be created and then expire,
which can trigger the standard PMKSA expiration deauthentication behavior.
Add a per-network disable_pmksa_caching parameter for wpa_supplicant so
such tests can explicitly avoid adding or selecting PMKSA cache entries.
This preserves the existing PMKSA expiration/removal deauthentication
behavior while providing a direct way to disable PMKSA caching.
The option defaults to disabled, matching existing behavior.
Signed-off-by: Darren Li <Darren.Li at infineon.com>
Signed-off-by: Jason Huang <jason.huang2 at infineon.com>
---
src/rsn_supp/pmksa_cache.c | 21 ++++++++++++++++++
src/rsn_supp/wpa.c | 34 ++++++++++++++++++++++++++++++
src/rsn_supp/wpa.h | 1 +
src/rsn_supp/wpa_i.h | 1 +
wpa_supplicant/config.c | 1 +
wpa_supplicant/config_file.c | 1 +
wpa_supplicant/config_ssid.h | 7 ++++++
wpa_supplicant/wpa_supplicant.conf | 5 +++++
wpa_supplicant/wpas_glue.c | 1 +
9 files changed, 72 insertions(+)
diff --git a/src/rsn_supp/pmksa_cache.c b/src/rsn_supp/pmksa_cache.c
index 9506dfdf1..3c4e37870 100644
--- a/src/rsn_supp/pmksa_cache.c
+++ b/src/rsn_supp/pmksa_cache.c
@@ -249,6 +249,12 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
if (wpa_key_mgmt_suite_b(akmp) && !kck)
return NULL;
+ if (pmksa->sm && pmksa->sm->disable_pmksa_caching) {
+ wpa_printf(MSG_DEBUG,
+ "RSN: PMKSA caching disabled - skip adding PMKSA cache entry");
+ return NULL;
+ }
+
entry = os_zalloc(sizeof(*entry));
if (entry == NULL)
return NULL;
@@ -337,6 +343,13 @@ pmksa_cache_add_entry(struct rsn_pmksa_cache *pmksa,
{
struct rsn_pmksa_cache_entry *pos, *prev;
+ if (pmksa->sm && pmksa->sm->disable_pmksa_caching) {
+ wpa_printf(MSG_DEBUG,
+ "RSN: PMKSA caching disabled - skip adding PMKSA cache entry");
+ _pmksa_cache_free_entry(entry);
+ return NULL;
+ }
+
/* Replace an old entry for the same Authenticator (if found) with the
* new entry */
pos = pmksa->pmksa;
@@ -653,6 +666,8 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get_current(struct wpa_sm *sm)
{
if (sm == NULL)
return NULL;
+ if (sm->disable_pmksa_caching)
+ return NULL;
return sm->cur_pmksa;
}
@@ -693,6 +708,12 @@ int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
wpa_printf(MSG_DEBUG, "RSN: PMKSA cache search - network_ctx=%p "
"try_opportunistic=%d akmp=0x%x",
network_ctx, try_opportunistic, akmp);
+ if (sm->disable_pmksa_caching) {
+ wpa_printf(MSG_DEBUG,
+ "RSN: PMKSA caching disabled - skip cache search");
+ sm->cur_pmksa = NULL;
+ return -1;
+ }
if (pmkid)
wpa_hexdump(MSG_DEBUG, "RSN: Search for PMKID",
pmkid, PMKID_LEN);
diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index 068d653f2..15f213685 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -445,6 +445,26 @@ static int wpa_supplicant_get_pmk(struct wpa_sm *sm,
fils_cache_id, auth_alg);
}
if (!sm->cur_pmksa && pmkid &&
+ sm->disable_pmksa_caching &&
+ sm->proto == WPA_PROTO_RSN &&
+ !wpa_key_mgmt_suite_b(sm->key_mgmt) &&
+ !wpa_key_mgmt_ft(sm->key_mgmt)) {
+ u8 new_pmkid[PMKID_LEN];
+
+ rsn_pmkid(sm->pmk, sm->pmk_len, src_addr,
+ sm->own_addr, new_pmkid,
+ sm->key_mgmt);
+ if (os_memcmp_const(pmkid, new_pmkid,
+ PMKID_LEN) != 0) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_INFO,
+ "RSN: PMKID mismatch with PMKSA caching disabled");
+ return -1;
+ }
+
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+ "RSN: PMKID matches fresh PMK with PMKSA caching disabled");
+ abort_cached = 0;
+ } else if (!sm->cur_pmksa && pmkid &&
pmksa_cache_get(sm->pmksa, src_addr, sm->own_addr,
pmkid, NULL, 0)) {
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
@@ -4837,6 +4857,13 @@ void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config)
}
#endif /* CONFIG_FILS */
sm->beacon_prot = config->beacon_prot;
+ sm->disable_pmksa_caching = config->disable_pmksa_caching;
+ if (sm->disable_pmksa_caching) {
+ pmksa_cache_clear_current(sm);
+ if (wpa_sm_get_state(sm) != WPA_COMPLETED)
+ pmksa_cache_flush(sm->pmksa, sm->network_ctx,
+ NULL, 0, false, NULL);
+ }
} else {
sm->network_ctx = NULL;
sm->allowed_pairwise_cipher = 0;
@@ -4850,6 +4877,7 @@ void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config)
sm->owe_ptk_workaround = 0;
sm->beacon_prot = 0;
sm->force_kdk_derivation = false;
+ sm->disable_pmksa_caching = 0;
}
}
@@ -5862,6 +5890,9 @@ void wpa_sm_pmksa_cache_add(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
int wpa_sm_pmksa_exists(struct wpa_sm *sm, const u8 *bssid, const u8 *own_addr,
const void *network_ctx)
{
+ if (sm->disable_pmksa_caching)
+ return 0;
+
return pmksa_cache_get(sm->pmksa, bssid, own_addr, NULL, network_ctx,
0) != NULL;
}
@@ -5873,6 +5904,9 @@ struct rsn_pmksa_cache_entry * wpa_sm_pmksa_cache_get(struct wpa_sm *sm,
const void *network_ctx,
int akmp)
{
+ if (sm->disable_pmksa_caching)
+ return NULL;
+
return pmksa_cache_get(sm->pmksa, aa, sm->own_addr, pmkid, network_ctx,
akmp);
}
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index d42a7c102..af6f48af6 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -172,6 +172,7 @@ struct rsn_supp_config {
const u8 *fils_cache_id;
int beacon_prot;
bool force_kdk_derivation;
+ int disable_pmksa_caching;
};
struct wpa_sm_link {
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index fc99d2041..d8c594c7e 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -257,6 +257,7 @@ struct wpa_sm {
int last_kck_eapol_key_ver;
u8 last_kck_aa[ETH_ALEN];
int last_eapol_key_ver;
+ int disable_pmksa_caching;
};
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index b05a4d985..d58b603fa 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -2960,6 +2960,7 @@ static const struct parse_data ssid_fields[] = {
#ifdef CONFIG_PASN
{ FUNC(pasn_groups) },
#endif /* CONFIG_PASN */
+ { INT_RANGE(disable_pmksa_caching, 0, 1) },
};
#undef OFFSET
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index 7360f7012..41c4fe06b 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -981,6 +981,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid,
INT(beacon_prot);
INT(transition_disable);
INT(sae_pk);
+ INT(disable_pmksa_caching);
#ifdef CONFIG_HT_OVERRIDES
INT_DEF(disable_ht, DEFAULT_DISABLE_HT);
INT_DEF(disable_ht40, DEFAULT_DISABLE_HT40);
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index 369b867b8..e41f72c93 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -1406,6 +1406,13 @@ struct wpa_ssid {
*/
int *pasn_groups;
#endif /* CONFIG_PASN */
+
+ /**
+ * disable_pmksa_caching - Disable PMKSA caching
+ * 0 = PMKSA caching enabled (default)
+ * 1 = PMKSA caching disabled
+ */
+ int disable_pmksa_caching;
};
#endif /* CONFIG_SSID_H */
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index 56533cb17..62d534e37 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -1260,6 +1260,11 @@ fast_reauth=1
# 0 = disabled (default unless changed with the global okc parameter)
# 1 = enabled
#
+# disable_pmksa_caching:
+# Disable PMKSA caching for this network.
+# 0 = PMKSA caching enabled (default)
+# 1 = PMKSA caching disabled
+#
# ft_eap_pmksa_caching:
# Whether FT-EAP PMKSA caching is allowed
# 0 = do not try to use PMKSA caching with FT-EAP (default)
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index e57114503..f19052cdc 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -1611,6 +1611,7 @@ void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s,
conf.force_kdk_derivation = wpa_s->conf->force_kdk_derivation;
#endif /* CONFIG_TESTING_OPTIONS */
#endif /* CONFIG_PASN */
+ conf.disable_pmksa_caching = ssid->disable_pmksa_caching;
}
wpa_sm_set_config(wpa_s->wpa, ssid ? &conf : NULL);
}
--
2.25.1
More information about the Hostap
mailing list