| The WPA2 four-way handshake protocol is vulnerable to replay attacks which can |
| result in unauthenticated clients gaining access to the network. |
| |
| Backport a number of patches from upstream to fix this. |
| |
| CVE: CVE-2017-13077 |
| CVE: CVE-2017-13078 |
| CVE: CVE-2017-13079 |
| CVE: CVE-2017-13080 |
| CVE: CVE-2017-13081 |
| CVE: CVE-2017-13082 |
| CVE: CVE-2017-13086 |
| CVE: CVE-2017-13087 |
| CVE: CVE-2017-13088 |
| |
| Upstream-Status: Backport |
| Signed-off-by: Ross Burton <ross.burton@intel.com> |
| |
| From 6c4bed4f47d1960ec04981a9d50e5076aea5223d Mon Sep 17 00:00:00 2001 |
| From: Jouni Malinen <j@w1.fi> |
| Date: Fri, 22 Sep 2017 11:03:15 +0300 |
| Subject: [PATCH 6/8] TDLS: Reject TPK-TK reconfiguration |
| |
| Do not try to reconfigure the same TPK-TK to the driver after it has |
| been successfully configured. This is an explicit check to avoid issues |
| related to resetting the TX/RX packet number. There was already a check |
| for this for TPK M2 (retries of that message are ignored completely), so |
| that behavior does not get modified. |
| |
| For TPK M3, the TPK-TK could have been reconfigured, but that was |
| followed by immediate teardown of the link due to an issue in updating |
| the STA entry. Furthermore, for TDLS with any real security (i.e., |
| ignoring open/WEP), the TPK message exchange is protected on the AP path |
| and simple replay attacks are not feasible. |
| |
| As an additional corner case, make sure the local nonce gets updated if |
| the peer uses a very unlikely "random nonce" of all zeros. |
| |
| Signed-off-by: Jouni Malinen <j@w1.fi> |
| --- |
| 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 e424168..9eb9738 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 @@ 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 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 @@ 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 |
| -- |
| 2.7.4 |