FILS: Accept another (Re)Association Request frame during an association

The previous implementation ended up starting a new EAPOL-Key 4-way
handshake if the STA were to attempt to perform another association.
This resulted in immediate disconnection since the PTK was not ready for
configuring FILS TK at the point when EAPOL-Key msg 1/4 is sent out.
This is better than alloing the association to continue with the same TK
reconfigured, but not really ideal.

Address this potential sequence by not starting a new 4-way handshake on
the additional association attempt. Instead, allow the association to
complete, but do so without reconfiguring the TK to avoid potential
issues with PN reuse with the same TK.

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2017-08-25 16:24:18 +03:00
parent 6db556b21d
commit 2f1357fb62
4 changed files with 23 additions and 2 deletions

View file

@ -2961,6 +2961,9 @@ void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta,
ieee802_1x_new_station(hapd, sta); ieee802_1x_new_station(hapd, sta);
if (reassoc) { if (reassoc) {
if (sta->auth_alg != WLAN_AUTH_FT && if (sta->auth_alg != WLAN_AUTH_FT &&
sta->auth_alg != WLAN_AUTH_FILS_SK &&
sta->auth_alg != WLAN_AUTH_FILS_SK_PFS &&
sta->auth_alg != WLAN_AUTH_FILS_PK &&
!(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS)))
wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH); wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH);
} else } else

View file

@ -2645,7 +2645,8 @@ static int add_associated_sta(struct hostapd_data *hapd,
*/ */
if (!sta->added_unassoc && if (!sta->added_unassoc &&
(!(sta->flags & WLAN_STA_AUTHORIZED) || (!(sta->flags & WLAN_STA_AUTHORIZED) ||
!wpa_auth_sta_ft_tk_already_set(sta->wpa_sm))) { (!wpa_auth_sta_ft_tk_already_set(sta->wpa_sm) &&
!wpa_auth_sta_fils_tk_already_set(sta->wpa_sm)))) {
hostapd_drv_sta_remove(hapd, sta->addr); hostapd_drv_sta_remove(hapd, sta->addr);
wpa_auth_sm_event(sta->wpa_sm, WPA_DRV_STA_REMOVED); wpa_auth_sm_event(sta->wpa_sm, WPA_DRV_STA_REMOVED);
set = 0; set = 0;

View file

@ -2152,6 +2152,7 @@ int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk,
if (res < 0) if (res < 0)
return res; return res;
sm->PTK_valid = TRUE; sm->PTK_valid = TRUE;
sm->tk_already_set = FALSE;
#ifdef CONFIG_IEEE80211R_AP #ifdef CONFIG_IEEE80211R_AP
if (fils_ft_len) { if (fils_ft_len) {
@ -2585,8 +2586,14 @@ int fils_set_tk(struct wpa_state_machine *sm)
enum wpa_alg alg; enum wpa_alg alg;
int klen; int klen;
if (!sm || !sm->PTK_valid) if (!sm || !sm->PTK_valid) {
wpa_printf(MSG_DEBUG, "FILS: No valid PTK available to set TK");
return -1; return -1;
}
if (sm->tk_already_set) {
wpa_printf(MSG_DEBUG, "FILS: TK already set to the driver");
return -1;
}
alg = wpa_cipher_to_alg(sm->pairwise); alg = wpa_cipher_to_alg(sm->pairwise);
klen = wpa_cipher_key_len(sm->pairwise); klen = wpa_cipher_key_len(sm->pairwise);
@ -2597,6 +2604,7 @@ int fils_set_tk(struct wpa_state_machine *sm)
wpa_printf(MSG_DEBUG, "FILS: Failed to set TK to the driver"); wpa_printf(MSG_DEBUG, "FILS: Failed to set TK to the driver");
return -1; return -1;
} }
sm->tk_already_set = TRUE;
return 0; return 0;
} }
@ -3970,6 +3978,14 @@ int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm)
} }
int wpa_auth_sta_fils_tk_already_set(struct wpa_state_machine *sm)
{
if (!sm || !wpa_key_mgmt_fils(sm->wpa_key_mgmt))
return 0;
return sm->tk_already_set;
}
int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm, int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
struct rsn_pmksa_cache_entry *entry) struct rsn_pmksa_cache_entry *entry)
{ {

View file

@ -314,6 +314,7 @@ int wpa_auth_get_pairwise(struct wpa_state_machine *sm);
int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm); int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm);
int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm); int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm);
int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm); int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm);
int wpa_auth_sta_fils_tk_already_set(struct wpa_state_machine *sm);
int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm, int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
struct rsn_pmksa_cache_entry *entry); struct rsn_pmksa_cache_entry *entry);
struct rsn_pmksa_cache_entry * struct rsn_pmksa_cache_entry *