From e7771f9e4a164c283346f7d399eb7f1c7175f7c8 Mon Sep 17 00:00:00 2001 From: Cy Schubert Date: Thu, 19 Jul 2018 17:34:58 +0000 Subject: [PATCH 1/5] Import upline security patch: Fix PTK rekeying to generate a new ANonce. This is also upline git commit 0adc9b28b39d414d5febfff752f6a1576f785c85. Obtained from: https://w1.fi/security/2017-1/\ rebased-v2.6-0005-Fix-PTK-rekeying-to-\ generate-a-new-ANonce.patch --- src/ap/wpa_auth.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 707971d06f21..bf10cc1646f7 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -1901,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]; @@ -2458,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: From b87b1451cb190c2ae09f46711933aa2938405396 Mon Sep 17 00:00:00 2001 From: Cy Schubert Date: Thu, 19 Jul 2018 17:37:13 +0000 Subject: [PATCH 2/5] Import upline security patch: TDLS: Reject TPK-TK reconfiguration. This is also upline git commmit ff89af96e5a35c86f50330d2b86c18323318a60c. Obtained from: https://w1.fi/security/2017-1/\ rebased-v2.6-0006-TDLS-Reject-TPK-TK-\ reconfiguration.patch --- src/rsn_supp/tdls.c | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c index e4241681842a..9eb973860049 100644 --- a/src/rsn_supp/tdls.c +++ b/src/rsn_supp/tdls.c @@ -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 wpa_tdls_peer *peer) 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 wpa_tdls_peer *peer) 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 wpa_sm *sm, struct wpa_tdls_peer *peer) 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 @@ static int wpa_tdls_send_tpk_m1(struct wpa_sm *sm, 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 wpa_sm *sm, struct wpa_tdls_peer *peer, } +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 @@ static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr, 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 @@ static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr, "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 From 6bcebda49663a58068118b1cacc4aecd27e2e54f Mon Sep 17 00:00:00 2001 From: Cy Schubert Date: Thu, 19 Jul 2018 17:46:33 +0000 Subject: [PATCH 3/5] Import upline security patch: WNM: Ignore WNM-Sleep Mode Request in wnm_sleep_mode=0 case. This is also upline git commit 114f2830d2c2aee6db23d48240e93415a256a37c. Obtained from: https://w1.fi/security/2017-1/\ rebased-v2.6-0007-WNM-Ignore-WNM-Sleep-Mode-\ Response-without-pending-r.patch --- wpa_supplicant/wnm_sta.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/wpa_supplicant/wnm_sta.c b/wpa_supplicant/wnm_sta.c index 1b3409c1fb71..67a07ff7b1e7 100644 --- a/wpa_supplicant/wnm_sta.c +++ b/wpa_supplicant/wnm_sta.c @@ -260,7 +260,7 @@ static void ieee802_11_rx_wnmsleep_resp(struct wpa_supplicant *wpa_s, 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(struct wpa_supplicant *wpa_s, 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 " From 63696d5028b91f9fa4607f778587311502810783 Mon Sep 17 00:00:00 2001 From: Cy Schubert Date: Thu, 19 Jul 2018 17:49:39 +0000 Subject: [PATCH 4/5] Import upline security patch: FILS: Do not allow multiple (Re)Association Response frames. This is also upline git commit e760851176c77ae6de19821bb1d5bf3ae2cb5187. Obtained from: https://w1.fi/security/2017-1/\ rebased-v2.6-0008-FT-Do-not-allow-multiple-\ Reassociation-Response-fram.patch --- src/rsn_supp/wpa.c | 3 +++ src/rsn_supp/wpa_ft.c | 8 ++++++++ src/rsn_supp/wpa_i.h | 1 + 3 files changed, 12 insertions(+) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 0550a412fcc7..2a53c6f4a55f 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -2440,6 +2440,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); diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index 205793e7f43a..d45bb4585e50 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -153,6 +153,7 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, 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, const u8 *ies, 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 wpa_sm *sm, const u8 *ies, return -1; } + sm->ft_reassoc_completed = 1; + if (wpa_ft_process_gtk_subelem(sm, parse.gtk, parse.gtk_len) < 0) return -1; diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h index 41f371f26c69..56f88dcdd899 100644 --- a/src/rsn_supp/wpa_i.h +++ b/src/rsn_supp/wpa_i.h @@ -128,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; From 765ef8a7642d07aa9616f2b1a9cdebb8e3552f6a Mon Sep 17 00:00:00 2001 From: Cy Schubert Date: Tue, 14 Aug 2018 20:10:25 +0000 Subject: [PATCH 5/5] WPA: Ignore unauthenticated encrypted EAPOL-Key data Ignore unauthenticated encrypted EAPOL-Key data in supplicant processing. When using WPA2, these are frames that have the Encrypted flag set, but not the MIC flag. When using WPA2, EAPOL-Key frames that had the Encrypted flag set but not the MIC flag, had their data field decrypted without first verifying the MIC. In case the data field was encrypted using RC4 (i.e., when negotiating TKIP as the pairwise cipher), this meant that unauthenticated but decrypted data would then be processed. An adversary could abuse this as a decryption oracle to recover sensitive information in the data field of EAPOL-Key messages (e.g., the group key). (CVE-2018-14526) Signed-off-by: Mathy Vanhoef Obtained from: git://w1.fi/hostap.git MFC after: 1 day Security: CVE-2018-14526 Security: VuXML: 6bedc863-9fbe-11e8-945f-206a8a720317 --- src/rsn_supp/wpa.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 2a53c6f4a55f..dcd75272151f 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -2072,6 +2072,17 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, if ((sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { + /* + * Only decrypt the Key Data field if the frame's authenticity + * was verified. When using AES-SIV (FILS), the MIC flag is not + * set, so this check should only be performed if mic_len != 0 + * which is the case in this code branch. + */ + if (!(key_info & WPA_KEY_INFO_MIC)) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Ignore EAPOL-Key with encrypted but unauthenticated data"); + goto out; + } if (wpa_supplicant_decrypt_key_data(sm, key, ver, key_data, &key_data_len)) goto out;