Blame SOURCES/rh1495527-0006-TDLS-Reject-TPK-TK-reconfiguration.patch

b645d2
From 6c4bed4f47d1960ec04981a9d50e5076aea5223d Mon Sep 17 00:00:00 2001
b645d2
From: Jouni Malinen <j@w1.fi>
b645d2
Date: Fri, 22 Sep 2017 11:03:15 +0300
b645d2
Subject: [PATCH 6/8] TDLS: Reject TPK-TK reconfiguration
b645d2
b645d2
Do not try to reconfigure the same TPK-TK to the driver after it has
b645d2
been successfully configured. This is an explicit check to avoid issues
b645d2
related to resetting the TX/RX packet number. There was already a check
b645d2
for this for TPK M2 (retries of that message are ignored completely), so
b645d2
that behavior does not get modified.
b645d2
b645d2
For TPK M3, the TPK-TK could have been reconfigured, but that was
b645d2
followed by immediate teardown of the link due to an issue in updating
b645d2
the STA entry. Furthermore, for TDLS with any real security (i.e.,
b645d2
ignoring open/WEP), the TPK message exchange is protected on the AP path
b645d2
and simple replay attacks are not feasible.
b645d2
b645d2
As an additional corner case, make sure the local nonce gets updated if
b645d2
the peer uses a very unlikely "random nonce" of all zeros.
b645d2
b645d2
Signed-off-by: Jouni Malinen <j@w1.fi>
b645d2
---
b645d2
 src/rsn_supp/tdls.c | 38 ++++++++++++++++++++++++++++++++++++--
b645d2
 1 file changed, 36 insertions(+), 2 deletions(-)
b645d2
b645d2
diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
b645d2
index e424168..9eb9738 100644
b645d2
--- a/src/rsn_supp/tdls.c
b645d2
+++ b/src/rsn_supp/tdls.c
b645d2
@@ -112,6 +112,7 @@ struct wpa_tdls_peer {
b645d2
 		u8 tk[16]; /* TPK-TK; assuming only CCMP will be used */
b645d2
 	} tpk;
b645d2
 	int tpk_set;
b645d2
+	int tk_set; /* TPK-TK configured to the driver */
b645d2
 	int tpk_success;
b645d2
 	int tpk_in_progress;
b645d2
 
b645d2
@@ -192,6 +193,20 @@ static int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
b645d2
 	u8 rsc[6];
b645d2
 	enum wpa_alg alg;
b645d2
 
b645d2
+	if (peer->tk_set) {
b645d2
+		/*
b645d2
+		 * This same TPK-TK has already been configured to the driver
b645d2
+		 * and this new configuration attempt (likely due to an
b645d2
+		 * unexpected retransmitted frame) would result in clearing
b645d2
+		 * the TX/RX sequence number which can break security, so must
b645d2
+		 * not allow that to happen.
b645d2
+		 */
b645d2
+		wpa_printf(MSG_INFO, "TDLS: TPK-TK for the peer " MACSTR
b645d2
+			   " has already been configured to the driver - do not reconfigure",
b645d2
+			   MAC2STR(peer->addr));
b645d2
+		return -1;
b645d2
+	}
b645d2
+
b645d2
 	os_memset(rsc, 0, 6);
b645d2
 
b645d2
 	switch (peer->cipher) {
b645d2
@@ -209,12 +224,15 @@ static int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
b645d2
 		return -1;
b645d2
 	}
b645d2
 
b645d2
+	wpa_printf(MSG_DEBUG, "TDLS: Configure pairwise key for peer " MACSTR,
b645d2
+		   MAC2STR(peer->addr));
b645d2
 	if (wpa_sm_set_key(sm, alg, peer->addr, -1, 1,
b645d2
 			   rsc, sizeof(rsc), peer->tpk.tk, key_len) < 0) {
b645d2
 		wpa_printf(MSG_WARNING, "TDLS: Failed to set TPK to the "
b645d2
 			   "driver");
b645d2
 		return -1;
b645d2
 	}
b645d2
+	peer->tk_set = 1;
b645d2
 	return 0;
b645d2
 }
b645d2
 
b645d2
@@ -696,7 +714,7 @@ static void wpa_tdls_peer_clear(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
b645d2
 	peer->cipher = 0;
b645d2
 	peer->qos_info = 0;
b645d2
 	peer->wmm_capable = 0;
b645d2
-	peer->tpk_set = peer->tpk_success = 0;
b645d2
+	peer->tk_set = peer->tpk_set = peer->tpk_success = 0;
b645d2
 	peer->chan_switch_enabled = 0;
b645d2
 	os_memset(&peer->tpk, 0, sizeof(peer->tpk));
b645d2
 	os_memset(peer->inonce, 0, WPA_NONCE_LEN);
b645d2
@@ -1159,6 +1177,7 @@ skip_rsnie:
b645d2
 		wpa_tdls_peer_free(sm, peer);
b645d2
 		return -1;
b645d2
 	}
b645d2
+	peer->tk_set = 0; /* A new nonce results in a new TK */
b645d2
 	wpa_hexdump(MSG_DEBUG, "TDLS: Initiator Nonce for TPK handshake",
b645d2
 		    peer->inonce, WPA_NONCE_LEN);
b645d2
 	os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
b645d2
@@ -1751,6 +1770,19 @@ static int wpa_tdls_addset_peer(struct wpa_sm *sm, struct wpa_tdls_peer *peer,
b645d2
 }
b645d2
 
b645d2
 
b645d2
+static int tdls_nonce_set(const u8 *nonce)
b645d2
+{
b645d2
+	int i;
b645d2
+
b645d2
+	for (i = 0; i < WPA_NONCE_LEN; i++) {
b645d2
+		if (nonce[i])
b645d2
+			return 1;
b645d2
+	}
b645d2
+
b645d2
+	return 0;
b645d2
+}
b645d2
+
b645d2
+
b645d2
 static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
b645d2
 				   const u8 *buf, size_t len)
b645d2
 {
b645d2
@@ -2004,7 +2036,8 @@ skip_rsn:
b645d2
 	peer->rsnie_i_len = kde.rsn_ie_len;
b645d2
 	peer->cipher = cipher;
b645d2
 
b645d2
-	if (os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) != 0) {
b645d2
+	if (os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) != 0 ||
b645d2
+	    !tdls_nonce_set(peer->inonce)) {
b645d2
 		/*
b645d2
 		 * There is no point in updating the RNonce for every obtained
b645d2
 		 * TPK M1 frame (e.g., retransmission due to timeout) with the
b645d2
@@ -2020,6 +2053,7 @@ skip_rsn:
b645d2
 				"TDLS: Failed to get random data for responder nonce");
b645d2
 			goto error;
b645d2
 		}
b645d2
+		peer->tk_set = 0; /* A new nonce results in a new TK */
b645d2
 	}
b645d2
 
b645d2
 #if 0
b645d2
-- 
b645d2
2.7.4
b645d2