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