From owner-svn-src-releng@freebsd.org Tue Oct 17 17:56:06 2017 Return-Path: Delivered-To: svn-src-releng@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 679A3E41FFF; Tue, 17 Oct 2017 17:56:06 +0000 (UTC) (envelope-from gordon@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 32FAD77B57; Tue, 17 Oct 2017 17:56:06 +0000 (UTC) (envelope-from gordon@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v9HHu53A062160; Tue, 17 Oct 2017 17:56:05 GMT (envelope-from gordon@FreeBSD.org) Received: (from gordon@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v9HHu41i062145; Tue, 17 Oct 2017 17:56:04 GMT (envelope-from gordon@FreeBSD.org) Message-Id: <201710171756.v9HHu41i062145@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: gordon set sender to gordon@FreeBSD.org using -f From: Gordon Tetlow Date: Tue, 17 Oct 2017 17:56:04 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-releng@freebsd.org Subject: svn commit: r324698 - in releng/11.0: . contrib/wpa/src/ap contrib/wpa/src/common contrib/wpa/src/rsn_supp contrib/wpa/wpa_supplicant sys/conf X-SVN-Group: releng X-SVN-Commit-Author: gordon X-SVN-Commit-Paths: in releng/11.0: . contrib/wpa/src/ap contrib/wpa/src/common contrib/wpa/src/rsn_supp contrib/wpa/wpa_supplicant sys/conf X-SVN-Commit-Revision: 324698 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-releng@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the release engineering / security commits to the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 17 Oct 2017 17:56:06 -0000 Author: gordon Date: Tue Oct 17 17:56:03 2017 New Revision: 324698 URL: https://svnweb.freebsd.org/changeset/base/324698 Log: Fix WPA2 protocol vulnerability. [SA-17:07] Approved by: so Modified: releng/11.0/UPDATING releng/11.0/contrib/wpa/src/ap/wpa_auth.c releng/11.0/contrib/wpa/src/ap/wpa_auth.h releng/11.0/contrib/wpa/src/ap/wpa_auth_ft.c releng/11.0/contrib/wpa/src/ap/wpa_auth_i.h releng/11.0/contrib/wpa/src/common/wpa_common.h releng/11.0/contrib/wpa/src/rsn_supp/tdls.c releng/11.0/contrib/wpa/src/rsn_supp/wpa.c releng/11.0/contrib/wpa/src/rsn_supp/wpa_ft.c releng/11.0/contrib/wpa/src/rsn_supp/wpa_i.h releng/11.0/contrib/wpa/wpa_supplicant/ctrl_iface.c releng/11.0/contrib/wpa/wpa_supplicant/events.c releng/11.0/contrib/wpa/wpa_supplicant/wnm_sta.c releng/11.0/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h releng/11.0/sys/conf/newvers.sh Modified: releng/11.0/UPDATING ============================================================================== --- releng/11.0/UPDATING Tue Oct 17 17:30:18 2017 (r324697) +++ releng/11.0/UPDATING Tue Oct 17 17:56:03 2017 (r324698) @@ -16,6 +16,10 @@ from older versions of FreeBSD, try WITHOUT_CLANG and the tip of head, and then rebuild without this option. The bootstrap process from older version of current across the gcc/clang cutover is a bit fragile. +20171017 p13 FreeBSD-SA-17:07.wpa + + Fix WPA2 protocol vulnerability. [SA-17:07] + 20170810 p12 FreeBSD-SA-17:06.openssh FreeBSD-EN-17:07.vnet Modified: releng/11.0/contrib/wpa/src/ap/wpa_auth.c ============================================================================== --- releng/11.0/contrib/wpa/src/ap/wpa_auth.c Tue Oct 17 17:30:18 2017 (r324697) +++ releng/11.0/contrib/wpa/src/ap/wpa_auth.c Tue Oct 17 17:56:03 2017 (r324698) @@ -1893,6 +1893,21 @@ SM_STATE(WPA_PTK, AUTHENTICATION2) } +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_STEP(WPA_PTK) 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: @@ -3206,6 +3224,14 @@ int wpa_auth_sta_wpa_version(struct wpa_state_machine if (sm == NULL) return 0; return sm->wpa; +} + + +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; } Modified: releng/11.0/contrib/wpa/src/ap/wpa_auth.h ============================================================================== --- releng/11.0/contrib/wpa/src/ap/wpa_auth.h Tue Oct 17 17:30:18 2017 (r324697) +++ releng/11.0/contrib/wpa/src/ap/wpa_auth.h Tue Oct 17 17:56:03 2017 (r324698) @@ -271,6 +271,7 @@ int wpa_auth_pairwise_set(struct wpa_state_machine *sm 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 * Modified: releng/11.0/contrib/wpa/src/ap/wpa_auth_ft.c ============================================================================== --- releng/11.0/contrib/wpa/src/ap/wpa_auth_ft.c Tue Oct 17 17:30:18 2017 (r324697) +++ releng/11.0/contrib/wpa/src/ap/wpa_auth_ft.c Tue Oct 17 17:56:03 2017 (r324698) @@ -780,6 +780,14 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm) 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 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm) /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ sm->pairwise_set = TRUE; + sm->tk_already_set = TRUE; } @@ -898,6 +907,7 @@ static int wpa_ft_process_auth_req(struct wpa_state_ma 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) + Modified: releng/11.0/contrib/wpa/src/ap/wpa_auth_i.h ============================================================================== --- releng/11.0/contrib/wpa/src/ap/wpa_auth_i.h Tue Oct 17 17:30:18 2017 (r324697) +++ releng/11.0/contrib/wpa/src/ap/wpa_auth_i.h Tue Oct 17 17:56:03 2017 (r324698) @@ -64,6 +64,7 @@ struct wpa_state_machine { struct wpa_ptk PTK; Boolean PTK_valid; Boolean pairwise_set; + Boolean tk_already_set; int keycount; Boolean Pair; struct wpa_key_replay_counter { Modified: releng/11.0/contrib/wpa/src/common/wpa_common.h ============================================================================== --- releng/11.0/contrib/wpa/src/common/wpa_common.h Tue Oct 17 17:30:18 2017 (r324697) +++ releng/11.0/contrib/wpa/src/common/wpa_common.h Tue Oct 17 17:56:03 2017 (r324698) @@ -213,8 +213,20 @@ struct wpa_ptk { 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) Modified: releng/11.0/contrib/wpa/src/rsn_supp/tdls.c ============================================================================== --- releng/11.0/contrib/wpa/src/rsn_supp/tdls.c Tue Oct 17 17:30:18 2017 (r324697) +++ releng/11.0/contrib/wpa/src/rsn_supp/tdls.c Tue Oct 17 17:56:03 2017 (r324698) @@ -112,6 +112,7 @@ struct wpa_tdls_peer { 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 @@ static int wpa_tdls_set_key(struct wpa_sm *sm, struct 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,12 +224,15 @@ static int wpa_tdls_set_key(struct wpa_sm *sm, struct 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 " "driver"); return -1; } + peer->tk_set = 1; return 0; } @@ -690,7 +708,7 @@ static void wpa_tdls_peer_clear(struct wpa_sm *sm, str 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 @@ skip_rsnie: 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 wpa_tdls_addset_peer(struct wpa_sm *sm, str } +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 @@ skip_rsn: 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 @@ skip_rsn: "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 @@ static int wpa_tdls_process_tpk_m2(struct wpa_sm *sm, "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) { Modified: releng/11.0/contrib/wpa/src/rsn_supp/wpa.c ============================================================================== --- releng/11.0/contrib/wpa/src/rsn_supp/wpa.c Tue Oct 17 17:30:18 2017 (r324697) +++ releng/11.0/contrib/wpa/src/rsn_supp/wpa.c Tue Oct 17 17:56:03 2017 (r324698) @@ -605,6 +605,12 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *s 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 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *s /* 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 @@ struct wpa_gtk_data { 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 @@ static int wpa_supplicant_install_gtk(struct wpa_sm *s } 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 @@ static int wpa_supplicant_pairwise_gtk(struct wpa_sm * (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 @@ static int wpa_supplicant_pairwise_gtk(struct wpa_sm * } +#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 @@ static int ieee80211w_set_keys(struct wpa_sm *sm, 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 @@ static void wpa_supplicant_process_1_of_2(struct wpa_s 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_deinit(struct wpa_sm *sm) */ 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 @@ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 * /* 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 @@ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 * 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 @@ void wpa_sm_notify_disassoc(struct wpa_sm *sm) #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 @@ void wpa_sm_drop_sa(struct wpa_sm *sm) 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 @@ int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 sub 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 @@ int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 sub 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"); Modified: releng/11.0/contrib/wpa/src/rsn_supp/wpa_ft.c ============================================================================== --- releng/11.0/contrib/wpa/src/rsn_supp/wpa_ft.c Tue Oct 17 17:30:18 2017 (r324697) +++ releng/11.0/contrib/wpa/src/rsn_supp/wpa_ft.c Tue Oct 17 17:56:03 2017 (r324698) @@ -153,6 +153,7 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size 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 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, co 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; @@ -780,6 +786,8 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, co wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, 16); return -1; } + + sm->ft_reassoc_completed = 1; if (wpa_ft_process_gtk_subelem(sm, parse.gtk, parse.gtk_len) < 0) return -1; Modified: releng/11.0/contrib/wpa/src/rsn_supp/wpa_i.h ============================================================================== --- releng/11.0/contrib/wpa/src/rsn_supp/wpa_i.h Tue Oct 17 17:30:18 2017 (r324697) +++ releng/11.0/contrib/wpa/src/rsn_supp/wpa_i.h Tue Oct 17 17:56:03 2017 (r324698) @@ -30,6 +30,12 @@ struct wpa_sm { 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 @@ struct wpa_sm { 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; Modified: releng/11.0/contrib/wpa/wpa_supplicant/ctrl_iface.c ============================================================================== --- releng/11.0/contrib/wpa/wpa_supplicant/ctrl_iface.c Tue Oct 17 17:30:18 2017 (r324697) +++ releng/11.0/contrib/wpa/wpa_supplicant/ctrl_iface.c Tue Oct 17 17:56:03 2017 (r324698) @@ -6891,6 +6891,7 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa } eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL); + wpa_s->wnmsleep_used = 0; } Modified: releng/11.0/contrib/wpa/wpa_supplicant/events.c ============================================================================== --- releng/11.0/contrib/wpa/wpa_supplicant/events.c Tue Oct 17 17:30:18 2017 (r324697) +++ releng/11.0/contrib/wpa/wpa_supplicant/events.c Tue Oct 17 17:56:03 2017 (r324698) @@ -303,6 +303,7 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplican wpa_s->key_mgmt = 0; wpas_rrm_reset(wpa_s); + wpa_s->wnmsleep_used = 0; } Modified: releng/11.0/contrib/wpa/wpa_supplicant/wnm_sta.c ============================================================================== --- releng/11.0/contrib/wpa/wpa_supplicant/wnm_sta.c Tue Oct 17 17:30:18 2017 (r324697) +++ releng/11.0/contrib/wpa/wpa_supplicant/wnm_sta.c Tue Oct 17 17:56:03 2017 (r324698) @@ -137,6 +137,8 @@ int ieee802_11_send_wnmsleep_req(struct wpa_supplicant 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 @@ static void wnm_sleep_mode_exit_success(struct wpa_sup 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 @@ static void ieee802_11_rx_wnmsleep_resp(struct wpa_sup 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); @@ -281,6 +295,8 @@ static void ieee802_11_rx_wnmsleep_resp(struct wpa_sup wpa_printf(MSG_DEBUG, "No WNM-Sleep IE found"); return; } + + wpa_s->wnmsleep_used = 0; if (wnmsleep_ie->status == WNM_STATUS_SLEEP_ACCEPT || wnmsleep_ie->status == WNM_STATUS_SLEEP_EXIT_ACCEPT_GTK_UPDATE) { Modified: releng/11.0/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h ============================================================================== --- releng/11.0/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h Tue Oct 17 17:30:18 2017 (r324697) +++ releng/11.0/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h Tue Oct 17 17:56:03 2017 (r324698) @@ -658,6 +658,7 @@ struct wpa_supplicant { 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; Modified: releng/11.0/sys/conf/newvers.sh ============================================================================== --- releng/11.0/sys/conf/newvers.sh Tue Oct 17 17:30:18 2017 (r324697) +++ releng/11.0/sys/conf/newvers.sh Tue Oct 17 17:56:03 2017 (r324698) @@ -32,7 +32,7 @@ TYPE="FreeBSD" REVISION="11.0" -BRANCH="RELEASE-p12" +BRANCH="RELEASE-p13" if [ -n "${BRANCH_OVERRIDE}" ]; then BRANCH=${BRANCH_OVERRIDE} fi From owner-svn-src-releng@freebsd.org Tue Oct 17 17:57:21 2017 Return-Path: Delivered-To: svn-src-releng@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 3BD76E420FD; Tue, 17 Oct 2017 17:57:21 +0000 (UTC) (envelope-from gordon@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id D238A77CBC; Tue, 17 Oct 2017 17:57:20 +0000 (UTC) (envelope-from gordon@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v9HHvKRt062260; Tue, 17 Oct 2017 17:57:20 GMT (envelope-from gordon@FreeBSD.org) Received: (from gordon@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v9HHvIZt062244; Tue, 17 Oct 2017 17:57:18 GMT (envelope-from gordon@FreeBSD.org) Message-Id: <201710171757.v9HHvIZt062244@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: gordon set sender to gordon@FreeBSD.org using -f From: Gordon Tetlow Date: Tue, 17 Oct 2017 17:57:18 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-releng@freebsd.org Subject: svn commit: r324699 - in releng/11.1: . contrib/wpa/src/ap contrib/wpa/src/common contrib/wpa/src/rsn_supp contrib/wpa/wpa_supplicant sys/conf X-SVN-Group: releng X-SVN-Commit-Author: gordon X-SVN-Commit-Paths: in releng/11.1: . contrib/wpa/src/ap contrib/wpa/src/common contrib/wpa/src/rsn_supp contrib/wpa/wpa_supplicant sys/conf X-SVN-Commit-Revision: 324699 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-releng@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the release engineering / security commits to the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 17 Oct 2017 17:57:21 -0000 Author: gordon Date: Tue Oct 17 17:57:18 2017 New Revision: 324699 URL: https://svnweb.freebsd.org/changeset/base/324699 Log: Fix WPA2 protocol vulnerability. [SA-17:07] Approved by: so Modified: releng/11.1/UPDATING releng/11.1/contrib/wpa/src/ap/wpa_auth.c releng/11.1/contrib/wpa/src/ap/wpa_auth.h releng/11.1/contrib/wpa/src/ap/wpa_auth_ft.c releng/11.1/contrib/wpa/src/ap/wpa_auth_i.h releng/11.1/contrib/wpa/src/common/wpa_common.h releng/11.1/contrib/wpa/src/rsn_supp/tdls.c releng/11.1/contrib/wpa/src/rsn_supp/wpa.c releng/11.1/contrib/wpa/src/rsn_supp/wpa_ft.c releng/11.1/contrib/wpa/src/rsn_supp/wpa_i.h releng/11.1/contrib/wpa/wpa_supplicant/ctrl_iface.c releng/11.1/contrib/wpa/wpa_supplicant/events.c releng/11.1/contrib/wpa/wpa_supplicant/wnm_sta.c releng/11.1/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h releng/11.1/sys/conf/newvers.sh Modified: releng/11.1/UPDATING ============================================================================== --- releng/11.1/UPDATING Tue Oct 17 17:56:03 2017 (r324698) +++ releng/11.1/UPDATING Tue Oct 17 17:57:18 2017 (r324699) @@ -16,6 +16,10 @@ from older versions of FreeBSD, try WITHOUT_CLANG and the tip of head, and then rebuild without this option. The bootstrap process from older version of current across the gcc/clang cutover is a bit fragile. +20171017 p13 FreeBSD-SA-17:07.wpa + + Fix WPA2 protocol vulnerability. [SA-17:07] + 20170810 p1 FreeBSD-SA-17:06.openssh FreeBSD-EN-17:07.vnet FreeBSD-EN-17:08.pf Modified: releng/11.1/contrib/wpa/src/ap/wpa_auth.c ============================================================================== --- releng/11.1/contrib/wpa/src/ap/wpa_auth.c Tue Oct 17 17:56:03 2017 (r324698) +++ releng/11.1/contrib/wpa/src/ap/wpa_auth.c Tue Oct 17 17:57:18 2017 (r324699) @@ -1893,6 +1893,21 @@ SM_STATE(WPA_PTK, AUTHENTICATION2) } +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_STEP(WPA_PTK) 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: @@ -3206,6 +3224,14 @@ int wpa_auth_sta_wpa_version(struct wpa_state_machine if (sm == NULL) return 0; return sm->wpa; +} + + +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; } Modified: releng/11.1/contrib/wpa/src/ap/wpa_auth.h ============================================================================== --- releng/11.1/contrib/wpa/src/ap/wpa_auth.h Tue Oct 17 17:56:03 2017 (r324698) +++ releng/11.1/contrib/wpa/src/ap/wpa_auth.h Tue Oct 17 17:57:18 2017 (r324699) @@ -271,6 +271,7 @@ int wpa_auth_pairwise_set(struct wpa_state_machine *sm 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 * Modified: releng/11.1/contrib/wpa/src/ap/wpa_auth_ft.c ============================================================================== --- releng/11.1/contrib/wpa/src/ap/wpa_auth_ft.c Tue Oct 17 17:56:03 2017 (r324698) +++ releng/11.1/contrib/wpa/src/ap/wpa_auth_ft.c Tue Oct 17 17:57:18 2017 (r324699) @@ -780,6 +780,14 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm) 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 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm) /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ sm->pairwise_set = TRUE; + sm->tk_already_set = TRUE; } @@ -898,6 +907,7 @@ static int wpa_ft_process_auth_req(struct wpa_state_ma 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) + Modified: releng/11.1/contrib/wpa/src/ap/wpa_auth_i.h ============================================================================== --- releng/11.1/contrib/wpa/src/ap/wpa_auth_i.h Tue Oct 17 17:56:03 2017 (r324698) +++ releng/11.1/contrib/wpa/src/ap/wpa_auth_i.h Tue Oct 17 17:57:18 2017 (r324699) @@ -64,6 +64,7 @@ struct wpa_state_machine { struct wpa_ptk PTK; Boolean PTK_valid; Boolean pairwise_set; + Boolean tk_already_set; int keycount; Boolean Pair; struct wpa_key_replay_counter { Modified: releng/11.1/contrib/wpa/src/common/wpa_common.h ============================================================================== --- releng/11.1/contrib/wpa/src/common/wpa_common.h Tue Oct 17 17:56:03 2017 (r324698) +++ releng/11.1/contrib/wpa/src/common/wpa_common.h Tue Oct 17 17:57:18 2017 (r324699) @@ -213,8 +213,20 @@ struct wpa_ptk { 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) Modified: releng/11.1/contrib/wpa/src/rsn_supp/tdls.c ============================================================================== --- releng/11.1/contrib/wpa/src/rsn_supp/tdls.c Tue Oct 17 17:56:03 2017 (r324698) +++ releng/11.1/contrib/wpa/src/rsn_supp/tdls.c Tue Oct 17 17:57:18 2017 (r324699) @@ -112,6 +112,7 @@ struct wpa_tdls_peer { 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 @@ static int wpa_tdls_set_key(struct wpa_sm *sm, struct 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,12 +224,15 @@ static int wpa_tdls_set_key(struct wpa_sm *sm, struct 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 " "driver"); return -1; } + peer->tk_set = 1; return 0; } @@ -690,7 +708,7 @@ static void wpa_tdls_peer_clear(struct wpa_sm *sm, str 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 @@ skip_rsnie: 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 wpa_tdls_addset_peer(struct wpa_sm *sm, str } +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 @@ skip_rsn: 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 @@ skip_rsn: "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 @@ static int wpa_tdls_process_tpk_m2(struct wpa_sm *sm, "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) { Modified: releng/11.1/contrib/wpa/src/rsn_supp/wpa.c ============================================================================== --- releng/11.1/contrib/wpa/src/rsn_supp/wpa.c Tue Oct 17 17:56:03 2017 (r324698) +++ releng/11.1/contrib/wpa/src/rsn_supp/wpa.c Tue Oct 17 17:57:18 2017 (r324699) @@ -605,6 +605,12 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *s 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 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *s /* 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 @@ struct wpa_gtk_data { 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 @@ static int wpa_supplicant_install_gtk(struct wpa_sm *s } 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 @@ static int wpa_supplicant_pairwise_gtk(struct wpa_sm * (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 @@ static int wpa_supplicant_pairwise_gtk(struct wpa_sm * } +#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 @@ static int ieee80211w_set_keys(struct wpa_sm *sm, 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 @@ static void wpa_supplicant_process_1_of_2(struct wpa_s 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_deinit(struct wpa_sm *sm) */ 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 @@ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 * /* 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 @@ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 * 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 @@ void wpa_sm_notify_disassoc(struct wpa_sm *sm) #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 @@ void wpa_sm_drop_sa(struct wpa_sm *sm) 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 @@ int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 sub 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 @@ int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 sub 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"); Modified: releng/11.1/contrib/wpa/src/rsn_supp/wpa_ft.c ============================================================================== --- releng/11.1/contrib/wpa/src/rsn_supp/wpa_ft.c Tue Oct 17 17:56:03 2017 (r324698) +++ releng/11.1/contrib/wpa/src/rsn_supp/wpa_ft.c Tue Oct 17 17:57:18 2017 (r324699) @@ -153,6 +153,7 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size 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 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, co 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; @@ -780,6 +786,8 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, co wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, 16); return -1; } + + sm->ft_reassoc_completed = 1; if (wpa_ft_process_gtk_subelem(sm, parse.gtk, parse.gtk_len) < 0) return -1; Modified: releng/11.1/contrib/wpa/src/rsn_supp/wpa_i.h ============================================================================== --- releng/11.1/contrib/wpa/src/rsn_supp/wpa_i.h Tue Oct 17 17:56:03 2017 (r324698) +++ releng/11.1/contrib/wpa/src/rsn_supp/wpa_i.h Tue Oct 17 17:57:18 2017 (r324699) @@ -30,6 +30,12 @@ struct wpa_sm { 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 @@ struct wpa_sm { 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; Modified: releng/11.1/contrib/wpa/wpa_supplicant/ctrl_iface.c ============================================================================== --- releng/11.1/contrib/wpa/wpa_supplicant/ctrl_iface.c Tue Oct 17 17:56:03 2017 (r324698) +++ releng/11.1/contrib/wpa/wpa_supplicant/ctrl_iface.c Tue Oct 17 17:57:18 2017 (r324699) @@ -6891,6 +6891,7 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa } eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL); + wpa_s->wnmsleep_used = 0; } Modified: releng/11.1/contrib/wpa/wpa_supplicant/events.c ============================================================================== --- releng/11.1/contrib/wpa/wpa_supplicant/events.c Tue Oct 17 17:56:03 2017 (r324698) +++ releng/11.1/contrib/wpa/wpa_supplicant/events.c Tue Oct 17 17:57:18 2017 (r324699) @@ -303,6 +303,7 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplican wpa_s->key_mgmt = 0; wpas_rrm_reset(wpa_s); + wpa_s->wnmsleep_used = 0; } Modified: releng/11.1/contrib/wpa/wpa_supplicant/wnm_sta.c ============================================================================== --- releng/11.1/contrib/wpa/wpa_supplicant/wnm_sta.c Tue Oct 17 17:56:03 2017 (r324698) +++ releng/11.1/contrib/wpa/wpa_supplicant/wnm_sta.c Tue Oct 17 17:57:18 2017 (r324699) @@ -137,6 +137,8 @@ int ieee802_11_send_wnmsleep_req(struct wpa_supplicant 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 @@ static void wnm_sleep_mode_exit_success(struct wpa_sup 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 @@ static void ieee802_11_rx_wnmsleep_resp(struct wpa_sup 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); @@ -281,6 +295,8 @@ static void ieee802_11_rx_wnmsleep_resp(struct wpa_sup wpa_printf(MSG_DEBUG, "No WNM-Sleep IE found"); return; } + + wpa_s->wnmsleep_used = 0; if (wnmsleep_ie->status == WNM_STATUS_SLEEP_ACCEPT || wnmsleep_ie->status == WNM_STATUS_SLEEP_EXIT_ACCEPT_GTK_UPDATE) { Modified: releng/11.1/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h ============================================================================== --- releng/11.1/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h Tue Oct 17 17:56:03 2017 (r324698) +++ releng/11.1/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h Tue Oct 17 17:57:18 2017 (r324699) @@ -658,6 +658,7 @@ struct wpa_supplicant { 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; Modified: releng/11.1/sys/conf/newvers.sh ============================================================================== --- releng/11.1/sys/conf/newvers.sh Tue Oct 17 17:56:03 2017 (r324698) +++ releng/11.1/sys/conf/newvers.sh Tue Oct 17 17:57:18 2017 (r324699) @@ -44,7 +44,7 @@ TYPE="FreeBSD" REVISION="11.1" -BRANCH="RELEASE-p1" +BRANCH="RELEASE-p2" if [ -n "${BRANCH_OVERRIDE}" ]; then BRANCH=${BRANCH_OVERRIDE} fi From owner-svn-src-releng@freebsd.org Tue Oct 17 21:20:08 2017 Return-Path: Delivered-To: svn-src-releng@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id AC3CAE47BEB; Tue, 17 Oct 2017 21:20:08 +0000 (UTC) (envelope-from gordon@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 798BC83F73; Tue, 17 Oct 2017 21:20:08 +0000 (UTC) (envelope-from gordon@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v9HLK7GN048070; Tue, 17 Oct 2017 21:20:07 GMT (envelope-from gordon@FreeBSD.org) Received: (from gordon@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v9HLK7Xe048069; Tue, 17 Oct 2017 21:20:07 GMT (envelope-from gordon@FreeBSD.org) Message-Id: <201710172120.v9HLK7Xe048069@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: gordon set sender to gordon@FreeBSD.org using -f From: Gordon Tetlow Date: Tue, 17 Oct 2017 21:20:07 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-releng@freebsd.org Subject: svn commit: r324708 - releng/11.1 X-SVN-Group: releng X-SVN-Commit-Author: gordon X-SVN-Commit-Paths: releng/11.1 X-SVN-Commit-Revision: 324708 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-releng@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the release engineering / security commits to the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 17 Oct 2017 21:20:08 -0000 Author: gordon Date: Tue Oct 17 21:20:07 2017 New Revision: 324708 URL: https://svnweb.freebsd.org/changeset/base/324708 Log: Correct copy-paste. 11.1 is p2, not p13. X-Pointy-Hat-To: gordon Approved by: so Modified: releng/11.1/UPDATING Modified: releng/11.1/UPDATING ============================================================================== --- releng/11.1/UPDATING Tue Oct 17 21:13:26 2017 (r324707) +++ releng/11.1/UPDATING Tue Oct 17 21:20:07 2017 (r324708) @@ -16,7 +16,7 @@ from older versions of FreeBSD, try WITHOUT_CLANG and the tip of head, and then rebuild without this option. The bootstrap process from older version of current across the gcc/clang cutover is a bit fragile. -20171017 p13 FreeBSD-SA-17:07.wpa +20171017 p2 FreeBSD-SA-17:07.wpa Fix WPA2 protocol vulnerability. [SA-17:07] From owner-svn-src-releng@freebsd.org Thu Oct 19 03:19:45 2017 Return-Path: Delivered-To: svn-src-releng@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 4606FE4D2C0; Thu, 19 Oct 2017 03:19:45 +0000 (UTC) (envelope-from gordon@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 10B3C758F0; Thu, 19 Oct 2017 03:19:44 +0000 (UTC) (envelope-from gordon@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v9J3JiTl001002; Thu, 19 Oct 2017 03:19:44 GMT (envelope-from gordon@FreeBSD.org) Received: (from gordon@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v9J3JghA000986; Thu, 19 Oct 2017 03:19:42 GMT (envelope-from gordon@FreeBSD.org) Message-Id: <201710190319.v9J3JghA000986@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: gordon set sender to gordon@FreeBSD.org using -f From: Gordon Tetlow Date: Thu, 19 Oct 2017 03:19:42 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-releng@freebsd.org Subject: svn commit: r324740 - in releng/10.3: . contrib/wpa/src/ap contrib/wpa/src/common contrib/wpa/src/rsn_supp contrib/wpa/wpa_supplicant sys/conf X-SVN-Group: releng X-SVN-Commit-Author: gordon X-SVN-Commit-Paths: in releng/10.3: . contrib/wpa/src/ap contrib/wpa/src/common contrib/wpa/src/rsn_supp contrib/wpa/wpa_supplicant sys/conf X-SVN-Commit-Revision: 324740 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-releng@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the release engineering / security commits to the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 19 Oct 2017 03:19:45 -0000 Author: gordon Date: Thu Oct 19 03:19:42 2017 New Revision: 324740 URL: https://svnweb.freebsd.org/changeset/base/324740 Log: Fix WPA2 protocol vulnerability. [SA-17:07] Approved by: so Modified: releng/10.3/UPDATING releng/10.3/contrib/wpa/src/ap/wpa_auth.c releng/10.3/contrib/wpa/src/ap/wpa_auth.h releng/10.3/contrib/wpa/src/ap/wpa_auth_ft.c releng/10.3/contrib/wpa/src/ap/wpa_auth_i.h releng/10.3/contrib/wpa/src/common/wpa_common.h releng/10.3/contrib/wpa/src/rsn_supp/tdls.c releng/10.3/contrib/wpa/src/rsn_supp/wpa.c releng/10.3/contrib/wpa/src/rsn_supp/wpa_ft.c releng/10.3/contrib/wpa/src/rsn_supp/wpa_i.h releng/10.3/contrib/wpa/wpa_supplicant/events.c releng/10.3/contrib/wpa/wpa_supplicant/wnm_sta.c releng/10.3/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h releng/10.3/sys/conf/newvers.sh Modified: releng/10.3/UPDATING ============================================================================== --- releng/10.3/UPDATING Thu Oct 19 03:18:22 2017 (r324739) +++ releng/10.3/UPDATING Thu Oct 19 03:19:42 2017 (r324740) @@ -16,6 +16,10 @@ from older versions of FreeBSD, try WITHOUT_CLANG to b stable/10, and then rebuild without this option. The bootstrap process from older version of current is a bit fragile. +20171017 p22 FreeBSD-SA-17:07.wpa + + Fix WPA2 protocol vulnerability. [SA-17:07] + 20170810 p21 FreeBSD-SA-17:06.openssh Fix OpenSSH Denial of Service vulnerability. [SA-17:06] Modified: releng/10.3/contrib/wpa/src/ap/wpa_auth.c ============================================================================== --- releng/10.3/contrib/wpa/src/ap/wpa_auth.c Thu Oct 19 03:18:22 2017 (r324739) +++ releng/10.3/contrib/wpa/src/ap/wpa_auth.c Thu Oct 19 03:19:42 2017 (r324740) @@ -1623,6 +1623,21 @@ SM_STATE(WPA_PTK, AUTHENTICATION2) } +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]; @@ -2111,9 +2126,12 @@ SM_STEP(WPA_PTK) 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: @@ -2863,6 +2881,14 @@ int wpa_auth_sta_wpa_version(struct wpa_state_machine if (sm == NULL) return 0; return sm->wpa; +} + + +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; } Modified: releng/10.3/contrib/wpa/src/ap/wpa_auth.h ============================================================================== --- releng/10.3/contrib/wpa/src/ap/wpa_auth.h Thu Oct 19 03:18:22 2017 (r324739) +++ releng/10.3/contrib/wpa/src/ap/wpa_auth.h Thu Oct 19 03:19:42 2017 (r324740) @@ -247,6 +247,7 @@ int wpa_auth_pairwise_set(struct wpa_state_machine *sm 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 * Modified: releng/10.3/contrib/wpa/src/ap/wpa_auth_ft.c ============================================================================== --- releng/10.3/contrib/wpa/src/ap/wpa_auth_ft.c Thu Oct 19 03:18:22 2017 (r324739) +++ releng/10.3/contrib/wpa/src/ap/wpa_auth_ft.c Thu Oct 19 03:19:42 2017 (r324740) @@ -762,6 +762,14 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm) 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 @@ -774,6 +782,7 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm) /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ sm->pairwise_set = TRUE; + sm->tk_already_set = TRUE; } @@ -887,6 +896,7 @@ static u16 wpa_ft_process_auth_req(struct wpa_state_ma wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN); sm->pairwise = pairwise; + sm->tk_already_set = FALSE; wpa_ft_install_ptk(sm); buflen = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) + Modified: releng/10.3/contrib/wpa/src/ap/wpa_auth_i.h ============================================================================== --- releng/10.3/contrib/wpa/src/ap/wpa_auth_i.h Thu Oct 19 03:18:22 2017 (r324739) +++ releng/10.3/contrib/wpa/src/ap/wpa_auth_i.h Thu Oct 19 03:19:42 2017 (r324740) @@ -61,6 +61,7 @@ struct wpa_state_machine { struct wpa_ptk PTK; Boolean PTK_valid; Boolean pairwise_set; + Boolean tk_already_set; int keycount; Boolean Pair; struct wpa_key_replay_counter { Modified: releng/10.3/contrib/wpa/src/common/wpa_common.h ============================================================================== --- releng/10.3/contrib/wpa/src/common/wpa_common.h Thu Oct 19 03:18:22 2017 (r324739) +++ releng/10.3/contrib/wpa/src/common/wpa_common.h Thu Oct 19 03:19:42 2017 (r324740) @@ -187,6 +187,17 @@ struct wpa_ptk { } u; } STRUCT_PACKED; +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) Modified: releng/10.3/contrib/wpa/src/rsn_supp/tdls.c ============================================================================== --- releng/10.3/contrib/wpa/src/rsn_supp/tdls.c Thu Oct 19 03:18:22 2017 (r324739) +++ releng/10.3/contrib/wpa/src/rsn_supp/tdls.c Thu Oct 19 03:19:42 2017 (r324740) @@ -103,6 +103,7 @@ struct wpa_tdls_peer { 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; struct tpk_timer { @@ -160,6 +161,20 @@ static int wpa_tdls_set_key(struct wpa_sm *sm, struct 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) { @@ -177,12 +192,15 @@ static int wpa_tdls_set_key(struct wpa_sm *sm, struct 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 " "driver"); return -1; } + peer->tk_set = 1; return 0; } @@ -613,7 +631,7 @@ static void wpa_tdls_peer_free(struct wpa_sm *sm, stru peer->sm_tmr.buf = NULL; peer->rsnie_i_len = peer->rsnie_p_len = 0; peer->cipher = 0; - peer->tpk_set = peer->tpk_success = 0; + peer->tk_set = peer->tpk_set = peer->tpk_success = 0; os_memset(&peer->tpk, 0, sizeof(peer->tpk)); os_memset(peer->inonce, 0, WPA_NONCE_LEN); os_memset(peer->rnonce, 0, WPA_NONCE_LEN); @@ -1002,6 +1020,7 @@ skip_rsnie: 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); @@ -1583,6 +1602,7 @@ skip_rsn: wpa_tdls_peer_free(sm, peer); goto error; } + peer->tk_set = 0; /* A new nonce results in a new TK */ #if 0 /* get version info from RSNIE received from Peer */ @@ -1710,6 +1730,14 @@ static int wpa_tdls_process_tpk_m2(struct wpa_sm *sm, "TPK M2: " 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) Modified: releng/10.3/contrib/wpa/src/rsn_supp/wpa.c ============================================================================== --- releng/10.3/contrib/wpa/src/rsn_supp/wpa.c Thu Oct 19 03:18:22 2017 (r324739) +++ releng/10.3/contrib/wpa/src/rsn_supp/wpa.c Thu Oct 19 03:19:42 2017 (r324740) @@ -517,6 +517,12 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *s 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"); @@ -553,6 +559,8 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *s return -1; } + sm->ptk_installed = 1; + if (sm->wpa_ptk_rekey) { eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL); eloop_register_timeout(sm->wpa_ptk_rekey, 0, wpa_sm_rekey_ptk, @@ -601,11 +609,23 @@ struct wpa_gtk_data { 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)", @@ -637,6 +657,15 @@ static int wpa_supplicant_install_gtk(struct wpa_sm *s return -1; } + 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; } @@ -694,7 +723,7 @@ static int wpa_supplicant_pairwise_gtk(struct wpa_sm * if (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"); return -1; @@ -709,6 +738,57 @@ static int wpa_supplicant_pairwise_gtk(struct wpa_sm * } +#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_IGTK_LEN; + 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_ALG_IGTK, broadcast_ether_addr, + keyidx, 0, igtk->pn, sizeof(igtk->pn), + igtk->igtk, WPA_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) { @@ -718,28 +798,12 @@ static int ieee80211w_set_keys(struct wpa_sm *sm, if (ie->igtk) { const struct wpa_igtk_kde *igtk; - u16 keyidx; if (ie->igtk_len != sizeof(*igtk)) 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, WPA_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_ALG_IGTK, broadcast_ether_addr, - keyidx, 0, igtk->pn, sizeof(igtk->pn), - igtk->igtk, WPA_IGTK_LEN) < 0) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Failed to configure IGTK to the driver"); - return -1; - } } return 0; @@ -1343,7 +1407,7 @@ static void wpa_supplicant_process_1_of_2(struct wpa_s 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; @@ -2043,7 +2107,7 @@ void wpa_sm_deinit(struct wpa_sm *sm) */ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid) { - int clear_ptk = 1; + int clear_keys = 1; if (sm == NULL) return; @@ -2069,11 +2133,11 @@ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 * /* 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. @@ -2081,6 +2145,12 @@ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 * wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PTK"); sm->ptk_set = 0; sm->tptk_set = 0; + 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 @@ -2105,6 +2175,9 @@ void wpa_sm_notify_disassoc(struct wpa_sm *sm) #ifdef CONFIG_TDLS wpa_tdls_disassoc(sm); #endif /* CONFIG_TDLS */ +#ifdef CONFIG_IEEE80211R + sm->ft_reassoc_completed = 0; +#endif /* CONFIG_IEEE80211R */ } @@ -2602,6 +2675,12 @@ void wpa_sm_drop_sa(struct wpa_sm *sm) 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 */ } @@ -2669,28 +2748,18 @@ int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 sub 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)) { wpa_printf(MSG_DEBUG, "Failed to install the GTK in " "WNM mode"); return -1; } #ifdef CONFIG_IEEE80211W } else if (subelem_id == WNM_SLEEP_SUBELEM_IGTK) { - os_memcpy(igd.keyid, buf + 2, 2); - os_memcpy(igd.pn, buf + 4, 6); + const struct wpa_igtk_kde *igtk; - keyidx = WPA_GET_LE16(igd.keyid); - os_memcpy(igd.igtk, buf + 10, WPA_IGTK_LEN); - - wpa_hexdump_key(MSG_DEBUG, "Install IGTK (WNM SLEEP)", - igd.igtk, WPA_IGTK_LEN); - if (wpa_sm_set_key(sm, WPA_ALG_IGTK, broadcast_ether_addr, - keyidx, 0, igd.pn, sizeof(igd.pn), - igd.igtk, WPA_IGTK_LEN) < 0) { - wpa_printf(MSG_DEBUG, "Failed to install the IGTK in " - "WNM mode"); + igtk = (const struct wpa_igtk_kde *) (buf + 2); + if (wpa_supplicant_install_igtk(sm, igtk, 1) < 0) return -1; - } #endif /* CONFIG_IEEE80211W */ } else { wpa_printf(MSG_DEBUG, "Unknown element id"); Modified: releng/10.3/contrib/wpa/src/rsn_supp/wpa_ft.c ============================================================================== --- releng/10.3/contrib/wpa/src/rsn_supp/wpa_ft.c Thu Oct 19 03:18:22 2017 (r324739) +++ releng/10.3/contrib/wpa/src/rsn_supp/wpa_ft.c Thu Oct 19 03:19:42 2017 (r324740) @@ -156,6 +156,7 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size 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; @@ -671,6 +672,11 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, co 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; @@ -768,6 +774,8 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, co wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, 16); return -1; } + + sm->ft_reassoc_completed = 1; if (wpa_ft_process_gtk_subelem(sm, parse.gtk, parse.gtk_len) < 0) return -1; Modified: releng/10.3/contrib/wpa/src/rsn_supp/wpa_i.h ============================================================================== --- releng/10.3/contrib/wpa/src/rsn_supp/wpa_i.h Thu Oct 19 03:18:22 2017 (r324739) +++ releng/10.3/contrib/wpa/src/rsn_supp/wpa_i.h Thu Oct 19 03:19:42 2017 (r324740) @@ -23,12 +23,19 @@ struct wpa_sm { size_t pmk_len; struct wpa_ptk ptk, tptk; int ptk_set, tptk_set; + int ptk_installed; u8 snonce[WPA_NONCE_LEN]; u8 anonce[WPA_NONCE_LEN]; /* ANonce from the last 1/4 msg */ int renew_snonce; 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 */ @@ -115,6 +122,7 @@ struct wpa_sm { 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; Modified: releng/10.3/contrib/wpa/wpa_supplicant/events.c ============================================================================== --- releng/10.3/contrib/wpa/wpa_supplicant/events.c Thu Oct 19 03:18:22 2017 (r324739) +++ releng/10.3/contrib/wpa/wpa_supplicant/events.c Thu Oct 19 03:19:42 2017 (r324740) @@ -181,6 +181,7 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplican wpa_s->ap_ies_from_associnfo = 0; wpa_s->current_ssid = NULL; wpa_s->key_mgmt = 0; + wpa_s->wnmsleep_used = 0; } Modified: releng/10.3/contrib/wpa/wpa_supplicant/wnm_sta.c ============================================================================== --- releng/10.3/contrib/wpa/wpa_supplicant/wnm_sta.c Thu Oct 19 03:18:22 2017 (r324739) +++ releng/10.3/contrib/wpa/wpa_supplicant/wnm_sta.c Thu Oct 19 03:19:42 2017 (r324740) @@ -130,6 +130,8 @@ int ieee802_11_send_wnmsleep_req(struct wpa_supplicant 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); @@ -180,6 +182,12 @@ static void wnm_sleep_mode_exit_success(struct wpa_sup 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 " @@ -239,6 +247,12 @@ static void ieee802_11_rx_wnmsleep_resp(struct wpa_sup u8 *tfsresp_ie_start = NULL; u8 *tfsresp_ie_end = NULL; + 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; + } + wpa_printf(MSG_DEBUG, "action=%d token = %d key_len_total = %d", frm[0], frm[1], key_len_total); pos += 4 + key_len_total; @@ -268,6 +282,8 @@ static void ieee802_11_rx_wnmsleep_resp(struct wpa_sup wpa_printf(MSG_DEBUG, "No WNM-Sleep IE found"); return; } + + wpa_s->wnmsleep_used = 0; if (wnmsleep_ie->status == WNM_STATUS_SLEEP_ACCEPT || wnmsleep_ie->status == WNM_STATUS_SLEEP_EXIT_ACCEPT_GTK_UPDATE) { Modified: releng/10.3/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h ============================================================================== --- releng/10.3/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h Thu Oct 19 03:18:22 2017 (r324739) +++ releng/10.3/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h Thu Oct 19 03:19:42 2017 (r324740) @@ -478,6 +478,7 @@ struct wpa_supplicant { struct os_time pending_eapol_rx_time; u8 pending_eapol_rx_src[ETH_ALEN]; unsigned int last_eapol_matches_bssid:1; + unsigned int wnmsleep_used:1; struct ibss_rsn *ibss_rsn; Modified: releng/10.3/sys/conf/newvers.sh ============================================================================== --- releng/10.3/sys/conf/newvers.sh Thu Oct 19 03:18:22 2017 (r324739) +++ releng/10.3/sys/conf/newvers.sh Thu Oct 19 03:19:42 2017 (r324740) @@ -32,7 +32,7 @@ TYPE="FreeBSD" REVISION="10.3" -BRANCH="RELEASE-p21" +BRANCH="RELEASE-p22" if [ "X${BRANCH_OVERRIDE}" != "X" ]; then BRANCH=${BRANCH_OVERRIDE} fi From owner-svn-src-releng@freebsd.org Thu Oct 19 03:20:19 2017 Return-Path: Delivered-To: svn-src-releng@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id E5D4BE4D3AD; Thu, 19 Oct 2017 03:20:19 +0000 (UTC) (envelope-from gordon@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 9398475B77; Thu, 19 Oct 2017 03:20:19 +0000 (UTC) (envelope-from gordon@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v9J3KIYE001108; Thu, 19 Oct 2017 03:20:18 GMT (envelope-from gordon@FreeBSD.org) Received: (from gordon@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v9J3KHNB001094; Thu, 19 Oct 2017 03:20:17 GMT (envelope-from gordon@FreeBSD.org) Message-Id: <201710190320.v9J3KHNB001094@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: gordon set sender to gordon@FreeBSD.org using -f From: Gordon Tetlow Date: Thu, 19 Oct 2017 03:20:17 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-releng@freebsd.org Subject: svn commit: r324741 - in releng/10.4: . contrib/wpa/src/ap contrib/wpa/src/common contrib/wpa/src/rsn_supp contrib/wpa/wpa_supplicant sys/conf X-SVN-Group: releng X-SVN-Commit-Author: gordon X-SVN-Commit-Paths: in releng/10.4: . contrib/wpa/src/ap contrib/wpa/src/common contrib/wpa/src/rsn_supp contrib/wpa/wpa_supplicant sys/conf X-SVN-Commit-Revision: 324741 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-releng@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the release engineering / security commits to the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 19 Oct 2017 03:20:20 -0000 Author: gordon Date: Thu Oct 19 03:20:17 2017 New Revision: 324741 URL: https://svnweb.freebsd.org/changeset/base/324741 Log: Fix WPA2 protocol vulnerability. [SA-17:07] Approved by: so Modified: releng/10.4/UPDATING releng/10.4/contrib/wpa/src/ap/wpa_auth.c releng/10.4/contrib/wpa/src/ap/wpa_auth.h releng/10.4/contrib/wpa/src/ap/wpa_auth_ft.c releng/10.4/contrib/wpa/src/ap/wpa_auth_i.h releng/10.4/contrib/wpa/src/common/wpa_common.h releng/10.4/contrib/wpa/src/rsn_supp/tdls.c releng/10.4/contrib/wpa/src/rsn_supp/wpa.c releng/10.4/contrib/wpa/src/rsn_supp/wpa_ft.c releng/10.4/contrib/wpa/src/rsn_supp/wpa_i.h releng/10.4/contrib/wpa/wpa_supplicant/events.c releng/10.4/contrib/wpa/wpa_supplicant/wnm_sta.c releng/10.4/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h releng/10.4/sys/conf/newvers.sh Modified: releng/10.4/UPDATING ============================================================================== --- releng/10.4/UPDATING Thu Oct 19 03:19:42 2017 (r324740) +++ releng/10.4/UPDATING Thu Oct 19 03:20:17 2017 (r324741) @@ -16,6 +16,10 @@ from older versions of FreeBSD, try WITHOUT_CLANG to b stable/10, and then rebuild without this option. The bootstrap process from older version of current is a bit fragile. +20171017: p1 FreeBSD-SA-17:07.wpa + + Fix WPA2 protocol vulnerability. [SA-17:07] + 20171003: 10.4-RELEASE. Modified: releng/10.4/contrib/wpa/src/ap/wpa_auth.c ============================================================================== --- releng/10.4/contrib/wpa/src/ap/wpa_auth.c Thu Oct 19 03:19:42 2017 (r324740) +++ releng/10.4/contrib/wpa/src/ap/wpa_auth.c Thu Oct 19 03:20:17 2017 (r324741) @@ -1623,6 +1623,21 @@ SM_STATE(WPA_PTK, AUTHENTICATION2) } +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]; @@ -2111,9 +2126,12 @@ SM_STEP(WPA_PTK) 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: @@ -2863,6 +2881,14 @@ int wpa_auth_sta_wpa_version(struct wpa_state_machine if (sm == NULL) return 0; return sm->wpa; +} + + +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; } Modified: releng/10.4/contrib/wpa/src/ap/wpa_auth.h ============================================================================== --- releng/10.4/contrib/wpa/src/ap/wpa_auth.h Thu Oct 19 03:19:42 2017 (r324740) +++ releng/10.4/contrib/wpa/src/ap/wpa_auth.h Thu Oct 19 03:20:17 2017 (r324741) @@ -247,6 +247,7 @@ int wpa_auth_pairwise_set(struct wpa_state_machine *sm 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 * Modified: releng/10.4/contrib/wpa/src/ap/wpa_auth_ft.c ============================================================================== --- releng/10.4/contrib/wpa/src/ap/wpa_auth_ft.c Thu Oct 19 03:19:42 2017 (r324740) +++ releng/10.4/contrib/wpa/src/ap/wpa_auth_ft.c Thu Oct 19 03:20:17 2017 (r324741) @@ -762,6 +762,14 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm) 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 @@ -774,6 +782,7 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm) /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ sm->pairwise_set = TRUE; + sm->tk_already_set = TRUE; } @@ -887,6 +896,7 @@ static u16 wpa_ft_process_auth_req(struct wpa_state_ma wpa_hexdump(MSG_DEBUG, "FT: PTKName", ptk_name, WPA_PMK_NAME_LEN); sm->pairwise = pairwise; + sm->tk_already_set = FALSE; wpa_ft_install_ptk(sm); buflen = 2 + sizeof(struct rsn_mdie) + 2 + sizeof(struct rsn_ftie) + Modified: releng/10.4/contrib/wpa/src/ap/wpa_auth_i.h ============================================================================== --- releng/10.4/contrib/wpa/src/ap/wpa_auth_i.h Thu Oct 19 03:19:42 2017 (r324740) +++ releng/10.4/contrib/wpa/src/ap/wpa_auth_i.h Thu Oct 19 03:20:17 2017 (r324741) @@ -61,6 +61,7 @@ struct wpa_state_machine { struct wpa_ptk PTK; Boolean PTK_valid; Boolean pairwise_set; + Boolean tk_already_set; int keycount; Boolean Pair; struct wpa_key_replay_counter { Modified: releng/10.4/contrib/wpa/src/common/wpa_common.h ============================================================================== --- releng/10.4/contrib/wpa/src/common/wpa_common.h Thu Oct 19 03:19:42 2017 (r324740) +++ releng/10.4/contrib/wpa/src/common/wpa_common.h Thu Oct 19 03:20:17 2017 (r324741) @@ -187,6 +187,17 @@ struct wpa_ptk { } u; } STRUCT_PACKED; +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) Modified: releng/10.4/contrib/wpa/src/rsn_supp/tdls.c ============================================================================== --- releng/10.4/contrib/wpa/src/rsn_supp/tdls.c Thu Oct 19 03:19:42 2017 (r324740) +++ releng/10.4/contrib/wpa/src/rsn_supp/tdls.c Thu Oct 19 03:20:17 2017 (r324741) @@ -103,6 +103,7 @@ struct wpa_tdls_peer { 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; struct tpk_timer { @@ -160,6 +161,20 @@ static int wpa_tdls_set_key(struct wpa_sm *sm, struct 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) { @@ -177,12 +192,15 @@ static int wpa_tdls_set_key(struct wpa_sm *sm, struct 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 " "driver"); return -1; } + peer->tk_set = 1; return 0; } @@ -613,7 +631,7 @@ static void wpa_tdls_peer_free(struct wpa_sm *sm, stru peer->sm_tmr.buf = NULL; peer->rsnie_i_len = peer->rsnie_p_len = 0; peer->cipher = 0; - peer->tpk_set = peer->tpk_success = 0; + peer->tk_set = peer->tpk_set = peer->tpk_success = 0; os_memset(&peer->tpk, 0, sizeof(peer->tpk)); os_memset(peer->inonce, 0, WPA_NONCE_LEN); os_memset(peer->rnonce, 0, WPA_NONCE_LEN); @@ -1002,6 +1020,7 @@ skip_rsnie: 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); @@ -1583,6 +1602,7 @@ skip_rsn: wpa_tdls_peer_free(sm, peer); goto error; } + peer->tk_set = 0; /* A new nonce results in a new TK */ #if 0 /* get version info from RSNIE received from Peer */ @@ -1710,6 +1730,14 @@ static int wpa_tdls_process_tpk_m2(struct wpa_sm *sm, "TPK M2: " 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) Modified: releng/10.4/contrib/wpa/src/rsn_supp/wpa.c ============================================================================== --- releng/10.4/contrib/wpa/src/rsn_supp/wpa.c Thu Oct 19 03:19:42 2017 (r324740) +++ releng/10.4/contrib/wpa/src/rsn_supp/wpa.c Thu Oct 19 03:20:17 2017 (r324741) @@ -517,6 +517,12 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *s 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"); @@ -553,6 +559,8 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *s return -1; } + sm->ptk_installed = 1; + if (sm->wpa_ptk_rekey) { eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL); eloop_register_timeout(sm->wpa_ptk_rekey, 0, wpa_sm_rekey_ptk, @@ -601,11 +609,23 @@ struct wpa_gtk_data { 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)", @@ -637,6 +657,15 @@ static int wpa_supplicant_install_gtk(struct wpa_sm *s return -1; } + 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; } @@ -694,7 +723,7 @@ static int wpa_supplicant_pairwise_gtk(struct wpa_sm * if (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"); return -1; @@ -709,6 +738,57 @@ static int wpa_supplicant_pairwise_gtk(struct wpa_sm * } +#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_IGTK_LEN; + 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_ALG_IGTK, broadcast_ether_addr, + keyidx, 0, igtk->pn, sizeof(igtk->pn), + igtk->igtk, WPA_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) { @@ -718,28 +798,12 @@ static int ieee80211w_set_keys(struct wpa_sm *sm, if (ie->igtk) { const struct wpa_igtk_kde *igtk; - u16 keyidx; if (ie->igtk_len != sizeof(*igtk)) 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, WPA_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_ALG_IGTK, broadcast_ether_addr, - keyidx, 0, igtk->pn, sizeof(igtk->pn), - igtk->igtk, WPA_IGTK_LEN) < 0) { - wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Failed to configure IGTK to the driver"); - return -1; - } } return 0; @@ -1343,7 +1407,7 @@ static void wpa_supplicant_process_1_of_2(struct wpa_s 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; @@ -2043,7 +2107,7 @@ void wpa_sm_deinit(struct wpa_sm *sm) */ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid) { - int clear_ptk = 1; + int clear_keys = 1; if (sm == NULL) return; @@ -2069,11 +2133,11 @@ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 * /* 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. @@ -2081,6 +2145,12 @@ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 * wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PTK"); sm->ptk_set = 0; sm->tptk_set = 0; + 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 @@ -2105,6 +2175,9 @@ void wpa_sm_notify_disassoc(struct wpa_sm *sm) #ifdef CONFIG_TDLS wpa_tdls_disassoc(sm); #endif /* CONFIG_TDLS */ +#ifdef CONFIG_IEEE80211R + sm->ft_reassoc_completed = 0; +#endif /* CONFIG_IEEE80211R */ } @@ -2602,6 +2675,12 @@ void wpa_sm_drop_sa(struct wpa_sm *sm) 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 */ } @@ -2669,28 +2748,18 @@ int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 sub 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)) { wpa_printf(MSG_DEBUG, "Failed to install the GTK in " "WNM mode"); return -1; } #ifdef CONFIG_IEEE80211W } else if (subelem_id == WNM_SLEEP_SUBELEM_IGTK) { - os_memcpy(igd.keyid, buf + 2, 2); - os_memcpy(igd.pn, buf + 4, 6); + const struct wpa_igtk_kde *igtk; - keyidx = WPA_GET_LE16(igd.keyid); - os_memcpy(igd.igtk, buf + 10, WPA_IGTK_LEN); - - wpa_hexdump_key(MSG_DEBUG, "Install IGTK (WNM SLEEP)", - igd.igtk, WPA_IGTK_LEN); - if (wpa_sm_set_key(sm, WPA_ALG_IGTK, broadcast_ether_addr, - keyidx, 0, igd.pn, sizeof(igd.pn), - igd.igtk, WPA_IGTK_LEN) < 0) { - wpa_printf(MSG_DEBUG, "Failed to install the IGTK in " - "WNM mode"); + igtk = (const struct wpa_igtk_kde *) (buf + 2); + if (wpa_supplicant_install_igtk(sm, igtk, 1) < 0) return -1; - } #endif /* CONFIG_IEEE80211W */ } else { wpa_printf(MSG_DEBUG, "Unknown element id"); Modified: releng/10.4/contrib/wpa/src/rsn_supp/wpa_ft.c ============================================================================== --- releng/10.4/contrib/wpa/src/rsn_supp/wpa_ft.c Thu Oct 19 03:19:42 2017 (r324740) +++ releng/10.4/contrib/wpa/src/rsn_supp/wpa_ft.c Thu Oct 19 03:20:17 2017 (r324741) @@ -156,6 +156,7 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size 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; @@ -671,6 +672,11 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, co 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; @@ -768,6 +774,8 @@ int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, co wpa_hexdump(MSG_MSGDUMP, "FT: Calculated MIC", mic, 16); return -1; } + + sm->ft_reassoc_completed = 1; if (wpa_ft_process_gtk_subelem(sm, parse.gtk, parse.gtk_len) < 0) return -1; Modified: releng/10.4/contrib/wpa/src/rsn_supp/wpa_i.h ============================================================================== --- releng/10.4/contrib/wpa/src/rsn_supp/wpa_i.h Thu Oct 19 03:19:42 2017 (r324740) +++ releng/10.4/contrib/wpa/src/rsn_supp/wpa_i.h Thu Oct 19 03:20:17 2017 (r324741) @@ -23,12 +23,19 @@ struct wpa_sm { size_t pmk_len; struct wpa_ptk ptk, tptk; int ptk_set, tptk_set; + int ptk_installed; u8 snonce[WPA_NONCE_LEN]; u8 anonce[WPA_NONCE_LEN]; /* ANonce from the last 1/4 msg */ int renew_snonce; 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 */ @@ -115,6 +122,7 @@ struct wpa_sm { 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; Modified: releng/10.4/contrib/wpa/wpa_supplicant/events.c ============================================================================== --- releng/10.4/contrib/wpa/wpa_supplicant/events.c Thu Oct 19 03:19:42 2017 (r324740) +++ releng/10.4/contrib/wpa/wpa_supplicant/events.c Thu Oct 19 03:20:17 2017 (r324741) @@ -181,6 +181,7 @@ void wpa_supplicant_mark_disassoc(struct wpa_supplican wpa_s->ap_ies_from_associnfo = 0; wpa_s->current_ssid = NULL; wpa_s->key_mgmt = 0; + wpa_s->wnmsleep_used = 0; } Modified: releng/10.4/contrib/wpa/wpa_supplicant/wnm_sta.c ============================================================================== --- releng/10.4/contrib/wpa/wpa_supplicant/wnm_sta.c Thu Oct 19 03:19:42 2017 (r324740) +++ releng/10.4/contrib/wpa/wpa_supplicant/wnm_sta.c Thu Oct 19 03:20:17 2017 (r324741) @@ -130,6 +130,8 @@ int ieee802_11_send_wnmsleep_req(struct wpa_supplicant 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); @@ -180,6 +182,12 @@ static void wnm_sleep_mode_exit_success(struct wpa_sup 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 " @@ -239,6 +247,12 @@ static void ieee802_11_rx_wnmsleep_resp(struct wpa_sup u8 *tfsresp_ie_start = NULL; u8 *tfsresp_ie_end = NULL; + 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; + } + wpa_printf(MSG_DEBUG, "action=%d token = %d key_len_total = %d", frm[0], frm[1], key_len_total); pos += 4 + key_len_total; @@ -268,6 +282,8 @@ static void ieee802_11_rx_wnmsleep_resp(struct wpa_sup wpa_printf(MSG_DEBUG, "No WNM-Sleep IE found"); return; } + + wpa_s->wnmsleep_used = 0; if (wnmsleep_ie->status == WNM_STATUS_SLEEP_ACCEPT || wnmsleep_ie->status == WNM_STATUS_SLEEP_EXIT_ACCEPT_GTK_UPDATE) { Modified: releng/10.4/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h ============================================================================== --- releng/10.4/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h Thu Oct 19 03:19:42 2017 (r324740) +++ releng/10.4/contrib/wpa/wpa_supplicant/wpa_supplicant_i.h Thu Oct 19 03:20:17 2017 (r324741) @@ -478,6 +478,7 @@ struct wpa_supplicant { struct os_time pending_eapol_rx_time; u8 pending_eapol_rx_src[ETH_ALEN]; unsigned int last_eapol_matches_bssid:1; + unsigned int wnmsleep_used:1; struct ibss_rsn *ibss_rsn; Modified: releng/10.4/sys/conf/newvers.sh ============================================================================== --- releng/10.4/sys/conf/newvers.sh Thu Oct 19 03:19:42 2017 (r324740) +++ releng/10.4/sys/conf/newvers.sh Thu Oct 19 03:20:17 2017 (r324741) @@ -32,7 +32,7 @@ TYPE="FreeBSD" REVISION="10.4" -BRANCH="RELEASE" +BRANCH="RELEASE-p1" if [ "X${BRANCH_OVERRIDE}" != "X" ]; then BRANCH=${BRANCH_OVERRIDE} fi