mirror of
https://github.com/vanhoefm/fragattacks.git
synced 2024-11-25 00:38:24 -05:00
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:
parent
35da7c20ac
commit
1a7963e36f
@ -2874,6 +2874,15 @@ 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_deny_ptk0_rekey") == 0) {
|
||||
bss->wpa_deny_ptk0_rekey = atoi(pos);
|
||||
if (bss->wpa_deny_ptk0_rekey < 0 ||
|
||||
bss->wpa_deny_ptk0_rekey > 2) {
|
||||
wpa_printf(MSG_ERROR,
|
||||
"Line %d: Invalid wpa_deny_ptk0_rekey=%d; allowed range 0..2",
|
||||
line, bss->wpa_deny_ptk0_rekey);
|
||||
return 1;
|
||||
}
|
||||
} else if (os_strcmp(buf, "wpa_group_update_count") == 0) {
|
||||
char *endp;
|
||||
unsigned long val = strtoul(pos, &endp, 0);
|
||||
|
@ -904,6 +904,8 @@ eapol_key_index_workaround=0
|
||||
|
||||
# EAP reauthentication period in seconds (default: 3600 seconds; 0 = disable
|
||||
# reauthentication).
|
||||
# Note: Reauthentications may enforce a disconnection, check the related
|
||||
# parameter wpa_deny_ptk0_rekey for details.
|
||||
#eap_reauth_period=3600
|
||||
|
||||
# Use PAE group address (01:80:c2:00:00:03) instead of individual target
|
||||
@ -1608,8 +1610,40 @@ own_ip_addr=127.0.0.1
|
||||
|
||||
# Maximum lifetime for PTK in seconds. This can be used to enforce rekeying of
|
||||
# PTK to mitigate some attacks against TKIP deficiencies.
|
||||
# Warning: PTK rekeying is buggy with many drivers/devices and with such
|
||||
# devices, the only secure method to rekey the PTK without Extended Key ID
|
||||
# support requires a disconnection. Check the related parameter
|
||||
# wpa_deny_ptk0_rekey for details.
|
||||
#wpa_ptk_rekey=600
|
||||
|
||||
# Workaround for PTK rekey issues
|
||||
#
|
||||
# Rekeying the PTK without using "Extended Key ID for Individually Addressed
|
||||
# Frames" (two different Key ID values for pairwise keys) can, depending on the
|
||||
# used cards/drivers, impact the security and stability of connections. Both
|
||||
# ends can accidentally trick one end to drop all packets send by it until the
|
||||
# connection is torn down or rekeyed again. Additionally, some drivers may
|
||||
# skip/break the encryption for the time window the key is updated (normally a
|
||||
# few milliseconds).
|
||||
#
|
||||
# To avoid such issues, hostapd can now replace all PTK rekeys using only keyid
|
||||
# 0 (PTK0 rekeys) with disconnection that forces the remote stations to
|
||||
# reconnect instead.
|
||||
#
|
||||
# EAP reauthentication depends on replacing the PTK and is therefore just
|
||||
# another way to rekey the PTK and is affected by this parameter, too.
|
||||
#
|
||||
# "Extended Key ID for Individually Addressed Frames" is avoiding the issues
|
||||
# using two separate keys and this parameter will be ignored when using it
|
||||
# (i.e., PTK rekeying is allowed regardless of this parameter value).
|
||||
#
|
||||
# Available options:
|
||||
# 0 = always rekey when configured/instructed (default)
|
||||
# 1 = only rekey when the local driver is explicitly indicating it can perform
|
||||
# this operation without issues
|
||||
# 2 = never allow PTK0 rekeys
|
||||
#wpa_deny_ptk0_rekey=0
|
||||
|
||||
# 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)
|
||||
|
@ -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 =
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
/*
|
||||
|
@ -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;
|
||||
|
@ -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.");
|
||||
|
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user