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