Changeset View
Changeset View
Standalone View
Standalone View
files/0001-hostapd-Avoid-key-reinstallation-in-FT-handshake.patch
- This file was added.
| From cf4cab804c7afd5c45505528a8d16e46163243a2 Mon Sep 17 00:00:00 2001 | |||||
| From: Mathy Vanhoef <Mathy.Vanhoef@cs.kuleuven.be> | |||||
| Date: Fri, 14 Jul 2017 15:15:35 +0200 | |||||
| Subject: [PATCH 1/8] hostapd: Avoid key reinstallation in FT handshake | |||||
| Do not reinstall TK to the driver during Reassociation Response frame | |||||
| processing if the first attempt of setting the TK succeeded. This avoids | |||||
| issues related to clearing the TX/RX PN that could result in reusing | |||||
| same PN values for transmitted frames (e.g., due to CCM nonce reuse and | |||||
| also hitting replay protection on the receiver) and accepting replayed | |||||
| frames on RX side. | |||||
| This issue was introduced by the commit | |||||
| 0e84c25434e6a1f283c7b4e62e483729085b78d2 ('FT: Fix PTK configuration in | |||||
| authenticator') which allowed wpa_ft_install_ptk() to be called multiple | |||||
| times with the same PTK. While the second configuration attempt is | |||||
| needed with some drivers, it must be done only if the first attempt | |||||
| failed. | |||||
| Signed-off-by: Mathy Vanhoef <Mathy.Vanhoef@cs.kuleuven.be> | |||||
| --- | |||||
| src/ap/ieee802_11.c | 16 +++++++++++++--- | |||||
| src/ap/wpa_auth.c | 11 +++++++++++ | |||||
| src/ap/wpa_auth.h | 3 ++- | |||||
| src/ap/wpa_auth_ft.c | 10 ++++++++++ | |||||
| src/ap/wpa_auth_i.h | 1 + | |||||
| 5 files changed, 37 insertions(+), 4 deletions(-) | |||||
| diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c | |||||
| index 4e04169..333035f 100644 | |||||
| --- a/src/ap/ieee802_11.c | |||||
| +++ b/src/ap/ieee802_11.c | |||||
| @@ -1841,6 +1841,7 @@ static int add_associated_sta(struct hostapd_data *hapd, | |||||
| { | |||||
| struct ieee80211_ht_capabilities ht_cap; | |||||
| struct ieee80211_vht_capabilities vht_cap; | |||||
| + int set = 1; | |||||
| /* | |||||
| * Remove the STA entry to ensure the STA PS state gets cleared and | |||||
| @@ -1848,9 +1849,18 @@ static int add_associated_sta(struct hostapd_data *hapd, | |||||
| * FT-over-the-DS, where a station re-associates back to the same AP but | |||||
| * skips the authentication flow, or if working with a driver that | |||||
| * does not support full AP client state. | |||||
| + * | |||||
| + * Skip this if the STA has already completed FT reassociation and the | |||||
| + * TK has been configured since the TX/RX PN must not be reset to 0 for | |||||
| + * the same key. | |||||
| */ | |||||
| - if (!sta->added_unassoc) | |||||
| + if (!sta->added_unassoc && | |||||
| + (!(sta->flags & WLAN_STA_AUTHORIZED) || | |||||
| + !wpa_auth_sta_ft_tk_already_set(sta->wpa_sm))) { | |||||
| hostapd_drv_sta_remove(hapd, sta->addr); | |||||
| + wpa_auth_sm_event(sta->wpa_sm, WPA_DRV_STA_REMOVED); | |||||
| + set = 0; | |||||
| + } | |||||
| #ifdef CONFIG_IEEE80211N | |||||
| if (sta->flags & WLAN_STA_HT) | |||||
| @@ -1873,11 +1883,11 @@ static int add_associated_sta(struct hostapd_data *hapd, | |||||
| sta->flags & WLAN_STA_VHT ? &vht_cap : NULL, | |||||
| sta->flags | WLAN_STA_ASSOC, sta->qosinfo, | |||||
| sta->vht_opmode, sta->p2p_ie ? 1 : 0, | |||||
| - sta->added_unassoc)) { | |||||
| + set)) { | |||||
| hostapd_logger(hapd, sta->addr, | |||||
| HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_NOTICE, | |||||
| "Could not %s STA to kernel driver", | |||||
| - sta->added_unassoc ? "set" : "add"); | |||||
| + set ? "set" : "add"); | |||||
| if (sta->added_unassoc) { | |||||
| hostapd_drv_sta_remove(hapd, sta->addr); | |||||
| diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c | |||||
| index 3587086..707971d 100644 | |||||
| --- a/src/ap/wpa_auth.c | |||||
| +++ b/src/ap/wpa_auth.c | |||||
| @@ -1745,6 +1745,9 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event) | |||||
| #else /* CONFIG_IEEE80211R */ | |||||
| break; | |||||
| #endif /* CONFIG_IEEE80211R */ | |||||
| + case WPA_DRV_STA_REMOVED: | |||||
| + sm->tk_already_set = FALSE; | |||||
| + return 0; | |||||
| } | |||||
| #ifdef CONFIG_IEEE80211R | |||||
| @@ -3250,6 +3253,14 @@ int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm) | |||||
| } | |||||
| +int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm) | |||||
| +{ | |||||
| + if (!sm || !wpa_key_mgmt_ft(sm->wpa_key_mgmt)) | |||||
| + return 0; | |||||
| + return sm->tk_already_set; | |||||
| +} | |||||
| + | |||||
| + | |||||
| int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm, | |||||
| struct rsn_pmksa_cache_entry *entry) | |||||
| { | |||||
| diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h | |||||
| index 0de8d97..97461b0 100644 | |||||
| --- a/src/ap/wpa_auth.h | |||||
| +++ b/src/ap/wpa_auth.h | |||||
| @@ -267,7 +267,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth, | |||||
| u8 *data, size_t data_len); | |||||
| enum wpa_event { | |||||
| WPA_AUTH, WPA_ASSOC, WPA_DISASSOC, WPA_DEAUTH, WPA_REAUTH, | |||||
| - WPA_REAUTH_EAPOL, WPA_ASSOC_FT | |||||
| + WPA_REAUTH_EAPOL, WPA_ASSOC_FT, WPA_DRV_STA_REMOVED | |||||
| }; | |||||
| void wpa_remove_ptk(struct wpa_state_machine *sm); | |||||
| int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event); | |||||
| @@ -280,6 +280,7 @@ int wpa_auth_pairwise_set(struct wpa_state_machine *sm); | |||||
| 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_wpa_version(struct wpa_state_machine *sm); | |||||
| +int wpa_auth_sta_ft_tk_already_set(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 * | |||||
| diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c | |||||
| index 42242a5..e63b99a 100644 | |||||
| --- a/src/ap/wpa_auth_ft.c | |||||
| +++ b/src/ap/wpa_auth_ft.c | |||||
| @@ -780,6 +780,14 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm) | |||||
| return; | |||||
| } | |||||
| + if (sm->tk_already_set) { | |||||
| + /* Must avoid TK reconfiguration to prevent clearing of TX/RX | |||||
| + * PN in the driver */ | |||||
| + wpa_printf(MSG_DEBUG, | |||||
| + "FT: Do not re-install same PTK to the driver"); | |||||
| + return; | |||||
| + } | |||||
| + | |||||
| /* FIX: add STA entry to kernel/driver here? The set_key will fail | |||||
| * most likely without this.. At the moment, STA entry is added only | |||||
| * after association has been completed. This function will be called | |||||
| @@ -792,6 +800,7 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm) | |||||
| /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ | |||||
| sm->pairwise_set = TRUE; | |||||
| + sm->tk_already_set = TRUE; | |||||
| } | |||||
| @@ -898,6 +907,7 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm, | |||||
| sm->pairwise = pairwise; | |||||
| sm->PTK_valid = TRUE; | |||||
| + sm->tk_already_set = FALSE; | |||||
| wpa_ft_install_ptk(sm); | |||||
| buflen = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) + | |||||
| diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h | |||||
| index 72b7eb3..7fd8f05 100644 | |||||
| --- a/src/ap/wpa_auth_i.h | |||||
| +++ b/src/ap/wpa_auth_i.h | |||||
| @@ -65,6 +65,7 @@ struct wpa_state_machine { | |||||
| struct wpa_ptk PTK; | |||||
| Boolean PTK_valid; | |||||
| Boolean pairwise_set; | |||||
| + Boolean tk_already_set; | |||||
| int keycount; | |||||
| Boolean Pair; | |||||
| struct wpa_key_replay_counter { | |||||
| -- | |||||
| 2.7.4 | |||||
Copyright © 2015-2021 Solus Project. The Solus logo is Copyright © 2016-2021 Solus Project. All Rights Reserved.