AP: Allow PTK rekeying without Ext KeyID to be disabled as a workaround

Rekeying a pairwise key using only keyid 0 (PTK0 rekey) has many broken
implementations and should be avoided when using or interacting with
one. The effects can be triggered by either end of the connection and
range from hardly noticeable disconnects over long connection freezes up
to leaking clear text MPDUs.

To allow affected users to mitigate the issues, add a new hostapd
configuration option "wpa_deny_ptk0_rekey" to replace all PTK0 rekeys
with disconnection. This requires the station to reassociate to get
connected again and as such, can result in connectivity issues as well.

Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
This commit is contained in:
Alexander Wetzel 2020-01-10 23:19:08 +01:00 committed by Jouni Malinen
parent 35da7c20ac
commit 1a7963e36f
8 changed files with 83 additions and 2 deletions

View file

@ -64,6 +64,7 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss)
bss->wpa_group_rekey = 600;
bss->wpa_gmk_rekey = 86400;
bss->wpa_deny_ptk0_rekey = PTK0_REKEY_ALLOW_ALWAYS;
bss->wpa_group_update_count = 4;
bss->wpa_pairwise_update_count = 4;
bss->wpa_disable_eapol_key_retries =

View file

@ -370,6 +370,7 @@ struct hostapd_bss_config {
int wpa_strict_rekey;
int wpa_gmk_rekey;
int wpa_ptk_rekey;
enum ptk0_rekey_handling wpa_deny_ptk0_rekey;
u32 wpa_group_update_count;
u32 wpa_pairwise_update_count;
int wpa_disable_eapol_key_retries;

View file

@ -781,8 +781,18 @@ static void wpa_request_new_ptk(struct wpa_state_machine *sm)
if (sm == NULL)
return;
sm->PTKRequest = TRUE;
sm->PTK_valid = 0;
if (sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
wpa_printf(MSG_INFO,
"WPA: PTK0 rekey not allowed, disconnect " MACSTR,
MAC2STR(sm->addr));
sm->Disconnect = TRUE;
/* Try to encourage the STA to reconnect */
sm->disconnect_reason =
WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
} else {
sm->PTKRequest = TRUE;
sm->PTK_valid = 0;
}
}
@ -1802,6 +1812,15 @@ int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event)
sm->Init = FALSE;
sm->AuthenticationRequest = TRUE;
break;
} else if (sm->wpa_auth->conf.wpa_deny_ptk0_rekey) {
wpa_printf(MSG_INFO,
"WPA: PTK0 rekey not allowed, disconnect "
MACSTR, MAC2STR(sm->addr));
sm->Disconnect = TRUE;
/* Try to encourage the STA reconnect */
sm->disconnect_reason =
WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA;
break;
}
if (sm->GUpdateStationKeys) {
/*

View file

@ -176,6 +176,7 @@ struct wpa_auth_config {
int wpa_strict_rekey;
int wpa_gmk_rekey;
int wpa_ptk_rekey;
int wpa_deny_ptk0_rekey;
u32 wpa_group_update_count;
u32 wpa_pairwise_update_count;
int wpa_disable_eapol_key_retries;

View file

@ -1381,6 +1381,16 @@ int hostapd_setup_wpa(struct hostapd_data *hapd)
_conf.tx_status = 1;
if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_MLME)
_conf.ap_mlme = 1;
if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_WIRED) &&
(hapd->conf->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_NEVER ||
(hapd->conf->wpa_deny_ptk0_rekey == PTK0_REKEY_ALLOW_LOCAL_OK &&
!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_SAFE_PTK0_REKEYS)))) {
wpa_msg(hapd->msg_ctx, MSG_INFO,
"Disable PTK0 rekey support - replaced with disconnect");
_conf.wpa_deny_ptk0_rekey = 1;
}
hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb, hapd);
if (hapd->wpa_auth == NULL) {
wpa_printf(MSG_ERROR, "WPA initialization failed.");

View file

@ -445,4 +445,10 @@ enum key_flag {
KEY_FLAG_MODIFY,
};
enum ptk0_rekey_handling {
PTK0_REKEY_ALLOW_ALWAYS,
PTK0_REKEY_ALLOW_LOCAL_OK,
PTK0_REKEY_ALLOW_NEVER
};
#endif /* DEFS_H */