+++ /dev/null
-From 41f140d38617e1fd3fa88c1667c1bce0cad79224 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?G=C3=BCnther=20Kelleter?= <guenther.kelleter@devolo.de>
-Date: Thu, 5 Jan 2017 17:00:33 +0100
-Subject: [PATCH] Add hostapd options wpa_group_update_count and
- wpa_pairwise_update_count
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-wpa_group_update_count and wpa_pairwise_update_count can now be used to
-set the GTK and PTK rekey retry limits (dot11RSNAConfigGroupUpdateCount
-and dot11RSNAConfigPairwiseUpdateCount). Defaults set to current
-hardcoded value (4).
-
-Some stations may suffer from frequent deauthentications due to GTK
-rekey failures: EAPOL 1/2 frame is not answered during the total timeout
-period of currently ~3.5 seconds. For example, a Galaxy S6 with Android
-6.0.1 appears to go into power save mode for up to 5 seconds. Increasing
-wpa_group_update_count to 6 fixed this issue.
-
-Signed-off-by: Günther Kelleter <guenther.kelleter@devolo.de>
----
- hostapd/config_file.c | 22 ++++++++++++++++++++++
- hostapd/hostapd.conf | 11 +++++++++++
- src/ap/ap_config.c | 2 ++
- src/ap/ap_config.h | 2 ++
- src/ap/wpa_auth.c | 37 ++++++++++++++++++-------------------
- src/ap/wpa_auth.h | 2 ++
- src/ap/wpa_auth_glue.c | 2 ++
- src/ap/wpa_auth_i.h | 4 ++--
- wpa_supplicant/ibss_rsn.c | 2 ++
- wpa_supplicant/mesh_rsn.c | 2 ++
- 10 files changed, 65 insertions(+), 21 deletions(-)
-
-diff --git a/hostapd/config_file.c b/hostapd/config_file.c
-index 8cfa198c3..02693a5b1 100644
---- a/hostapd/config_file.c
-+++ b/hostapd/config_file.c
-@@ -2489,6 +2489,28 @@ static int hostapd_config_fill(struct hostapd_config *conf,
- bss->wpa_gmk_rekey = atoi(pos);
- } else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) {
- bss->wpa_ptk_rekey = atoi(pos);
-+ } else if (os_strcmp(buf, "wpa_group_update_count") == 0) {
-+ char *endp;
-+ unsigned long val = strtoul(pos, &endp, 0);
-+
-+ if (*endp || val < 1 || val > (u32) -1) {
-+ wpa_printf(MSG_ERROR,
-+ "Line %d: Invalid wpa_group_update_count=%lu; allowed range 1..4294967295",
-+ line, val);
-+ return 1;
-+ }
-+ bss->wpa_group_update_count = (u32) val;
-+ } else if (os_strcmp(buf, "wpa_pairwise_update_count") == 0) {
-+ char *endp;
-+ unsigned long val = strtoul(pos, &endp, 0);
-+
-+ if (*endp || val < 1 || val > (u32) -1) {
-+ wpa_printf(MSG_ERROR,
-+ "Line %d: Invalid wpa_pairwise_update_count=%lu; allowed range 1..4294967295",
-+ line, val);
-+ return 1;
-+ }
-+ bss->wpa_pairwise_update_count = (u32) val;
- } else if (os_strcmp(buf, "wpa_passphrase") == 0) {
- int len = os_strlen(pos);
- if (len < 8 || len > 63) {
-diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf
-index 314f3842b..1fb1bd987 100644
---- a/hostapd/hostapd.conf
-+++ b/hostapd/hostapd.conf
-@@ -1221,6 +1221,11 @@ own_ip_addr=127.0.0.1
- # (dot11RSNAConfigGroupRekeyStrict)
- #wpa_strict_rekey=1
-
-+# The number of times EAPOL-Key Message 1/2 in the RSN Group Key Handshake is
-+#retried per GTK Handshake attempt. (dot11RSNAConfigGroupUpdateCount)
-+# Range 1..4294967295; default: 4
-+#wpa_group_update_count=4
-+
- # Time interval for rekeying GMK (master key used internally to generate GTKs
- # (in seconds).
- #wpa_gmk_rekey=86400
-@@ -1229,6 +1234,12 @@ own_ip_addr=127.0.0.1
- # PTK to mitigate some attacks against TKIP deficiencies.
- #wpa_ptk_rekey=600
-
-+# The number of times EAPOL-Key Message 1/4 and Message 3/4 in the RSN 4-Way
-+# Handshake are retried per 4-Way Handshake attempt.
-+# (dot11RSNAConfigPairwiseUpdateCount)
-+# Range 1..4294967295; default: 4
-+#wpa_pairwise_update_count=4
-+
- # Enable IEEE 802.11i/RSN/WPA2 pre-authentication. This is used to speed up
- # roaming be pre-authenticating IEEE 802.1X/EAP part of the full RSN
- # authentication and key handshake before actually associating with a new AP.
-diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c
-index c2b80ad97..9abcab7fb 100644
---- a/src/ap/ap_config.c
-+++ b/src/ap/ap_config.c
-@@ -56,6 +56,8 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
-
- bss->wpa_group_rekey = 600;
- bss->wpa_gmk_rekey = 86400;
-+ bss->wpa_group_update_count = 4;
-+ bss->wpa_pairwise_update_count = 4;
- bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
- bss->wpa_pairwise = WPA_CIPHER_TKIP;
- bss->wpa_group = WPA_CIPHER_TKIP;
-diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h
-index 31b1e7762..7495dc96f 100644
---- a/src/ap/ap_config.h
-+++ b/src/ap/ap_config.h
-@@ -330,6 +330,8 @@ struct hostapd_bss_config {
- int wpa_strict_rekey;
- int wpa_gmk_rekey;
- int wpa_ptk_rekey;
-+ u32 wpa_group_update_count;
-+ u32 wpa_pairwise_update_count;
- int rsn_pairwise;
- int rsn_preauth;
- char *rsn_preauth_interfaces;
-diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c
-index 0bd901fbf..8c082f426 100644
---- a/src/ap/wpa_auth.c
-+++ b/src/ap/wpa_auth.c
-@@ -60,8 +60,6 @@ static void wpa_group_put(struct wpa_authenticator *wpa_auth,
- struct wpa_group *group);
- static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos);
-
--static const u32 dot11RSNAConfigGroupUpdateCount = 4;
--static const u32 dot11RSNAConfigPairwiseUpdateCount = 4;
- static const u32 eapol_key_timeout_first = 100; /* ms */
- static const u32 eapol_key_timeout_subseq = 1000; /* ms */
- static const u32 eapol_key_timeout_first_group = 500; /* ms */
-@@ -1623,7 +1621,7 @@ static void wpa_send_eapol(struct wpa_authenticator *wpa_auth,
- {
- int timeout_ms;
- int pairwise = key_info & WPA_KEY_INFO_KEY_TYPE;
-- int ctr;
-+ u32 ctr;
-
- if (sm == NULL)
- return;
-@@ -1640,7 +1638,7 @@ static void wpa_send_eapol(struct wpa_authenticator *wpa_auth,
- if (pairwise && ctr == 1 && !(key_info & WPA_KEY_INFO_MIC))
- sm->pending_1_of_4_timeout = 1;
- wpa_printf(MSG_DEBUG, "WPA: Use EAPOL-Key timeout of %u ms (retry "
-- "counter %d)", timeout_ms, ctr);
-+ "counter %u)", timeout_ms, ctr);
- eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000,
- wpa_send_eapol_timeout, wpa_auth, sm);
- }
-@@ -2002,7 +2000,7 @@ SM_STATE(WPA_PTK, PTKSTART)
- sm->alt_snonce_valid = FALSE;
-
- sm->TimeoutCtr++;
-- if (sm->TimeoutCtr > (int) dot11RSNAConfigPairwiseUpdateCount) {
-+ if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) {
- /* No point in sending the EAPOL-Key - we will disconnect
- * immediately following this. */
- return;
-@@ -2693,7 +2691,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
- sm->TimeoutEvt = FALSE;
-
- sm->TimeoutCtr++;
-- if (sm->TimeoutCtr > (int) dot11RSNAConfigPairwiseUpdateCount) {
-+ if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) {
- /* No point in sending the EAPOL-Key - we will disconnect
- * immediately following this. */
- return;
-@@ -2988,11 +2986,12 @@ SM_STEP(WPA_PTK)
- sm->EAPOLKeyPairwise)
- SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
- else if (sm->TimeoutCtr >
-- (int) dot11RSNAConfigPairwiseUpdateCount) {
-+ sm->wpa_auth->conf.wpa_pairwise_update_count) {
- wpa_auth->dot11RSNA4WayHandshakeFailures++;
-- wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
-- "PTKSTART: Retry limit %d reached",
-- dot11RSNAConfigPairwiseUpdateCount);
-+ wpa_auth_vlogger(
-+ sm->wpa_auth, sm->addr, LOGGER_DEBUG,
-+ "PTKSTART: Retry limit %u reached",
-+ sm->wpa_auth->conf.wpa_pairwise_update_count);
- SM_ENTER(WPA_PTK, DISCONNECT);
- } else if (sm->TimeoutEvt)
- SM_ENTER(WPA_PTK, PTKSTART);
-@@ -3016,12 +3015,12 @@ SM_STEP(WPA_PTK)
- sm->EAPOLKeyPairwise && sm->MICVerified)
- SM_ENTER(WPA_PTK, PTKINITDONE);
- else if (sm->TimeoutCtr >
-- (int) dot11RSNAConfigPairwiseUpdateCount) {
-+ sm->wpa_auth->conf.wpa_pairwise_update_count) {
- wpa_auth->dot11RSNA4WayHandshakeFailures++;
-- wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
-- "PTKINITNEGOTIATING: Retry limit %d "
-- "reached",
-- dot11RSNAConfigPairwiseUpdateCount);
-+ wpa_auth_vlogger(
-+ sm->wpa_auth, sm->addr, LOGGER_DEBUG,
-+ "PTKINITNEGOTIATING: Retry limit %u reached",
-+ sm->wpa_auth->conf.wpa_pairwise_update_count);
- SM_ENTER(WPA_PTK, DISCONNECT);
- } else if (sm->TimeoutEvt)
- SM_ENTER(WPA_PTK, PTKINITNEGOTIATING);
-@@ -3056,7 +3055,7 @@ SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING)
- SM_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group);
-
- sm->GTimeoutCtr++;
-- if (sm->GTimeoutCtr > (int) dot11RSNAConfigGroupUpdateCount) {
-+ if (sm->GTimeoutCtr > sm->wpa_auth->conf.wpa_group_update_count) {
- /* No point in sending the EAPOL-Key - we will disconnect
- * immediately following this. */
- return;
-@@ -3154,7 +3153,7 @@ SM_STEP(WPA_PTK_GROUP)
- !sm->EAPOLKeyPairwise && sm->MICVerified)
- SM_ENTER(WPA_PTK_GROUP, REKEYESTABLISHED);
- else if (sm->GTimeoutCtr >
-- (int) dot11RSNAConfigGroupUpdateCount)
-+ sm->wpa_auth->conf.wpa_group_update_count)
- SM_ENTER(WPA_PTK_GROUP, KEYERROR);
- else if (sm->TimeoutEvt)
- SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING);
-@@ -3614,8 +3613,8 @@ int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen)
- "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n",
- RSN_VERSION,
- !!wpa_auth->conf.wpa_strict_rekey,
-- dot11RSNAConfigGroupUpdateCount,
-- dot11RSNAConfigPairwiseUpdateCount,
-+ wpa_auth->conf.wpa_group_update_count,
-+ wpa_auth->conf.wpa_pairwise_update_count,
- wpa_cipher_key_len(wpa_auth->conf.wpa_group) * 8,
- dot11RSNAConfigPMKLifetime,
- dot11RSNAConfigPMKReauthThreshold,
-diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
-index 9cbe3889b..0920a169d 100644
---- a/src/ap/wpa_auth.h
-+++ b/src/ap/wpa_auth.h
-@@ -144,6 +144,8 @@ struct wpa_auth_config {
- int wpa_strict_rekey;
- int wpa_gmk_rekey;
- int wpa_ptk_rekey;
-+ u32 wpa_group_update_count;
-+ u32 wpa_pairwise_update_count;
- int rsn_pairwise;
- int rsn_preauth;
- int eapol_version;
-diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c
-index 22518a1f1..394f77a66 100644
---- a/src/ap/wpa_auth_glue.c
-+++ b/src/ap/wpa_auth_glue.c
-@@ -41,6 +41,8 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf,
- wconf->wpa_strict_rekey = conf->wpa_strict_rekey;
- wconf->wpa_gmk_rekey = conf->wpa_gmk_rekey;
- wconf->wpa_ptk_rekey = conf->wpa_ptk_rekey;
-+ wconf->wpa_group_update_count = conf->wpa_group_update_count;
-+ wconf->wpa_pairwise_update_count = conf->wpa_pairwise_update_count;
- wconf->rsn_pairwise = conf->rsn_pairwise;
- wconf->rsn_preauth = conf->rsn_preauth;
- wconf->eapol_version = conf->eapol_version;
-diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h
-index 065a624ad..cda2c5065 100644
---- a/src/ap/wpa_auth_i.h
-+++ b/src/ap/wpa_auth_i.h
-@@ -48,8 +48,8 @@ struct wpa_state_machine {
- Boolean AuthenticationRequest;
- Boolean ReAuthenticationRequest;
- Boolean Disconnect;
-- int TimeoutCtr;
-- int GTimeoutCtr;
-+ u32 TimeoutCtr;
-+ u32 GTimeoutCtr;
- Boolean TimeoutEvt;
- Boolean EAPOLKeyReceived;
- Boolean EAPOLKeyPairwise;
-diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c
-index 521a692ba..954061ae4 100644
---- a/wpa_supplicant/ibss_rsn.c
-+++ b/wpa_supplicant/ibss_rsn.c
-@@ -428,6 +428,8 @@ static int ibss_rsn_auth_init_group(struct ibss_rsn *ibss_rsn,
- conf.wpa_group = WPA_CIPHER_CCMP;
- conf.eapol_version = 2;
- conf.wpa_group_rekey = ssid->group_rekey ? ssid->group_rekey : 600;
-+ conf.wpa_group_update_count = 4;
-+ conf.wpa_pairwise_update_count = 4;
-
- ibss_rsn->auth_group = wpa_init(own_addr, &conf, &cb, ibss_rsn);
- if (ibss_rsn->auth_group == NULL) {
-diff --git a/wpa_supplicant/mesh_rsn.c b/wpa_supplicant/mesh_rsn.c
-index 33040f30b..628382cbf 100644
---- a/wpa_supplicant/mesh_rsn.c
-+++ b/wpa_supplicant/mesh_rsn.c
-@@ -158,6 +158,8 @@ static int __mesh_rsn_auth_init(struct mesh_rsn *rsn, const u8 *addr,
- conf.wpa_group = rsn->group_cipher;
- conf.eapol_version = 0;
- conf.wpa_group_rekey = -1;
-+ conf.wpa_group_update_count = 4;
-+ conf.wpa_pairwise_update_count = 4;
- #ifdef CONFIG_IEEE80211W
- conf.ieee80211w = ieee80211w;
- if (ieee80211w != NO_MGMT_FRAME_PROTECTION)
---
-2.13.6
-