Add hostapd options wpa_group_update_count and wpa_pairwise_update_count
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>
This commit is contained in:
parent
e54691106b
commit
41f140d386
10 changed files with 65 additions and 21 deletions
|
@ -2489,6 +2489,28 @@ static int hostapd_config_fill(struct hostapd_config *conf,
|
||||||
bss->wpa_gmk_rekey = atoi(pos);
|
bss->wpa_gmk_rekey = atoi(pos);
|
||||||
} else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) {
|
} else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) {
|
||||||
bss->wpa_ptk_rekey = atoi(pos);
|
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) {
|
} else if (os_strcmp(buf, "wpa_passphrase") == 0) {
|
||||||
int len = os_strlen(pos);
|
int len = os_strlen(pos);
|
||||||
if (len < 8 || len > 63) {
|
if (len < 8 || len > 63) {
|
||||||
|
|
|
@ -1221,6 +1221,11 @@ own_ip_addr=127.0.0.1
|
||||||
# (dot11RSNAConfigGroupRekeyStrict)
|
# (dot11RSNAConfigGroupRekeyStrict)
|
||||||
#wpa_strict_rekey=1
|
#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
|
# Time interval for rekeying GMK (master key used internally to generate GTKs
|
||||||
# (in seconds).
|
# (in seconds).
|
||||||
#wpa_gmk_rekey=86400
|
#wpa_gmk_rekey=86400
|
||||||
|
@ -1229,6 +1234,12 @@ own_ip_addr=127.0.0.1
|
||||||
# PTK to mitigate some attacks against TKIP deficiencies.
|
# PTK to mitigate some attacks against TKIP deficiencies.
|
||||||
#wpa_ptk_rekey=600
|
#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
|
# 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
|
# roaming be pre-authenticating IEEE 802.1X/EAP part of the full RSN
|
||||||
# authentication and key handshake before actually associating with a new AP.
|
# authentication and key handshake before actually associating with a new AP.
|
||||||
|
|
|
@ -56,6 +56,8 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
|
||||||
|
|
||||||
bss->wpa_group_rekey = 600;
|
bss->wpa_group_rekey = 600;
|
||||||
bss->wpa_gmk_rekey = 86400;
|
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_key_mgmt = WPA_KEY_MGMT_PSK;
|
||||||
bss->wpa_pairwise = WPA_CIPHER_TKIP;
|
bss->wpa_pairwise = WPA_CIPHER_TKIP;
|
||||||
bss->wpa_group = WPA_CIPHER_TKIP;
|
bss->wpa_group = WPA_CIPHER_TKIP;
|
||||||
|
|
|
@ -330,6 +330,8 @@ struct hostapd_bss_config {
|
||||||
int wpa_strict_rekey;
|
int wpa_strict_rekey;
|
||||||
int wpa_gmk_rekey;
|
int wpa_gmk_rekey;
|
||||||
int wpa_ptk_rekey;
|
int wpa_ptk_rekey;
|
||||||
|
u32 wpa_group_update_count;
|
||||||
|
u32 wpa_pairwise_update_count;
|
||||||
int rsn_pairwise;
|
int rsn_pairwise;
|
||||||
int rsn_preauth;
|
int rsn_preauth;
|
||||||
char *rsn_preauth_interfaces;
|
char *rsn_preauth_interfaces;
|
||||||
|
|
|
@ -60,8 +60,6 @@ static void wpa_group_put(struct wpa_authenticator *wpa_auth,
|
||||||
struct wpa_group *group);
|
struct wpa_group *group);
|
||||||
static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos);
|
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_first = 100; /* ms */
|
||||||
static const u32 eapol_key_timeout_subseq = 1000; /* 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_first_group = 500; /* ms */
|
||||||
|
@ -1623,7 +1621,7 @@ static void wpa_send_eapol(struct wpa_authenticator *wpa_auth,
|
||||||
{
|
{
|
||||||
int timeout_ms;
|
int timeout_ms;
|
||||||
int pairwise = key_info & WPA_KEY_INFO_KEY_TYPE;
|
int pairwise = key_info & WPA_KEY_INFO_KEY_TYPE;
|
||||||
int ctr;
|
u32 ctr;
|
||||||
|
|
||||||
if (sm == NULL)
|
if (sm == NULL)
|
||||||
return;
|
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))
|
if (pairwise && ctr == 1 && !(key_info & WPA_KEY_INFO_MIC))
|
||||||
sm->pending_1_of_4_timeout = 1;
|
sm->pending_1_of_4_timeout = 1;
|
||||||
wpa_printf(MSG_DEBUG, "WPA: Use EAPOL-Key timeout of %u ms (retry "
|
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,
|
eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000,
|
||||||
wpa_send_eapol_timeout, wpa_auth, sm);
|
wpa_send_eapol_timeout, wpa_auth, sm);
|
||||||
}
|
}
|
||||||
|
@ -2002,7 +2000,7 @@ SM_STATE(WPA_PTK, PTKSTART)
|
||||||
sm->alt_snonce_valid = FALSE;
|
sm->alt_snonce_valid = FALSE;
|
||||||
|
|
||||||
sm->TimeoutCtr++;
|
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
|
/* No point in sending the EAPOL-Key - we will disconnect
|
||||||
* immediately following this. */
|
* immediately following this. */
|
||||||
return;
|
return;
|
||||||
|
@ -2693,7 +2691,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING)
|
||||||
sm->TimeoutEvt = FALSE;
|
sm->TimeoutEvt = FALSE;
|
||||||
|
|
||||||
sm->TimeoutCtr++;
|
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
|
/* No point in sending the EAPOL-Key - we will disconnect
|
||||||
* immediately following this. */
|
* immediately following this. */
|
||||||
return;
|
return;
|
||||||
|
@ -2988,11 +2986,12 @@ SM_STEP(WPA_PTK)
|
||||||
sm->EAPOLKeyPairwise)
|
sm->EAPOLKeyPairwise)
|
||||||
SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
|
SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING);
|
||||||
else if (sm->TimeoutCtr >
|
else if (sm->TimeoutCtr >
|
||||||
(int) dot11RSNAConfigPairwiseUpdateCount) {
|
sm->wpa_auth->conf.wpa_pairwise_update_count) {
|
||||||
wpa_auth->dot11RSNA4WayHandshakeFailures++;
|
wpa_auth->dot11RSNA4WayHandshakeFailures++;
|
||||||
wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
|
wpa_auth_vlogger(
|
||||||
"PTKSTART: Retry limit %d reached",
|
sm->wpa_auth, sm->addr, LOGGER_DEBUG,
|
||||||
dot11RSNAConfigPairwiseUpdateCount);
|
"PTKSTART: Retry limit %u reached",
|
||||||
|
sm->wpa_auth->conf.wpa_pairwise_update_count);
|
||||||
SM_ENTER(WPA_PTK, DISCONNECT);
|
SM_ENTER(WPA_PTK, DISCONNECT);
|
||||||
} else if (sm->TimeoutEvt)
|
} else if (sm->TimeoutEvt)
|
||||||
SM_ENTER(WPA_PTK, PTKSTART);
|
SM_ENTER(WPA_PTK, PTKSTART);
|
||||||
|
@ -3016,12 +3015,12 @@ SM_STEP(WPA_PTK)
|
||||||
sm->EAPOLKeyPairwise && sm->MICVerified)
|
sm->EAPOLKeyPairwise && sm->MICVerified)
|
||||||
SM_ENTER(WPA_PTK, PTKINITDONE);
|
SM_ENTER(WPA_PTK, PTKINITDONE);
|
||||||
else if (sm->TimeoutCtr >
|
else if (sm->TimeoutCtr >
|
||||||
(int) dot11RSNAConfigPairwiseUpdateCount) {
|
sm->wpa_auth->conf.wpa_pairwise_update_count) {
|
||||||
wpa_auth->dot11RSNA4WayHandshakeFailures++;
|
wpa_auth->dot11RSNA4WayHandshakeFailures++;
|
||||||
wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG,
|
wpa_auth_vlogger(
|
||||||
"PTKINITNEGOTIATING: Retry limit %d "
|
sm->wpa_auth, sm->addr, LOGGER_DEBUG,
|
||||||
"reached",
|
"PTKINITNEGOTIATING: Retry limit %u reached",
|
||||||
dot11RSNAConfigPairwiseUpdateCount);
|
sm->wpa_auth->conf.wpa_pairwise_update_count);
|
||||||
SM_ENTER(WPA_PTK, DISCONNECT);
|
SM_ENTER(WPA_PTK, DISCONNECT);
|
||||||
} else if (sm->TimeoutEvt)
|
} else if (sm->TimeoutEvt)
|
||||||
SM_ENTER(WPA_PTK, PTKINITNEGOTIATING);
|
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_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group);
|
||||||
|
|
||||||
sm->GTimeoutCtr++;
|
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
|
/* No point in sending the EAPOL-Key - we will disconnect
|
||||||
* immediately following this. */
|
* immediately following this. */
|
||||||
return;
|
return;
|
||||||
|
@ -3154,7 +3153,7 @@ SM_STEP(WPA_PTK_GROUP)
|
||||||
!sm->EAPOLKeyPairwise && sm->MICVerified)
|
!sm->EAPOLKeyPairwise && sm->MICVerified)
|
||||||
SM_ENTER(WPA_PTK_GROUP, REKEYESTABLISHED);
|
SM_ENTER(WPA_PTK_GROUP, REKEYESTABLISHED);
|
||||||
else if (sm->GTimeoutCtr >
|
else if (sm->GTimeoutCtr >
|
||||||
(int) dot11RSNAConfigGroupUpdateCount)
|
sm->wpa_auth->conf.wpa_group_update_count)
|
||||||
SM_ENTER(WPA_PTK_GROUP, KEYERROR);
|
SM_ENTER(WPA_PTK_GROUP, KEYERROR);
|
||||||
else if (sm->TimeoutEvt)
|
else if (sm->TimeoutEvt)
|
||||||
SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING);
|
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",
|
"dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n",
|
||||||
RSN_VERSION,
|
RSN_VERSION,
|
||||||
!!wpa_auth->conf.wpa_strict_rekey,
|
!!wpa_auth->conf.wpa_strict_rekey,
|
||||||
dot11RSNAConfigGroupUpdateCount,
|
wpa_auth->conf.wpa_group_update_count,
|
||||||
dot11RSNAConfigPairwiseUpdateCount,
|
wpa_auth->conf.wpa_pairwise_update_count,
|
||||||
wpa_cipher_key_len(wpa_auth->conf.wpa_group) * 8,
|
wpa_cipher_key_len(wpa_auth->conf.wpa_group) * 8,
|
||||||
dot11RSNAConfigPMKLifetime,
|
dot11RSNAConfigPMKLifetime,
|
||||||
dot11RSNAConfigPMKReauthThreshold,
|
dot11RSNAConfigPMKReauthThreshold,
|
||||||
|
|
|
@ -144,6 +144,8 @@ struct wpa_auth_config {
|
||||||
int wpa_strict_rekey;
|
int wpa_strict_rekey;
|
||||||
int wpa_gmk_rekey;
|
int wpa_gmk_rekey;
|
||||||
int wpa_ptk_rekey;
|
int wpa_ptk_rekey;
|
||||||
|
u32 wpa_group_update_count;
|
||||||
|
u32 wpa_pairwise_update_count;
|
||||||
int rsn_pairwise;
|
int rsn_pairwise;
|
||||||
int rsn_preauth;
|
int rsn_preauth;
|
||||||
int eapol_version;
|
int eapol_version;
|
||||||
|
|
|
@ -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_strict_rekey = conf->wpa_strict_rekey;
|
||||||
wconf->wpa_gmk_rekey = conf->wpa_gmk_rekey;
|
wconf->wpa_gmk_rekey = conf->wpa_gmk_rekey;
|
||||||
wconf->wpa_ptk_rekey = conf->wpa_ptk_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_pairwise = conf->rsn_pairwise;
|
||||||
wconf->rsn_preauth = conf->rsn_preauth;
|
wconf->rsn_preauth = conf->rsn_preauth;
|
||||||
wconf->eapol_version = conf->eapol_version;
|
wconf->eapol_version = conf->eapol_version;
|
||||||
|
|
|
@ -48,8 +48,8 @@ struct wpa_state_machine {
|
||||||
Boolean AuthenticationRequest;
|
Boolean AuthenticationRequest;
|
||||||
Boolean ReAuthenticationRequest;
|
Boolean ReAuthenticationRequest;
|
||||||
Boolean Disconnect;
|
Boolean Disconnect;
|
||||||
int TimeoutCtr;
|
u32 TimeoutCtr;
|
||||||
int GTimeoutCtr;
|
u32 GTimeoutCtr;
|
||||||
Boolean TimeoutEvt;
|
Boolean TimeoutEvt;
|
||||||
Boolean EAPOLKeyReceived;
|
Boolean EAPOLKeyReceived;
|
||||||
Boolean EAPOLKeyPairwise;
|
Boolean EAPOLKeyPairwise;
|
||||||
|
|
|
@ -428,6 +428,8 @@ static int ibss_rsn_auth_init_group(struct ibss_rsn *ibss_rsn,
|
||||||
conf.wpa_group = WPA_CIPHER_CCMP;
|
conf.wpa_group = WPA_CIPHER_CCMP;
|
||||||
conf.eapol_version = 2;
|
conf.eapol_version = 2;
|
||||||
conf.wpa_group_rekey = ssid->group_rekey ? ssid->group_rekey : 600;
|
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);
|
ibss_rsn->auth_group = wpa_init(own_addr, &conf, &cb, ibss_rsn);
|
||||||
if (ibss_rsn->auth_group == NULL) {
|
if (ibss_rsn->auth_group == NULL) {
|
||||||
|
|
|
@ -158,6 +158,8 @@ static int __mesh_rsn_auth_init(struct mesh_rsn *rsn, const u8 *addr,
|
||||||
conf.wpa_group = rsn->group_cipher;
|
conf.wpa_group = rsn->group_cipher;
|
||||||
conf.eapol_version = 0;
|
conf.eapol_version = 0;
|
||||||
conf.wpa_group_rekey = -1;
|
conf.wpa_group_rekey = -1;
|
||||||
|
conf.wpa_group_update_count = 4;
|
||||||
|
conf.wpa_pairwise_update_count = 4;
|
||||||
#ifdef CONFIG_IEEE80211W
|
#ifdef CONFIG_IEEE80211W
|
||||||
conf.ieee80211w = ieee80211w;
|
conf.ieee80211w = ieee80211w;
|
||||||
if (ieee80211w != NO_MGMT_FRAME_PROTECTION)
|
if (ieee80211w != NO_MGMT_FRAME_PROTECTION)
|
||||||
|
|
Loading…
Reference in a new issue