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

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