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