eloop_register_timeout(sec + 1, 0, pmksa_cache_expire, pmksa, NULL);
entry = pmksa->sm->cur_pmksa ? pmksa->sm->cur_pmksa :
- pmksa_cache_get(pmksa, pmksa->sm->bssid, NULL, NULL);
+ pmksa_cache_get(pmksa, pmksa->sm->bssid, NULL, NULL, 0);
if (entry) {
sec = pmksa->pmksa->reauth_time - now.sec;
if (sec < 0)
* @aa: Authenticator address or %NULL to match any
* @pmkid: PMKID or %NULL to match any
* @network_ctx: Network context or %NULL to match any
+ * @akmp: Specific AKMP to search for or 0 for 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 void *network_ctx)
+ const void *network_ctx,
+ int akmp)
{
struct rsn_pmksa_cache_entry *entry = pmksa->pmksa;
while (entry) {
if ((aa == NULL || os_memcmp(entry->aa, aa, ETH_ALEN) == 0) &&
(pmkid == NULL ||
os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0) &&
+ (!akmp || akmp == entry->akmp) &&
(network_ctx == NULL || network_ctx == entry->network_ctx))
return entry;
entry = entry->next;
* @pmksa: Pointer to PMKSA cache data from pmksa_cache_init()
* @network_ctx: Network configuration context
* @aa: Authenticator address for the new AP
+ * @akmp: Specific AKMP to search for or 0 for any
* Returns: Pointer to a new PMKSA cache entry or %NULL if not available
*
* Try to create a new PMKSA cache entry opportunistically by guessing that the
*/
struct rsn_pmksa_cache_entry *
pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa, void *network_ctx,
- const u8 *aa)
+ const u8 *aa, int akmp)
{
struct rsn_pmksa_cache_entry *entry = pmksa->pmksa;
if (network_ctx == NULL)
return NULL;
while (entry) {
- if (entry->network_ctx == network_ctx) {
+ if (entry->network_ctx == network_ctx &&
+ (!akmp || entry->akmp == akmp)) {
entry = pmksa_cache_clone_entry(pmksa, entry, aa);
if (entry) {
wpa_printf(MSG_DEBUG, "RSN: added "
*/
int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
const u8 *bssid, void *network_ctx,
- int try_opportunistic, const u8 *fils_cache_id)
+ int try_opportunistic, const u8 *fils_cache_id,
+ int akmp)
{
struct rsn_pmksa_cache *pmksa = sm->pmksa;
wpa_printf(MSG_DEBUG, "RSN: PMKSA cache search - network_ctx=%p "
- "try_opportunistic=%d", network_ctx, try_opportunistic);
+ "try_opportunistic=%d akmp=0x%x",
+ network_ctx, try_opportunistic, akmp);
if (pmkid)
wpa_hexdump(MSG_DEBUG, "RSN: Search for PMKID",
pmkid, PMKID_LEN);
sm->cur_pmksa = NULL;
if (pmkid)
sm->cur_pmksa = pmksa_cache_get(pmksa, NULL, pmkid,
- network_ctx);
+ network_ctx, akmp);
if (sm->cur_pmksa == NULL && bssid)
sm->cur_pmksa = pmksa_cache_get(pmksa, bssid, NULL,
- network_ctx);
+ network_ctx, akmp);
if (sm->cur_pmksa == NULL && try_opportunistic && bssid)
sm->cur_pmksa = pmksa_cache_get_opportunistic(pmksa,
network_ctx,
- bssid);
+ bssid, akmp);
if (sm->cur_pmksa == NULL && fils_cache_id)
sm->cur_pmksa = pmksa_cache_get_fils_cache_id(pmksa,
network_ctx,
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 void *network_ctx);
+ const void *network_ctx,
+ int akmp);
int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len);
struct rsn_pmksa_cache_entry * pmksa_cache_head(struct rsn_pmksa_cache *pmksa);
struct rsn_pmksa_cache_entry *
void pmksa_cache_clear_current(struct wpa_sm *sm);
int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
const u8 *bssid, void *network_ctx,
- int try_opportunistic, const u8 *fils_cache_id);
+ int try_opportunistic, const u8 *fils_cache_id,
+ int akmp);
struct rsn_pmksa_cache_entry *
pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa,
- void *network_ctx, const u8 *aa);
+ void *network_ctx, const u8 *aa, int akmp);
void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx,
const u8 *pmk, size_t pmk_len);
dl_list_for_each_safe(candidate, n, &sm->pmksa_candidates,
struct rsn_pmksa_candidate, list) {
struct rsn_pmksa_cache_entry *p = NULL;
- p = pmksa_cache_get(sm->pmksa, candidate->bssid, NULL, NULL);
+ p = pmksa_cache_get(sm->pmksa, candidate->bssid, NULL, NULL, 0);
if (os_memcmp(sm->bssid, candidate->bssid, ETH_ALEN) != 0 &&
(p == NULL || p->opportunistic)) {
wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: PMKSA "
if (sm->network_ctx && sm->proactive_key_caching)
pmksa_cache_get_opportunistic(sm->pmksa, sm->network_ctx,
- bssid);
+ bssid, 0);
if (!preauth) {
wpa_printf(MSG_DEBUG, "RSN: Ignored PMKID candidate without "
if (wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie))
return;
- pmksa = pmksa_cache_get(sm->pmksa, bssid, NULL, NULL);
+ pmksa = pmksa_cache_get(sm->pmksa, bssid, NULL, NULL, 0);
if (pmksa && (!pmksa->opportunistic ||
!(ie.capabilities & WPA_CAPABILITY_PREAUTH)))
return;
* 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);
+ NULL, 0);
if (sm->cur_pmksa) {
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
"RSN: found matching PMKID from PMKSA cache");
fils_cache_id);
}
if (!sm->cur_pmksa && pmkid &&
- pmksa_cache_get(sm->pmksa, src_addr, pmkid, NULL))
- {
+ pmksa_cache_get(sm->pmksa, src_addr, pmkid, NULL,
+ 0)) {
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
"RSN: the new PMK matches with the "
"PMKID");
int wpa_sm_pmksa_exists(struct wpa_sm *sm, const u8 *bssid,
const void *network_ctx)
{
- return pmksa_cache_get(sm->pmksa, bssid, NULL, network_ctx) != NULL;
+ return pmksa_cache_get(sm->pmksa, bssid, NULL, network_ctx, 0) != NULL;
}
for (i = 0; i < ie.num_pmkid; i++) {
pmksa_set = pmksa_cache_set_current(wpa_s->wpa,
ie.pmkid + i * PMKID_LEN,
- NULL, NULL, 0, NULL);
+ NULL, NULL, 0, NULL, 0);
if (pmksa_set == 0) {
eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
break;
/* Update the current PMKSA used for this connection */
pmksa_cache_set_current(wpa_s->wpa,
data->assoc_info.fils_pmkid,
- NULL, NULL, 0, NULL);
+ NULL, NULL, 0, NULL, 0);
}
}
#endif /* CONFIG_FILS */
ret = -2;
else {
ret = pmksa_cache_set_current(wpa_s.wpa, NULL, bssid, NULL, 0,
- NULL) ? 0 : -3;
+ NULL, 0) ? 0 : -3;
}
test_eapol_clean(&wpa_s);
#endif /* CONFIG_FILS */
if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
wpa_s->current_ssid,
- try_opportunistic, cache_id) == 0)
+ try_opportunistic, cache_id,
+ 0) == 0)
eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie);
if (wpa_supplicant_set_suites(wpa_s, bss, ssid,
#ifdef CONFIG_SAE
if (!skip_auth && params.auth_alg == WPA_AUTH_ALG_SAE &&
pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, ssid, 0,
- NULL) == 0) {
+ NULL, WPA_KEY_MGMT_SAE) == 0) {
wpa_dbg(wpa_s, MSG_DEBUG,
"PMKSA cache entry found - try to use PMKSA caching instead of new SAE authentication");
wpa_sm_set_pmk_from_pmksa(wpa_s->wpa);
if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
ssid, 0,
- wpa_bss_get_fils_cache_id(bss)) ==
- 0)
+ wpa_bss_get_fils_cache_id(bss),
+ 0) == 0)
wpa_printf(MSG_DEBUG,
"SME: Try to use FILS with PMKSA caching");
resp = fils_build_auth(wpa_s->wpa, ssid->fils_dh_group, md);
#endif /* CONFIG_FILS */
if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid,
ssid, try_opportunistic,
- cache_id) == 0)
+ cache_id, 0) == 0)
eapol_sm_notify_pmkid_attempt(wpa_s->eapol);
wpa_ie_len = max_wpa_ie_len;
if (wpa_supplicant_set_suites(wpa_s, bss, ssid,