From patchwork Sat Jan 4 22:10:01 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Wetzel X-Patchwork-Id: 1217670 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=quarantine dis=none) header.from=wetzel-home.de Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="ttJv28lN"; dkim=fail reason="signature verification failed" (1024-bit key; secure) header.d=wetzel-home.de header.i=@wetzel-home.de header.b="xfmTBD76"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 47qww102YLz9sPJ for ; Sun, 5 Jan 2020 09:11:12 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=jqWxf4y9diffrlJjbVCx/3WSWUWGo/Up/sjrkTs7y+s=; b=ttJv28lNE7OCrx LVz6DEIdr5pWMWsmY5Y+Ex0nxfLQrfwGZ6P/6C1itVjAiANhQmUfsplrnjEoL3mdZSzcsZCJ6PnhL /n6hxmkmTHZgY0Sauj307RK9oDhouISS3rKAIC3muscbMIXFfhz0tkQyyQUcfx3TX1Do6zH7nWxh9 O0xecg/37riTw7TD03uWOAgw3NsuCF+mEU2j2iaqMdN/IbzgkwUjwhNG6d76xEPfeAny/rBTAnji2 I9kdIIMZj3WzxrB9a4ahoCSPqnH2tksOFo303gqGs+nXHQUO3ygxabBSzU4escoiY/DxaQMN4jYks kVEGYFBqaqpVnvUYNnqg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.92.3 #3 (Red Hat Linux)) id 1inrdS-0002kM-L6; Sat, 04 Jan 2020 22:11:06 +0000 Received: from 11.mo6.mail-out.ovh.net ([188.165.38.119]) by bombadil.infradead.org with esmtps (Exim 4.92.3 #3 (Red Hat Linux)) id 1inrdO-0002g9-Vm for hostap@lists.infradead.org; Sat, 04 Jan 2020 22:11:05 +0000 Received: from player794.ha.ovh.net (unknown [10.108.35.122]) by mo6.mail-out.ovh.net (Postfix) with ESMTP id 0871C1F6C3F for ; Sat, 4 Jan 2020 23:10:57 +0100 (CET) Received: from awhome.eu (p4FF91EE6.dip0.t-ipconnect.de [79.249.30.230]) (Authenticated sender: postmaster@awhome.eu) by player794.ha.ovh.net (Postfix) with ESMTPSA id 1102EAD8662E; Sat, 4 Jan 2020 22:10:52 +0000 (UTC) From: Alexander Wetzel DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=wetzel-home.de; s=wetzel-home; t=1578175792; bh=REkYZbKj77kielFkeCP/0D825RdbxXrupXwfYbYEmnk=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=xfmTBD767C3+GUtkk4dJBri+0kglsqaSF6F77NcAVcLx3jbchEYaM0dAspI780BKw NBEoHue46ocsHhI1pPYWsXbscoTsR7+IkpFQk8f+4A+DzDCd9aIvne5BF0Sbvq6sYd ym/yHIUHIhLt+lw1p84lL4MMjd9Yzhx0lUBhhTzo= To: j@w1.fi Subject: [Patch v9 02/16] AP: Address PTK rekey issues Date: Sat, 4 Jan 2020 23:10:01 +0100 Message-Id: <20200104221015.90469-3-alexander@wetzel-home.de> X-Mailer: git-send-email 2.24.1 In-Reply-To: <20200104221015.90469-1-alexander@wetzel-home.de> References: <20200104221015.90469-1-alexander@wetzel-home.de> MIME-Version: 1.0 X-Ovh-Tracer-Id: 968555398828662012 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: 0 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedufedrvdeghedgudeitdcutefuodetggdotefrodftvfcurfhrohhfihhlvgemucfqggfjpdevjffgvefmvefgnecuuegrihhlohhuthemucehtddtnecunecujfgurhephffvufffkffojghfggfgsedtkeertdertddtnecuhfhrohhmpeetlhgvgigrnhguvghrucghvghtiigvlhcuoegrlhgvgigrnhguvghrseifvghtiigvlhdqhhhomhgvrdguvgeqnecukfhppedtrddtrddtrddtpdejledrvdegledrfedtrddvfedtnecurfgrrhgrmhepmhhouggvpehsmhhtphdqohhuthdphhgvlhhopehplhgrhigvrhejleegrdhhrgdrohhvhhdrnhgvthdpihhnvghtpedtrddtrddtrddtpdhmrghilhhfrhhomheprghlvgigrghnuggvrhesfigvthiivghlqdhhohhmvgdruggvpdhrtghpthhtohephhhoshhtrghpsehlihhsthhsrdhinhhfrhgruggvrggurdhorhhgnecuvehluhhsthgvrhfuihiivgeptd X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20200104_141103_461453_6C973EEF X-CRM114-Status: GOOD ( 20.10 ) X-Spam-Score: -0.2 (/) X-Spam-Report: SpamAssassin version 3.4.2 on bombadil.infradead.org summary: Content analysis details: (-0.2 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at https://www.dnswl.org/, no trust [188.165.38.119 listed in list.dnswl.org] 0.0 RCVD_IN_MSPIKE_H3 RBL: Good reputation (+3) [188.165.38.119 listed in wl.mailspike.net] 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record -0.0 SPF_PASS SPF: sender matches SPF record -0.1 DKIM_VALID_EF Message has a valid DKIM or DK signature from envelope-from domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature 0.0 RCVD_IN_MSPIKE_WL Mailspike good senders X-BeenThere: hostap@lists.infradead.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alexander Wetzel , hostap@lists.infradead.org, luca@coelho.fi, johannes@sipsolutions.net Sender: "Hostap" Errors-To: hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org Rekeying a pairwise key using only keyid 0 (PTK0 rekeys) has many broken implementations and should be avoided for both security and usability reasons. 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 which can be used to calculate the outgoing PTK. To avoid the issues replace PTK0 rekeys by default with disconnects and add the new option "wpa_deny_ptk0_rekey" to let the user control the behavior. Signed-off-by: Alexander Wetzel --- hostapd/config_file.c | 9 +++++++++ hostapd/hostapd.conf | 32 ++++++++++++++++++++++++++++++++ src/ap/ap_config.c | 1 + src/ap/ap_config.h | 1 + src/ap/wpa_auth.c | 23 +++++++++++++++++++++-- src/ap/wpa_auth.h | 1 + src/ap/wpa_auth_glue.c | 12 ++++++++++++ src/common/defs.h | 6 ++++++ 8 files changed, 83 insertions(+), 2 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 21c9ab288..b88071a58 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -2884,6 +2884,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); diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 263a04e8f..b61176717 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -903,6 +903,8 @@ eapol_key_index_workaround=0 # EAP reauthentication period in seconds (default: 3600 seconds; 0 = disable # reauthentication). +# Reauthentications may enforce a disconnect, check the related setting +# "wpa_deny_ptk0_rekey" for details. #eap_reauth_period=3600 # Use PAE group address (01:80:c2:00:00:03) instead of individual target @@ -1607,8 +1609,38 @@ 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 the only secure +# method to rekey the PTK without Extended Key ID support requires a disconnect. +# Check the related setting "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" can - depending on the cards/drivers - reduce both the security and +# the stability of connections. Both ends can freeze the connection or even leak +# the PTK by repeating MPDU's without encryption. To avoid the issues hostapd is +# now by default replacing all PTK rekeys using only keyid 0 (PTK0 rekeys) with +# disconnects. +# This is a regression for setups able to rekey the PTK and actually do so. +# +# Eap reauthentication depends on replacing the PTK and is therefore just +# another way to rekey the PTK and affected by the setting, too. +# +# Unfortunately there is no way to detect if a remote stations can safely rekey +# the PTK and the default is therefore to replace all those rekeys with a +# disconnect when not two keyids (Extended Key ID for Individually Addressed +# Frames) are available for it. +# +# If you are sure your cards/drivers don't need the workaround the old behavior +# can be restored by setting wpa_deny_ptk0_rekey = 0. +# +# Available options: +# 0 = always rekey when configured/instructed (old behavior) +# 1 = only rekey when the local driver is able to do it bug free +# 2 = never allow PTK0 rekeys (default) +# wpa_deny_ptk0_rekey = 2 + # 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) diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index 68af3c1d1..98a7f6e26 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -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_NEVER; bss->wpa_group_update_count = 4; bss->wpa_pairwise_update_count = 4; bss->wpa_disable_eapol_key_retries = diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 7e4b9262c..0b4483ea1 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -368,6 +368,7 @@ struct hostapd_bss_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; diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 6611b0e53..5c52f0f76 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -755,8 +755,17 @@ 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_WARNING, + "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; + } else { + sm->PTKRequest = TRUE; + sm->PTK_valid = 0; + } } @@ -1775,6 +1784,16 @@ 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_WARNING, + "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) { /* diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index 933a4b8ed..0e44cbe0b 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -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; diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index b655ae57b..951c7364b 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -1348,6 +1348,18 @@ 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"); + _conf.wpa_deny_ptk0_rekey = 1; + } else { + wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "Support PTK0 rekey"); + _conf.wpa_deny_ptk0_rekey = 0; + } + hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb, hapd); if (hapd->wpa_auth == NULL) { wpa_printf(MSG_ERROR, "WPA initialization failed."); diff --git a/src/common/defs.h b/src/common/defs.h index e2fa4b291..1cf027340 100644 --- a/src/common/defs.h +++ b/src/common/defs.h @@ -423,4 +423,10 @@ enum chan_width { CHAN_WIDTH_UNKNOWN }; +enum ptk0_rekey_handling { + PTK0_REKEY_ALLOW_ALWAYS, + PTK0_REKEY_ALLOW_LOCAL_OK, + PTK0_REKEY_ALLOW_NEVER +}; + #endif /* DEFS_H */