lkundrak / rpms / hostapd

Forked from rpms/hostapd 4 years ago
Clone

Blame rebased-v2.6-0006-TDLS-Reject-TPK-TK-reconfiguration.patch

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