]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Add hostapd options wpa_group_update_count and wpa_pairwise_update_count
authorGünther Kelleter <guenther.kelleter@devolo.de>
Thu, 5 Jan 2017 16:00:33 +0000 (17:00 +0100)
committerJouni Malinen <j@w1.fi>
Mon, 6 Feb 2017 22:25:36 +0000 (00:25 +0200)
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
hostapd/hostapd.conf
src/ap/ap_config.c
src/ap/ap_config.h
src/ap/wpa_auth.c
src/ap/wpa_auth.h
src/ap/wpa_auth_glue.c
src/ap/wpa_auth_i.h
wpa_supplicant/ibss_rsn.c
wpa_supplicant/mesh_rsn.c

index 8cfa198c347be5c6f3432e1e5d04b930cbcf4db4..02693a5b18c8219c2ef686423a186205b81bf129 100644 (file)
@@ -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) {
index 314f3842b9e5a83c7dd40e708afa565f4e714226..1fb1bd987eb7182912cae493e8d93ecb0812cce2 100644 (file)
@@ -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.
index c2b80ad97ee029ff5e3f29302fd4101c16ecbcee..9abcab7fb03b2d676f35fe9a7088b17e432feb75 100644 (file)
@@ -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;
index 31b1e7762b57e67716fdb1388013002730f53962..7495dc96f2f7261bef2ed1a4df69ce6ba42a5d80 100644 (file)
@@ -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;
index 0bd901fbfc7cbf7ef22f6ead51c0120e97562cf8..8c082f42600195fd1fcf1968b08a8a35631931a3 100644 (file)
@@ -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,
index 9cbe3889b42a152583e4ef03cad8381e9d678b9c..0920a169dffb4742577d3f0768263a923fcb5c9b 100644 (file)
@@ -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;
index 22518a1f1303e261613b78bbd23522b60ef78646..394f77a661a0f894c3996448e34ee179adfc54c0 100644 (file)
@@ -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;
index 065a624ad4f59231a276568bd500c7dd0e6979e4..cda2c5065e1eb0327e627d33d83302784c5284c8 100644 (file)
@@ -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;
index 521a692ba24ac1e4409c18d1aed35c77f8b1c830..954061ae43b74f5cc7174ac9cded60618e7e0a4a 100644 (file)
@@ -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) {
index 33040f30baa839d374d92d0adde949b97177f075..628382cbfb70e68a01dd4a7d225edeff2277decc 100644 (file)
@@ -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)