Brad Bishop | d5ae7d9 | 2018-06-14 09:52:03 -0700 | [diff] [blame] | 1 | The WPA2 four-way handshake protocol is vulnerable to replay attacks which can |
| 2 | result in unauthenticated clients gaining access to the network. |
| 3 | |
| 4 | Backport a number of patches from upstream to fix this. |
| 5 | |
| 6 | CVE: CVE-2017-13077 |
| 7 | CVE: CVE-2017-13078 |
| 8 | CVE: CVE-2017-13079 |
| 9 | CVE: CVE-2017-13080 |
| 10 | CVE: CVE-2017-13081 |
| 11 | CVE: CVE-2017-13082 |
| 12 | CVE: CVE-2017-13086 |
| 13 | CVE: CVE-2017-13087 |
| 14 | CVE: CVE-2017-13088 |
| 15 | |
| 16 | Upstream-Status: Backport |
| 17 | Signed-off-by: Ross Burton <ross.burton@intel.com> |
| 18 | |
| 19 | From 6c4bed4f47d1960ec04981a9d50e5076aea5223d Mon Sep 17 00:00:00 2001 |
| 20 | From: Jouni Malinen <j@w1.fi> |
| 21 | Date: Fri, 22 Sep 2017 11:03:15 +0300 |
| 22 | Subject: [PATCH 6/8] TDLS: Reject TPK-TK reconfiguration |
| 23 | |
| 24 | Do not try to reconfigure the same TPK-TK to the driver after it has |
| 25 | been successfully configured. This is an explicit check to avoid issues |
| 26 | related to resetting the TX/RX packet number. There was already a check |
| 27 | for this for TPK M2 (retries of that message are ignored completely), so |
| 28 | that behavior does not get modified. |
| 29 | |
| 30 | For TPK M3, the TPK-TK could have been reconfigured, but that was |
| 31 | followed by immediate teardown of the link due to an issue in updating |
| 32 | the STA entry. Furthermore, for TDLS with any real security (i.e., |
| 33 | ignoring open/WEP), the TPK message exchange is protected on the AP path |
| 34 | and simple replay attacks are not feasible. |
| 35 | |
| 36 | As an additional corner case, make sure the local nonce gets updated if |
| 37 | the peer uses a very unlikely "random nonce" of all zeros. |
| 38 | |
| 39 | Signed-off-by: Jouni Malinen <j@w1.fi> |
| 40 | --- |
| 41 | src/rsn_supp/tdls.c | 38 ++++++++++++++++++++++++++++++++++++-- |
| 42 | 1 file changed, 36 insertions(+), 2 deletions(-) |
| 43 | |
| 44 | diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c |
| 45 | index e424168..9eb9738 100644 |
| 46 | --- a/src/rsn_supp/tdls.c |
| 47 | +++ b/src/rsn_supp/tdls.c |
| 48 | @@ -112,6 +112,7 @@ struct wpa_tdls_peer { |
| 49 | u8 tk[16]; /* TPK-TK; assuming only CCMP will be used */ |
| 50 | } tpk; |
| 51 | int tpk_set; |
| 52 | + int tk_set; /* TPK-TK configured to the driver */ |
| 53 | int tpk_success; |
| 54 | int tpk_in_progress; |
| 55 | |
| 56 | @@ -192,6 +193,20 @@ static int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer) |
| 57 | u8 rsc[6]; |
| 58 | enum wpa_alg alg; |
| 59 | |
| 60 | + if (peer->tk_set) { |
| 61 | + /* |
| 62 | + * This same TPK-TK has already been configured to the driver |
| 63 | + * and this new configuration attempt (likely due to an |
| 64 | + * unexpected retransmitted frame) would result in clearing |
| 65 | + * the TX/RX sequence number which can break security, so must |
| 66 | + * not allow that to happen. |
| 67 | + */ |
| 68 | + wpa_printf(MSG_INFO, "TDLS: TPK-TK for the peer " MACSTR |
| 69 | + " has already been configured to the driver - do not reconfigure", |
| 70 | + MAC2STR(peer->addr)); |
| 71 | + return -1; |
| 72 | + } |
| 73 | + |
| 74 | os_memset(rsc, 0, 6); |
| 75 | |
| 76 | switch (peer->cipher) { |
| 77 | @@ -209,12 +224,15 @@ static int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer) |
| 78 | return -1; |
| 79 | } |
| 80 | |
| 81 | + wpa_printf(MSG_DEBUG, "TDLS: Configure pairwise key for peer " MACSTR, |
| 82 | + MAC2STR(peer->addr)); |
| 83 | if (wpa_sm_set_key(sm, alg, peer->addr, -1, 1, |
| 84 | rsc, sizeof(rsc), peer->tpk.tk, key_len) < 0) { |
| 85 | wpa_printf(MSG_WARNING, "TDLS: Failed to set TPK to the " |
| 86 | "driver"); |
| 87 | return -1; |
| 88 | } |
| 89 | + peer->tk_set = 1; |
| 90 | return 0; |
| 91 | } |
| 92 | |
| 93 | @@ -696,7 +714,7 @@ static void wpa_tdls_peer_clear(struct wpa_sm *sm, struct wpa_tdls_peer *peer) |
| 94 | peer->cipher = 0; |
| 95 | peer->qos_info = 0; |
| 96 | peer->wmm_capable = 0; |
| 97 | - peer->tpk_set = peer->tpk_success = 0; |
| 98 | + peer->tk_set = peer->tpk_set = peer->tpk_success = 0; |
| 99 | peer->chan_switch_enabled = 0; |
| 100 | os_memset(&peer->tpk, 0, sizeof(peer->tpk)); |
| 101 | os_memset(peer->inonce, 0, WPA_NONCE_LEN); |
| 102 | @@ -1159,6 +1177,7 @@ skip_rsnie: |
| 103 | wpa_tdls_peer_free(sm, peer); |
| 104 | return -1; |
| 105 | } |
| 106 | + peer->tk_set = 0; /* A new nonce results in a new TK */ |
| 107 | wpa_hexdump(MSG_DEBUG, "TDLS: Initiator Nonce for TPK handshake", |
| 108 | peer->inonce, WPA_NONCE_LEN); |
| 109 | os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN); |
| 110 | @@ -1751,6 +1770,19 @@ static int wpa_tdls_addset_peer(struct wpa_sm *sm, struct wpa_tdls_peer *peer, |
| 111 | } |
| 112 | |
| 113 | |
| 114 | +static int tdls_nonce_set(const u8 *nonce) |
| 115 | +{ |
| 116 | + int i; |
| 117 | + |
| 118 | + for (i = 0; i < WPA_NONCE_LEN; i++) { |
| 119 | + if (nonce[i]) |
| 120 | + return 1; |
| 121 | + } |
| 122 | + |
| 123 | + return 0; |
| 124 | +} |
| 125 | + |
| 126 | + |
| 127 | static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr, |
| 128 | const u8 *buf, size_t len) |
| 129 | { |
| 130 | @@ -2004,7 +2036,8 @@ skip_rsn: |
| 131 | peer->rsnie_i_len = kde.rsn_ie_len; |
| 132 | peer->cipher = cipher; |
| 133 | |
| 134 | - if (os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) != 0) { |
| 135 | + if (os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) != 0 || |
| 136 | + !tdls_nonce_set(peer->inonce)) { |
| 137 | /* |
| 138 | * There is no point in updating the RNonce for every obtained |
| 139 | * TPK M1 frame (e.g., retransmission due to timeout) with the |
| 140 | @@ -2020,6 +2053,7 @@ skip_rsn: |
| 141 | "TDLS: Failed to get random data for responder nonce"); |
| 142 | goto error; |
| 143 | } |
| 144 | + peer->tk_set = 0; /* A new nonce results in a new TK */ |
| 145 | } |
| 146 | |
| 147 | #if 0 |
| 148 | -- |
| 149 | 2.7.4 |