1 From: Mathy Vanhoef <Mathy.Vanhoef@cs.kuleuven.be>
2 Date: Fri, 14 Jul 2017 15:15:35 +0200
3 Subject: [PATCH] hostapd: Avoid key reinstallation in FT handshake
5 Do not reinstall TK to the driver during Reassociation Response frame
6 processing if the first attempt of setting the TK succeeded. This avoids
7 issues related to clearing the TX/RX PN that could result in reusing
8 same PN values for transmitted frames (e.g., due to CCM nonce reuse and
9 also hitting replay protection on the receiver) and accepting replayed
12 This issue was introduced by the commit
13 0e84c25434e6a1f283c7b4e62e483729085b78d2 ('FT: Fix PTK configuration in
14 authenticator') which allowed wpa_ft_install_ptk() to be called multiple
15 times with the same PTK. While the second configuration attempt is
16 needed with some drivers, it must be done only if the first attempt
19 Signed-off-by: Mathy Vanhoef <Mathy.Vanhoef@cs.kuleuven.be>
22 --- a/src/ap/ieee802_11.c
23 +++ b/src/ap/ieee802_11.c
24 @@ -2522,6 +2522,7 @@ static int add_associated_sta(struct hos
26 struct ieee80211_ht_capabilities ht_cap;
27 struct ieee80211_vht_capabilities vht_cap;
31 * Remove the STA entry to ensure the STA PS state gets cleared and
32 @@ -2529,9 +2530,18 @@ static int add_associated_sta(struct hos
33 * FT-over-the-DS, where a station re-associates back to the same AP but
34 * skips the authentication flow, or if working with a driver that
35 * does not support full AP client state.
37 + * Skip this if the STA has already completed FT reassociation and the
38 + * TK has been configured since the TX/RX PN must not be reset to 0 for
41 - if (!sta->added_unassoc)
42 + if (!sta->added_unassoc &&
43 + (!(sta->flags & WLAN_STA_AUTHORIZED) ||
44 + !wpa_auth_sta_ft_tk_already_set(sta->wpa_sm))) {
45 hostapd_drv_sta_remove(hapd, sta->addr);
46 + wpa_auth_sm_event(sta->wpa_sm, WPA_DRV_STA_REMOVED);
50 #ifdef CONFIG_IEEE80211N
51 if (sta->flags & WLAN_STA_HT)
52 @@ -2554,11 +2564,11 @@ static int add_associated_sta(struct hos
53 sta->flags & WLAN_STA_VHT ? &vht_cap : NULL,
54 sta->flags | WLAN_STA_ASSOC, sta->qosinfo,
55 sta->vht_opmode, sta->p2p_ie ? 1 : 0,
56 - sta->added_unassoc)) {
58 hostapd_logger(hapd, sta->addr,
59 HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_NOTICE,
60 "Could not %s STA to kernel driver",
61 - sta->added_unassoc ? "set" : "add");
62 + set ? "set" : "add");
64 if (sta->added_unassoc) {
65 hostapd_drv_sta_remove(hapd, sta->addr);
66 --- a/src/ap/wpa_auth.c
67 +++ b/src/ap/wpa_auth.c
68 @@ -1783,6 +1783,9 @@ int wpa_auth_sm_event(struct wpa_state_m
69 #else /* CONFIG_FILS */
71 #endif /* CONFIG_FILS */
72 + case WPA_DRV_STA_REMOVED:
73 + sm->tk_already_set = FALSE;
77 #ifdef CONFIG_IEEE80211R_AP
78 @@ -3922,6 +3925,14 @@ int wpa_auth_sta_wpa_version(struct wpa_
82 +int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm)
84 + if (!sm || !wpa_key_mgmt_ft(sm->wpa_key_mgmt))
86 + return sm->tk_already_set;
90 int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
91 struct rsn_pmksa_cache_entry *entry)
93 --- a/src/ap/wpa_auth.h
94 +++ b/src/ap/wpa_auth.h
95 @@ -300,7 +300,7 @@ void wpa_receive(struct wpa_authenticato
96 u8 *data, size_t data_len);
98 WPA_AUTH, WPA_ASSOC, WPA_DISASSOC, WPA_DEAUTH, WPA_REAUTH,
99 - WPA_REAUTH_EAPOL, WPA_ASSOC_FT, WPA_ASSOC_FILS
100 + WPA_REAUTH_EAPOL, WPA_ASSOC_FT, WPA_ASSOC_FILS, WPA_DRV_STA_REMOVED
102 void wpa_remove_ptk(struct wpa_state_machine *sm);
103 int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event);
104 @@ -313,6 +313,7 @@ int wpa_auth_pairwise_set(struct wpa_sta
105 int wpa_auth_get_pairwise(struct wpa_state_machine *sm);
106 int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm);
107 int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm);
108 +int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm);
109 int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
110 struct rsn_pmksa_cache_entry *entry);
111 struct rsn_pmksa_cache_entry *
112 --- a/src/ap/wpa_auth_ft.c
113 +++ b/src/ap/wpa_auth_ft.c
114 @@ -1937,6 +1937,14 @@ void wpa_ft_install_ptk(struct wpa_state
118 + if (sm->tk_already_set) {
119 + /* Must avoid TK reconfiguration to prevent clearing of TX/RX
120 + * PN in the driver */
121 + wpa_printf(MSG_DEBUG,
122 + "FT: Do not re-install same PTK to the driver");
126 /* FIX: add STA entry to kernel/driver here? The set_key will fail
127 * most likely without this.. At the moment, STA entry is added only
128 * after association has been completed. This function will be called
129 @@ -1949,6 +1957,7 @@ void wpa_ft_install_ptk(struct wpa_state
131 /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
132 sm->pairwise_set = TRUE;
133 + sm->tk_already_set = TRUE;
137 @@ -2152,6 +2161,7 @@ static int wpa_ft_process_auth_req(struc
139 sm->pairwise = pairwise;
140 sm->PTK_valid = TRUE;
141 + sm->tk_already_set = FALSE;
142 wpa_ft_install_ptk(sm);
144 buflen = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) +
145 --- a/src/ap/wpa_auth_i.h
146 +++ b/src/ap/wpa_auth_i.h
147 @@ -61,6 +61,7 @@ struct wpa_state_machine {
150 Boolean pairwise_set;
151 + Boolean tk_already_set;
154 struct wpa_key_replay_counter {