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 @@ -2154,6 +2154,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 @@ -2161,9 +2162,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 @@ -2186,11 +2196,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 @@ -1751,6 +1751,9 @@ int wpa_auth_sm_event(struct wpa_state_m
69 #else /* CONFIG_IEEE80211R_AP */
71 #endif /* CONFIG_IEEE80211R_AP */
72 + case WPA_DRV_STA_REMOVED:
73 + sm->tk_already_set = FALSE;
77 #ifdef CONFIG_IEEE80211R_AP
78 @@ -3725,6 +3728,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_ft.c
94 +++ b/src/ap/wpa_auth_ft.c
95 @@ -794,6 +794,14 @@ void wpa_ft_install_ptk(struct wpa_state
99 + if (sm->tk_already_set) {
100 + /* Must avoid TK reconfiguration to prevent clearing of TX/RX
101 + * PN in the driver */
102 + wpa_printf(MSG_DEBUG,
103 + "FT: Do not re-install same PTK to the driver");
107 /* FIX: add STA entry to kernel/driver here? The set_key will fail
108 * most likely without this.. At the moment, STA entry is added only
109 * after association has been completed. This function will be called
110 @@ -806,6 +814,7 @@ void wpa_ft_install_ptk(struct wpa_state
112 /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
113 sm->pairwise_set = TRUE;
114 + sm->tk_already_set = TRUE;
118 @@ -1002,6 +1011,7 @@ static int wpa_ft_process_auth_req(struc
120 sm->pairwise = pairwise;
121 sm->PTK_valid = TRUE;
122 + sm->tk_already_set = FALSE;
123 wpa_ft_install_ptk(sm);
125 buflen = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) +
126 --- a/src/ap/wpa_auth.h
127 +++ b/src/ap/wpa_auth.h
128 @@ -268,7 +268,7 @@ void wpa_receive(struct wpa_authenticato
129 u8 *data, size_t data_len);
131 WPA_AUTH, WPA_ASSOC, WPA_DISASSOC, WPA_DEAUTH, WPA_REAUTH,
132 - WPA_REAUTH_EAPOL, WPA_ASSOC_FT
133 + WPA_REAUTH_EAPOL, WPA_ASSOC_FT, WPA_DRV_STA_REMOVED
135 void wpa_remove_ptk(struct wpa_state_machine *sm);
136 int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event);
137 @@ -281,6 +281,7 @@ int wpa_auth_pairwise_set(struct wpa_sta
138 int wpa_auth_get_pairwise(struct wpa_state_machine *sm);
139 int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm);
140 int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm);
141 +int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm);
142 int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
143 struct rsn_pmksa_cache_entry *entry);
144 struct rsn_pmksa_cache_entry *
145 --- a/src/ap/wpa_auth_i.h
146 +++ b/src/ap/wpa_auth_i.h
147 @@ -65,6 +65,7 @@ struct wpa_state_machine {
150 Boolean pairwise_set;
151 + Boolean tk_already_set;
154 struct wpa_key_replay_counter {