Add SA-17:07.

This commit is contained in:
Gordon Tetlow 2017-10-17 18:11:23 +00:00
parent d0cf868b6d
commit bff7593acd
Notes: svn2git 2020-12-08 03:00:23 +00:00
svn path=/head/; revision=51128
4 changed files with 845 additions and 0 deletions

View file

@ -0,0 +1,159 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512
=============================================================================
FreeBSD-SA-17:07.wpa Security Advisory
The FreeBSD Project
Topic: WPA2 protocol vulnerability
Category: contrib
Module: wpa
Announced: 2017-10-16
Credits: Mathy Vanhoef
Affects: All supported versions of FreeBSD.
Corrected: 2017-10-17 17:30:18 UTC (stable/11, 11.1-STABLE)
2017-10-17 17:57:18 UTC (releng/11.1, 11.1-RELEASE-p2)
2017-10-17 17:56:03 UTC (releng/11.0, 11.0-RELEASE-p13)
CVE Name: CVE-2017-13077, CVE-2017-13078, CVE-2017-13079,
CVE-2017-13080, CVE-2017-13081, CVE-2017-13082,
CVE-2017-13086, CVE-2017-13087, CVE-2017-13088
For general information regarding FreeBSD Security Advisories,
including descriptions of the fields above, security branches, and the
following sections, please visit <URL:https://security.FreeBSD.org/>.
I. Background
Wi-Fi Protected Access II (WPA2) is a security protocol developed by the
Wi-Fi Alliance to secure wireless computer networks.
hostapd and wpa_supplicant are implementations of user space daemon for
access points and wireless client that implements the WPA2 protocol.
II. Problem Description
A vulnerability was found in how a number of implementations can be
triggered to reconfigure WPA/WPA2/RSN keys (TK, GTK, or IGTK) by
replaying a specific frame that is used to manage the keys.
III. Impact
Such reinstallation of the encryption key can result in two different
types of vulnerabilities: disabling replay protection and significantly
reducing the security of encryption to the point of allowing frames to
be decrypted or some parts of the keys to be determined by an attacker
depending on which cipher is used.
IV. Workaround
An updated version of wpa_supplicant is available in the FreeBSD Ports
Collection. Install version 2.6_2 or later of the
security/wpa_supplicant port/pkg. Once installed, update /etc/rc.conf
to use the new binary:
wpa_supplicant_program="/usr/local/sbin/wpa_supplicant"
and restart networking.
An updated version of hostapd is available in the FreeBSD Ports
Collection. Install version 2.6_1 or later of the net/hostapd port/pkg.
Once installed, update /etc/rc.conf to use the new binary:
hostapd_program="/usr/local/sbin/hostapd"
and restart hostapd.
V. Solution
Patches are currently available for stable/11, releng/11.0, and
releng/11.1. Patches for stable/10, releng/10.3, and releng/10.4 are
still being evaluated.
Perform one of the following:
1) Upgrade your vulnerable system to a supported FreeBSD stable or
release / security branch (releng) dated after the correction date.
Restart the Wi-Fi network interfaces/hostapd or reboot the system.
2) To update your vulnerable system via a binary patch:
Systems running a RELEASE version of FreeBSD on the i386 or amd64
platforms can be updated via the freebsd-update(8) utility:
# freebsd-update fetch
# freebsd-update install
Restart the Wi-Fi network interfaces/hostapd or reboot the system.
3) To update your vulnerable system via a source code patch:
The following patches have been verified to apply to the applicable
FreeBSD release branches.
a) Download the relevant patch from the location below, and verify the
detached PGP signature using your PGP utility.
[FreeBSD 11.0-RELEASE, 11.1-RELEASE, and 11-STABLE]
# fetch https://security.FreeBSD.org/patches/SA-17:07/wpa-11.patch
# fetch https://security.FreeBSD.org/patches/SA-17:07/wpa-11.patch.asc
# gpg --verify wpa-11.patch.asc
b) Apply the patch. Execute the following commands as root:
# cd /usr/src
# patch < /path/to/patch
c) Recompile the operating system using buildworld and installworld as
described in <URL:https://www.FreeBSD.org/handbook/makeworld.html>.
Restart the applicable daemons, or reboot the system.
VI. Correction details
The following list contains the correction revision numbers for each
affected branch.
Branch/path Revision
- -------------------------------------------------------------------------
stable/11/ r324697
releng/11.0/ r324698
releng/11.1/ r324699
- -------------------------------------------------------------------------
To see which files were modified by a particular revision, run the
following command, replacing NNNNNN with the revision number, on a
machine with Subversion installed:
# svn diff -cNNNNNN --summarize svn://svn.freebsd.org/base
Or visit the following URL, replacing NNNNNN with the revision number:
<URL:https://svnweb.freebsd.org/base?view=revision&revision=NNNNNN>
VII. References
<URL:https://w1.fi/security/2017-1/wpa-packet-number-reuse-with-replayed-messages.txt>
<URL:https://www.krackattacks.com/>
The latest revision of this advisory is available at
<URL:https://security.FreeBSD.org/advisories/FreeBSD-SA-17:07.wpa.asc>
-----BEGIN PGP SIGNATURE-----
iQKTBAEBCgB9FiEEHPf/b631yp++G4yy7Wfs1l3PaucFAlnmRUZfFIAAAAAALgAo
aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldDFD
RjdGRjZGQURGNUNBOUZCRTFCOENCMkVENjdFQ0Q2NURDRjZBRTcACgkQ7Wfs1l3P
aueKcxAAwObogcEZAgGioU4uZvk9kKIpmG/NwvUjcZ0viFhePowKnh6/UoFDd+13
NsjriznPNKbXPch2Gp3Zwgd/hff10vlvr69QOFXnI3/Y8b+thxkl1kCAxC0xkfEl
eQBzjllMrjtrSgfKtoWInxnZLIrghuJAg4Jvvz+uWd3VTggM0pQgLUuhR/a8lWHd
3HBj5//sOhmVW2OFYC5dskYAn6TqyHtlMP9AT32h6QEyEzJeNWMlToELxy6OK59j
MYaS0vclz7QT+4SATvcl8RCmxmYfyWxEtFhDmPNz4mfQ915AxTjGFv7KbjTZtunl
k3niR3O8F450xduw5Yj9Mz3YdZ4ZYmvHbDgQLsMNwAmtQvXSteXUUBVNVAg9PsjR
4kxlEFsStWh6CtJVKYUvKDThnHrWYLiVUh6o/FtRm5fx2ws/gcj7H9csr8mQ0pkO
zm9jVOgMe7pqI7gygOfb61Rjz6PnLgVQcnP2LoC9pB21O5Q/Q2rv9d6XN3mQ6CQ2
+mUEZ5M7TWyd6gFrP2Eu6srec1nT1NjVjzyyupgusiQve3xV0wacG0jwgy7+VXE8
Ls2a/SObVDZkvFhOYMrLVui33l7f/vgT0KImyO2fkaWjbDcEyVcm1f+A7K+hqwp8
2O/Eh+NVSG0GIbt9pro0BxsZhMb/V4WmWV+4WnLKPwCQZ9fimKA=
=aNWn
-----END PGP SIGNATURE-----

View file

@ -0,0 +1,656 @@
--- contrib/wpa/src/ap/wpa_auth.c.orig
+++ contrib/wpa/src/ap/wpa_auth.c
@@ -1893,6 +1893,21 @@
}
+static int wpa_auth_sm_ptk_update(struct wpa_state_machine *sm)
+{
+ if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) {
+ wpa_printf(MSG_ERROR,
+ "WPA: Failed to get random data for ANonce");
+ sm->Disconnect = TRUE;
+ return -1;
+ }
+ wpa_hexdump(MSG_DEBUG, "WPA: Assign new ANonce", sm->ANonce,
+ WPA_NONCE_LEN);
+ sm->TimeoutCtr = 0;
+ return 0;
+}
+
+
SM_STATE(WPA_PTK, INITPMK)
{
u8 msk[2 * PMK_LEN];
@@ -2414,9 +2429,12 @@
SM_ENTER(WPA_PTK, AUTHENTICATION);
else if (sm->ReAuthenticationRequest)
SM_ENTER(WPA_PTK, AUTHENTICATION2);
- else if (sm->PTKRequest)
- SM_ENTER(WPA_PTK, PTKSTART);
- else switch (sm->wpa_ptk_state) {
+ else if (sm->PTKRequest) {
+ if (wpa_auth_sm_ptk_update(sm) < 0)
+ SM_ENTER(WPA_PTK, DISCONNECTED);
+ else
+ SM_ENTER(WPA_PTK, PTKSTART);
+ } else switch (sm->wpa_ptk_state) {
case WPA_PTK_INITIALIZE:
break;
case WPA_PTK_DISCONNECT:
@@ -3209,6 +3227,14 @@
}
+int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm)
+{
+ if (!sm || !wpa_key_mgmt_ft(sm->wpa_key_mgmt))
+ return 0;
+ return sm->tk_already_set;
+}
+
+
int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
struct rsn_pmksa_cache_entry *entry)
{
--- contrib/wpa/src/ap/wpa_auth.h.orig
+++ contrib/wpa/src/ap/wpa_auth.h
@@ -271,6 +271,7 @@
int wpa_auth_get_pairwise(struct wpa_state_machine *sm);
int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm);
int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm);
+int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm);
int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm,
struct rsn_pmksa_cache_entry *entry);
struct rsn_pmksa_cache_entry *
--- contrib/wpa/src/ap/wpa_auth_ft.c.orig
+++ contrib/wpa/src/ap/wpa_auth_ft.c
@@ -780,6 +780,14 @@
return;
}
+ if (sm->tk_already_set) {
+ /* Must avoid TK reconfiguration to prevent clearing of TX/RX
+ * PN in the driver */
+ wpa_printf(MSG_DEBUG,
+ "FT: Do not re-install same PTK to the driver");
+ return;
+ }
+
/* FIX: add STA entry to kernel/driver here? The set_key will fail
* most likely without this.. At the moment, STA entry is added only
* after association has been completed. This function will be called
@@ -792,6 +800,7 @@
/* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
sm->pairwise_set = TRUE;
+ sm->tk_already_set = TRUE;
}
@@ -898,6 +907,7 @@
sm->pairwise = pairwise;
sm->PTK_valid = TRUE;
+ sm->tk_already_set = FALSE;
wpa_ft_install_ptk(sm);
buflen = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) +
--- contrib/wpa/src/ap/wpa_auth_i.h.orig
+++ contrib/wpa/src/ap/wpa_auth_i.h
@@ -64,6 +64,7 @@
struct wpa_ptk PTK;
Boolean PTK_valid;
Boolean pairwise_set;
+ Boolean tk_already_set;
int keycount;
Boolean Pair;
struct wpa_key_replay_counter {
--- contrib/wpa/src/common/wpa_common.h.orig
+++ contrib/wpa/src/common/wpa_common.h
@@ -213,9 +213,21 @@
size_t kck_len;
size_t kek_len;
size_t tk_len;
+ int installed; /* 1 if key has already been installed to driver */
};
+struct wpa_gtk {
+ u8 gtk[WPA_GTK_MAX_LEN];
+ size_t gtk_len;
+};
+#ifdef CONFIG_IEEE80211W
+struct wpa_igtk {
+ u8 igtk[WPA_IGTK_MAX_LEN];
+ size_t igtk_len;
+};
+#endif /* CONFIG_IEEE80211W */
+
/* WPA IE version 1
* 00-50-f2:1 (OUI:OUI type)
* 0x01 0x00 (version; little endian)
--- contrib/wpa/src/rsn_supp/tdls.c.orig
+++ contrib/wpa/src/rsn_supp/tdls.c
@@ -112,6 +112,7 @@
u8 tk[16]; /* TPK-TK; assuming only CCMP will be used */
} tpk;
int tpk_set;
+ int tk_set; /* TPK-TK configured to the driver */
int tpk_success;
int tpk_in_progress;
@@ -192,6 +193,20 @@
u8 rsc[6];
enum wpa_alg alg;
+ if (peer->tk_set) {
+ /*
+ * This same TPK-TK has already been configured to the driver
+ * and this new configuration attempt (likely due to an
+ * unexpected retransmitted frame) would result in clearing
+ * the TX/RX sequence number which can break security, so must
+ * not allow that to happen.
+ */
+ wpa_printf(MSG_INFO, "TDLS: TPK-TK for the peer " MACSTR
+ " has already been configured to the driver - do not reconfigure",
+ MAC2STR(peer->addr));
+ return -1;
+ }
+
os_memset(rsc, 0, 6);
switch (peer->cipher) {
@@ -209,6 +224,8 @@
return -1;
}
+ wpa_printf(MSG_DEBUG, "TDLS: Configure pairwise key for peer " MACSTR,
+ MAC2STR(peer->addr));
if (wpa_sm_set_key(sm, alg, peer->addr, -1, 1,
rsc, sizeof(rsc), peer->tpk.tk, key_len) < 0) {
wpa_printf(MSG_WARNING, "TDLS: Failed to set TPK to the "
@@ -215,6 +232,7 @@
"driver");
return -1;
}
+ peer->tk_set = 1;
return 0;
}
@@ -690,7 +708,7 @@
peer->cipher = 0;
peer->qos_info = 0;
peer->wmm_capable = 0;
- peer->tpk_set = peer->tpk_success = 0;
+ peer->tk_set = peer->tpk_set = peer->tpk_success = 0;
peer->chan_switch_enabled = 0;
os_memset(&peer->tpk, 0, sizeof(peer->tpk));
os_memset(peer->inonce, 0, WPA_NONCE_LEN);
@@ -1153,6 +1171,7 @@
wpa_tdls_peer_free(sm, peer);
return -1;
}
+ peer->tk_set = 0; /* A new nonce results in a new TK */
wpa_hexdump(MSG_DEBUG, "TDLS: Initiator Nonce for TPK handshake",
peer->inonce, WPA_NONCE_LEN);
os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
@@ -1745,6 +1764,19 @@
}
+static int tdls_nonce_set(const u8 *nonce)
+{
+ int i;
+
+ for (i = 0; i < WPA_NONCE_LEN; i++) {
+ if (nonce[i])
+ return 1;
+ }
+
+ return 0;
+}
+
+
static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
const u8 *buf, size_t len)
{
@@ -1998,7 +2030,8 @@
peer->rsnie_i_len = kde.rsn_ie_len;
peer->cipher = cipher;
- if (os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) != 0) {
+ if (os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) != 0 ||
+ !tdls_nonce_set(peer->inonce)) {
/*
* There is no point in updating the RNonce for every obtained
* TPK M1 frame (e.g., retransmission due to timeout) with the
@@ -2014,6 +2047,7 @@
"TDLS: Failed to get random data for responder nonce");
goto error;
}
+ peer->tk_set = 0; /* A new nonce results in a new TK */
}
#if 0
@@ -2170,6 +2204,14 @@
"ignore TPK M2 from " MACSTR, MAC2STR(src_addr));
return -1;
}
+
+ if (peer->tpk_success) {
+ wpa_printf(MSG_INFO, "TDLS: Ignore incoming TPK M2 retry, from "
+ MACSTR " as TPK M3 was already sent",
+ MAC2STR(src_addr));
+ return 0;
+ }
+
wpa_tdls_tpk_retry_timeout_cancel(sm, peer, WLAN_TDLS_SETUP_REQUEST);
if (len < 3 + 2 + 1) {
--- contrib/wpa/src/rsn_supp/wpa.c.orig
+++ contrib/wpa/src/rsn_supp/wpa.c
@@ -605,6 +605,12 @@
const u8 *key_rsc;
u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ if (sm->ptk.installed) {
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+ "WPA: Do not re-install same PTK to the driver");
+ return 0;
+ }
+
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
"WPA: Installing PTK to the driver");
@@ -643,6 +649,7 @@
/* TK is not needed anymore in supplicant */
os_memset(sm->ptk.tk, 0, WPA_TK_MAX_LEN);
+ sm->ptk.installed = 1;
if (sm->wpa_ptk_rekey) {
eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL);
@@ -692,11 +699,23 @@
static int wpa_supplicant_install_gtk(struct wpa_sm *sm,
const struct wpa_gtk_data *gd,
- const u8 *key_rsc)
+ const u8 *key_rsc, int wnm_sleep)
{
const u8 *_gtk = gd->gtk;
u8 gtk_buf[32];
+ /* Detect possible key reinstallation */
+ if ((sm->gtk.gtk_len == (size_t) gd->gtk_len &&
+ os_memcmp(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len) == 0) ||
+ (sm->gtk_wnm_sleep.gtk_len == (size_t) gd->gtk_len &&
+ os_memcmp(sm->gtk_wnm_sleep.gtk, gd->gtk,
+ sm->gtk_wnm_sleep.gtk_len) == 0)) {
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+ "WPA: Not reinstalling already in-use GTK to the driver (keyidx=%d tx=%d len=%d)",
+ gd->keyidx, gd->tx, gd->gtk_len);
+ return 0;
+ }
+
wpa_hexdump_key(MSG_DEBUG, "WPA: Group Key", gd->gtk, gd->gtk_len);
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
"WPA: Installing GTK to the driver (keyidx=%d tx=%d len=%d)",
@@ -731,6 +750,15 @@
}
os_memset(gtk_buf, 0, sizeof(gtk_buf));
+ if (wnm_sleep) {
+ sm->gtk_wnm_sleep.gtk_len = gd->gtk_len;
+ os_memcpy(sm->gtk_wnm_sleep.gtk, gd->gtk,
+ sm->gtk_wnm_sleep.gtk_len);
+ } else {
+ sm->gtk.gtk_len = gd->gtk_len;
+ os_memcpy(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len);
+ }
+
return 0;
}
@@ -788,7 +816,7 @@
(wpa_supplicant_check_group_cipher(sm, sm->group_cipher,
gtk_len, gtk_len,
&gd.key_rsc_len, &gd.alg) ||
- wpa_supplicant_install_gtk(sm, &gd, key->key_rsc))) {
+ wpa_supplicant_install_gtk(sm, &gd, key->key_rsc, 0))) {
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
"RSN: Failed to install GTK");
os_memset(&gd, 0, sizeof(gd));
@@ -802,6 +830,58 @@
}
+#ifdef CONFIG_IEEE80211W
+static int wpa_supplicant_install_igtk(struct wpa_sm *sm,
+ const struct wpa_igtk_kde *igtk,
+ int wnm_sleep)
+{
+ size_t len = wpa_cipher_key_len(sm->mgmt_group_cipher);
+ u16 keyidx = WPA_GET_LE16(igtk->keyid);
+
+ /* Detect possible key reinstallation */
+ if ((sm->igtk.igtk_len == len &&
+ os_memcmp(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len) == 0) ||
+ (sm->igtk_wnm_sleep.igtk_len == len &&
+ os_memcmp(sm->igtk_wnm_sleep.igtk, igtk->igtk,
+ sm->igtk_wnm_sleep.igtk_len) == 0)) {
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+ "WPA: Not reinstalling already in-use IGTK to the driver (keyidx=%d)",
+ keyidx);
+ return 0;
+ }
+
+ wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG,
+ "WPA: IGTK keyid %d pn %02x%02x%02x%02x%02x%02x",
+ keyidx, MAC2STR(igtk->pn));
+ wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK", igtk->igtk, len);
+ if (keyidx > 4095) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "WPA: Invalid IGTK KeyID %d", keyidx);
+ return -1;
+ }
+ if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher),
+ broadcast_ether_addr,
+ keyidx, 0, igtk->pn, sizeof(igtk->pn),
+ igtk->igtk, len) < 0) {
+ wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
+ "WPA: Failed to configure IGTK to the driver");
+ return -1;
+ }
+
+ if (wnm_sleep) {
+ sm->igtk_wnm_sleep.igtk_len = len;
+ os_memcpy(sm->igtk_wnm_sleep.igtk, igtk->igtk,
+ sm->igtk_wnm_sleep.igtk_len);
+ } else {
+ sm->igtk.igtk_len = len;
+ os_memcpy(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len);
+ }
+
+ return 0;
+}
+#endif /* CONFIG_IEEE80211W */
+
+
static int ieee80211w_set_keys(struct wpa_sm *sm,
struct wpa_eapol_ie_parse *ie)
{
@@ -812,30 +892,14 @@
if (ie->igtk) {
size_t len;
const struct wpa_igtk_kde *igtk;
- u16 keyidx;
+
len = wpa_cipher_key_len(sm->mgmt_group_cipher);
if (ie->igtk_len != WPA_IGTK_KDE_PREFIX_LEN + len)
return -1;
+
igtk = (const struct wpa_igtk_kde *) ie->igtk;
- keyidx = WPA_GET_LE16(igtk->keyid);
- wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: IGTK keyid %d "
- "pn %02x%02x%02x%02x%02x%02x",
- keyidx, MAC2STR(igtk->pn));
- wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK",
- igtk->igtk, len);
- if (keyidx > 4095) {
- wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
- "WPA: Invalid IGTK KeyID %d", keyidx);
+ if (wpa_supplicant_install_igtk(sm, igtk, 0) < 0)
return -1;
- }
- if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher),
- broadcast_ether_addr,
- keyidx, 0, igtk->pn, sizeof(igtk->pn),
- igtk->igtk, len) < 0) {
- wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
- "WPA: Failed to configure IGTK to the driver");
- return -1;
- }
}
return 0;
@@ -1483,7 +1547,7 @@
if (ret)
goto failed;
- if (wpa_supplicant_install_gtk(sm, &gd, key->key_rsc) ||
+ if (wpa_supplicant_install_gtk(sm, &gd, key->key_rsc, 0) ||
wpa_supplicant_send_2_of_2(sm, key, ver, key_info))
goto failed;
os_memset(&gd, 0, sizeof(gd));
@@ -2251,7 +2315,7 @@
*/
void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid)
{
- int clear_ptk = 1;
+ int clear_keys = 1;
if (sm == NULL)
return;
@@ -2277,11 +2341,11 @@
/* Prepare for the next transition */
wpa_ft_prepare_auth_request(sm, NULL);
- clear_ptk = 0;
+ clear_keys = 0;
}
#endif /* CONFIG_IEEE80211R */
- if (clear_ptk) {
+ if (clear_keys) {
/*
* IEEE 802.11, 8.4.10: Delete PTK SA on (re)association if
* this is not part of a Fast BSS Transition.
@@ -2291,6 +2355,12 @@
os_memset(&sm->ptk, 0, sizeof(sm->ptk));
sm->tptk_set = 0;
os_memset(&sm->tptk, 0, sizeof(sm->tptk));
+ os_memset(&sm->gtk, 0, sizeof(sm->gtk));
+ os_memset(&sm->gtk_wnm_sleep, 0, sizeof(sm->gtk_wnm_sleep));
+#ifdef CONFIG_IEEE80211W
+ os_memset(&sm->igtk, 0, sizeof(sm->igtk));
+ os_memset(&sm->igtk_wnm_sleep, 0, sizeof(sm->igtk_wnm_sleep));
+#endif /* CONFIG_IEEE80211W */
}
#ifdef CONFIG_TDLS
@@ -2322,6 +2392,9 @@
#ifdef CONFIG_TDLS
wpa_tdls_disassoc(sm);
#endif /* CONFIG_TDLS */
+#ifdef CONFIG_IEEE80211R
+ sm->ft_reassoc_completed = 0;
+#endif /* CONFIG_IEEE80211R */
/* Keys are not needed in the WPA state machine anymore */
wpa_sm_drop_sa(sm);
@@ -2807,6 +2880,12 @@
os_memset(sm->pmk, 0, sizeof(sm->pmk));
os_memset(&sm->ptk, 0, sizeof(sm->ptk));
os_memset(&sm->tptk, 0, sizeof(sm->tptk));
+ os_memset(&sm->gtk, 0, sizeof(sm->gtk));
+ os_memset(&sm->gtk_wnm_sleep, 0, sizeof(sm->gtk_wnm_sleep));
+#ifdef CONFIG_IEEE80211W
+ os_memset(&sm->igtk, 0, sizeof(sm->igtk));
+ os_memset(&sm->igtk_wnm_sleep, 0, sizeof(sm->igtk_wnm_sleep));
+#endif /* CONFIG_IEEE80211W */
#ifdef CONFIG_IEEE80211R
os_memset(sm->xxkey, 0, sizeof(sm->xxkey));
os_memset(sm->pmk_r0, 0, sizeof(sm->pmk_r0));
@@ -2870,7 +2949,7 @@
wpa_hexdump_key(MSG_DEBUG, "Install GTK (WNM SLEEP)",
gd.gtk, gd.gtk_len);
- if (wpa_supplicant_install_gtk(sm, &gd, key_rsc)) {
+ if (wpa_supplicant_install_gtk(sm, &gd, key_rsc, 1)) {
os_memset(&gd, 0, sizeof(gd));
wpa_printf(MSG_DEBUG, "Failed to install the GTK in "
"WNM mode");
@@ -2879,29 +2958,11 @@
os_memset(&gd, 0, sizeof(gd));
#ifdef CONFIG_IEEE80211W
} else if (subelem_id == WNM_SLEEP_SUBELEM_IGTK) {
- struct wpa_igtk_kde igd;
- u16 keyidx;
+ const struct wpa_igtk_kde *igtk;
- os_memset(&igd, 0, sizeof(igd));
- keylen = wpa_cipher_key_len(sm->mgmt_group_cipher);
- os_memcpy(igd.keyid, buf + 2, 2);
- os_memcpy(igd.pn, buf + 4, 6);
-
- keyidx = WPA_GET_LE16(igd.keyid);
- os_memcpy(igd.igtk, buf + 10, keylen);
-
- wpa_hexdump_key(MSG_DEBUG, "Install IGTK (WNM SLEEP)",
- igd.igtk, keylen);
- if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher),
- broadcast_ether_addr,
- keyidx, 0, igd.pn, sizeof(igd.pn),
- igd.igtk, keylen) < 0) {
- wpa_printf(MSG_DEBUG, "Failed to install the IGTK in "
- "WNM mode");
- os_memset(&igd, 0, sizeof(igd));
+ igtk = (const struct wpa_igtk_kde *) (buf + 2);
+ if (wpa_supplicant_install_igtk(sm, igtk, 1) < 0)
return -1;
- }
- os_memset(&igd, 0, sizeof(igd));
#endif /* CONFIG_IEEE80211W */
} else {
wpa_printf(MSG_DEBUG, "Unknown element id");
--- contrib/wpa/src/rsn_supp/wpa_ft.c.orig
+++ contrib/wpa/src/rsn_supp/wpa_ft.c
@@ -153,6 +153,7 @@
u16 capab;
sm->ft_completed = 0;
+ sm->ft_reassoc_completed = 0;
buf_len = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) +
2 + sm->r0kh_id_len + ric_ies_len + 100;
@@ -681,6 +682,11 @@
return -1;
}
+ if (sm->ft_reassoc_completed) {
+ wpa_printf(MSG_DEBUG, "FT: Reassociation has already been completed for this FT protocol instance - ignore unexpected retransmission");
+ return 0;
+ }
+
if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) {
wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs");
return -1;
@@ -781,6 +787,8 @@
return -1;
}
+ sm->ft_reassoc_completed = 1;
+
if (wpa_ft_process_gtk_subelem(sm, parse.gtk, parse.gtk_len) < 0)
return -1;
--- contrib/wpa/src/rsn_supp/wpa_i.h.orig
+++ contrib/wpa/src/rsn_supp/wpa_i.h
@@ -30,6 +30,12 @@
u8 rx_replay_counter[WPA_REPLAY_COUNTER_LEN];
int rx_replay_counter_set;
u8 request_counter[WPA_REPLAY_COUNTER_LEN];
+ struct wpa_gtk gtk;
+ struct wpa_gtk gtk_wnm_sleep;
+#ifdef CONFIG_IEEE80211W
+ struct wpa_igtk igtk;
+ struct wpa_igtk igtk_wnm_sleep;
+#endif /* CONFIG_IEEE80211W */
struct eapol_sm *eapol; /* EAPOL state machine from upper level code */
@@ -121,6 +127,7 @@
size_t r0kh_id_len;
u8 r1kh_id[FT_R1KH_ID_LEN];
int ft_completed;
+ int ft_reassoc_completed;
int over_the_ds_in_progress;
u8 target_ap[ETH_ALEN]; /* over-the-DS target AP */
int set_ptk_after_assoc;
--- contrib/wpa/wpa_supplicant/ctrl_iface.c.orig
+++ contrib/wpa/wpa_supplicant/ctrl_iface.c
@@ -6891,6 +6891,7 @@
}
eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL);
+ wpa_s->wnmsleep_used = 0;
}
--- contrib/wpa/wpa_supplicant/events.c.orig
+++ contrib/wpa/wpa_supplicant/events.c
@@ -303,6 +303,7 @@
wpa_s->key_mgmt = 0;
wpas_rrm_reset(wpa_s);
+ wpa_s->wnmsleep_used = 0;
}
--- contrib/wpa/wpa_supplicant/wnm_sta.c.orig
+++ contrib/wpa/wpa_supplicant/wnm_sta.c
@@ -137,6 +137,8 @@
if (res < 0)
wpa_printf(MSG_DEBUG, "Failed to send WNM-Sleep Request "
"(action=%d, intval=%d)", action, intval);
+ else
+ wpa_s->wnmsleep_used = 1;
os_free(wnmsleep_ie);
os_free(wnmtfs_ie);
@@ -187,6 +189,12 @@
end = ptr + key_len_total;
wpa_hexdump_key(MSG_DEBUG, "WNM: Key Data", ptr, key_len_total);
+ if (key_len_total && !wpa_sm_pmf_enabled(wpa_s->wpa)) {
+ wpa_msg(wpa_s, MSG_INFO,
+ "WNM: Ignore Key Data in WNM-Sleep Mode Response - PMF not enabled");
+ return;
+ }
+
while (ptr + 1 < end) {
if (ptr + 2 + ptr[1] > end) {
wpa_printf(MSG_DEBUG, "WNM: Invalid Key Data element "
@@ -247,6 +255,12 @@
u8 *tfsresp_ie_end = NULL;
size_t left;
+ if (!wpa_s->wnmsleep_used) {
+ wpa_printf(MSG_DEBUG,
+ "WNM: Ignore WNM-Sleep Mode Response frame since WNM-Sleep Mode operation has not been requested");
+ return;
+ }
+
if (len < 3)
return;
key_len_total = WPA_GET_LE16(frm + 1);
@@ -282,6 +296,8 @@
return;
}
+ wpa_s->wnmsleep_used = 0;
+
if (wnmsleep_ie->status == WNM_STATUS_SLEEP_ACCEPT ||
wnmsleep_ie->status == WNM_STATUS_SLEEP_EXIT_ACCEPT_GTK_UPDATE) {
wpa_printf(MSG_DEBUG, "Successfully recv WNM-Sleep Response "
--- contrib/wpa/wpa_supplicant/wpa_supplicant_i.h.orig
+++ contrib/wpa/wpa_supplicant/wpa_supplicant_i.h
@@ -658,6 +658,7 @@
unsigned int reattach:1; /* reassociation to the same BSS requested */
unsigned int mac_addr_changed:1;
unsigned int added_vif:1;
+ unsigned int wnmsleep_used:1;
struct os_reltime last_mac_addr_change;
int last_mac_addr_style;

View file

@ -0,0 +1,18 @@
-----BEGIN PGP SIGNATURE-----
iQKTBAABCgB9FiEEHPf/b631yp++G4yy7Wfs1l3PaucFAlnmRVxfFIAAAAAALgAo
aXNzdWVyLWZwckBub3RhdGlvbnMub3BlbnBncC5maWZ0aGhvcnNlbWFuLm5ldDFD
RjdGRjZGQURGNUNBOUZCRTFCOENCMkVENjdFQ0Q2NURDRjZBRTcACgkQ7Wfs1l3P
aueRhRAAmv4P5U4e6PpiJHsgVTaZbegTzCAHpTKjvvA2gnSweZdY3aqiKvuFcqjJ
A/Vtm/4GYeAFeBctZhEbb0bxBKod5vvTaC/VOwR+es1uP8rAHnhsvSXkv/UwJWo8
p77SV7eSrNNhb2UGG4xSd3WyQPVFkyFgX+xB8EVszBGAEgQwog+ZfVnTLEotSYZ6
hg4gKQxOAMCCdONslh3kBRepk8VpWgLjdX2rMZjaM8UBBNhqFAAbdPCBHldqU7Ra
cELsKGlI8ZrKBZGRUv7d6l0TRyErC6sMcHjV+zvuPl0s7g6GKX+7hXQhtT0Rj9aR
r7rd4JFUPdyA7QExWkm2yR+XMoaziWe1f1HfGdGO3QVUPfojNIDXU4/W6XtGo3vm
dlD+2fNz6LFPNSbWETxHr8vvMJLhbWU2/1q34dj1aFIf7D00cN+TzIFLdspm0x0u
5dVDw16NL5Z7W3stAxGAoeS18ZKIg3ZlndtSOydrt6lF8BZtSlS4mOikO/qX1ySs
vE2yFNslvwG63Pr1fEeme9j1SFd32m2+UuWgIihYxUxyIfAF/ohtNTEfefmKaAJQ
hNj41nFzvR9sxKlGmNosPTBybbvjP5P/nFeC3Azk1BAmkadlasueIRUwgagAxgQQ
WwU3LOCxQ4zoLe4mLDMguo4GrbO9p2LNhsI03rEDYD+iDLXzKzs=
=hrIq
-----END PGP SIGNATURE-----

View file

@ -7,6 +7,18 @@
<year>
<name>2017</name>
<month>
<name>10</name>
<day>
<name>17</name>
<advisory>
<name>FreeBSD-SA-17:07.wpa</name>
</advisory>
</day>
</month>
<month>
<name>8</name>