Module Name: src Committed By: spz Date: Mon Oct 16 17:36:16 UTC 2017
Modified Files: src/external/bsd/wpa/dist/src/ap: ieee802_11.c wpa_auth.c wpa_auth.h wpa_auth_ft.c wpa_auth_i.h src/external/bsd/wpa/dist/src/common: wpa_common.h src/external/bsd/wpa/dist/src/rsn_supp: tdls.c wpa.c wpa_ft.c wpa_i.h src/external/bsd/wpa/dist/wpa_supplicant: wnm_sta.c Log Message: apply patches from upstream, namely from https://w1.fi/security/2017-1/ : rebased-v2.6-0001-hostapd-Avoid-key-reinstallation-in-FT-handshake.patch 02-Oct-2017 16:19 6.1K rebased-v2.6-0002-Prevent-reinstallation-of-an-already-in-use-group-ke.patch 02-Oct-2017 16:19 7.7K rebased-v2.6-0003-Extend-protection-of-GTK-IGTK-reinstallation-of-WNM-.patch 02-Oct-2017 16:19 6.7K rebased-v2.6-0004-Prevent-installation-of-an-all-zero-TK.patch 02-Oct-2017 16:19 2.5K rebased-v2.6-0005-Fix-PTK-rekeying-to-generate-a-new-ANonce.patch 02-Oct-2017 16:19 1.9K rebased-v2.6-0006-TDLS-Reject-TPK-TK-reconfiguration.patch 02-Oct-2017 16:19 4.2K rebased-v2.6-0007-WNM-Ignore-WNM-Sleep-Mode-Response-without-pending-r.patch 02-Oct-2017 16:19 1.6K rebased-v2.6-0008-FT-Do-not-allow-multiple-Reassociation-Response-fram.patch 02-Oct-2017 16:19 2.7K for CVE-2017-13077 CVE-2017-13078 CVE-2017-13079 CVE-2017-13080 CVE-2017-13081 CVE-2017-13082 CVE-2017-13086 CVE-2017-13087 CVE-2017-13088 (see https://w1.fi/security/2017-1/wpa-packet-number-reuse-with-replayed-messages.txt for details) To generate a diff of this commit: cvs rdiff -u -r1.1.1.7 -r1.2 src/external/bsd/wpa/dist/src/ap/ieee802_11.c \ src/external/bsd/wpa/dist/src/ap/wpa_auth_ft.c cvs rdiff -u -r1.9 -r1.10 src/external/bsd/wpa/dist/src/ap/wpa_auth.c cvs rdiff -u -r1.1.1.6 -r1.2 src/external/bsd/wpa/dist/src/ap/wpa_auth.h \ src/external/bsd/wpa/dist/src/ap/wpa_auth_i.h cvs rdiff -u -r1.2 -r1.3 src/external/bsd/wpa/dist/src/common/wpa_common.h cvs rdiff -u -r1.1.1.5 -r1.2 src/external/bsd/wpa/dist/src/rsn_supp/tdls.c cvs rdiff -u -r1.1.1.8 -r1.2 src/external/bsd/wpa/dist/src/rsn_supp/wpa.c cvs rdiff -u -r1.1.1.6 -r1.2 src/external/bsd/wpa/dist/src/rsn_supp/wpa_ft.c \ src/external/bsd/wpa/dist/src/rsn_supp/wpa_i.h cvs rdiff -u -r1.3 -r1.4 src/external/bsd/wpa/dist/wpa_supplicant/wnm_sta.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/external/bsd/wpa/dist/src/ap/ieee802_11.c diff -u src/external/bsd/wpa/dist/src/ap/ieee802_11.c:1.1.1.7 src/external/bsd/wpa/dist/src/ap/ieee802_11.c:1.2 --- src/external/bsd/wpa/dist/src/ap/ieee802_11.c:1.1.1.7 Mon Nov 21 16:42:50 2016 +++ src/external/bsd/wpa/dist/src/ap/ieee802_11.c Mon Oct 16 17:36:16 2017 @@ -1841,6 +1841,7 @@ static int add_associated_sta(struct hos { struct ieee80211_ht_capabilities ht_cap; struct ieee80211_vht_capabilities vht_cap; + int set = 1; /* * Remove the STA entry to ensure the STA PS state gets cleared and @@ -1848,9 +1849,18 @@ static int add_associated_sta(struct hos * FT-over-the-DS, where a station re-associates back to the same AP but * skips the authentication flow, or if working with a driver that * does not support full AP client state. + * + * Skip this if the STA has already completed FT reassociation and the + * TK has been configured since the TX/RX PN must not be reset to 0 for + * the same key. */ - if (!sta->added_unassoc) + if (!sta->added_unassoc && + (!(sta->flags & WLAN_STA_AUTHORIZED) || + !wpa_auth_sta_ft_tk_already_set(sta->wpa_sm))) { hostapd_drv_sta_remove(hapd, sta->addr); + wpa_auth_sm_event(sta->wpa_sm, WPA_DRV_STA_REMOVED); + set = 0; + } #ifdef CONFIG_IEEE80211N if (sta->flags & WLAN_STA_HT) @@ -1873,11 +1883,11 @@ static int add_associated_sta(struct hos sta->flags & WLAN_STA_VHT ? &vht_cap : NULL, sta->flags | WLAN_STA_ASSOC, sta->qosinfo, sta->vht_opmode, sta->p2p_ie ? 1 : 0, - sta->added_unassoc)) { + set)) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_NOTICE, "Could not %s STA to kernel driver", - sta->added_unassoc ? "set" : "add"); + set ? "set" : "add"); if (sta->added_unassoc) { hostapd_drv_sta_remove(hapd, sta->addr); Index: src/external/bsd/wpa/dist/src/ap/wpa_auth_ft.c diff -u src/external/bsd/wpa/dist/src/ap/wpa_auth_ft.c:1.1.1.7 src/external/bsd/wpa/dist/src/ap/wpa_auth_ft.c:1.2 --- src/external/bsd/wpa/dist/src/ap/wpa_auth_ft.c:1.1.1.7 Mon Nov 21 16:42:50 2016 +++ src/external/bsd/wpa/dist/src/ap/wpa_auth_ft.c Mon Oct 16 17:36:16 2017 @@ -780,6 +780,14 @@ void wpa_ft_install_ptk(struct wpa_state 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 /* 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(struc 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) + Index: src/external/bsd/wpa/dist/src/ap/wpa_auth.c diff -u src/external/bsd/wpa/dist/src/ap/wpa_auth.c:1.9 src/external/bsd/wpa/dist/src/ap/wpa_auth.c:1.10 --- src/external/bsd/wpa/dist/src/ap/wpa_auth.c:1.9 Mon Nov 21 20:15:17 2016 +++ src/external/bsd/wpa/dist/src/ap/wpa_auth.c Mon Oct 16 17:36:16 2017 @@ -1745,6 +1745,9 @@ int wpa_auth_sm_event(struct wpa_state_m #else /* CONFIG_IEEE80211R */ break; #endif /* CONFIG_IEEE80211R */ + case WPA_DRV_STA_REMOVED: + sm->tk_already_set = FALSE; + return 0; } #ifdef CONFIG_IEEE80211R @@ -1898,6 +1901,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]; @@ -2455,9 +2473,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: @@ -3250,6 +3271,14 @@ int wpa_auth_sta_wpa_version(struct 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; +} + + int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm, struct rsn_pmksa_cache_entry *entry) { Index: src/external/bsd/wpa/dist/src/ap/wpa_auth.h diff -u src/external/bsd/wpa/dist/src/ap/wpa_auth.h:1.1.1.6 src/external/bsd/wpa/dist/src/ap/wpa_auth.h:1.2 --- src/external/bsd/wpa/dist/src/ap/wpa_auth.h:1.1.1.6 Mon Nov 21 16:42:50 2016 +++ src/external/bsd/wpa/dist/src/ap/wpa_auth.h Mon Oct 16 17:36:16 2017 @@ -267,7 +267,7 @@ void wpa_receive(struct wpa_authenticato u8 *data, size_t data_len); enum wpa_event { WPA_AUTH, WPA_ASSOC, WPA_DISASSOC, WPA_DEAUTH, WPA_REAUTH, - WPA_REAUTH_EAPOL, WPA_ASSOC_FT + WPA_REAUTH_EAPOL, WPA_ASSOC_FT, WPA_DRV_STA_REMOVED }; void wpa_remove_ptk(struct wpa_state_machine *sm); int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event); @@ -280,6 +280,7 @@ int wpa_auth_pairwise_set(struct wpa_sta 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 * Index: src/external/bsd/wpa/dist/src/ap/wpa_auth_i.h diff -u src/external/bsd/wpa/dist/src/ap/wpa_auth_i.h:1.1.1.6 src/external/bsd/wpa/dist/src/ap/wpa_auth_i.h:1.2 --- src/external/bsd/wpa/dist/src/ap/wpa_auth_i.h:1.1.1.6 Mon Nov 21 16:42:50 2016 +++ src/external/bsd/wpa/dist/src/ap/wpa_auth_i.h Mon Oct 16 17:36:16 2017 @@ -65,6 +65,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 { Index: src/external/bsd/wpa/dist/src/common/wpa_common.h diff -u src/external/bsd/wpa/dist/src/common/wpa_common.h:1.2 src/external/bsd/wpa/dist/src/common/wpa_common.h:1.3 --- src/external/bsd/wpa/dist/src/common/wpa_common.h:1.2 Thu Jan 12 19:15:10 2017 +++ src/external/bsd/wpa/dist/src/common/wpa_common.h Mon Oct 16 17:36:16 2017 @@ -218,8 +218,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) Index: src/external/bsd/wpa/dist/src/rsn_supp/tdls.c diff -u src/external/bsd/wpa/dist/src/rsn_supp/tdls.c:1.1.1.5 src/external/bsd/wpa/dist/src/rsn_supp/tdls.c:1.2 --- src/external/bsd/wpa/dist/src/rsn_supp/tdls.c:1.1.1.5 Mon Nov 21 16:42:49 2016 +++ src/external/bsd/wpa/dist/src/rsn_supp/tdls.c Mon Oct 16 17:36:16 2017 @@ -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_s 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_s 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; } @@ -696,7 +714,7 @@ static void wpa_tdls_peer_clear(struct w 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); @@ -1159,6 +1177,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); @@ -1751,6 +1770,19 @@ static int wpa_tdls_addset_peer(struct w } +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) { @@ -2004,7 +2036,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 @@ -2020,6 +2053,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 Index: src/external/bsd/wpa/dist/src/rsn_supp/wpa.c diff -u src/external/bsd/wpa/dist/src/rsn_supp/wpa.c:1.1.1.8 src/external/bsd/wpa/dist/src/rsn_supp/wpa.c:1.2 --- src/external/bsd/wpa/dist/src/rsn_supp/wpa.c:1.1.1.8 Mon Nov 21 16:42:49 2016 +++ src/external/bsd/wpa/dist/src/rsn_supp/wpa.c Mon Oct 16 17:36:16 2017 @@ -510,7 +510,6 @@ static void wpa_supplicant_process_1_of_ os_memset(buf, 0, sizeof(buf)); } sm->tptk_set = 1; - sm->tk_to_set = 1; kde = sm->assoc_wpa_ie; kde_len = sm->assoc_wpa_ie_len; @@ -615,7 +614,7 @@ static int wpa_supplicant_install_ptk(st enum wpa_alg alg; const u8 *key_rsc; - if (!sm->tk_to_set) { + if (sm->ptk.installed) { wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Do not re-install same PTK to the driver"); return 0; @@ -659,7 +658,7 @@ static int wpa_supplicant_install_ptk(st /* TK is not needed anymore in supplicant */ os_memset(sm->ptk.tk, 0, WPA_TK_MAX_LEN); - sm->tk_to_set = 0; + sm->ptk.installed = 1; if (sm->wpa_ptk_rekey) { eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL); @@ -709,11 +708,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)", @@ -748,6 +759,15 @@ static int wpa_supplicant_install_gtk(st } 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; } @@ -840,7 +860,7 @@ static int wpa_supplicant_pairwise_gtk(s (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_rsc))) { + wpa_supplicant_install_gtk(sm, &gd, key_rsc, 0))) { wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: Failed to install GTK"); os_memset(&gd, 0, sizeof(gd)); @@ -854,6 +874,58 @@ static int wpa_supplicant_pairwise_gtk(s } +#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) { @@ -864,30 +936,14 @@ static int ieee80211w_set_keys(struct wp 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); - 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"); + if (wpa_supplicant_install_igtk(sm, igtk, 0) < 0) return -1; - } } return 0; @@ -1536,7 +1592,7 @@ static void wpa_supplicant_process_1_of_ if (wpa_supplicant_rsc_relaxation(sm, key->key_rsc)) key_rsc = null_rsc; - if (wpa_supplicant_install_gtk(sm, &gd, key_rsc) || + if (wpa_supplicant_install_gtk(sm, &gd, key_rsc, 0) || wpa_supplicant_send_2_of_2(sm, key, ver, key_info) < 0) goto failed; os_memset(&gd, 0, sizeof(gd)); @@ -2307,7 +2363,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; @@ -2333,11 +2389,11 @@ void wpa_sm_notify_assoc(struct wpa_sm * /* 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. @@ -2347,6 +2403,12 @@ void wpa_sm_notify_assoc(struct wpa_sm * 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 @@ -2378,6 +2440,9 @@ void wpa_sm_notify_disassoc(struct wpa_s #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); @@ -2877,6 +2942,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)); @@ -2940,7 +3011,7 @@ int wpa_wnmsleep_install_key(struct wpa_ 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"); @@ -2949,29 +3020,11 @@ int wpa_wnmsleep_install_key(struct wpa_ 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"); Index: src/external/bsd/wpa/dist/src/rsn_supp/wpa_ft.c diff -u src/external/bsd/wpa/dist/src/rsn_supp/wpa_ft.c:1.1.1.6 src/external/bsd/wpa/dist/src/rsn_supp/wpa_ft.c:1.2 --- src/external/bsd/wpa/dist/src/rsn_supp/wpa_ft.c:1.1.1.6 Mon Nov 21 16:42:49 2016 +++ src/external/bsd/wpa/dist/src/rsn_supp/wpa_ft.c Mon Oct 16 17:36:16 2017 @@ -153,6 +153,7 @@ static u8 * wpa_ft_gen_req_ies(struct wp 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 return -1; } + if (sm->ft_reassoc_completed) { + wpa_printf(MSG_DEBUG, "FT: Reassociation has already been completed for this FT protocol instance - ignore unexpected retransmission"); + return 0; + } + if (wpa_ft_parse_ies(ies, ies_len, &parse) < 0) { wpa_printf(MSG_DEBUG, "FT: Failed to parse IEs"); return -1; @@ -781,6 +787,8 @@ int wpa_ft_validate_reassoc_resp(struct return -1; } + sm->ft_reassoc_completed = 1; + if (wpa_ft_process_gtk_subelem(sm, parse.gtk, parse.gtk_len) < 0) return -1; Index: src/external/bsd/wpa/dist/src/rsn_supp/wpa_i.h diff -u src/external/bsd/wpa/dist/src/rsn_supp/wpa_i.h:1.1.1.6 src/external/bsd/wpa/dist/src/rsn_supp/wpa_i.h:1.2 --- src/external/bsd/wpa/dist/src/rsn_supp/wpa_i.h:1.1.1.6 Mon Nov 21 16:42:49 2016 +++ src/external/bsd/wpa/dist/src/rsn_supp/wpa_i.h Mon Oct 16 17:36:16 2017 @@ -24,13 +24,18 @@ struct wpa_sm { struct wpa_ptk ptk, tptk; int ptk_set, tptk_set; unsigned int msg_3_of_4_ok:1; - unsigned int tk_to_set:1; 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 */ @@ -123,6 +128,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; Index: src/external/bsd/wpa/dist/wpa_supplicant/wnm_sta.c diff -u src/external/bsd/wpa/dist/wpa_supplicant/wnm_sta.c:1.3 src/external/bsd/wpa/dist/wpa_supplicant/wnm_sta.c:1.4 --- src/external/bsd/wpa/dist/wpa_supplicant/wnm_sta.c:1.3 Mon Nov 21 20:15:17 2016 +++ src/external/bsd/wpa/dist/wpa_supplicant/wnm_sta.c Mon Oct 16 17:36:16 2017 @@ -260,7 +260,7 @@ static void ieee802_11_rx_wnmsleep_resp( if (!wpa_s->wnmsleep_used) { wpa_printf(MSG_DEBUG, - "WNM: Ignore WNM-Sleep Mode Response frame since WNM-Sleep Mode has not been used in this association"); + "WNM: Ignore WNM-Sleep Mode Response frame since WNM-Sleep Mode operation has not been requested"); return; } @@ -299,6 +299,8 @@ static void ieee802_11_rx_wnmsleep_resp( return; } + wpa_s->wnmsleep_used = 0; + if (wnmsleep_ie->status == WNM_STATUS_SLEEP_ACCEPT || wnmsleep_ie->status == WNM_STATUS_SLEEP_EXIT_ACCEPT_GTK_UPDATE) { wpa_printf(MSG_DEBUG, "Successfully recv WNM-Sleep Response "