diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index b17fc88b9..4df9e253c 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -2181,10 +2181,12 @@ void wpa_sm_notify_disassoc(struct wpa_sm *sm) * @sm: Pointer to WPA state machine data from wpa_sm_init() * @pmk: The new PMK * @pmk_len: The length of the new PMK in bytes + * @bssid: AA to add into PMKSA cache or %NULL to not cache the PMK * * Configure the PMK for WPA state machine. */ -void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len) +void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len, + const u8 *bssid) { if (sm == NULL) return; @@ -2197,6 +2199,11 @@ void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len) sm->xxkey_len = pmk_len; os_memcpy(sm->xxkey, pmk, pmk_len); #endif /* CONFIG_IEEE80211R */ + + if (bssid) { + pmksa_cache_add(sm->pmksa, pmk, pmk_len, bssid, sm->own_addr, + sm->network_ctx, sm->key_mgmt); + } } diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index 63032b023..595fdf209 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -105,7 +105,8 @@ struct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx); void wpa_sm_deinit(struct wpa_sm *sm); void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid); void wpa_sm_notify_disassoc(struct wpa_sm *sm); -void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len); +void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len, + const u8 *bssid); void wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm); void wpa_sm_set_fast_reauth(struct wpa_sm *sm, int fast_reauth); void wpa_sm_set_scard_ctx(struct wpa_sm *sm, void *scard_ctx); diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c index 3083dd809..0e487d2c0 100644 --- a/wpa_supplicant/ibss_rsn.c +++ b/wpa_supplicant/ibss_rsn.c @@ -230,7 +230,7 @@ static int ibss_rsn_supp_init(struct ibss_rsn_peer *peer, const u8 *own_addr, wpa_sm_set_param(peer->supp, WPA_PARAM_PAIRWISE, WPA_CIPHER_CCMP); wpa_sm_set_param(peer->supp, WPA_PARAM_GROUP, WPA_CIPHER_CCMP); wpa_sm_set_param(peer->supp, WPA_PARAM_KEY_MGMT, WPA_KEY_MGMT_PSK); - wpa_sm_set_pmk(peer->supp, psk, PMK_LEN); + wpa_sm_set_pmk(peer->supp, psk, PMK_LEN, NULL); peer->supp_ie_len = sizeof(peer->supp_ie); if (wpa_sm_set_assoc_wpa_ie_default(peer->supp, peer->supp_ie, diff --git a/wpa_supplicant/sme.c b/wpa_supplicant/sme.c index 36b4f87ed..9841c10eb 100644 --- a/wpa_supplicant/sme.c +++ b/wpa_supplicant/sme.c @@ -199,6 +199,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, "0x%x", params.auth_alg); } #ifdef CONFIG_SAE + wpa_s->sme.sae_pmksa_caching = 0; if (wpa_key_mgmt_sae(ssid->key_mgmt)) { const u8 *rsn; struct wpa_ie_data ied; @@ -391,6 +392,15 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s, } #ifdef CONFIG_SAE + if (params.auth_alg == WPA_AUTH_ALG_SAE && + pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, ssid, 0) == 0) + { + wpa_dbg(wpa_s, MSG_DEBUG, + "PMKSA cache entry found - try to use PMKSA caching instead of new SAE authentication"); + params.auth_alg = WPA_AUTH_ALG_OPEN; + wpa_s->sme.sae_pmksa_caching = 1; + } + if (params.auth_alg == WPA_AUTH_ALG_SAE) { if (start) resp = sme_auth_build_sae_commit(wpa_s, ssid, @@ -667,7 +677,8 @@ void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data) wpa_printf(MSG_DEBUG, "SME: SAE completed - setting PMK for " "4-way handshake"); - wpa_sm_set_pmk(wpa_s->wpa, wpa_s->sme.sae.pmk, PMK_LEN); + wpa_sm_set_pmk(wpa_s->wpa, wpa_s->sme.sae.pmk, PMK_LEN, + wpa_s->pending_bssid); } #endif /* CONFIG_SAE */ @@ -881,6 +892,27 @@ void sme_event_assoc_reject(struct wpa_supplicant *wpa_s, eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL); +#ifdef CONFIG_SAE + if (wpa_s->sme.sae_pmksa_caching && wpa_s->current_ssid && + wpa_key_mgmt_sae(wpa_s->current_ssid->key_mgmt)) { + wpa_dbg(wpa_s, MSG_DEBUG, + "PMKSA caching attempt rejected - drop PMKSA cache entry and fall back to SAE authentication"); + wpa_sm_aborted_cached(wpa_s->wpa); + wpa_sm_pmksa_cache_flush(wpa_s->wpa, wpa_s->current_ssid); + if (wpa_s->current_bss) { + struct wpa_bss *bss = wpa_s->current_bss; + struct wpa_ssid *ssid = wpa_s->current_ssid; + + wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid, + WLAN_REASON_DEAUTH_LEAVING); + wpas_connect_work_done(wpa_s); + wpa_supplicant_mark_disassoc(wpa_s); + wpa_supplicant_connect(wpa_s, bss, ssid); + return; + } + } +#endif /* CONFIG_SAE */ + /* * For now, unconditionally terminate the previous authentication. In * theory, this should not be needed, but mac80211 gets quite confused diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index e7aeeacfe..028e034bb 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1177,7 +1177,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, } if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) { - wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN); + wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL); #ifndef CONFIG_NO_PBKDF2 if (bss && ssid->bssid_set && ssid->ssid_len == 0 && ssid->passphrase) { @@ -1186,7 +1186,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, 4096, psk, PMK_LEN); wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)", psk, PMK_LEN); - wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN); + wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL); } #endif /* CONFIG_NO_PBKDF2 */ #ifdef CONFIG_EXT_PASSWORD @@ -1222,7 +1222,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, wpa_hexdump_key(MSG_MSGDUMP, "PSK (from " "external passphrase)", psk, PMK_LEN); - wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN); + wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL); } else #endif /* CONFIG_NO_PBKDF2 */ if (wpabuf_len(pw) == 2 * PMK_LEN) { @@ -1233,7 +1233,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, ext_password_free(pw); return -1; } - wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN); + wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL); } else { wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable " "PSK available"); diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index ba9df624f..f968c96c5 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -651,6 +651,7 @@ struct wpa_supplicant { struct sae_data sae; struct wpabuf *sae_token; int sae_group_index; + unsigned int sae_pmksa_caching:1; #endif /* CONFIG_SAE */ } sme; #endif /* CONFIG_SME */