blob: 5535a3c5a13704a6750299b5af12dcf4ca53073b [file] [log] [blame]
Brad Bishop316dfdd2018-06-25 12:45:53 -04001From 044ae35c5694c39a4aca2a33502cc3897e88f79e Mon Sep 17 00:00:00 2001
2From: Mathy Vanhoef <Mathy.Vanhoef@cs.kuleuven.be>
3Date: Fri, 14 Jul 2017 15:15:35 +0200
4Subject: [PATCH 1/7] hostapd: Avoid key reinstallation in FT handshake
5
6Do not reinstall TK to the driver during Reassociation Response frame
7processing if the first attempt of setting the TK succeeded. This avoids
8issues related to clearing the TX/RX PN that could result in reusing
9same PN values for transmitted frames (e.g., due to CCM nonce reuse and
10also hitting replay protection on the receiver) and accepting replayed
11frames on RX side.
12
13This issue was introduced by the commit
140e84c25434e6a1f283c7b4e62e483729085b78d2 ('FT: Fix PTK configuration in
15authenticator') which allowed wpa_ft_install_ptk() to be called multiple
16times with the same PTK. While the second configuration attempt is
17needed with some drivers, it must be done only if the first attempt
18failed.
19
20Signed-off-by: Mathy Vanhoef <Mathy.Vanhoef@cs.kuleuven.be>
21
22Upstream-Status: Backport
23Signed-off-by: Zheng Ruoqin <zhengrq.fnst@cn.fujitsu.com>
24---
25 src/ap/ieee802_11.c | 16 +++++++++++++---
26 src/ap/wpa_auth.c | 11 +++++++++++
27 src/ap/wpa_auth.h | 3 ++-
28 src/ap/wpa_auth_ft.c | 10 ++++++++++
29 src/ap/wpa_auth_i.h | 1 +
30 5 files changed, 37 insertions(+), 4 deletions(-)
31
32diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
33index 4e04169..333035f 100644
34--- a/src/ap/ieee802_11.c
35+++ b/src/ap/ieee802_11.c
36@@ -1841,6 +1841,7 @@ static int add_associated_sta(struct hostapd_data *hapd,
37 {
38 struct ieee80211_ht_capabilities ht_cap;
39 struct ieee80211_vht_capabilities vht_cap;
40+ int set = 1;
41
42 /*
43 * Remove the STA entry to ensure the STA PS state gets cleared and
44@@ -1848,9 +1849,18 @@ static int add_associated_sta(struct hostapd_data *hapd,
45 * FT-over-the-DS, where a station re-associates back to the same AP but
46 * skips the authentication flow, or if working with a driver that
47 * does not support full AP client state.
48+ *
49+ * Skip this if the STA has already completed FT reassociation and the
50+ * TK has been configured since the TX/RX PN must not be reset to 0 for
51+ * the same key.
52 */
53- if (!sta->added_unassoc)
54+ if (!sta->added_unassoc &&
55+ (!(sta->flags & WLAN_STA_AUTHORIZED) ||
56+ !wpa_auth_sta_ft_tk_already_set(sta->wpa_sm))) {
57 hostapd_drv_sta_remove(hapd, sta->addr);
58+ wpa_auth_sm_event(sta->wpa_sm, WPA_DRV_STA_REMOVED);
59+ set = 0;
60+ }
61
62 #ifdef CONFIG_IEEE80211N
63 if (sta->flags & WLAN_STA_HT)
64@@ -1873,11 +1883,11 @@ static int add_associated_sta(struct hostapd_data *hapd,
65 sta->flags & WLAN_STA_VHT ? &vht_cap : NULL,
66 sta->flags | WLAN_STA_ASSOC, sta->qosinfo,
67 sta->vht_opmode, sta->p2p_ie ? 1 : 0,
68- sta->added_unassoc)) {
69+ set)) {
70 hostapd_logger(hapd, sta->addr,
71 HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_NOTICE,
72 "Could not %s STA to kernel driver",
73- sta->added_unassoc ? "set" : "add");
74+ set ? "set" : "add");
75
76 if (sta->added_unassoc) {
77 hostapd_drv_sta_remove(hapd, sta->addr);
78diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
79index 3587086..707971d 100644
80--- a/src/ap/wpa_auth.c
81+++ b/src/ap/wpa_auth.c
82@@ -1745,6 +1745,9 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event)
83 #else /* CONFIG_IEEE80211R */
84 break;
85 #endif /* CONFIG_IEEE80211R */
86+ case WPA_DRV_STA_REMOVED:
87+ sm->tk_already_set = FALSE;
88+ return 0;
89 }
90
91 #ifdef CONFIG_IEEE80211R
92@@ -3250,6 +3253,14 @@ int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm)
93 }
94
95
96+int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm)
97+{
98+ if (!sm || !wpa_key_mgmt_ft(sm->wpa_key_mgmt))
99+ return 0;
100+ return sm->tk_already_set;
101+}
102+
103+
104 int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
105 struct rsn_pmksa_cache_entry *entry)
106 {
107diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
108index 0de8d97..97461b0 100644
109--- a/src/ap/wpa_auth.h
110+++ b/src/ap/wpa_auth.h
111@@ -267,7 +267,7 @@ void wpa_receive(struct wpa_authenticator *wpa_auth,
112 u8 *data, size_t data_len);
113 enum wpa_event {
114 WPA_AUTH, WPA_ASSOC, WPA_DISASSOC, WPA_DEAUTH, WPA_REAUTH,
115- WPA_REAUTH_EAPOL, WPA_ASSOC_FT
116+ WPA_REAUTH_EAPOL, WPA_ASSOC_FT, WPA_DRV_STA_REMOVED
117 };
118 void wpa_remove_ptk(struct wpa_state_machine *sm);
119 int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event);
120@@ -280,6 +280,7 @@ int wpa_auth_pairwise_set(struct wpa_state_machine *sm);
121 int wpa_auth_get_pairwise(struct wpa_state_machine *sm);
122 int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm);
123 int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm);
124+int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm);
125 int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
126 struct rsn_pmksa_cache_entry *entry);
127 struct rsn_pmksa_cache_entry *
128diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
129index 42242a5..e63b99a 100644
130--- a/src/ap/wpa_auth_ft.c
131+++ b/src/ap/wpa_auth_ft.c
132@@ -780,6 +780,14 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm)
133 return;
134 }
135
136+ if (sm->tk_already_set) {
137+ /* Must avoid TK reconfiguration to prevent clearing of TX/RX
138+ * PN in the driver */
139+ wpa_printf(MSG_DEBUG,
140+ "FT: Do not re-install same PTK to the driver");
141+ return;
142+ }
143+
144 /* FIX: add STA entry to kernel/driver here? The set_key will fail
145 * most likely without this.. At the moment, STA entry is added only
146 * after association has been completed. This function will be called
147@@ -792,6 +800,7 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm)
148
149 /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
150 sm->pairwise_set = TRUE;
151+ sm->tk_already_set = TRUE;
152 }
153
154
155@@ -898,6 +907,7 @@ static int wpa_ft_process_auth_req(struct wpa_state_machine *sm,
156
157 sm->pairwise = pairwise;
158 sm->PTK_valid = TRUE;
159+ sm->tk_already_set = FALSE;
160 wpa_ft_install_ptk(sm);
161
162 buflen = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) +
163diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h
164index 72b7eb3..7fd8f05 100644
165--- a/src/ap/wpa_auth_i.h
166+++ b/src/ap/wpa_auth_i.h
167@@ -65,6 +65,7 @@ struct wpa_state_machine {
168 struct wpa_ptk PTK;
169 Boolean PTK_valid;
170 Boolean pairwise_set;
171+ Boolean tk_already_set;
172 int keycount;
173 Boolean Pair;
174 struct wpa_key_replay_counter {
175--
1761.8.3.1
177