hostapd: backport extra changes related to KRACK
[openwrt/openwrt.git] / package / network / services / hostapd / patches / 013-Add-hostapd-options-wpa_group_update_count-and-wpa_p.patch
1 From 41f140d38617e1fd3fa88c1667c1bce0cad79224 Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?G=C3=BCnther=20Kelleter?= <guenther.kelleter@devolo.de>
3 Date: Thu, 5 Jan 2017 17:00:33 +0100
4 Subject: [PATCH] Add hostapd options wpa_group_update_count and
5 wpa_pairwise_update_count
6 MIME-Version: 1.0
7 Content-Type: text/plain; charset=UTF-8
8 Content-Transfer-Encoding: 8bit
9
10 wpa_group_update_count and wpa_pairwise_update_count can now be used to
11 set the GTK and PTK rekey retry limits (dot11RSNAConfigGroupUpdateCount
12 and dot11RSNAConfigPairwiseUpdateCount). Defaults set to current
13 hardcoded value (4).
14
15 Some stations may suffer from frequent deauthentications due to GTK
16 rekey failures: EAPOL 1/2 frame is not answered during the total timeout
17 period of currently ~3.5 seconds. For example, a Galaxy S6 with Android
18 6.0.1 appears to go into power save mode for up to 5 seconds. Increasing
19 wpa_group_update_count to 6 fixed this issue.
20
21 Signed-off-by: Günther Kelleter <guenther.kelleter@devolo.de>
22 ---
23 hostapd/config_file.c | 22 ++++++++++++++++++++++
24 hostapd/hostapd.conf | 11 +++++++++++
25 src/ap/ap_config.c | 2 ++
26 src/ap/ap_config.h | 2 ++
27 src/ap/wpa_auth.c | 37 ++++++++++++++++++-------------------
28 src/ap/wpa_auth.h | 2 ++
29 src/ap/wpa_auth_glue.c | 2 ++
30 src/ap/wpa_auth_i.h | 4 ++--
31 wpa_supplicant/ibss_rsn.c | 2 ++
32 wpa_supplicant/mesh_rsn.c | 2 ++
33 10 files changed, 65 insertions(+), 21 deletions(-)
34
35 diff --git a/hostapd/config_file.c b/hostapd/config_file.c
36 index 8cfa198c3..02693a5b1 100644
37 --- a/hostapd/config_file.c
38 +++ b/hostapd/config_file.c
39 @@ -2489,6 +2489,28 @@ static int hostapd_config_fill(struct hostapd_config *conf,
40 bss->wpa_gmk_rekey = atoi(pos);
41 } else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) {
42 bss->wpa_ptk_rekey = atoi(pos);
43 + } else if (os_strcmp(buf, "wpa_group_update_count") == 0) {
44 + char *endp;
45 + unsigned long val = strtoul(pos, &endp, 0);
46 +
47 + if (*endp || val < 1 || val > (u32) -1) {
48 + wpa_printf(MSG_ERROR,
49 + "Line %d: Invalid wpa_group_update_count=%lu; allowed range 1..4294967295",
50 + line, val);
51 + return 1;
52 + }
53 + bss->wpa_group_update_count = (u32) val;
54 + } else if (os_strcmp(buf, "wpa_pairwise_update_count") == 0) {
55 + char *endp;
56 + unsigned long val = strtoul(pos, &endp, 0);
57 +
58 + if (*endp || val < 1 || val > (u32) -1) {
59 + wpa_printf(MSG_ERROR,
60 + "Line %d: Invalid wpa_pairwise_update_count=%lu; allowed range 1..4294967295",
61 + line, val);
62 + return 1;
63 + }
64 + bss->wpa_pairwise_update_count = (u32) val;
65 } else if (os_strcmp(buf, "wpa_passphrase") == 0) {
66 int len = os_strlen(pos);
67 if (len < 8 || len > 63) {
68 diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
69 index 314f3842b..1fb1bd987 100644
70 --- a/hostapd/hostapd.conf
71 +++ b/hostapd/hostapd.conf
72 @@ -1221,6 +1221,11 @@ own_ip_addr=127.0.0.1
73 # (dot11RSNAConfigGroupRekeyStrict)
74 #wpa_strict_rekey=1
75
76 +# The number of times EAPOL-Key Message 1/2 in the RSN Group Key Handshake is
77 +#retried per GTK Handshake attempt. (dot11RSNAConfigGroupUpdateCount)
78 +# Range 1..4294967295; default: 4
79 +#wpa_group_update_count=4
80 +
81 # Time interval for rekeying GMK (master key used internally to generate GTKs
82 # (in seconds).
83 #wpa_gmk_rekey=86400
84 @@ -1229,6 +1234,12 @@ own_ip_addr=127.0.0.1
85 # PTK to mitigate some attacks against TKIP deficiencies.
86 #wpa_ptk_rekey=600
87
88 +# The number of times EAPOL-Key Message 1/4 and Message 3/4 in the RSN 4-Way
89 +# Handshake are retried per 4-Way Handshake attempt.
90 +# (dot11RSNAConfigPairwiseUpdateCount)
91 +# Range 1..4294967295; default: 4
92 +#wpa_pairwise_update_count=4
93 +
94 # Enable IEEE 802.11i/RSN/WPA2 pre-authentication. This is used to speed up
95 # roaming be pre-authenticating IEEE 802.1X/EAP part of the full RSN
96 # authentication and key handshake before actually associating with a new AP.
97 diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
98 index c2b80ad97..9abcab7fb 100644
99 --- a/src/ap/ap_config.c
100 +++ b/src/ap/ap_config.c
101 @@ -56,6 +56,8 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
102
103 bss->wpa_group_rekey = 600;
104 bss->wpa_gmk_rekey = 86400;
105 + bss->wpa_group_update_count = 4;
106 + bss->wpa_pairwise_update_count = 4;
107 bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
108 bss->wpa_pairwise = WPA_CIPHER_TKIP;
109 bss->wpa_group = WPA_CIPHER_TKIP;
110 diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
111 index 31b1e7762..7495dc96f 100644
112 --- a/src/ap/ap_config.h
113 +++ b/src/ap/ap_config.h
114 @@ -330,6 +330,8 @@ struct hostapd_bss_config {
115 int wpa_strict_rekey;
116 int wpa_gmk_rekey;
117 int wpa_ptk_rekey;
118 + u32 wpa_group_update_count;
119 + u32 wpa_pairwise_update_count;
120 int rsn_pairwise;
121 int rsn_preauth;
122 char *rsn_preauth_interfaces;
123 diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
124 index 0bd901fbf..8c082f426 100644
125 --- a/src/ap/wpa_auth.c
126 +++ b/src/ap/wpa_auth.c
127 @@ -60,8 +60,6 @@ static void wpa_group_put(struct wpa_authenticator *wpa_auth,
128 struct wpa_group *group);
129 static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos);
130
131 -static const u32 dot11RSNAConfigGroupUpdateCount = 4;
132 -static const u32 dot11RSNAConfigPairwiseUpdateCount = 4;
133 static const u32 eapol_key_timeout_first = 100; /* ms */
134 static const u32 eapol_key_timeout_subseq = 1000; /* ms */
135 static const u32 eapol_key_timeout_first_group = 500; /* ms */
136 @@ -1623,7 +1621,7 @@ static void wpa_send_eapol(struct wpa_authenticator *wpa_auth,
137 {
138 int timeout_ms;
139 int pairwise = key_info & WPA_KEY_INFO_KEY_TYPE;
140 - int ctr;
141 + u32 ctr;
142
143 if (sm == NULL)
144 return;
145 @@ -1640,7 +1638,7 @@ static void wpa_send_eapol(struct wpa_authenticator *wpa_auth,
146 if (pairwise && ctr == 1 && !(key_info & WPA_KEY_INFO_MIC))
147 sm->pending_1_of_4_timeout = 1;
148 wpa_printf(MSG_DEBUG, "WPA: Use EAPOL-Key timeout of %u ms (retry "
149 - "counter %d)", timeout_ms, ctr);
150 + "counter %u)", timeout_ms, ctr);
151 eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000,
152 wpa_send_eapol_timeout, wpa_auth, sm);
153 }
154 @@ -2002,7 +2000,7 @@ SM_STATE(WPA_PTK, PTKSTART)
155 sm->alt_snonce_valid = FALSE;
156
157 sm->TimeoutCtr++;
158 - if (sm->TimeoutCtr > (int) dot11RSNAConfigPairwiseUpdateCount) {
159 + if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) {
160 /* No point in sending the EAPOL-Key - we will disconnect
161 * immediately following this. */
162 return;
163 @@ -2693,7 +2691,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
164 sm->TimeoutEvt = FALSE;
165
166 sm->TimeoutCtr++;
167 - if (sm->TimeoutCtr > (int) dot11RSNAConfigPairwiseUpdateCount) {
168 + if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) {
169 /* No point in sending the EAPOL-Key - we will disconnect
170 * immediately following this. */
171 return;
172 @@ -2988,11 +2986,12 @@ SM_STEP(WPA_PTK)
173 sm->EAPOLKeyPairwise)
174 SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
175 else if (sm->TimeoutCtr >
176 - (int) dot11RSNAConfigPairwiseUpdateCount) {
177 + sm->wpa_auth->conf.wpa_pairwise_update_count) {
178 wpa_auth->dot11RSNA4WayHandshakeFailures++;
179 - wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
180 - "PTKSTART: Retry limit %d reached",
181 - dot11RSNAConfigPairwiseUpdateCount);
182 + wpa_auth_vlogger(
183 + sm->wpa_auth, sm->addr, LOGGER_DEBUG,
184 + "PTKSTART: Retry limit %u reached",
185 + sm->wpa_auth->conf.wpa_pairwise_update_count);
186 SM_ENTER(WPA_PTK, DISCONNECT);
187 } else if (sm->TimeoutEvt)
188 SM_ENTER(WPA_PTK, PTKSTART);
189 @@ -3016,12 +3015,12 @@ SM_STEP(WPA_PTK)
190 sm->EAPOLKeyPairwise && sm->MICVerified)
191 SM_ENTER(WPA_PTK, PTKINITDONE);
192 else if (sm->TimeoutCtr >
193 - (int) dot11RSNAConfigPairwiseUpdateCount) {
194 + sm->wpa_auth->conf.wpa_pairwise_update_count) {
195 wpa_auth->dot11RSNA4WayHandshakeFailures++;
196 - wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
197 - "PTKINITNEGOTIATING: Retry limit %d "
198 - "reached",
199 - dot11RSNAConfigPairwiseUpdateCount);
200 + wpa_auth_vlogger(
201 + sm->wpa_auth, sm->addr, LOGGER_DEBUG,
202 + "PTKINITNEGOTIATING: Retry limit %u reached",
203 + sm->wpa_auth->conf.wpa_pairwise_update_count);
204 SM_ENTER(WPA_PTK, DISCONNECT);
205 } else if (sm->TimeoutEvt)
206 SM_ENTER(WPA_PTK, PTKINITNEGOTIATING);
207 @@ -3056,7 +3055,7 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING)
208 SM_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group);
209
210 sm->GTimeoutCtr++;
211 - if (sm->GTimeoutCtr > (int) dot11RSNAConfigGroupUpdateCount) {
212 + if (sm->GTimeoutCtr > sm->wpa_auth->conf.wpa_group_update_count) {
213 /* No point in sending the EAPOL-Key - we will disconnect
214 * immediately following this. */
215 return;
216 @@ -3154,7 +3153,7 @@ SM_STEP(WPA_PTK_GROUP)
217 !sm->EAPOLKeyPairwise && sm->MICVerified)
218 SM_ENTER(WPA_PTK_GROUP, REKEYESTABLISHED);
219 else if (sm->GTimeoutCtr >
220 - (int) dot11RSNAConfigGroupUpdateCount)
221 + sm->wpa_auth->conf.wpa_group_update_count)
222 SM_ENTER(WPA_PTK_GROUP, KEYERROR);
223 else if (sm->TimeoutEvt)
224 SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING);
225 @@ -3614,8 +3613,8 @@ int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen)
226 "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n",
227 RSN_VERSION,
228 !!wpa_auth->conf.wpa_strict_rekey,
229 - dot11RSNAConfigGroupUpdateCount,
230 - dot11RSNAConfigPairwiseUpdateCount,
231 + wpa_auth->conf.wpa_group_update_count,
232 + wpa_auth->conf.wpa_pairwise_update_count,
233 wpa_cipher_key_len(wpa_auth->conf.wpa_group) * 8,
234 dot11RSNAConfigPMKLifetime,
235 dot11RSNAConfigPMKReauthThreshold,
236 diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
237 index 9cbe3889b..0920a169d 100644
238 --- a/src/ap/wpa_auth.h
239 +++ b/src/ap/wpa_auth.h
240 @@ -144,6 +144,8 @@ struct wpa_auth_config {
241 int wpa_strict_rekey;
242 int wpa_gmk_rekey;
243 int wpa_ptk_rekey;
244 + u32 wpa_group_update_count;
245 + u32 wpa_pairwise_update_count;
246 int rsn_pairwise;
247 int rsn_preauth;
248 int eapol_version;
249 diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
250 index 22518a1f1..394f77a66 100644
251 --- a/src/ap/wpa_auth_glue.c
252 +++ b/src/ap/wpa_auth_glue.c
253 @@ -41,6 +41,8 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
254 wconf->wpa_strict_rekey = conf->wpa_strict_rekey;
255 wconf->wpa_gmk_rekey = conf->wpa_gmk_rekey;
256 wconf->wpa_ptk_rekey = conf->wpa_ptk_rekey;
257 + wconf->wpa_group_update_count = conf->wpa_group_update_count;
258 + wconf->wpa_pairwise_update_count = conf->wpa_pairwise_update_count;
259 wconf->rsn_pairwise = conf->rsn_pairwise;
260 wconf->rsn_preauth = conf->rsn_preauth;
261 wconf->eapol_version = conf->eapol_version;
262 diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h
263 index 065a624ad..cda2c5065 100644
264 --- a/src/ap/wpa_auth_i.h
265 +++ b/src/ap/wpa_auth_i.h
266 @@ -48,8 +48,8 @@ struct wpa_state_machine {
267 Boolean AuthenticationRequest;
268 Boolean ReAuthenticationRequest;
269 Boolean Disconnect;
270 - int TimeoutCtr;
271 - int GTimeoutCtr;
272 + u32 TimeoutCtr;
273 + u32 GTimeoutCtr;
274 Boolean TimeoutEvt;
275 Boolean EAPOLKeyReceived;
276 Boolean EAPOLKeyPairwise;
277 diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c
278 index 521a692ba..954061ae4 100644
279 --- a/wpa_supplicant/ibss_rsn.c
280 +++ b/wpa_supplicant/ibss_rsn.c
281 @@ -428,6 +428,8 @@ static int ibss_rsn_auth_init_group(struct ibss_rsn *ibss_rsn,
282 conf.wpa_group = WPA_CIPHER_CCMP;
283 conf.eapol_version = 2;
284 conf.wpa_group_rekey = ssid->group_rekey ? ssid->group_rekey : 600;
285 + conf.wpa_group_update_count = 4;
286 + conf.wpa_pairwise_update_count = 4;
287
288 ibss_rsn->auth_group = wpa_init(own_addr, &conf, &cb, ibss_rsn);
289 if (ibss_rsn->auth_group == NULL) {
290 diff --git a/wpa_supplicant/mesh_rsn.c b/wpa_supplicant/mesh_rsn.c
291 index 33040f30b..628382cbf 100644
292 --- a/wpa_supplicant/mesh_rsn.c
293 +++ b/wpa_supplicant/mesh_rsn.c
294 @@ -158,6 +158,8 @@ static int __mesh_rsn_auth_init(struct mesh_rsn *rsn, const u8 *addr,
295 conf.wpa_group = rsn->group_cipher;
296 conf.eapol_version = 0;
297 conf.wpa_group_rekey = -1;
298 + conf.wpa_group_update_count = 4;
299 + conf.wpa_pairwise_update_count = 4;
300 #ifdef CONFIG_IEEE80211W
301 conf.ieee80211w = ieee80211w;
302 if (ieee80211w != NO_MGMT_FRAME_PROTECTION)
303 --
304 2.13.6
305