diff -ru ./hostapd/config_file.c /home/user/hostapd/wpa-2.4/hostapd/config_file.c --- ./hostapd/config_file.c 2015-03-15 18:30:39.000000000 +0100 +++ /home/user/hostapd/wpa-2.4/hostapd/config_file.c 2017-11-03 17:26:16.262042753 +0100 @@ -2341,6 +2341,8 @@ 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_disable_eapol_key_retries") == 0) { + bss->wpa_disable_eapol_key_retries = atoi(pos); } else if (os_strcmp(buf, "wpa_passphrase") == 0) { int len = os_strlen(pos); if (len < 8 || len > 63) { diff -ru ./hostapd/defconfig /home/user/hostapd/wpa-2.4/hostapd/defconfig --- ./hostapd/defconfig 2015-03-15 18:30:39.000000000 +0100 +++ /home/user/hostapd/wpa-2.4/hostapd/defconfig 2017-11-03 17:26:16.272042752 +0100 @@ -314,3 +314,7 @@ # http://wireless.kernel.org/en/users/Documentation/acs # #CONFIG_ACS=y + +# Override default value for the wpa_disable_eapol_key_retries configuration +# parameter. See that parameter in hostapd.conf for more details. +#CFLAGS += -DDEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES=1 diff -ru ./hostapd/hostapd.conf /home/user/hostapd/wpa-2.4/hostapd/hostapd.conf --- ./hostapd/hostapd.conf 2015-03-15 18:30:39.000000000 +0100 +++ /home/user/hostapd/wpa-2.4/hostapd/hostapd.conf 2017-11-03 17:26:16.272042752 +0100 @@ -1123,6 +1123,30 @@ # PTK to mitigate some attacks against TKIP deficiencies. #wpa_ptk_rekey=600 +# Workaround for key reinstallation attacks +# +# This parameter can be used to disable retransmission of EAPOL-Key frames that +# are used to install keys (EAPOL-Key message 3/4 and group message 1/2). This +# is similar to setting wpa_group_update_count=1 and +# wpa_pairwise_update_count=1, but with no impact to message 1/4 and with +# extended timeout on the response to avoid causing issues with stations that +# may use aggressive power saving have very long time in replying to the +# EAPOL-Key messages. +# +# This option can be used to work around key reinstallation attacks on the +# station (supplicant) side in cases those station devices cannot be updated +# for some reason. By removing the retransmissions the attacker cannot cause +# key reinstallation with a delayed frame transmission. This is related to the +# station side vulnerabilities CVE-2017-13077, CVE-2017-13078, CVE-2017-13079, +# CVE-2017-13080, and CVE-2017-13081. +# +# This workaround might cause interoperability issues and reduced robustness of +# key negotiation especially in environments with heavy traffic load due to the +# number of attempts to perform the key exchange is reduced significantly. As +# such, this workaround is disabled by default (unless overridden in build +# configuration). To enable this, set the parameter to 1. +#wpa_disable_eapol_key_retries=1 + # 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 -ru ./src/ap/ap_config.c /home/user/hostapd/wpa-2.4/src/ap/ap_config.c --- ./src/ap/ap_config.c 2015-03-15 18:30:39.000000000 +0100 +++ /home/user/hostapd/wpa-2.4/src/ap/ap_config.c 2017-11-03 17:26:16.272042752 +0100 @@ -36,6 +36,10 @@ } +#ifndef DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES +#define DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES 0 +#endif /* DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES */ + void hostapd_config_defaults_bss(struct hostapd_bss_config *bss) { bss->logger_syslog_level = HOSTAPD_LEVEL_INFO; @@ -53,6 +57,8 @@ bss->wpa_group_rekey = 600; bss->wpa_gmk_rekey = 86400; + bss->wpa_disable_eapol_key_retries = + DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES; bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK; bss->wpa_pairwise = WPA_CIPHER_TKIP; bss->wpa_group = WPA_CIPHER_TKIP; diff -ru ./src/ap/ap_config.h /home/user/hostapd/wpa-2.4/src/ap/ap_config.h --- ./src/ap/ap_config.h 2015-03-15 18:30:39.000000000 +0100 +++ /home/user/hostapd/wpa-2.4/src/ap/ap_config.h 2017-11-03 17:26:16.272042752 +0100 @@ -304,6 +304,7 @@ int wpa_strict_rekey; int wpa_gmk_rekey; int wpa_ptk_rekey; + int wpa_disable_eapol_key_retries; int rsn_pairwise; int rsn_preauth; char *rsn_preauth_interfaces; diff -ru ./src/ap/wpa_auth.c /home/user/hostapd/wpa-2.4/src/ap/wpa_auth.c --- ./src/ap/wpa_auth.c 2017-11-02 18:48:27.000000000 +0100 +++ /home/user/hostapd/wpa-2.4/src/ap/wpa_auth.c 2017-11-03 17:36:11.270933605 +0100 @@ -51,6 +51,7 @@ 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 */ +static const u32 eapol_key_timeout_no_retrans = 4000; /* ms */ /* TODO: make these configurable */ static const int dot11RSNAConfigPMKLifetime = 43200; @@ -1597,6 +1598,9 @@ eapol_key_timeout_first_group; else timeout_ms = eapol_key_timeout_subseq; + if (wpa_auth->conf.wpa_disable_eapol_key_retries && + (!pairwise || (key_info & WPA_KEY_INFO_MIC))) + timeout_ms = eapol_key_timeout_no_retrans; 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 " @@ -2158,6 +2162,11 @@ sm->TimeoutEvt = FALSE; sm->TimeoutCtr++; + if (sm->wpa_auth->conf.wpa_disable_eapol_key_retries && + sm->TimeoutCtr > 1) { + /* Do not allow retransmission of EAPOL-Key msg 3/4 */ + return; + } if (sm->TimeoutCtr > (int) dot11RSNAConfigPairwiseUpdateCount) { /* No point in sending the EAPOL-Key - we will disconnect * immediately following this. */ @@ -2470,7 +2479,9 @@ sm->EAPOLKeyPairwise && sm->MICVerified) SM_ENTER(WPA_PTK, PTKINITDONE); else if (sm->TimeoutCtr > - (int) dot11RSNAConfigPairwiseUpdateCount) { + (int) dot11RSNAConfigPairwiseUpdateCount || + (sm->wpa_auth->conf.wpa_disable_eapol_key_retries && + sm->TimeoutCtr > 1)) { wpa_auth->dot11RSNA4WayHandshakeFailures++; wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, "PTKINITNEGOTIATING: Retry limit %d " @@ -2510,6 +2521,11 @@ SM_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group); sm->GTimeoutCtr++; + if (sm->wpa_auth->conf.wpa_disable_eapol_key_retries && + sm->GTimeoutCtr > 1) { + /* Do not allow retransmission of EAPOL-Key group msg 1/2 */ + return; + } if (sm->GTimeoutCtr > (int) dot11RSNAConfigGroupUpdateCount) { /* No point in sending the EAPOL-Key - we will disconnect * immediately following this. */ @@ -2607,7 +2623,9 @@ !sm->EAPOLKeyPairwise && sm->MICVerified) SM_ENTER(WPA_PTK_GROUP, REKEYESTABLISHED); else if (sm->GTimeoutCtr > - (int) dot11RSNAConfigGroupUpdateCount) + (int) dot11RSNAConfigGroupUpdateCount || + (sm->wpa_auth->conf.wpa_disable_eapol_key_retries && + sm->GTimeoutCtr > 1)) SM_ENTER(WPA_PTK_GROUP, KEYERROR); else if (sm->TimeoutEvt) SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING); diff -ru ./src/ap/wpa_auth_glue.c /home/user/hostapd/wpa-2.4/src/ap/wpa_auth_glue.c --- ./src/ap/wpa_auth_glue.c 2015-03-15 18:30:39.000000000 +0100 +++ /home/user/hostapd/wpa-2.4/src/ap/wpa_auth_glue.c 2017-11-03 17:26:16.282042750 +0100 @@ -39,6 +39,8 @@ 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_disable_eapol_key_retries = + conf->wpa_disable_eapol_key_retries; wconf->rsn_pairwise = conf->rsn_pairwise; wconf->rsn_preauth = conf->rsn_preauth; wconf->eapol_version = conf->eapol_version; diff -ru ./src/ap/wpa_auth.h /home/user/hostapd/wpa-2.4/src/ap/wpa_auth.h --- ./src/ap/wpa_auth.h 2017-11-02 18:48:27.000000000 +0100 +++ /home/user/hostapd/wpa-2.4/src/ap/wpa_auth.h 2017-11-03 17:26:16.282042750 +0100 @@ -132,6 +132,7 @@ int wpa_strict_rekey; int wpa_gmk_rekey; int wpa_ptk_rekey; + int wpa_disable_eapol_key_retries; int rsn_pairwise; int rsn_preauth; int eapol_version;