blob: 1531f51cb872e1ef1ef917a90330e1347d5ba2e6 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * wpa_supplicant - TDLS
3 * Copyright (c) 2010-2011, Atheros Communications
4 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
8
9#include "utils/includes.h"
10
11#include "utils/common.h"
12#include "utils/eloop.h"
13#include "utils/os.h"
14#include "common/ieee802_11_defs.h"
Dmitry Shmidtd80a4012015-11-05 16:35:40 -080015#include "common/ieee802_11_common.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070016#include "crypto/sha256.h"
17#include "crypto/crypto.h"
18#include "crypto/aes_wrap.h"
19#include "rsn_supp/wpa.h"
20#include "rsn_supp/wpa_ie.h"
21#include "rsn_supp/wpa_i.h"
22#include "drivers/driver.h"
23#include "l2_packet/l2_packet.h"
24
25#ifdef CONFIG_TDLS_TESTING
26#define TDLS_TESTING_LONG_FRAME BIT(0)
27#define TDLS_TESTING_ALT_RSN_IE BIT(1)
28#define TDLS_TESTING_DIFF_BSSID BIT(2)
29#define TDLS_TESTING_SHORT_LIFETIME BIT(3)
30#define TDLS_TESTING_WRONG_LIFETIME_RESP BIT(4)
31#define TDLS_TESTING_WRONG_LIFETIME_CONF BIT(5)
32#define TDLS_TESTING_LONG_LIFETIME BIT(6)
33#define TDLS_TESTING_CONCURRENT_INIT BIT(7)
34#define TDLS_TESTING_NO_TPK_EXPIRATION BIT(8)
35#define TDLS_TESTING_DECLINE_RESP BIT(9)
36#define TDLS_TESTING_IGNORE_AP_PROHIBIT BIT(10)
Dmitry Shmidt21de2142014-04-08 10:50:52 -070037#define TDLS_TESTING_WRONG_MIC BIT(11)
Roshan Pius3a1667e2018-07-03 15:17:14 -070038#define TDLS_TESTING_DOUBLE_TPK_M2 BIT(12)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070039unsigned int tdls_testing = 0;
40#endif /* CONFIG_TDLS_TESTING */
41
42#define TPK_LIFETIME 43200 /* 12 hours */
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -070043#define TPK_M1_RETRY_COUNT 3
44#define TPK_M1_TIMEOUT 5000 /* in milliseconds */
45#define TPK_M2_RETRY_COUNT 10
46#define TPK_M2_TIMEOUT 500 /* in milliseconds */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070047
48#define TDLS_MIC_LEN 16
49
50#define TDLS_TIMEOUT_LEN 4
51
52struct wpa_tdls_ftie {
53 u8 ie_type; /* FTIE */
54 u8 ie_len;
55 u8 mic_ctrl[2];
56 u8 mic[TDLS_MIC_LEN];
57 u8 Anonce[WPA_NONCE_LEN]; /* Responder Nonce in TDLS */
58 u8 Snonce[WPA_NONCE_LEN]; /* Initiator Nonce in TDLS */
59 /* followed by optional elements */
60} STRUCT_PACKED;
61
62struct wpa_tdls_timeoutie {
63 u8 ie_type; /* Timeout IE */
64 u8 ie_len;
65 u8 interval_type;
66 u8 value[TDLS_TIMEOUT_LEN];
67} STRUCT_PACKED;
68
69struct wpa_tdls_lnkid {
70 u8 ie_type; /* Link Identifier IE */
71 u8 ie_len;
72 u8 bssid[ETH_ALEN];
73 u8 init_sta[ETH_ALEN];
74 u8 resp_sta[ETH_ALEN];
75} STRUCT_PACKED;
76
77/* TDLS frame headers as per IEEE Std 802.11z-2010 */
78struct wpa_tdls_frame {
79 u8 payloadtype; /* IEEE80211_TDLS_RFTYPE */
80 u8 category; /* Category */
81 u8 action; /* Action (enum tdls_frame_type) */
82} STRUCT_PACKED;
83
84static u8 * wpa_add_tdls_timeoutie(u8 *pos, u8 *ie, size_t ie_len, u32 tsecs);
85static void wpa_tdls_tpk_retry_timeout(void *eloop_ctx, void *timeout_ctx);
86static void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer);
Sunil Duttd0ef38b2013-09-30 17:34:13 +030087static void wpa_tdls_disable_peer_link(struct wpa_sm *sm,
88 struct wpa_tdls_peer *peer);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -070089static int wpa_tdls_send_teardown(struct wpa_sm *sm, const u8 *addr,
90 u16 reason_code);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070091
92
93#define TDLS_MAX_IE_LEN 80
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080094#define IEEE80211_MAX_SUPP_RATES 32
95
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070096struct wpa_tdls_peer {
97 struct wpa_tdls_peer *next;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -070098 unsigned int reconfig_key:1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070099 int initiator; /* whether this end was initiator for TDLS setup */
100 u8 addr[ETH_ALEN]; /* other end MAC address */
101 u8 inonce[WPA_NONCE_LEN]; /* Initiator Nonce */
102 u8 rnonce[WPA_NONCE_LEN]; /* Responder Nonce */
103 u8 rsnie_i[TDLS_MAX_IE_LEN]; /* Initiator RSN IE */
104 size_t rsnie_i_len;
105 u8 rsnie_p[TDLS_MAX_IE_LEN]; /* Peer RSN IE */
106 size_t rsnie_p_len;
107 u32 lifetime;
108 int cipher; /* Selected cipher (WPA_CIPHER_*) */
109 u8 dtoken;
110
111 struct tpk {
112 u8 kck[16]; /* TPK-KCK */
113 u8 tk[16]; /* TPK-TK; assuming only CCMP will be used */
114 } tpk;
115 int tpk_set;
Jouni Malinenc580b552017-09-22 11:03:15 +0300116 int tk_set; /* TPK-TK configured to the driver */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700117 int tpk_success;
Sunil Dutt73b28cc2013-09-30 17:38:41 +0300118 int tpk_in_progress;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700119
120 struct tpk_timer {
121 u8 dest[ETH_ALEN];
122 int count; /* Retry Count */
123 int timer; /* Timeout in milliseconds */
124 u8 action_code; /* TDLS frame type */
125 u8 dialog_token;
126 u16 status_code;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -0700127 u32 peer_capab;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700128 int buf_len; /* length of TPK message for retransmission */
129 u8 *buf; /* buffer for TPK message */
130 } sm_tmr;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800131
132 u16 capability;
133
134 u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
135 size_t supp_rates_len;
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800136
137 struct ieee80211_ht_capabilities *ht_capabilities;
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -0800138 struct ieee80211_vht_capabilities *vht_capabilities;
Hai Shaloma20dcd72022-02-04 13:43:00 -0800139 struct ieee80211_he_capabilities *he_capabilities;
140 size_t he_capab_len;
141 struct ieee80211_he_6ghz_band_cap *he_6ghz_band_capabilities;
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800142
143 u8 qos_info;
144
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700145 u16 aid;
146
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800147 u8 *ext_capab;
148 size_t ext_capab_len;
Dmitry Shmidt344abd32014-01-14 13:17:00 -0800149
150 u8 *supp_channels;
151 size_t supp_channels_len;
152
153 u8 *supp_oper_classes;
154 size_t supp_oper_classes_len;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -0700155
156 u8 wmm_capable;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800157
158 /* channel switch currently enabled */
159 int chan_switch_enabled;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700160};
161
162
163static int wpa_tdls_get_privacy(struct wpa_sm *sm)
164{
165 /*
166 * Get info needed from supplicant to check if the current BSS supports
167 * security. Other than OPEN mode, rest are considered secured
168 * WEP/WPA/WPA2 hence TDLS frames are processed for TPK handshake.
169 */
170 return sm->pairwise_cipher != WPA_CIPHER_NONE;
171}
172
173
174static u8 * wpa_add_ie(u8 *pos, const u8 *ie, size_t ie_len)
175{
176 os_memcpy(pos, ie, ie_len);
177 return pos + ie_len;
178}
179
180
181static int wpa_tdls_del_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
182{
Sunil Ravi38ad1ed2023-01-17 23:58:31 +0000183 if (wpa_sm_set_key(sm, -1, WPA_ALG_NONE, peer->addr,
Hai Shalomfdcde762020-04-02 11:19:20 -0700184 0, 0, NULL, 0, NULL, 0, KEY_FLAG_PAIRWISE) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700185 wpa_printf(MSG_WARNING, "TDLS: Failed to delete TPK-TK from "
186 "the driver");
187 return -1;
188 }
189
190 return 0;
191}
192
193
194static int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
195{
196 u8 key_len;
197 u8 rsc[6];
198 enum wpa_alg alg;
199
Jouni Malinenc580b552017-09-22 11:03:15 +0300200 if (peer->tk_set) {
201 /*
202 * This same TPK-TK has already been configured to the driver
203 * and this new configuration attempt (likely due to an
204 * unexpected retransmitted frame) would result in clearing
205 * the TX/RX sequence number which can break security, so must
206 * not allow that to happen.
207 */
208 wpa_printf(MSG_INFO, "TDLS: TPK-TK for the peer " MACSTR
209 " has already been configured to the driver - do not reconfigure",
210 MAC2STR(peer->addr));
211 return -1;
212 }
213
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700214 os_memset(rsc, 0, 6);
215
216 switch (peer->cipher) {
217 case WPA_CIPHER_CCMP:
218 alg = WPA_ALG_CCMP;
219 key_len = 16;
220 break;
221 case WPA_CIPHER_NONE:
222 wpa_printf(MSG_DEBUG, "TDLS: Pairwise Cipher Suite: "
223 "NONE - do not use pairwise keys");
224 return -1;
225 default:
226 wpa_printf(MSG_WARNING, "TDLS: Unsupported pairwise cipher %d",
227 sm->pairwise_cipher);
228 return -1;
229 }
230
Jouni Malinenc580b552017-09-22 11:03:15 +0300231 wpa_printf(MSG_DEBUG, "TDLS: Configure pairwise key for peer " MACSTR,
232 MAC2STR(peer->addr));
Sunil Ravi38ad1ed2023-01-17 23:58:31 +0000233 if (wpa_sm_set_key(sm, -1, alg, peer->addr, 0, 1, rsc, sizeof(rsc),
Hai Shalomfdcde762020-04-02 11:19:20 -0700234 peer->tpk.tk, key_len,
235 KEY_FLAG_PAIRWISE_RX_TX) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700236 wpa_printf(MSG_WARNING, "TDLS: Failed to set TPK to the "
237 "driver");
238 return -1;
239 }
Jouni Malinenc580b552017-09-22 11:03:15 +0300240 peer->tk_set = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700241 return 0;
242}
243
244
245static int wpa_tdls_send_tpk_msg(struct wpa_sm *sm, const u8 *dst,
246 u8 action_code, u8 dialog_token,
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -0700247 u16 status_code, u32 peer_capab,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700248 int initiator, const u8 *buf, size_t len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700249{
250 return wpa_sm_send_tdls_mgmt(sm, dst, action_code, dialog_token,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700251 status_code, peer_capab, initiator, buf,
252 len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700253}
254
255
256static int wpa_tdls_tpk_send(struct wpa_sm *sm, const u8 *dest, u8 action_code,
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -0700257 u8 dialog_token, u16 status_code, u32 peer_capab,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700258 int initiator, const u8 *msg, size_t msg_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700259{
260 struct wpa_tdls_peer *peer;
261
262 wpa_printf(MSG_DEBUG, "TDLS: TPK send dest=" MACSTR " action_code=%u "
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700263 "dialog_token=%u status_code=%u peer_capab=%u initiator=%d "
264 "msg_len=%u",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700265 MAC2STR(dest), action_code, dialog_token, status_code,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700266 peer_capab, initiator, (unsigned int) msg_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700267
268 if (wpa_tdls_send_tpk_msg(sm, dest, action_code, dialog_token,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700269 status_code, peer_capab, initiator, msg,
270 msg_len)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700271 wpa_printf(MSG_INFO, "TDLS: Failed to send message "
272 "(action_code=%u)", action_code);
273 return -1;
274 }
275
276 if (action_code == WLAN_TDLS_SETUP_CONFIRM ||
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800277 action_code == WLAN_TDLS_TEARDOWN ||
278 action_code == WLAN_TDLS_DISCOVERY_REQUEST ||
279 action_code == WLAN_TDLS_DISCOVERY_RESPONSE)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700280 return 0; /* No retries */
281
282 for (peer = sm->tdls; peer; peer = peer->next) {
283 if (os_memcmp(peer->addr, dest, ETH_ALEN) == 0)
284 break;
285 }
286
287 if (peer == NULL) {
288 wpa_printf(MSG_INFO, "TDLS: No matching entry found for "
289 "retry " MACSTR, MAC2STR(dest));
290 return 0;
291 }
292
293 eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
294
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -0700295 if (action_code == WLAN_TDLS_SETUP_RESPONSE) {
296 peer->sm_tmr.count = TPK_M2_RETRY_COUNT;
297 peer->sm_tmr.timer = TPK_M2_TIMEOUT;
298 } else {
299 peer->sm_tmr.count = TPK_M1_RETRY_COUNT;
300 peer->sm_tmr.timer = TPK_M1_TIMEOUT;
301 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700302
303 /* Copy message to resend on timeout */
304 os_memcpy(peer->sm_tmr.dest, dest, ETH_ALEN);
305 peer->sm_tmr.action_code = action_code;
306 peer->sm_tmr.dialog_token = dialog_token;
307 peer->sm_tmr.status_code = status_code;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -0700308 peer->sm_tmr.peer_capab = peer_capab;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700309 peer->sm_tmr.buf_len = msg_len;
310 os_free(peer->sm_tmr.buf);
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700311 peer->sm_tmr.buf = os_memdup(msg, msg_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700312 if (peer->sm_tmr.buf == NULL)
313 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700314
315 wpa_printf(MSG_DEBUG, "TDLS: Retry timeout registered "
316 "(action_code=%u)", action_code);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -0700317 eloop_register_timeout(peer->sm_tmr.timer / 1000,
318 (peer->sm_tmr.timer % 1000) * 1000,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700319 wpa_tdls_tpk_retry_timeout, sm, peer);
320 return 0;
321}
322
323
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800324static int wpa_tdls_do_teardown(struct wpa_sm *sm, struct wpa_tdls_peer *peer,
Sunil Dutt6a9f5222013-09-30 17:10:18 +0300325 u16 reason_code)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800326{
327 int ret;
328
Sunil Dutt6a9f5222013-09-30 17:10:18 +0300329 ret = wpa_tdls_send_teardown(sm, peer->addr, reason_code);
330 /* disable the link after teardown was sent */
Sunil Duttd0ef38b2013-09-30 17:34:13 +0300331 wpa_tdls_disable_peer_link(sm, peer);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800332
333 return ret;
334}
335
336
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700337static void wpa_tdls_tpk_retry_timeout(void *eloop_ctx, void *timeout_ctx)
338{
339
340 struct wpa_sm *sm = eloop_ctx;
341 struct wpa_tdls_peer *peer = timeout_ctx;
342
343 if (peer->sm_tmr.count) {
344 peer->sm_tmr.count--;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700345
346 wpa_printf(MSG_INFO, "TDLS: Retrying sending of message "
347 "(action_code=%u)",
348 peer->sm_tmr.action_code);
349
350 if (peer->sm_tmr.buf == NULL) {
351 wpa_printf(MSG_INFO, "TDLS: No retry buffer available "
352 "for action_code=%u",
353 peer->sm_tmr.action_code);
354 eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm,
355 peer);
356 return;
357 }
358
359 /* resend TPK Handshake Message to Peer */
360 if (wpa_tdls_send_tpk_msg(sm, peer->sm_tmr.dest,
361 peer->sm_tmr.action_code,
362 peer->sm_tmr.dialog_token,
363 peer->sm_tmr.status_code,
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -0700364 peer->sm_tmr.peer_capab,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700365 peer->initiator,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700366 peer->sm_tmr.buf,
367 peer->sm_tmr.buf_len)) {
368 wpa_printf(MSG_INFO, "TDLS: Failed to retry "
369 "transmission");
370 }
371
372 eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -0700373 eloop_register_timeout(peer->sm_tmr.timer / 1000,
374 (peer->sm_tmr.timer % 1000) * 1000,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700375 wpa_tdls_tpk_retry_timeout, sm, peer);
376 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700377 eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
378
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800379 wpa_printf(MSG_DEBUG, "TDLS: Sending Teardown Request");
380 wpa_tdls_do_teardown(sm, peer,
Sunil Dutt6a9f5222013-09-30 17:10:18 +0300381 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700382 }
383}
384
385
386static void wpa_tdls_tpk_retry_timeout_cancel(struct wpa_sm *sm,
387 struct wpa_tdls_peer *peer,
388 u8 action_code)
389{
390 if (action_code == peer->sm_tmr.action_code) {
391 wpa_printf(MSG_DEBUG, "TDLS: Retry timeout cancelled for "
392 "action_code=%u", action_code);
393
394 /* Cancel Timeout registered */
395 eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
396
397 /* free all resources meant for retry */
398 os_free(peer->sm_tmr.buf);
399 peer->sm_tmr.buf = NULL;
400
401 peer->sm_tmr.count = 0;
402 peer->sm_tmr.timer = 0;
403 peer->sm_tmr.buf_len = 0;
404 peer->sm_tmr.action_code = 0xff;
405 } else {
406 wpa_printf(MSG_INFO, "TDLS: Error in cancelling retry timeout "
407 "(Unknown action_code=%u)", action_code);
408 }
409}
410
411
412static void wpa_tdls_generate_tpk(struct wpa_tdls_peer *peer,
413 const u8 *own_addr, const u8 *bssid)
414{
415 u8 key_input[SHA256_MAC_LEN];
416 const u8 *nonce[2];
417 size_t len[2];
418 u8 data[3 * ETH_ALEN];
419
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700420 /* IEEE Std 802.11-2016 12.7.9.2:
421 * TPK-Key-Input = Hash(min(SNonce, ANonce) || max(SNonce, ANonce))
422 * Hash = SHA-256 for TDLS
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700423 */
424 len[0] = WPA_NONCE_LEN;
425 len[1] = WPA_NONCE_LEN;
426 if (os_memcmp(peer->inonce, peer->rnonce, WPA_NONCE_LEN) < 0) {
427 nonce[0] = peer->inonce;
428 nonce[1] = peer->rnonce;
429 } else {
430 nonce[0] = peer->rnonce;
431 nonce[1] = peer->inonce;
432 }
433 wpa_hexdump(MSG_DEBUG, "TDLS: min(Nonce)", nonce[0], WPA_NONCE_LEN);
434 wpa_hexdump(MSG_DEBUG, "TDLS: max(Nonce)", nonce[1], WPA_NONCE_LEN);
435 sha256_vector(2, nonce, len, key_input);
436 wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-Key-Input",
437 key_input, SHA256_MAC_LEN);
438
439 /*
Dmitry Shmidtd2986c22017-10-23 14:22:09 -0700440 * TPK = KDF-Hash-Length(TPK-Key-Input, "TDLS PMK",
441 * min(MAC_I, MAC_R) || max(MAC_I, MAC_R) || BSSID)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700442 */
443
444 if (os_memcmp(own_addr, peer->addr, ETH_ALEN) < 0) {
445 os_memcpy(data, own_addr, ETH_ALEN);
446 os_memcpy(data + ETH_ALEN, peer->addr, ETH_ALEN);
447 } else {
448 os_memcpy(data, peer->addr, ETH_ALEN);
449 os_memcpy(data + ETH_ALEN, own_addr, ETH_ALEN);
450 }
451 os_memcpy(data + 2 * ETH_ALEN, bssid, ETH_ALEN);
452 wpa_hexdump(MSG_DEBUG, "TDLS: KDF Context", data, sizeof(data));
453
454 sha256_prf(key_input, SHA256_MAC_LEN, "TDLS PMK", data, sizeof(data),
455 (u8 *) &peer->tpk, sizeof(peer->tpk));
456 wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-KCK",
457 peer->tpk.kck, sizeof(peer->tpk.kck));
458 wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-TK",
459 peer->tpk.tk, sizeof(peer->tpk.tk));
460 peer->tpk_set = 1;
461}
462
463
464/**
465 * wpa_tdls_ftie_mic - Calculate TDLS FTIE MIC
466 * @kck: TPK-KCK
467 * @lnkid: Pointer to the beginning of Link Identifier IE
Sunil Ravi38ad1ed2023-01-17 23:58:31 +0000468 * @rsne: Pointer to the beginning of RSNE used for handshake
469 * @rsne_len: Length of RSNE in octets
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700470 * @timeoutie: Pointer to the beginning of Timeout IE used for handshake
Sunil Ravi38ad1ed2023-01-17 23:58:31 +0000471 * @fte: Pointer to the beginning of FTE
472 * @fre_len: Length of FTE in octets
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700473 * @mic: Pointer for writing MIC
474 *
475 * Calculate MIC for TDLS frame.
476 */
477static int wpa_tdls_ftie_mic(const u8 *kck, u8 trans_seq, const u8 *lnkid,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +0000478 const u8 *rsne, size_t rsne_len,
479 const u8 *timeoutie,
480 const u8 *fte, size_t fte_len, u8 *mic)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700481{
482 u8 *buf, *pos;
483 struct wpa_tdls_ftie *_ftie;
484 const struct wpa_tdls_lnkid *_lnkid;
485 int ret;
Sunil Ravi38ad1ed2023-01-17 23:58:31 +0000486 int len = 2 * ETH_ALEN + 1 + 2 + lnkid[1] + rsne_len +
487 2 + timeoutie[1] + fte_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700488 buf = os_zalloc(len);
489 if (!buf) {
490 wpa_printf(MSG_WARNING, "TDLS: No memory for MIC calculation");
491 return -1;
492 }
493
494 pos = buf;
495 _lnkid = (const struct wpa_tdls_lnkid *) lnkid;
496 /* 1) TDLS initiator STA MAC address */
497 os_memcpy(pos, _lnkid->init_sta, ETH_ALEN);
498 pos += ETH_ALEN;
499 /* 2) TDLS responder STA MAC address */
500 os_memcpy(pos, _lnkid->resp_sta, ETH_ALEN);
501 pos += ETH_ALEN;
502 /* 3) Transaction Sequence number */
503 *pos++ = trans_seq;
504 /* 4) Link Identifier IE */
505 os_memcpy(pos, lnkid, 2 + lnkid[1]);
506 pos += 2 + lnkid[1];
507 /* 5) RSN IE */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +0000508 os_memcpy(pos, rsne, rsne_len);
509 pos += rsne_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700510 /* 6) Timeout Interval IE */
511 os_memcpy(pos, timeoutie, 2 + timeoutie[1]);
512 pos += 2 + timeoutie[1];
513 /* 7) FTIE, with the MIC field of the FTIE set to 0 */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +0000514 os_memcpy(pos, fte, fte_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700515 _ftie = (struct wpa_tdls_ftie *) pos;
516 os_memset(_ftie->mic, 0, TDLS_MIC_LEN);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +0000517 pos += fte_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700518
519 wpa_hexdump(MSG_DEBUG, "TDLS: Data for FTIE MIC", buf, pos - buf);
520 wpa_hexdump_key(MSG_DEBUG, "TDLS: KCK", kck, 16);
521 ret = omac1_aes_128(kck, buf, pos - buf, mic);
522 os_free(buf);
523 wpa_hexdump(MSG_DEBUG, "TDLS: FTIE MIC", mic, 16);
524 return ret;
525}
526
527
528/**
529 * wpa_tdls_key_mic_teardown - Calculate TDLS FTIE MIC for Teardown frame
530 * @kck: TPK-KCK
531 * @trans_seq: Transaction Sequence Number (4 - Teardown)
532 * @rcode: Reason code for Teardown
533 * @dtoken: Dialog Token used for that particular link
534 * @lnkid: Pointer to the beginning of Link Identifier IE
Sunil Ravi38ad1ed2023-01-17 23:58:31 +0000535 * @fte: Pointer to the beginning of FTE
536 * @fre_len: Length of FTE in octets
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700537 * @mic: Pointer for writing MIC
538 *
539 * Calculate MIC for TDLS frame.
540 */
541static int wpa_tdls_key_mic_teardown(const u8 *kck, u8 trans_seq, u16 rcode,
542 u8 dtoken, const u8 *lnkid,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +0000543 const u8 *fte, size_t fte_len, u8 *mic)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700544{
545 u8 *buf, *pos;
546 struct wpa_tdls_ftie *_ftie;
547 int ret;
548 int len;
549
550 if (lnkid == NULL)
551 return -1;
552
553 len = 2 + lnkid[1] + sizeof(rcode) + sizeof(dtoken) +
Sunil Ravi38ad1ed2023-01-17 23:58:31 +0000554 sizeof(trans_seq) + fte_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700555
556 buf = os_zalloc(len);
557 if (!buf) {
558 wpa_printf(MSG_WARNING, "TDLS: No memory for MIC calculation");
559 return -1;
560 }
561
562 pos = buf;
563 /* 1) Link Identifier IE */
564 os_memcpy(pos, lnkid, 2 + lnkid[1]);
565 pos += 2 + lnkid[1];
566 /* 2) Reason Code */
567 WPA_PUT_LE16(pos, rcode);
568 pos += sizeof(rcode);
569 /* 3) Dialog token */
570 *pos++ = dtoken;
571 /* 4) Transaction Sequence number */
572 *pos++ = trans_seq;
573 /* 7) FTIE, with the MIC field of the FTIE set to 0 */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +0000574 os_memcpy(pos, fte, fte_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700575 _ftie = (struct wpa_tdls_ftie *) pos;
576 os_memset(_ftie->mic, 0, TDLS_MIC_LEN);
Sunil Ravi38ad1ed2023-01-17 23:58:31 +0000577 pos += fte_len;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700578
579 wpa_hexdump(MSG_DEBUG, "TDLS: Data for FTIE MIC", buf, pos - buf);
580 wpa_hexdump_key(MSG_DEBUG, "TDLS: KCK", kck, 16);
581 ret = omac1_aes_128(kck, buf, pos - buf, mic);
582 os_free(buf);
583 wpa_hexdump(MSG_DEBUG, "TDLS: FTIE MIC", mic, 16);
584 return ret;
585}
586
587
588static int wpa_supplicant_verify_tdls_mic(u8 trans_seq,
589 struct wpa_tdls_peer *peer,
590 const u8 *lnkid, const u8 *timeoutie,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +0000591 const struct wpa_tdls_ftie *ftie,
592 size_t fte_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700593{
594 u8 mic[16];
595
596 if (peer->tpk_set) {
597 wpa_tdls_ftie_mic(peer->tpk.kck, trans_seq, lnkid,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +0000598 peer->rsnie_p, peer->rsnie_p_len, timeoutie,
599 (const u8 *) ftie, fte_len, mic);
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700600 if (os_memcmp_const(mic, ftie->mic, 16) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700601 wpa_printf(MSG_INFO, "TDLS: Invalid MIC in FTIE - "
602 "dropping packet");
603 wpa_hexdump(MSG_DEBUG, "TDLS: Received MIC",
604 ftie->mic, 16);
605 wpa_hexdump(MSG_DEBUG, "TDLS: Calculated MIC",
606 mic, 16);
607 return -1;
608 }
609 } else {
610 wpa_printf(MSG_WARNING, "TDLS: Could not verify TDLS MIC, "
611 "TPK not set - dropping packet");
612 return -1;
613 }
614 return 0;
615}
616
617
618static int wpa_supplicant_verify_tdls_mic_teardown(
619 u8 trans_seq, u16 rcode, u8 dtoken, struct wpa_tdls_peer *peer,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +0000620 const u8 *lnkid, const struct wpa_tdls_ftie *ftie, size_t fte_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700621{
622 u8 mic[16];
623
624 if (peer->tpk_set) {
625 wpa_tdls_key_mic_teardown(peer->tpk.kck, trans_seq, rcode,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +0000626 dtoken, lnkid, (const u8 *) ftie,
627 fte_len, mic);
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700628 if (os_memcmp_const(mic, ftie->mic, 16) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700629 wpa_printf(MSG_INFO, "TDLS: Invalid MIC in Teardown - "
630 "dropping packet");
631 return -1;
632 }
633 } else {
634 wpa_printf(MSG_INFO, "TDLS: Could not verify TDLS Teardown "
635 "MIC, TPK not set - dropping packet");
636 return -1;
637 }
638 return 0;
639}
640
641
642static void wpa_tdls_tpk_timeout(void *eloop_ctx, void *timeout_ctx)
643{
644 struct wpa_sm *sm = eloop_ctx;
645 struct wpa_tdls_peer *peer = timeout_ctx;
646
647 /*
648 * On TPK lifetime expiration, we have an option of either tearing down
649 * the direct link or trying to re-initiate it. The selection of what
650 * to do is not strictly speaking controlled by our role in the expired
651 * link, but for now, use that to select whether to renew or tear down
652 * the link.
653 */
654
655 if (peer->initiator) {
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800656 u8 addr[ETH_ALEN];
657
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700658 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime expired for " MACSTR
659 " - try to renew", MAC2STR(peer->addr));
Dmitry Shmidtd80a4012015-11-05 16:35:40 -0800660 /* cache the peer address before do_teardown */
661 os_memcpy(addr, peer->addr, ETH_ALEN);
662 wpa_tdls_do_teardown(sm, peer,
663 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
664 wpa_tdls_start(sm, addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700665 } else {
666 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime expired for " MACSTR
667 " - tear down", MAC2STR(peer->addr));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800668 wpa_tdls_do_teardown(sm, peer,
Sunil Dutt6a9f5222013-09-30 17:10:18 +0300669 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700670 }
671}
672
673
Dmitry Shmidtd30ac602014-06-30 09:54:22 -0700674static void wpa_tdls_peer_remove_from_list(struct wpa_sm *sm,
675 struct wpa_tdls_peer *peer)
676{
677 struct wpa_tdls_peer *cur, *prev;
678
679 cur = sm->tdls;
680 prev = NULL;
681 while (cur && cur != peer) {
682 prev = cur;
683 cur = cur->next;
684 }
685
686 if (cur != peer) {
687 wpa_printf(MSG_ERROR, "TDLS: Could not find peer " MACSTR
688 " to remove it from the list",
689 MAC2STR(peer->addr));
690 return;
691 }
692
693 if (prev)
694 prev->next = peer->next;
695 else
696 sm->tdls = peer->next;
697}
698
699
700static void wpa_tdls_peer_clear(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700701{
702 wpa_printf(MSG_DEBUG, "TDLS: Clear state for peer " MACSTR,
703 MAC2STR(peer->addr));
704 eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer);
705 eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
Dmitry Shmidt8da800a2013-04-24 12:57:01 -0700706 peer->reconfig_key = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700707 peer->initiator = 0;
Sunil Dutt73b28cc2013-09-30 17:38:41 +0300708 peer->tpk_in_progress = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700709 os_free(peer->sm_tmr.buf);
710 peer->sm_tmr.buf = NULL;
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800711 os_free(peer->ht_capabilities);
712 peer->ht_capabilities = NULL;
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -0800713 os_free(peer->vht_capabilities);
714 peer->vht_capabilities = NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -0800715 os_free(peer->he_capabilities);
716 peer->he_capabilities = NULL;
717 os_free(peer->he_6ghz_band_capabilities);
718 peer->he_6ghz_band_capabilities = NULL;
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800719 os_free(peer->ext_capab);
720 peer->ext_capab = NULL;
Dmitry Shmidt344abd32014-01-14 13:17:00 -0800721 os_free(peer->supp_channels);
722 peer->supp_channels = NULL;
723 os_free(peer->supp_oper_classes);
724 peer->supp_oper_classes = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700725 peer->rsnie_i_len = peer->rsnie_p_len = 0;
726 peer->cipher = 0;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -0700727 peer->qos_info = 0;
728 peer->wmm_capable = 0;
Jouni Malinenc580b552017-09-22 11:03:15 +0300729 peer->tk_set = peer->tpk_set = peer->tpk_success = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800730 peer->chan_switch_enabled = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700731 os_memset(&peer->tpk, 0, sizeof(peer->tpk));
732 os_memset(peer->inonce, 0, WPA_NONCE_LEN);
733 os_memset(peer->rnonce, 0, WPA_NONCE_LEN);
734}
735
736
Dmitry Shmidtd30ac602014-06-30 09:54:22 -0700737static void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
738{
739 wpa_tdls_peer_clear(sm, peer);
740 wpa_tdls_peer_remove_from_list(sm, peer);
741 os_free(peer);
742}
743
744
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700745static void wpa_tdls_linkid(struct wpa_sm *sm, struct wpa_tdls_peer *peer,
746 struct wpa_tdls_lnkid *lnkid)
747{
748 lnkid->ie_type = WLAN_EID_LINK_ID;
749 lnkid->ie_len = 3 * ETH_ALEN;
750 os_memcpy(lnkid->bssid, sm->bssid, ETH_ALEN);
751 if (peer->initiator) {
752 os_memcpy(lnkid->init_sta, sm->own_addr, ETH_ALEN);
753 os_memcpy(lnkid->resp_sta, peer->addr, ETH_ALEN);
754 } else {
755 os_memcpy(lnkid->init_sta, peer->addr, ETH_ALEN);
756 os_memcpy(lnkid->resp_sta, sm->own_addr, ETH_ALEN);
757 }
758}
759
760
Dmitry Shmidtb58836e2014-04-29 14:35:56 -0700761static int wpa_tdls_send_teardown(struct wpa_sm *sm, const u8 *addr,
762 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700763{
764 struct wpa_tdls_peer *peer;
765 struct wpa_tdls_ftie *ftie;
766 struct wpa_tdls_lnkid lnkid;
767 u8 dialog_token;
768 u8 *rbuf, *pos;
769 int ielen;
770
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800771 if (sm->tdls_disabled || !sm->tdls_supported)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700772 return -1;
773
774 /* Find the node and free from the list */
775 for (peer = sm->tdls; peer; peer = peer->next) {
776 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
777 break;
778 }
779
780 if (peer == NULL) {
781 wpa_printf(MSG_INFO, "TDLS: No matching entry found for "
782 "Teardown " MACSTR, MAC2STR(addr));
783 return 0;
784 }
785
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800786 /* Cancel active channel switch before teardown */
787 if (peer->chan_switch_enabled) {
788 wpa_printf(MSG_DEBUG, "TDLS: First returning link with " MACSTR
789 " to base channel", MAC2STR(addr));
790 wpa_sm_tdls_disable_channel_switch(sm, peer->addr);
791 }
792
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700793 dialog_token = peer->dtoken;
794
795 wpa_printf(MSG_DEBUG, "TDLS: TDLS Teardown for " MACSTR,
796 MAC2STR(addr));
797
798 ielen = 0;
799 if (wpa_tdls_get_privacy(sm) && peer->tpk_set && peer->tpk_success) {
800 /* To add FTIE for Teardown request and compute MIC */
801 ielen += sizeof(*ftie);
802#ifdef CONFIG_TDLS_TESTING
803 if (tdls_testing & TDLS_TESTING_LONG_FRAME)
804 ielen += 170;
805#endif /* CONFIG_TDLS_TESTING */
806 }
807
808 rbuf = os_zalloc(ielen + 1);
809 if (rbuf == NULL)
810 return -1;
811 pos = rbuf;
812
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700813 if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700814 goto skip_ies;
815
816 ftie = (struct wpa_tdls_ftie *) pos;
817 ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
818 /* Using the recent nonce which should be for CONFIRM frame */
819 os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN);
820 os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
821 ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2;
822 pos = (u8 *) (ftie + 1);
823#ifdef CONFIG_TDLS_TESTING
824 if (tdls_testing & TDLS_TESTING_LONG_FRAME) {
825 wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to "
826 "FTIE");
827 ftie->ie_len += 170;
828 *pos++ = 255; /* FTIE subelem */
829 *pos++ = 168; /* FTIE subelem length */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800830 pos += 168;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700831 }
832#endif /* CONFIG_TDLS_TESTING */
833 wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TDLS Teardown handshake",
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800834 (u8 *) ftie, pos - (u8 *) ftie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700835
836 /* compute MIC before sending */
837 wpa_tdls_linkid(sm, peer, &lnkid);
838 wpa_tdls_key_mic_teardown(peer->tpk.kck, 4, reason_code,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +0000839 dialog_token, (const u8 *) &lnkid,
840 (const u8 *) ftie, 2 + ftie->ie_len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700841 ftie->mic);
842
843skip_ies:
844 /* TODO: register for a Timeout handler, if Teardown is not received at
845 * the other end, then try again another time */
846
847 /* request driver to send Teardown using this FTIE */
848 wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_TEARDOWN, 0,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700849 reason_code, 0, peer->initiator, rbuf, pos - rbuf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700850 os_free(rbuf);
851
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700852 return 0;
853}
854
855
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800856int wpa_tdls_teardown_link(struct wpa_sm *sm, const u8 *addr, u16 reason_code)
857{
858 struct wpa_tdls_peer *peer;
859
860 if (sm->tdls_disabled || !sm->tdls_supported)
861 return -1;
862
863 for (peer = sm->tdls; peer; peer = peer->next) {
864 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
865 break;
866 }
867
868 if (peer == NULL) {
869 wpa_printf(MSG_DEBUG, "TDLS: Could not find peer " MACSTR
870 " for link Teardown", MAC2STR(addr));
871 return -1;
872 }
873
874 if (!peer->tpk_success) {
875 wpa_printf(MSG_DEBUG, "TDLS: Peer " MACSTR
876 " not connected - cannot Teardown link", MAC2STR(addr));
877 return -1;
878 }
879
Sunil Dutt6a9f5222013-09-30 17:10:18 +0300880 return wpa_tdls_do_teardown(sm, peer, reason_code);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800881}
882
883
Sunil Dutt38ffd882013-09-30 17:23:23 +0300884static void wpa_tdls_disable_peer_link(struct wpa_sm *sm,
885 struct wpa_tdls_peer *peer)
886{
887 wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr);
888 wpa_tdls_peer_free(sm, peer);
889}
890
891
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700892void wpa_tdls_disable_unreachable_link(struct wpa_sm *sm, const u8 *addr)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800893{
894 struct wpa_tdls_peer *peer;
895
896 for (peer = sm->tdls; peer; peer = peer->next) {
897 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
898 break;
899 }
900
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700901 if (!peer || !peer->tpk_success) {
902 wpa_printf(MSG_DEBUG, "TDLS: Peer " MACSTR
903 " not connected - cannot teardown unreachable link",
904 MAC2STR(addr));
905 return;
906 }
907
908 if (wpa_tdls_is_external_setup(sm)) {
909 /*
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800910 * Get us on the base channel, disable the link, send a
911 * teardown packet through the AP, and then reset link data.
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700912 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800913 if (peer->chan_switch_enabled)
914 wpa_sm_tdls_disable_channel_switch(sm, peer->addr);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700915 wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, addr);
916 wpa_tdls_send_teardown(sm, addr,
917 WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE);
918 wpa_tdls_peer_free(sm, peer);
919 } else {
Sunil Dutt38ffd882013-09-30 17:23:23 +0300920 wpa_tdls_disable_peer_link(sm, peer);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700921 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800922}
923
924
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -0800925const char * wpa_tdls_get_link_status(struct wpa_sm *sm, const u8 *addr)
926{
927 struct wpa_tdls_peer *peer;
928
929 if (sm->tdls_disabled || !sm->tdls_supported)
930 return "disabled";
931
932 for (peer = sm->tdls; peer; peer = peer->next) {
933 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
934 break;
935 }
936
937 if (peer == NULL)
938 return "peer does not exist";
939
940 if (!peer->tpk_success)
941 return "peer not connected";
942
943 return "connected";
944}
945
946
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700947static int wpa_tdls_recv_teardown(struct wpa_sm *sm, const u8 *src_addr,
948 const u8 *buf, size_t len)
949{
950 struct wpa_tdls_peer *peer = NULL;
951 struct wpa_tdls_ftie *ftie;
952 struct wpa_tdls_lnkid *lnkid;
953 struct wpa_eapol_ie_parse kde;
954 u16 reason_code;
955 const u8 *pos;
956 int ielen;
957
958 /* Find the node and free from the list */
959 for (peer = sm->tdls; peer; peer = peer->next) {
960 if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0)
961 break;
962 }
963
964 if (peer == NULL) {
965 wpa_printf(MSG_INFO, "TDLS: No matching entry found for "
966 "Teardown " MACSTR, MAC2STR(src_addr));
967 return 0;
968 }
969
970 pos = buf;
971 pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */;
972
973 reason_code = WPA_GET_LE16(pos);
974 pos += 2;
975
976 wpa_printf(MSG_DEBUG, "TDLS: TDLS Teardown Request from " MACSTR
977 " (reason code %u)", MAC2STR(src_addr), reason_code);
978
979 ielen = len - (pos - buf); /* start of IE in buf */
Dmitry Shmidt7f656022015-02-25 14:36:37 -0800980
981 /*
982 * Don't reject the message if failing to parse IEs. The IEs we need are
983 * explicitly checked below. Some APs may add arbitrary padding to the
984 * end of short TDLS frames and that would look like invalid IEs.
985 */
986 if (wpa_supplicant_parse_ies((const u8 *) pos, ielen, &kde) < 0)
987 wpa_printf(MSG_DEBUG,
988 "TDLS: Failed to parse IEs in Teardown - ignore as an interop workaround");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700989
990 if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) {
991 wpa_printf(MSG_INFO, "TDLS: No Link Identifier IE in TDLS "
992 "Teardown");
993 return -1;
994 }
995 lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
996
997 if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success)
998 goto skip_ftie;
999
1000 if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie)) {
1001 wpa_printf(MSG_INFO, "TDLS: No FTIE in TDLS Teardown");
1002 return -1;
1003 }
1004
1005 ftie = (struct wpa_tdls_ftie *) kde.ftie;
1006
1007 /* Process MIC check to see if TDLS Teardown is right */
1008 if (wpa_supplicant_verify_tdls_mic_teardown(4, reason_code,
1009 peer->dtoken, peer,
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00001010 (const u8 *) lnkid,
1011 ftie, kde.ftie_len) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001012 wpa_printf(MSG_DEBUG, "TDLS: MIC failure for TDLS "
1013 "Teardown Request from " MACSTR, MAC2STR(src_addr));
1014 return -1;
1015 }
1016
1017skip_ftie:
1018 /*
1019 * Request the driver to disable the direct link and clear associated
1020 * keys.
1021 */
Sunil Dutt38ffd882013-09-30 17:23:23 +03001022 wpa_tdls_disable_peer_link(sm, peer);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001023 return 0;
1024}
1025
1026
1027/**
1028 * wpa_tdls_send_error - To send suitable TDLS status response with
1029 * appropriate status code mentioning reason for error/failure.
1030 * @dst - MAC addr of Peer station
1031 * @tdls_action - TDLS frame type for which error code is sent
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001032 * @initiator - was this end the initiator of the connection
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001033 * @status - status code mentioning reason
1034 */
1035
1036static int wpa_tdls_send_error(struct wpa_sm *sm, const u8 *dst,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001037 u8 tdls_action, u8 dialog_token, int initiator,
1038 u16 status)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001039{
1040 wpa_printf(MSG_DEBUG, "TDLS: Sending error to " MACSTR
1041 " (action=%u status=%u)",
1042 MAC2STR(dst), tdls_action, status);
1043 return wpa_tdls_tpk_send(sm, dst, tdls_action, dialog_token, status,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001044 0, initiator, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001045}
1046
1047
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001048static struct wpa_tdls_peer *
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001049wpa_tdls_add_peer(struct wpa_sm *sm, const u8 *addr, int *existing)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001050{
1051 struct wpa_tdls_peer *peer;
1052
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001053 if (existing)
1054 *existing = 0;
1055 for (peer = sm->tdls; peer; peer = peer->next) {
1056 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0) {
1057 if (existing)
1058 *existing = 1;
1059 return peer; /* re-use existing entry */
1060 }
1061 }
1062
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001063 wpa_printf(MSG_INFO, "TDLS: Creating peer entry for " MACSTR,
1064 MAC2STR(addr));
1065
1066 peer = os_zalloc(sizeof(*peer));
1067 if (peer == NULL)
1068 return NULL;
1069
1070 os_memcpy(peer->addr, addr, ETH_ALEN);
1071 peer->next = sm->tdls;
1072 sm->tdls = peer;
1073
1074 return peer;
1075}
1076
1077
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001078static int wpa_tdls_send_tpk_m1(struct wpa_sm *sm,
1079 struct wpa_tdls_peer *peer)
1080{
1081 size_t buf_len;
1082 struct wpa_tdls_timeoutie timeoutie;
1083 u16 rsn_capab;
1084 struct wpa_tdls_ftie *ftie;
1085 u8 *rbuf, *pos, *count_pos;
1086 u16 count;
1087 struct rsn_ie_hdr *hdr;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07001088 int status;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001089
1090 if (!wpa_tdls_get_privacy(sm)) {
1091 wpa_printf(MSG_DEBUG, "TDLS: No security used on the link");
1092 peer->rsnie_i_len = 0;
1093 goto skip_rsnie;
1094 }
1095
1096 /*
1097 * TPK Handshake Message 1:
1098 * FTIE: ANonce=0, SNonce=initiator nonce MIC=0, DataKDs=(RSNIE_I,
1099 * Timeout Interval IE))
1100 */
1101
1102 /* Filling RSN IE */
1103 hdr = (struct rsn_ie_hdr *) peer->rsnie_i;
1104 hdr->elem_id = WLAN_EID_RSN;
1105 WPA_PUT_LE16(hdr->version, RSN_VERSION);
1106
1107 pos = (u8 *) (hdr + 1);
1108 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
1109 pos += RSN_SELECTOR_LEN;
1110 count_pos = pos;
1111 pos += 2;
1112
1113 count = 0;
1114
1115 /*
1116 * AES-CCMP is the default Encryption preferred for TDLS, so
1117 * RSN IE is filled only with CCMP CIPHER
1118 * Note: TKIP is not used to encrypt TDLS link.
1119 *
1120 * Regardless of the cipher used on the AP connection, select CCMP
1121 * here.
1122 */
1123 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
1124 pos += RSN_SELECTOR_LEN;
1125 count++;
1126
1127 WPA_PUT_LE16(count_pos, count);
1128
1129 WPA_PUT_LE16(pos, 1);
1130 pos += 2;
1131 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE);
1132 pos += RSN_SELECTOR_LEN;
1133
1134 rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
1135 rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2;
1136#ifdef CONFIG_TDLS_TESTING
1137 if (tdls_testing & TDLS_TESTING_ALT_RSN_IE) {
1138 wpa_printf(MSG_DEBUG, "TDLS: Use alternative RSN IE for "
1139 "testing");
1140 rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
1141 }
1142#endif /* CONFIG_TDLS_TESTING */
1143 WPA_PUT_LE16(pos, rsn_capab);
1144 pos += 2;
1145#ifdef CONFIG_TDLS_TESTING
1146 if (tdls_testing & TDLS_TESTING_ALT_RSN_IE) {
1147 /* Number of PMKIDs */
1148 *pos++ = 0x00;
1149 *pos++ = 0x00;
1150 }
1151#endif /* CONFIG_TDLS_TESTING */
1152
1153 hdr->len = (pos - peer->rsnie_i) - 2;
1154 peer->rsnie_i_len = pos - peer->rsnie_i;
1155 wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for TPK handshake",
1156 peer->rsnie_i, peer->rsnie_i_len);
1157
1158skip_rsnie:
1159 buf_len = 0;
1160 if (wpa_tdls_get_privacy(sm))
1161 buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) +
1162 sizeof(struct wpa_tdls_timeoutie);
1163#ifdef CONFIG_TDLS_TESTING
1164 if (wpa_tdls_get_privacy(sm) &&
1165 (tdls_testing & TDLS_TESTING_LONG_FRAME))
1166 buf_len += 170;
1167 if (tdls_testing & TDLS_TESTING_DIFF_BSSID)
1168 buf_len += sizeof(struct wpa_tdls_lnkid);
1169#endif /* CONFIG_TDLS_TESTING */
1170 rbuf = os_zalloc(buf_len + 1);
1171 if (rbuf == NULL) {
1172 wpa_tdls_peer_free(sm, peer);
Hai Shalom60840252021-02-19 19:02:11 -08001173 return -2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001174 }
1175 pos = rbuf;
1176
1177 if (!wpa_tdls_get_privacy(sm))
1178 goto skip_ies;
1179
1180 /* Initiator RSN IE */
1181 pos = wpa_add_ie(pos, peer->rsnie_i, peer->rsnie_i_len);
1182
1183 ftie = (struct wpa_tdls_ftie *) pos;
1184 ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
1185 ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2;
1186
1187 if (os_get_random(peer->inonce, WPA_NONCE_LEN)) {
1188 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1189 "TDLS: Failed to get random data for initiator Nonce");
1190 os_free(rbuf);
1191 wpa_tdls_peer_free(sm, peer);
Hai Shalom60840252021-02-19 19:02:11 -08001192 return -2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001193 }
Jouni Malinenc580b552017-09-22 11:03:15 +03001194 peer->tk_set = 0; /* A new nonce results in a new TK */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001195 wpa_hexdump(MSG_DEBUG, "TDLS: Initiator Nonce for TPK handshake",
1196 peer->inonce, WPA_NONCE_LEN);
1197 os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
1198
1199 wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TPK Handshake M1",
1200 (u8 *) ftie, sizeof(struct wpa_tdls_ftie));
1201
1202 pos = (u8 *) (ftie + 1);
1203
1204#ifdef CONFIG_TDLS_TESTING
1205 if (tdls_testing & TDLS_TESTING_LONG_FRAME) {
1206 wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to "
1207 "FTIE");
1208 ftie->ie_len += 170;
1209 *pos++ = 255; /* FTIE subelem */
1210 *pos++ = 168; /* FTIE subelem length */
1211 pos += 168;
1212 }
1213#endif /* CONFIG_TDLS_TESTING */
1214
1215 /* Lifetime */
1216 peer->lifetime = TPK_LIFETIME;
1217#ifdef CONFIG_TDLS_TESTING
1218 if (tdls_testing & TDLS_TESTING_SHORT_LIFETIME) {
1219 wpa_printf(MSG_DEBUG, "TDLS: Testing - use short TPK "
1220 "lifetime");
1221 peer->lifetime = 301;
1222 }
1223 if (tdls_testing & TDLS_TESTING_LONG_LIFETIME) {
1224 wpa_printf(MSG_DEBUG, "TDLS: Testing - use long TPK "
1225 "lifetime");
1226 peer->lifetime = 0xffffffff;
1227 }
1228#endif /* CONFIG_TDLS_TESTING */
1229 pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie,
1230 sizeof(timeoutie), peer->lifetime);
1231 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", peer->lifetime);
1232
1233skip_ies:
1234
1235#ifdef CONFIG_TDLS_TESTING
1236 if (tdls_testing & TDLS_TESTING_DIFF_BSSID) {
Paul Stewart092955c2017-02-06 09:13:09 -08001237 struct wpa_tdls_lnkid *l = (struct wpa_tdls_lnkid *) pos;
1238
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001239 wpa_printf(MSG_DEBUG, "TDLS: Testing - use incorrect BSSID in "
1240 "Link Identifier");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001241 wpa_tdls_linkid(sm, peer, l);
1242 l->bssid[5] ^= 0x01;
1243 pos += sizeof(*l);
1244 }
1245#endif /* CONFIG_TDLS_TESTING */
1246
1247 wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Request / TPK "
1248 "Handshake Message 1 (peer " MACSTR ")",
1249 MAC2STR(peer->addr));
1250
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07001251 status = wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_SETUP_REQUEST,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001252 1, 0, 0, peer->initiator, rbuf, pos - rbuf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001253 os_free(rbuf);
1254
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07001255 return status;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001256}
1257
1258
1259static int wpa_tdls_send_tpk_m2(struct wpa_sm *sm,
1260 const unsigned char *src_addr, u8 dtoken,
1261 struct wpa_tdls_lnkid *lnkid,
1262 const struct wpa_tdls_peer *peer)
1263{
1264 u8 *rbuf, *pos;
1265 size_t buf_len;
1266 u32 lifetime;
1267 struct wpa_tdls_timeoutie timeoutie;
1268 struct wpa_tdls_ftie *ftie;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07001269 int status;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001270
1271 buf_len = 0;
1272 if (wpa_tdls_get_privacy(sm)) {
1273 /* Peer RSN IE, FTIE(Initiator Nonce, Responder Nonce),
1274 * Lifetime */
1275 buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) +
1276 sizeof(struct wpa_tdls_timeoutie);
1277#ifdef CONFIG_TDLS_TESTING
1278 if (tdls_testing & TDLS_TESTING_LONG_FRAME)
1279 buf_len += 170;
1280#endif /* CONFIG_TDLS_TESTING */
1281 }
1282
1283 rbuf = os_zalloc(buf_len + 1);
1284 if (rbuf == NULL)
1285 return -1;
1286 pos = rbuf;
1287
1288 if (!wpa_tdls_get_privacy(sm))
1289 goto skip_ies;
1290
1291 /* Peer RSN IE */
1292 pos = wpa_add_ie(pos, peer->rsnie_p, peer->rsnie_p_len);
1293
1294 ftie = (struct wpa_tdls_ftie *) pos;
1295 ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
1296 /* TODO: ftie->mic_control to set 2-RESPONSE */
1297 os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN);
1298 os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
1299 ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2;
1300 wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TPK M2",
1301 (u8 *) ftie, sizeof(*ftie));
1302
1303 pos = (u8 *) (ftie + 1);
1304
1305#ifdef CONFIG_TDLS_TESTING
1306 if (tdls_testing & TDLS_TESTING_LONG_FRAME) {
1307 wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to "
1308 "FTIE");
1309 ftie->ie_len += 170;
1310 *pos++ = 255; /* FTIE subelem */
1311 *pos++ = 168; /* FTIE subelem length */
1312 pos += 168;
1313 }
1314#endif /* CONFIG_TDLS_TESTING */
1315
1316 /* Lifetime */
1317 lifetime = peer->lifetime;
1318#ifdef CONFIG_TDLS_TESTING
1319 if (tdls_testing & TDLS_TESTING_WRONG_LIFETIME_RESP) {
1320 wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong TPK "
1321 "lifetime in response");
1322 lifetime++;
1323 }
1324#endif /* CONFIG_TDLS_TESTING */
1325 pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie,
1326 sizeof(timeoutie), lifetime);
1327 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds from initiator",
1328 lifetime);
1329
1330 /* compute MIC before sending */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00001331 wpa_tdls_ftie_mic(peer->tpk.kck, 2, (const u8 *) lnkid, peer->rsnie_p,
1332 peer->rsnie_p_len, (const u8 *) &timeoutie,
1333 (const u8 *) ftie, 2 + ftie->ie_len, ftie->mic);
Dmitry Shmidt21de2142014-04-08 10:50:52 -07001334#ifdef CONFIG_TDLS_TESTING
1335 if (tdls_testing & TDLS_TESTING_WRONG_MIC) {
1336 wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong MIC");
1337 ftie->mic[0] ^= 0x01;
1338 }
1339#endif /* CONFIG_TDLS_TESTING */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001340
1341skip_ies:
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07001342 status = wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001343 dtoken, 0, 0, peer->initiator, rbuf,
1344 pos - rbuf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001345 os_free(rbuf);
1346
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07001347 return status;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001348}
1349
1350
1351static int wpa_tdls_send_tpk_m3(struct wpa_sm *sm,
1352 const unsigned char *src_addr, u8 dtoken,
1353 struct wpa_tdls_lnkid *lnkid,
1354 const struct wpa_tdls_peer *peer)
1355{
1356 u8 *rbuf, *pos;
1357 size_t buf_len;
1358 struct wpa_tdls_ftie *ftie;
1359 struct wpa_tdls_timeoutie timeoutie;
1360 u32 lifetime;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07001361 int status;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07001362 u32 peer_capab = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001363
1364 buf_len = 0;
1365 if (wpa_tdls_get_privacy(sm)) {
1366 /* Peer RSN IE, FTIE(Initiator Nonce, Responder Nonce),
1367 * Lifetime */
1368 buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) +
1369 sizeof(struct wpa_tdls_timeoutie);
1370#ifdef CONFIG_TDLS_TESTING
1371 if (tdls_testing & TDLS_TESTING_LONG_FRAME)
1372 buf_len += 170;
1373#endif /* CONFIG_TDLS_TESTING */
1374 }
1375
1376 rbuf = os_zalloc(buf_len + 1);
1377 if (rbuf == NULL)
1378 return -1;
1379 pos = rbuf;
1380
1381 if (!wpa_tdls_get_privacy(sm))
1382 goto skip_ies;
1383
1384 /* Peer RSN IE */
1385 pos = wpa_add_ie(pos, peer->rsnie_p, peer->rsnie_p_len);
1386
1387 ftie = (struct wpa_tdls_ftie *) pos;
1388 ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
1389 /*TODO: ftie->mic_control to set 3-CONFIRM */
1390 os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN);
1391 os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
1392 ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2;
1393
1394 pos = (u8 *) (ftie + 1);
1395
1396#ifdef CONFIG_TDLS_TESTING
1397 if (tdls_testing & TDLS_TESTING_LONG_FRAME) {
1398 wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to "
1399 "FTIE");
1400 ftie->ie_len += 170;
1401 *pos++ = 255; /* FTIE subelem */
1402 *pos++ = 168; /* FTIE subelem length */
1403 pos += 168;
1404 }
1405#endif /* CONFIG_TDLS_TESTING */
1406
1407 /* Lifetime */
1408 lifetime = peer->lifetime;
1409#ifdef CONFIG_TDLS_TESTING
1410 if (tdls_testing & TDLS_TESTING_WRONG_LIFETIME_CONF) {
1411 wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong TPK "
1412 "lifetime in confirm");
1413 lifetime++;
1414 }
1415#endif /* CONFIG_TDLS_TESTING */
1416 pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie,
1417 sizeof(timeoutie), lifetime);
1418 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds",
1419 lifetime);
1420
1421 /* compute MIC before sending */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00001422 wpa_tdls_ftie_mic(peer->tpk.kck, 3, (const u8 *) lnkid, peer->rsnie_p,
1423 peer->rsnie_p_len, (const u8 *) &timeoutie,
1424 (const u8 *) ftie, 2 + ftie->ie_len, ftie->mic);
Dmitry Shmidt21de2142014-04-08 10:50:52 -07001425#ifdef CONFIG_TDLS_TESTING
1426 if (tdls_testing & TDLS_TESTING_WRONG_MIC) {
1427 wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong MIC");
1428 ftie->mic[0] ^= 0x01;
1429 }
1430#endif /* CONFIG_TDLS_TESTING */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001431
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07001432skip_ies:
1433
Hai Shaloma20dcd72022-02-04 13:43:00 -08001434 if (peer->he_capabilities)
1435 peer_capab |= TDLS_PEER_HE;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07001436 if (peer->vht_capabilities)
1437 peer_capab |= TDLS_PEER_VHT;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07001438 if (peer->ht_capabilities)
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07001439 peer_capab |= TDLS_PEER_HT;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07001440 if (peer->wmm_capable)
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07001441 peer_capab |= TDLS_PEER_WMM;
1442
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07001443 status = wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001444 dtoken, 0, peer_capab, peer->initiator,
1445 rbuf, pos - rbuf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001446 os_free(rbuf);
1447
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07001448 return status;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001449}
1450
1451
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001452static int wpa_tdls_send_discovery_response(struct wpa_sm *sm,
1453 struct wpa_tdls_peer *peer,
1454 u8 dialog_token)
1455{
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001456 size_t buf_len = 0;
1457 struct wpa_tdls_timeoutie timeoutie;
1458 u16 rsn_capab;
1459 u8 *rbuf, *pos, *count_pos;
1460 u16 count;
1461 struct rsn_ie_hdr *hdr;
1462 int status;
1463
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001464 wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Discovery Response "
1465 "(peer " MACSTR ")", MAC2STR(peer->addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001466 if (!wpa_tdls_get_privacy(sm))
1467 goto skip_rsn_ies;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001468
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001469 /* Filling RSN IE */
1470 hdr = (struct rsn_ie_hdr *) peer->rsnie_i;
1471 hdr->elem_id = WLAN_EID_RSN;
1472 WPA_PUT_LE16(hdr->version, RSN_VERSION);
1473 pos = (u8 *) (hdr + 1);
1474 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
1475 pos += RSN_SELECTOR_LEN;
1476 count_pos = pos;
1477 pos += 2;
1478 count = 0;
1479
1480 /*
1481 * AES-CCMP is the default encryption preferred for TDLS, so
1482 * RSN IE is filled only with CCMP cipher suite.
1483 * Note: TKIP is not used to encrypt TDLS link.
1484 *
1485 * Regardless of the cipher used on the AP connection, select CCMP
1486 * here.
1487 */
1488 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
1489 pos += RSN_SELECTOR_LEN;
1490 count++;
1491 WPA_PUT_LE16(count_pos, count);
1492 WPA_PUT_LE16(pos, 1);
1493 pos += 2;
1494 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE);
1495 pos += RSN_SELECTOR_LEN;
1496
1497 rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
1498 rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2;
1499 WPA_PUT_LE16(pos, rsn_capab);
1500 pos += 2;
1501 hdr->len = (pos - (u8 *) hdr) - 2;
1502 peer->rsnie_i_len = pos - peer->rsnie_i;
1503
1504 wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for Discovery Response",
1505 (u8 *) hdr, hdr->len + 2);
1506skip_rsn_ies:
1507 buf_len = 0;
1508 if (wpa_tdls_get_privacy(sm)) {
1509 /* Peer RSN IE, Lifetime */
1510 buf_len += peer->rsnie_i_len +
1511 sizeof(struct wpa_tdls_timeoutie);
1512 }
1513 rbuf = os_zalloc(buf_len + 1);
1514 if (rbuf == NULL) {
1515 wpa_tdls_peer_free(sm, peer);
1516 return -1;
1517 }
1518 pos = rbuf;
1519
1520 if (!wpa_tdls_get_privacy(sm))
1521 goto skip_ies;
1522 /* Initiator RSN IE */
1523 pos = wpa_add_ie(pos, peer->rsnie_i, peer->rsnie_i_len);
1524 /* Lifetime */
1525 peer->lifetime = TPK_LIFETIME;
1526 pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie,
1527 sizeof(timeoutie), peer->lifetime);
1528 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", peer->lifetime);
1529skip_ies:
1530 status = wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_DISCOVERY_RESPONSE,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001531 dialog_token, 0, 0, 0, rbuf, pos - rbuf);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001532 os_free(rbuf);
1533
1534 return status;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001535}
1536
1537
1538static int
1539wpa_tdls_process_discovery_request(struct wpa_sm *sm, const u8 *addr,
1540 const u8 *buf, size_t len)
1541{
1542 struct wpa_eapol_ie_parse kde;
1543 const struct wpa_tdls_lnkid *lnkid;
1544 struct wpa_tdls_peer *peer;
1545 size_t min_req_len = sizeof(struct wpa_tdls_frame) +
1546 1 /* dialog token */ + sizeof(struct wpa_tdls_lnkid);
1547 u8 dialog_token;
1548
1549 wpa_printf(MSG_DEBUG, "TDLS: Discovery Request from " MACSTR,
1550 MAC2STR(addr));
1551
1552 if (len < min_req_len) {
1553 wpa_printf(MSG_DEBUG, "TDLS Discovery Request is too short: "
1554 "%d", (int) len);
1555 return -1;
1556 }
1557
1558 dialog_token = buf[sizeof(struct wpa_tdls_frame)];
1559
Dmitry Shmidt0c08fdc2014-06-20 10:16:40 -07001560 /*
1561 * Some APs will tack on a weird IE to the end of a TDLS
1562 * discovery request packet. This needn't fail the response,
1563 * since the required IE are verified separately.
1564 */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001565 if (wpa_supplicant_parse_ies(buf + sizeof(struct wpa_tdls_frame) + 1,
1566 len - (sizeof(struct wpa_tdls_frame) + 1),
Dmitry Shmidt0c08fdc2014-06-20 10:16:40 -07001567 &kde) < 0) {
1568 wpa_printf(MSG_DEBUG,
1569 "TDLS: Failed to parse IEs in Discovery Request - ignore as an interop workaround");
1570 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001571
1572 if (!kde.lnkid) {
1573 wpa_printf(MSG_DEBUG, "TDLS: Link ID not found in Discovery "
1574 "Request");
1575 return -1;
1576 }
1577
1578 lnkid = (const struct wpa_tdls_lnkid *) kde.lnkid;
1579
1580 if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) {
1581 wpa_printf(MSG_DEBUG, "TDLS: Discovery Request from different "
1582 " BSS " MACSTR, MAC2STR(lnkid->bssid));
1583 return -1;
1584 }
1585
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001586 peer = wpa_tdls_add_peer(sm, addr, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001587 if (peer == NULL)
1588 return -1;
1589
1590 return wpa_tdls_send_discovery_response(sm, peer, dialog_token);
1591}
1592
1593
1594int wpa_tdls_send_discovery_request(struct wpa_sm *sm, const u8 *addr)
1595{
1596 if (sm->tdls_disabled || !sm->tdls_supported)
1597 return -1;
1598
1599 wpa_printf(MSG_DEBUG, "TDLS: Sending Discovery Request to peer "
1600 MACSTR, MAC2STR(addr));
1601 return wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_DISCOVERY_REQUEST,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001602 1, 0, 0, 1, NULL, 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001603}
1604
1605
1606static int copy_supp_rates(const struct wpa_eapol_ie_parse *kde,
1607 struct wpa_tdls_peer *peer)
1608{
1609 if (!kde->supp_rates) {
1610 wpa_printf(MSG_DEBUG, "TDLS: No supported rates received");
1611 return -1;
1612 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001613 peer->supp_rates_len = merge_byte_arrays(
1614 peer->supp_rates, sizeof(peer->supp_rates),
1615 kde->supp_rates + 2, kde->supp_rates_len - 2,
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001616 kde->ext_supp_rates ? kde->ext_supp_rates + 2 : NULL,
Hai Shalom021b0b52019-04-10 11:17:58 -07001617 kde->ext_supp_rates ? kde->ext_supp_rates_len - 2 : 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001618 return 0;
1619}
1620
1621
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001622static int copy_peer_ht_capab(const struct wpa_eapol_ie_parse *kde,
1623 struct wpa_tdls_peer *peer)
1624{
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07001625 if (!kde->ht_capabilities) {
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001626 wpa_printf(MSG_DEBUG, "TDLS: No supported ht capabilities "
1627 "received");
1628 return 0;
1629 }
1630
1631 if (!peer->ht_capabilities) {
1632 peer->ht_capabilities =
1633 os_zalloc(sizeof(struct ieee80211_ht_capabilities));
1634 if (peer->ht_capabilities == NULL)
1635 return -1;
1636 }
1637
1638 os_memcpy(peer->ht_capabilities, kde->ht_capabilities,
1639 sizeof(struct ieee80211_ht_capabilities));
1640 wpa_hexdump(MSG_DEBUG, "TDLS: Peer HT capabilities",
1641 (u8 *) peer->ht_capabilities,
1642 sizeof(struct ieee80211_ht_capabilities));
1643
1644 return 0;
1645}
1646
1647
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -08001648static int copy_peer_vht_capab(const struct wpa_eapol_ie_parse *kde,
1649 struct wpa_tdls_peer *peer)
1650{
Dmitry Shmidt9d9e6022015-04-23 10:34:55 -07001651 if (!kde->vht_capabilities) {
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -08001652 wpa_printf(MSG_DEBUG, "TDLS: No supported vht capabilities "
1653 "received");
1654 return 0;
1655 }
1656
1657 if (!peer->vht_capabilities) {
1658 peer->vht_capabilities =
1659 os_zalloc(sizeof(struct ieee80211_vht_capabilities));
1660 if (peer->vht_capabilities == NULL)
1661 return -1;
1662 }
1663
1664 os_memcpy(peer->vht_capabilities, kde->vht_capabilities,
1665 sizeof(struct ieee80211_vht_capabilities));
1666 wpa_hexdump(MSG_DEBUG, "TDLS: Peer VHT capabilities",
1667 (u8 *) peer->vht_capabilities,
1668 sizeof(struct ieee80211_vht_capabilities));
1669
1670 return 0;
1671}
1672
1673
Hai Shaloma20dcd72022-02-04 13:43:00 -08001674static int copy_peer_he_capab(const struct wpa_eapol_ie_parse *kde,
1675 struct wpa_tdls_peer *peer)
1676{
1677 if (!kde->he_capabilities) {
1678 wpa_printf(MSG_DEBUG, "TDLS: No HE capabilities received");
1679 return 0;
1680 }
1681
1682 os_free(peer->he_capabilities);
1683 peer->he_capab_len = 0;
1684 peer->he_capabilities = os_memdup(kde->he_capabilities,
1685 kde->he_capab_len);
1686 if (!peer->he_capabilities)
1687 return -1;
1688
1689 peer->he_capab_len = kde->he_capab_len;
1690 wpa_hexdump(MSG_DEBUG, "TDLS: Peer HE capabilities",
1691 peer->he_capabilities, peer->he_capab_len);
1692
1693 return 0;
1694}
1695
1696
1697static int copy_peer_he_6ghz_band_capab(const struct wpa_eapol_ie_parse *kde,
1698 struct wpa_tdls_peer *peer)
1699{
1700 if (!kde->he_6ghz_capabilities) {
1701 wpa_printf(MSG_DEBUG,
1702 "TDLS: No HE 6 GHz band capabilities received");
1703 return 0;
1704 }
1705
1706 if (!peer->he_6ghz_band_capabilities) {
1707 peer->he_6ghz_band_capabilities =
1708 os_zalloc(sizeof(struct ieee80211_he_6ghz_band_cap));
1709 if (peer->he_6ghz_band_capabilities == NULL)
1710 return -1;
1711 }
1712
1713 os_memcpy(peer->he_6ghz_band_capabilities, kde->he_6ghz_capabilities,
1714 sizeof(struct ieee80211_he_6ghz_band_cap));
1715
1716 wpa_hexdump(MSG_DEBUG, "TDLS: Peer 6 GHz band HE capabilities",
1717 peer->he_6ghz_band_capabilities,
1718 sizeof(struct ieee80211_he_6ghz_band_cap));
1719
1720 return 0;
1721}
1722
1723
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001724static int copy_peer_ext_capab(const struct wpa_eapol_ie_parse *kde,
1725 struct wpa_tdls_peer *peer)
1726{
1727 if (!kde->ext_capab) {
1728 wpa_printf(MSG_DEBUG, "TDLS: No extended capabilities "
1729 "received");
1730 return 0;
1731 }
1732
1733 if (!peer->ext_capab || peer->ext_capab_len < kde->ext_capab_len - 2) {
1734 /* Need to allocate buffer to fit the new information */
1735 os_free(peer->ext_capab);
1736 peer->ext_capab = os_zalloc(kde->ext_capab_len - 2);
1737 if (peer->ext_capab == NULL)
1738 return -1;
1739 }
1740
1741 peer->ext_capab_len = kde->ext_capab_len - 2;
1742 os_memcpy(peer->ext_capab, kde->ext_capab + 2, peer->ext_capab_len);
1743
1744 return 0;
1745}
1746
1747
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001748static int copy_peer_wmm_capab(const struct wpa_eapol_ie_parse *kde,
1749 struct wpa_tdls_peer *peer)
1750{
1751 struct wmm_information_element *wmm;
1752
1753 if (!kde->wmm) {
1754 wpa_printf(MSG_DEBUG, "TDLS: No supported WMM capabilities received");
1755 return 0;
1756 }
1757
1758 if (kde->wmm_len < sizeof(struct wmm_information_element)) {
1759 wpa_printf(MSG_DEBUG, "TDLS: Invalid supported WMM capabilities received");
1760 return -1;
1761 }
1762
1763 wmm = (struct wmm_information_element *) kde->wmm;
1764 peer->qos_info = wmm->qos_info;
1765
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07001766 peer->wmm_capable = 1;
1767
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001768 wpa_printf(MSG_DEBUG, "TDLS: Peer WMM QOS Info 0x%x", peer->qos_info);
1769 return 0;
1770}
1771
1772
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001773static int copy_peer_supp_channels(const struct wpa_eapol_ie_parse *kde,
1774 struct wpa_tdls_peer *peer)
1775{
1776 if (!kde->supp_channels) {
1777 wpa_printf(MSG_DEBUG, "TDLS: No supported channels received");
1778 return 0;
1779 }
1780
1781 if (!peer->supp_channels ||
1782 peer->supp_channels_len < kde->supp_channels_len) {
1783 os_free(peer->supp_channels);
1784 peer->supp_channels = os_zalloc(kde->supp_channels_len);
1785 if (peer->supp_channels == NULL)
1786 return -1;
1787 }
1788
1789 peer->supp_channels_len = kde->supp_channels_len;
1790
1791 os_memcpy(peer->supp_channels, kde->supp_channels,
1792 peer->supp_channels_len);
1793 wpa_hexdump(MSG_DEBUG, "TDLS: Peer Supported Channels",
1794 (u8 *) peer->supp_channels, peer->supp_channels_len);
1795 return 0;
1796}
1797
1798
1799static int copy_peer_supp_oper_classes(const struct wpa_eapol_ie_parse *kde,
1800 struct wpa_tdls_peer *peer)
1801{
1802 if (!kde->supp_oper_classes) {
1803 wpa_printf(MSG_DEBUG, "TDLS: No supported operating classes received");
1804 return 0;
1805 }
1806
1807 if (!peer->supp_oper_classes ||
1808 peer->supp_oper_classes_len < kde->supp_oper_classes_len) {
1809 os_free(peer->supp_oper_classes);
1810 peer->supp_oper_classes = os_zalloc(kde->supp_oper_classes_len);
1811 if (peer->supp_oper_classes == NULL)
1812 return -1;
1813 }
1814
1815 peer->supp_oper_classes_len = kde->supp_oper_classes_len;
1816 os_memcpy(peer->supp_oper_classes, kde->supp_oper_classes,
1817 peer->supp_oper_classes_len);
1818 wpa_hexdump(MSG_DEBUG, "TDLS: Peer Supported Operating Classes",
1819 (u8 *) peer->supp_oper_classes,
1820 peer->supp_oper_classes_len);
1821 return 0;
1822}
1823
1824
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07001825static int wpa_tdls_addset_peer(struct wpa_sm *sm, struct wpa_tdls_peer *peer,
1826 int add)
1827{
1828 return wpa_sm_tdls_peer_addset(sm, peer->addr, add, peer->aid,
1829 peer->capability,
1830 peer->supp_rates, peer->supp_rates_len,
1831 peer->ht_capabilities,
1832 peer->vht_capabilities,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001833 peer->he_capabilities,
1834 peer->he_capab_len,
1835 peer->he_6ghz_band_capabilities,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001836 peer->qos_info, peer->wmm_capable,
1837 peer->ext_capab, peer->ext_capab_len,
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07001838 peer->supp_channels,
1839 peer->supp_channels_len,
1840 peer->supp_oper_classes,
1841 peer->supp_oper_classes_len);
1842}
1843
1844
Jouni Malinenc580b552017-09-22 11:03:15 +03001845static int tdls_nonce_set(const u8 *nonce)
1846{
1847 int i;
1848
1849 for (i = 0; i < WPA_NONCE_LEN; i++) {
1850 if (nonce[i])
1851 return 1;
1852 }
1853
1854 return 0;
1855}
1856
1857
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001858static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
1859 const u8 *buf, size_t len)
1860{
1861 struct wpa_tdls_peer *peer;
1862 struct wpa_eapol_ie_parse kde;
1863 struct wpa_ie_data ie;
1864 int cipher;
1865 const u8 *cpos;
1866 struct wpa_tdls_ftie *ftie = NULL;
1867 struct wpa_tdls_timeoutie *timeoutie;
1868 struct wpa_tdls_lnkid *lnkid;
1869 u32 lifetime = 0;
1870#if 0
1871 struct rsn_ie_hdr *hdr;
1872 u8 *pos;
1873 u16 rsn_capab;
1874 u16 rsn_ver;
1875#endif
1876 u8 dtoken;
1877 u16 ielen;
1878 u16 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1879 int tdls_prohibited = sm->tdls_prohibited;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001880 int existing_peer = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001881
1882 if (len < 3 + 3)
1883 return -1;
1884
1885 cpos = buf;
1886 cpos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */;
1887
1888 /* driver had already verified the frame format */
1889 dtoken = *cpos++; /* dialog token */
1890
1891 wpa_printf(MSG_INFO, "TDLS: Dialog Token in TPK M1 %d", dtoken);
1892
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001893 peer = wpa_tdls_add_peer(sm, src_addr, &existing_peer);
1894 if (peer == NULL)
1895 goto error;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001896
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07001897 /* If found, use existing entry instead of adding a new one;
1898 * how to handle the case where both ends initiate at the
1899 * same time? */
1900 if (existing_peer) {
1901 if (peer->tpk_success) {
1902 wpa_printf(MSG_DEBUG, "TDLS: TDLS Setup Request while "
1903 "direct link is enabled - tear down the "
1904 "old link first");
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07001905 wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr);
1906 wpa_tdls_peer_clear(sm, peer);
1907 } else if (peer->initiator) {
1908 /*
1909 * An entry is already present, so check if we already
1910 * sent a TDLS Setup Request. If so, compare MAC
1911 * addresses and let the STA with the lower MAC address
1912 * continue as the initiator. The other negotiation is
1913 * terminated.
1914 */
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07001915 if (os_memcmp(sm->own_addr, src_addr, ETH_ALEN) < 0) {
1916 wpa_printf(MSG_DEBUG, "TDLS: Discard request "
1917 "from peer with higher address "
1918 MACSTR, MAC2STR(src_addr));
1919 return -1;
1920 } else {
1921 wpa_printf(MSG_DEBUG, "TDLS: Accept request "
1922 "from peer with lower address "
1923 MACSTR " (terminate previously "
1924 "initiated negotiation",
1925 MAC2STR(src_addr));
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07001926 wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK,
1927 peer->addr);
1928 wpa_tdls_peer_clear(sm, peer);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07001929 }
1930 }
1931 }
1932
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001933 /* capability information */
1934 peer->capability = WPA_GET_LE16(cpos);
1935 cpos += 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001936
1937 ielen = len - (cpos - buf); /* start of IE in buf */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08001938
1939 /*
1940 * Don't reject the message if failing to parse IEs. The IEs we need are
1941 * explicitly checked below. Some APs may add arbitrary padding to the
1942 * end of short TDLS frames and that would look like invalid IEs.
1943 */
1944 if (wpa_supplicant_parse_ies(cpos, ielen, &kde) < 0)
1945 wpa_printf(MSG_DEBUG,
1946 "TDLS: Failed to parse IEs in TPK M1 - ignore as an interop workaround");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001947
1948 if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) {
1949 wpa_printf(MSG_INFO, "TDLS: No valid Link Identifier IE in "
1950 "TPK M1");
1951 goto error;
1952 }
1953 wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M1",
1954 kde.lnkid, kde.lnkid_len);
1955 lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
1956 if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) {
1957 wpa_printf(MSG_INFO, "TDLS: TPK M1 from diff BSS");
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001958 status = WLAN_STATUS_REQUEST_DECLINED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001959 goto error;
1960 }
1961
1962 wpa_printf(MSG_DEBUG, "TDLS: TPK M1 - TPK initiator " MACSTR,
1963 MAC2STR(src_addr));
1964
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001965 if (copy_supp_rates(&kde, peer) < 0)
1966 goto error;
1967
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001968 if (copy_peer_ht_capab(&kde, peer) < 0)
1969 goto error;
1970
Hai Shaloma20dcd72022-02-04 13:43:00 -08001971 if (copy_peer_vht_capab(&kde, peer) < 0 ||
1972 copy_peer_he_capab(&kde, peer) < 0 ||
1973 copy_peer_he_6ghz_band_capab(&kde, peer) < 0)
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -08001974 goto error;
1975
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001976 if (copy_peer_ext_capab(&kde, peer) < 0)
1977 goto error;
1978
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001979 if (copy_peer_supp_channels(&kde, peer) < 0)
1980 goto error;
1981
1982 if (copy_peer_supp_oper_classes(&kde, peer) < 0)
1983 goto error;
1984
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001985 peer->qos_info = kde.qosinfo;
1986
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001987 /* Overwrite with the qos_info obtained in WMM IE */
1988 if (copy_peer_wmm_capab(&kde, peer) < 0)
1989 goto error;
1990
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001991 peer->aid = kde.aid;
1992
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001993#ifdef CONFIG_TDLS_TESTING
1994 if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) {
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001995 peer = wpa_tdls_add_peer(sm, src_addr, NULL);
1996 if (peer == NULL)
1997 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001998 wpa_printf(MSG_DEBUG, "TDLS: Testing concurrent initiation of "
1999 "TDLS setup - send own request");
2000 peer->initiator = 1;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002001 wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002002 NULL, NULL, 0, NULL, 0, 0, NULL, 0,
2003 NULL, 0, NULL, 0);
Hai Shalom60840252021-02-19 19:02:11 -08002004 if (wpa_tdls_send_tpk_m1(sm, peer) == -2) {
2005 peer = NULL;
2006 goto error;
2007 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002008 }
2009
2010 if ((tdls_testing & TDLS_TESTING_IGNORE_AP_PROHIBIT) &&
2011 tdls_prohibited) {
2012 wpa_printf(MSG_DEBUG, "TDLS: Testing - ignore AP prohibition "
2013 "on TDLS");
2014 tdls_prohibited = 0;
2015 }
2016#endif /* CONFIG_TDLS_TESTING */
2017
2018 if (tdls_prohibited) {
2019 wpa_printf(MSG_INFO, "TDLS: TDLS prohibited in this BSS");
2020 status = WLAN_STATUS_REQUEST_DECLINED;
2021 goto error;
2022 }
2023
2024 if (!wpa_tdls_get_privacy(sm)) {
2025 if (kde.rsn_ie) {
2026 wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M1 while "
2027 "security is disabled");
2028 status = WLAN_STATUS_SECURITY_DISABLED;
2029 goto error;
2030 }
2031 goto skip_rsn;
2032 }
2033
2034 if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie) ||
2035 kde.rsn_ie == NULL) {
2036 wpa_printf(MSG_INFO, "TDLS: No FTIE or RSN IE in TPK M1");
2037 status = WLAN_STATUS_INVALID_PARAMETERS;
2038 goto error;
2039 }
2040
2041 if (kde.rsn_ie_len > TDLS_MAX_IE_LEN) {
2042 wpa_printf(MSG_INFO, "TDLS: Too long Initiator RSN IE in "
2043 "TPK M1");
2044 status = WLAN_STATUS_INVALID_RSNIE;
2045 goto error;
2046 }
2047
2048 if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) {
2049 wpa_printf(MSG_INFO, "TDLS: Failed to parse RSN IE in TPK M1");
2050 status = WLAN_STATUS_INVALID_RSNIE;
2051 goto error;
2052 }
2053
2054 cipher = ie.pairwise_cipher;
2055 if (cipher & WPA_CIPHER_CCMP) {
2056 wpa_printf(MSG_DEBUG, "TDLS: Using CCMP for direct link");
2057 cipher = WPA_CIPHER_CCMP;
2058 } else {
2059 wpa_printf(MSG_INFO, "TDLS: No acceptable cipher in TPK M1");
2060 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
2061 goto error;
2062 }
2063
2064 if ((ie.capabilities &
2065 (WPA_CAPABILITY_NO_PAIRWISE | WPA_CAPABILITY_PEERKEY_ENABLED)) !=
2066 WPA_CAPABILITY_PEERKEY_ENABLED) {
2067 wpa_printf(MSG_INFO, "TDLS: Invalid RSN Capabilities in "
2068 "TPK M1");
2069 status = WLAN_STATUS_INVALID_RSN_IE_CAPAB;
2070 goto error;
2071 }
2072
2073 /* Lifetime */
2074 if (kde.key_lifetime == NULL) {
2075 wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M1");
2076 status = WLAN_STATUS_UNACCEPTABLE_LIFETIME;
2077 goto error;
2078 }
2079 timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime;
2080 lifetime = WPA_GET_LE32(timeoutie->value);
2081 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", lifetime);
2082 if (lifetime < 300) {
2083 wpa_printf(MSG_INFO, "TDLS: Too short TPK lifetime");
2084 status = WLAN_STATUS_UNACCEPTABLE_LIFETIME;
2085 goto error;
2086 }
2087
2088skip_rsn:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002089#ifdef CONFIG_TDLS_TESTING
2090 if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) {
2091 if (os_memcmp(sm->own_addr, peer->addr, ETH_ALEN) < 0) {
2092 /*
2093 * The request frame from us is going to win, so do not
2094 * replace information based on this request frame from
2095 * the peer.
2096 */
2097 goto skip_rsn_check;
2098 }
2099 }
2100#endif /* CONFIG_TDLS_TESTING */
2101
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002102 peer->initiator = 0; /* Need to check */
2103 peer->dtoken = dtoken;
2104
2105 if (!wpa_tdls_get_privacy(sm)) {
2106 peer->rsnie_i_len = 0;
2107 peer->rsnie_p_len = 0;
2108 peer->cipher = WPA_CIPHER_NONE;
2109 goto skip_rsn_check;
2110 }
2111
2112 ftie = (struct wpa_tdls_ftie *) kde.ftie;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002113 os_memcpy(peer->rsnie_i, kde.rsn_ie, kde.rsn_ie_len);
2114 peer->rsnie_i_len = kde.rsn_ie_len;
2115 peer->cipher = cipher;
2116
Jouni Malinenc580b552017-09-22 11:03:15 +03002117 if (os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) != 0 ||
2118 !tdls_nonce_set(peer->inonce)) {
Sunil Dutt61024722013-09-15 12:09:40 -07002119 /*
2120 * There is no point in updating the RNonce for every obtained
2121 * TPK M1 frame (e.g., retransmission due to timeout) with the
2122 * same INonce (SNonce in FTIE). However, if the TPK M1 is
2123 * retransmitted with a different INonce, update the RNonce
2124 * since this is for a new TDLS session.
2125 */
2126 wpa_printf(MSG_DEBUG,
2127 "TDLS: New TPK M1 INonce - generate new RNonce");
2128 os_memcpy(peer->inonce, ftie->Snonce, WPA_NONCE_LEN);
2129 if (os_get_random(peer->rnonce, WPA_NONCE_LEN)) {
2130 wpa_msg(sm->ctx->ctx, MSG_WARNING,
2131 "TDLS: Failed to get random data for responder nonce");
Sunil Dutt61024722013-09-15 12:09:40 -07002132 goto error;
2133 }
Jouni Malinenc580b552017-09-22 11:03:15 +03002134 peer->tk_set = 0; /* A new nonce results in a new TK */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002135 }
2136
2137#if 0
2138 /* get version info from RSNIE received from Peer */
2139 hdr = (struct rsn_ie_hdr *) kde.rsn_ie;
2140 rsn_ver = WPA_GET_LE16(hdr->version);
2141
2142 /* use min(peer's version, out version) */
2143 if (rsn_ver > RSN_VERSION)
2144 rsn_ver = RSN_VERSION;
2145
2146 hdr = (struct rsn_ie_hdr *) peer->rsnie_p;
2147
2148 hdr->elem_id = WLAN_EID_RSN;
2149 WPA_PUT_LE16(hdr->version, rsn_ver);
2150 pos = (u8 *) (hdr + 1);
2151
2152 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
2153 pos += RSN_SELECTOR_LEN;
2154 /* Include only the selected cipher in pairwise cipher suite */
2155 WPA_PUT_LE16(pos, 1);
2156 pos += 2;
2157 if (cipher == WPA_CIPHER_CCMP)
2158 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
2159 pos += RSN_SELECTOR_LEN;
2160
2161 WPA_PUT_LE16(pos, 1);
2162 pos += 2;
2163 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE);
2164 pos += RSN_SELECTOR_LEN;
2165
2166 rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
2167 rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2;
2168 WPA_PUT_LE16(pos, rsn_capab);
2169 pos += 2;
2170
2171 hdr->len = (pos - peer->rsnie_p) - 2;
2172 peer->rsnie_p_len = pos - peer->rsnie_p;
2173#endif
2174
2175 /* temp fix: validation of RSNIE later */
2176 os_memcpy(peer->rsnie_p, peer->rsnie_i, peer->rsnie_i_len);
2177 peer->rsnie_p_len = peer->rsnie_i_len;
2178
2179 wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for TPK handshake",
2180 peer->rsnie_p, peer->rsnie_p_len);
2181
2182 peer->lifetime = lifetime;
2183
2184 wpa_tdls_generate_tpk(peer, sm->own_addr, sm->bssid);
2185
2186skip_rsn_check:
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002187#ifdef CONFIG_TDLS_TESTING
2188 if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT)
2189 goto skip_add_peer;
2190#endif /* CONFIG_TDLS_TESTING */
2191
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002192 /* add supported rates, capabilities, and qos_info to the TDLS peer */
2193 if (wpa_tdls_addset_peer(sm, peer, 1) < 0)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002194 goto error;
2195
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002196#ifdef CONFIG_TDLS_TESTING
2197skip_add_peer:
2198#endif /* CONFIG_TDLS_TESTING */
Sunil Dutt73b28cc2013-09-30 17:38:41 +03002199 peer->tpk_in_progress = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002200
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002201 wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Response / TPK M2");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002202 if (wpa_tdls_send_tpk_m2(sm, src_addr, dtoken, lnkid, peer) < 0) {
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002203 wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002204 goto error;
2205 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002206
Roshan Pius3a1667e2018-07-03 15:17:14 -07002207#ifdef CONFIG_TDLS_TESTING
2208 if (tdls_testing & TDLS_TESTING_DOUBLE_TPK_M2) {
2209 wpa_printf(MSG_INFO, "TDLS: Testing - Send another TPK M2");
2210 wpa_tdls_send_tpk_m2(sm, src_addr, dtoken, lnkid, peer);
2211 }
2212#endif /* CONFIG_TDLS_TESTING */
2213
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002214 return 0;
2215
2216error:
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002217 wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE, dtoken, 0,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002218 status);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002219 if (peer)
2220 wpa_tdls_peer_free(sm, peer);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002221 return -1;
2222}
2223
2224
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002225static int wpa_tdls_enable_link(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002226{
2227 peer->tpk_success = 1;
Sunil Dutt73b28cc2013-09-30 17:38:41 +03002228 peer->tpk_in_progress = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002229 eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer);
2230 if (wpa_tdls_get_privacy(sm)) {
2231 u32 lifetime = peer->lifetime;
2232 /*
2233 * Start the initiator process a bit earlier to avoid race
2234 * condition with the responder sending teardown request.
2235 */
2236 if (lifetime > 3 && peer->initiator)
2237 lifetime -= 3;
2238 eloop_register_timeout(lifetime, 0, wpa_tdls_tpk_timeout,
2239 sm, peer);
2240#ifdef CONFIG_TDLS_TESTING
Hai Shalom74f70d42019-02-11 14:42:39 -08002241 if (tdls_testing & TDLS_TESTING_NO_TPK_EXPIRATION) {
2242 wpa_printf(MSG_DEBUG,
2243 "TDLS: Testing - disable TPK expiration");
2244 eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer);
2245 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002246#endif /* CONFIG_TDLS_TESTING */
2247 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002248
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002249 if (peer->reconfig_key && wpa_tdls_set_key(sm, peer) < 0) {
2250 wpa_printf(MSG_INFO, "TDLS: Could not configure key to the "
2251 "driver");
2252 return -1;
2253 }
2254 peer->reconfig_key = 0;
2255
2256 return wpa_sm_tdls_oper(sm, TDLS_ENABLE_LINK, peer->addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002257}
2258
2259
2260static int wpa_tdls_process_tpk_m2(struct wpa_sm *sm, const u8 *src_addr,
2261 const u8 *buf, size_t len)
2262{
2263 struct wpa_tdls_peer *peer;
2264 struct wpa_eapol_ie_parse kde;
2265 struct wpa_ie_data ie;
2266 int cipher;
2267 struct wpa_tdls_ftie *ftie;
2268 struct wpa_tdls_timeoutie *timeoutie;
2269 struct wpa_tdls_lnkid *lnkid;
2270 u32 lifetime;
2271 u8 dtoken;
2272 int ielen;
2273 u16 status;
2274 const u8 *pos;
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002275 int ret = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002276
2277 wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Response / TPK M2 "
2278 "(Peer " MACSTR ")", MAC2STR(src_addr));
2279 for (peer = sm->tdls; peer; peer = peer->next) {
2280 if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0)
2281 break;
2282 }
2283 if (peer == NULL) {
2284 wpa_printf(MSG_INFO, "TDLS: No matching peer found for "
2285 "TPK M2: " MACSTR, MAC2STR(src_addr));
2286 return -1;
2287 }
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07002288 if (!peer->initiator) {
2289 /*
2290 * This may happen if both devices try to initiate TDLS at the
2291 * same time and we accept the TPK M1 from the peer in
2292 * wpa_tdls_process_tpk_m1() and clear our previous state.
2293 */
2294 wpa_printf(MSG_INFO, "TDLS: We were not the initiator, so "
2295 "ignore TPK M2 from " MACSTR, MAC2STR(src_addr));
2296 return -1;
2297 }
Dmitry Shmidt7d56b752015-12-22 10:59:44 -08002298
2299 if (peer->tpk_success) {
2300 wpa_printf(MSG_INFO, "TDLS: Ignore incoming TPK M2 retry, from "
2301 MACSTR " as TPK M3 was already sent",
2302 MAC2STR(src_addr));
2303 return 0;
2304 }
2305
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002306 wpa_tdls_tpk_retry_timeout_cancel(sm, peer, WLAN_TDLS_SETUP_REQUEST);
2307
Sunil Duttadce9cf2013-09-15 11:51:00 -07002308 if (len < 3 + 2 + 1) {
Sunil Duttd0ef38b2013-09-30 17:34:13 +03002309 wpa_tdls_disable_peer_link(sm, peer);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002310 return -1;
Sunil Duttadce9cf2013-09-15 11:51:00 -07002311 }
2312
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002313 pos = buf;
2314 pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */;
2315 status = WPA_GET_LE16(pos);
2316 pos += 2 /* status code */;
2317
2318 if (status != WLAN_STATUS_SUCCESS) {
2319 wpa_printf(MSG_INFO, "TDLS: Status code in TPK M2: %u",
2320 status);
Sunil Duttd0ef38b2013-09-30 17:34:13 +03002321 wpa_tdls_disable_peer_link(sm, peer);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002322 return -1;
2323 }
2324
2325 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
2326
2327 /* TODO: need to verify dialog token matches here or in kernel */
2328 dtoken = *pos++; /* dialog token */
2329
2330 wpa_printf(MSG_DEBUG, "TDLS: Dialog Token in TPK M2 %d", dtoken);
2331
Sunil Duttadce9cf2013-09-15 11:51:00 -07002332 if (len < 3 + 2 + 1 + 2) {
Sunil Duttd0ef38b2013-09-30 17:34:13 +03002333 wpa_tdls_disable_peer_link(sm, peer);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002334 return -1;
Sunil Duttadce9cf2013-09-15 11:51:00 -07002335 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002336
2337 /* capability information */
2338 peer->capability = WPA_GET_LE16(pos);
2339 pos += 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002340
2341 ielen = len - (pos - buf); /* start of IE in buf */
Dmitry Shmidt7f656022015-02-25 14:36:37 -08002342
2343 /*
2344 * Don't reject the message if failing to parse IEs. The IEs we need are
2345 * explicitly checked below. Some APs may add arbitrary padding to the
2346 * end of short TDLS frames and that would look like invalid IEs.
2347 */
2348 if (wpa_supplicant_parse_ies(pos, ielen, &kde) < 0)
2349 wpa_printf(MSG_DEBUG,
2350 "TDLS: Failed to parse IEs in TPK M2 - ignore as an interop workaround");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002351
2352#ifdef CONFIG_TDLS_TESTING
2353 if (tdls_testing & TDLS_TESTING_DECLINE_RESP) {
2354 wpa_printf(MSG_DEBUG, "TDLS: Testing - decline response");
2355 status = WLAN_STATUS_REQUEST_DECLINED;
2356 goto error;
2357 }
2358#endif /* CONFIG_TDLS_TESTING */
2359
2360 if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) {
2361 wpa_printf(MSG_INFO, "TDLS: No valid Link Identifier IE in "
2362 "TPK M2");
2363 goto error;
2364 }
2365 wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M2",
2366 kde.lnkid, kde.lnkid_len);
2367 lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
2368
2369 if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) {
2370 wpa_printf(MSG_INFO, "TDLS: TPK M2 from different BSS");
2371 status = WLAN_STATUS_NOT_IN_SAME_BSS;
2372 goto error;
2373 }
2374
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002375 if (copy_supp_rates(&kde, peer) < 0)
2376 goto error;
2377
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002378 if (copy_peer_ht_capab(&kde, peer) < 0)
2379 goto error;
2380
Hai Shaloma20dcd72022-02-04 13:43:00 -08002381 if (copy_peer_vht_capab(&kde, peer) < 0 ||
2382 copy_peer_he_capab(&kde, peer) < 0 ||
2383 copy_peer_he_6ghz_band_capab(&kde, peer) < 0)
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -08002384 goto error;
2385
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002386 if (copy_peer_ext_capab(&kde, peer) < 0)
2387 goto error;
2388
Dmitry Shmidt344abd32014-01-14 13:17:00 -08002389 if (copy_peer_supp_channels(&kde, peer) < 0)
2390 goto error;
2391
2392 if (copy_peer_supp_oper_classes(&kde, peer) < 0)
2393 goto error;
2394
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002395 peer->qos_info = kde.qosinfo;
2396
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002397 /* Overwrite with the qos_info obtained in WMM IE */
2398 if (copy_peer_wmm_capab(&kde, peer) < 0)
2399 goto error;
2400
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002401 peer->aid = kde.aid;
2402
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002403 if (!wpa_tdls_get_privacy(sm)) {
2404 peer->rsnie_p_len = 0;
2405 peer->cipher = WPA_CIPHER_NONE;
2406 goto skip_rsn;
2407 }
2408
2409 if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie) ||
2410 kde.rsn_ie == NULL) {
2411 wpa_printf(MSG_INFO, "TDLS: No FTIE or RSN IE in TPK M2");
2412 status = WLAN_STATUS_INVALID_PARAMETERS;
2413 goto error;
2414 }
2415 wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M2",
2416 kde.rsn_ie, kde.rsn_ie_len);
2417
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002418 if (kde.rsn_ie_len > TDLS_MAX_IE_LEN) {
2419 wpa_printf(MSG_INFO,
2420 "TDLS: Too long Responder RSN IE in TPK M2");
2421 status = WLAN_STATUS_INVALID_RSNIE;
2422 goto error;
2423 }
2424
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002425 /*
2426 * FIX: bitwise comparison of RSN IE is not the correct way of
2427 * validation this. It can be different, but certain fields must
2428 * match. Since we list only a single pairwise cipher in TPK M1, the
2429 * memcmp is likely to work in most cases, though.
2430 */
2431 if (kde.rsn_ie_len != peer->rsnie_i_len ||
2432 os_memcmp(peer->rsnie_i, kde.rsn_ie, peer->rsnie_i_len) != 0) {
2433 wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M2 does "
2434 "not match with RSN IE used in TPK M1");
2435 wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Sent in TPK M1",
2436 peer->rsnie_i, peer->rsnie_i_len);
2437 wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M2",
2438 kde.rsn_ie, kde.rsn_ie_len);
2439 status = WLAN_STATUS_INVALID_RSNIE;
2440 goto error;
2441 }
2442
2443 if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) {
2444 wpa_printf(MSG_INFO, "TDLS: Failed to parse RSN IE in TPK M2");
2445 status = WLAN_STATUS_INVALID_RSNIE;
2446 goto error;
2447 }
2448
2449 cipher = ie.pairwise_cipher;
2450 if (cipher == WPA_CIPHER_CCMP) {
2451 wpa_printf(MSG_DEBUG, "TDLS: Using CCMP for direct link");
2452 cipher = WPA_CIPHER_CCMP;
2453 } else {
2454 wpa_printf(MSG_INFO, "TDLS: No acceptable cipher in TPK M2");
2455 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
2456 goto error;
2457 }
2458
2459 wpa_hexdump(MSG_DEBUG, "TDLS: FTIE Received from TPK M2",
2460 kde.ftie, sizeof(*ftie));
2461 ftie = (struct wpa_tdls_ftie *) kde.ftie;
2462
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002463 if (os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002464 wpa_printf(MSG_INFO, "TDLS: FTIE SNonce in TPK M2 does "
2465 "not match with FTIE SNonce used in TPK M1");
2466 /* Silently discard the frame */
2467 return -1;
2468 }
2469
2470 /* Responder Nonce and RSN IE */
2471 os_memcpy(peer->rnonce, ftie->Anonce, WPA_NONCE_LEN);
2472 os_memcpy(peer->rsnie_p, kde.rsn_ie, kde.rsn_ie_len);
2473 peer->rsnie_p_len = kde.rsn_ie_len;
2474 peer->cipher = cipher;
2475
2476 /* Lifetime */
2477 if (kde.key_lifetime == NULL) {
2478 wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M2");
2479 status = WLAN_STATUS_UNACCEPTABLE_LIFETIME;
2480 goto error;
2481 }
2482 timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime;
2483 lifetime = WPA_GET_LE32(timeoutie->value);
2484 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds in TPK M2",
2485 lifetime);
2486 if (lifetime != peer->lifetime) {
2487 wpa_printf(MSG_INFO, "TDLS: Unexpected TPK lifetime %u in "
2488 "TPK M2 (expected %u)", lifetime, peer->lifetime);
2489 status = WLAN_STATUS_UNACCEPTABLE_LIFETIME;
2490 goto error;
2491 }
2492
2493 wpa_tdls_generate_tpk(peer, sm->own_addr, sm->bssid);
2494
2495 /* Process MIC check to see if TPK M2 is right */
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002496 if (wpa_supplicant_verify_tdls_mic(2, peer, (const u8 *) lnkid,
2497 (const u8 *) timeoutie, ftie,
2498 kde.ftie_len) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002499 /* Discard the frame */
2500 wpa_tdls_del_key(sm, peer);
Sunil Dutt38ffd882013-09-30 17:23:23 +03002501 wpa_tdls_disable_peer_link(sm, peer);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002502 return -1;
2503 }
2504
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002505 if (wpa_tdls_set_key(sm, peer) < 0) {
2506 /*
2507 * Some drivers may not be able to config the key prior to full
2508 * STA entry having been configured.
2509 */
2510 wpa_printf(MSG_DEBUG, "TDLS: Try to configure TPK again after "
2511 "STA entry is complete");
2512 peer->reconfig_key = 1;
2513 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002514
2515skip_rsn:
2516 peer->dtoken = dtoken;
2517
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002518 /* add supported rates, capabilities, and qos_info to the TDLS peer */
2519 if (wpa_tdls_addset_peer(sm, peer, 0) < 0)
2520 goto error;
2521
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002522 wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Confirm / "
2523 "TPK Handshake Message 3");
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002524 if (wpa_tdls_send_tpk_m3(sm, src_addr, dtoken, lnkid, peer) < 0)
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002525 goto error_no_msg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002526
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002527 if (!peer->tpk_success) {
2528 /*
2529 * Enable Link only when tpk_success is 0, signifying that this
2530 * processing of TPK M2 frame is not because of a retransmission
2531 * during TDLS setup handshake.
2532 */
2533 ret = wpa_tdls_enable_link(sm, peer);
2534 if (ret < 0) {
2535 wpa_printf(MSG_DEBUG, "TDLS: Could not enable link");
2536 wpa_tdls_do_teardown(
2537 sm, peer,
2538 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
2539 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002540 }
2541 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002542
2543error:
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002544 wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, dtoken, 1,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002545 status);
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08002546error_no_msg:
Sunil Duttd0ef38b2013-09-30 17:34:13 +03002547 wpa_tdls_disable_peer_link(sm, peer);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002548 return -1;
2549}
2550
2551
2552static int wpa_tdls_process_tpk_m3(struct wpa_sm *sm, const u8 *src_addr,
2553 const u8 *buf, size_t len)
2554{
2555 struct wpa_tdls_peer *peer;
2556 struct wpa_eapol_ie_parse kde;
2557 struct wpa_tdls_ftie *ftie;
2558 struct wpa_tdls_timeoutie *timeoutie;
2559 struct wpa_tdls_lnkid *lnkid;
2560 int ielen;
2561 u16 status;
2562 const u8 *pos;
2563 u32 lifetime;
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002564 int ret = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002565
2566 wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Confirm / TPK M3 "
2567 "(Peer " MACSTR ")", MAC2STR(src_addr));
2568 for (peer = sm->tdls; peer; peer = peer->next) {
2569 if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0)
2570 break;
2571 }
2572 if (peer == NULL) {
2573 wpa_printf(MSG_INFO, "TDLS: No matching peer found for "
2574 "TPK M3: " MACSTR, MAC2STR(src_addr));
2575 return -1;
2576 }
2577 wpa_tdls_tpk_retry_timeout_cancel(sm, peer, WLAN_TDLS_SETUP_RESPONSE);
2578
2579 if (len < 3 + 3)
Sunil Duttadce9cf2013-09-15 11:51:00 -07002580 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002581 pos = buf;
2582 pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */;
2583
2584 status = WPA_GET_LE16(pos);
2585
2586 if (status != 0) {
2587 wpa_printf(MSG_INFO, "TDLS: Status code in TPK M3: %u",
2588 status);
Sunil Duttadce9cf2013-09-15 11:51:00 -07002589 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002590 }
2591 pos += 2 /* status code */ + 1 /* dialog token */;
2592
2593 ielen = len - (pos - buf); /* start of IE in buf */
Dmitry Shmidt0c08fdc2014-06-20 10:16:40 -07002594
2595 /*
2596 * Don't reject the message if failing to parse IEs. The IEs we need are
2597 * explicitly checked below. Some APs piggy-back broken IEs to the end
2598 * of a TDLS Confirm packet, which will fail the link if we don't ignore
2599 * this error.
2600 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002601 if (wpa_supplicant_parse_ies((const u8 *) pos, ielen, &kde) < 0) {
Dmitry Shmidt0c08fdc2014-06-20 10:16:40 -07002602 wpa_printf(MSG_DEBUG,
2603 "TDLS: Failed to parse KDEs in TPK M3 - ignore as an interop workaround");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002604 }
2605
2606 if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) {
2607 wpa_printf(MSG_INFO, "TDLS: No Link Identifier IE in TPK M3");
Sunil Duttadce9cf2013-09-15 11:51:00 -07002608 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002609 }
2610 wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M3",
2611 (u8 *) kde.lnkid, kde.lnkid_len);
2612 lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
2613
2614 if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) {
2615 wpa_printf(MSG_INFO, "TDLS: TPK M3 from diff BSS");
Sunil Duttadce9cf2013-09-15 11:51:00 -07002616 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002617 }
2618
2619 if (!wpa_tdls_get_privacy(sm))
2620 goto skip_rsn;
2621
2622 if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie)) {
2623 wpa_printf(MSG_INFO, "TDLS: No FTIE in TPK M3");
Sunil Duttadce9cf2013-09-15 11:51:00 -07002624 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002625 }
2626 wpa_hexdump(MSG_DEBUG, "TDLS: FTIE Received from TPK M3",
2627 kde.ftie, sizeof(*ftie));
2628 ftie = (struct wpa_tdls_ftie *) kde.ftie;
2629
2630 if (kde.rsn_ie == NULL) {
2631 wpa_printf(MSG_INFO, "TDLS: No RSN IE in TPK M3");
Sunil Duttadce9cf2013-09-15 11:51:00 -07002632 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002633 }
2634 wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M3",
2635 kde.rsn_ie, kde.rsn_ie_len);
2636 if (kde.rsn_ie_len != peer->rsnie_p_len ||
2637 os_memcmp(kde.rsn_ie, peer->rsnie_p, peer->rsnie_p_len) != 0) {
2638 wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M3 does not match "
2639 "with the one sent in TPK M2");
Sunil Duttadce9cf2013-09-15 11:51:00 -07002640 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002641 }
2642
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002643 if (os_memcmp(peer->rnonce, ftie->Anonce, WPA_NONCE_LEN) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002644 wpa_printf(MSG_INFO, "TDLS: FTIE ANonce in TPK M3 does "
2645 "not match with FTIE ANonce used in TPK M2");
Sunil Duttadce9cf2013-09-15 11:51:00 -07002646 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002647 }
2648
Dmitry Shmidt57c2d392016-02-23 13:40:19 -08002649 if (os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002650 wpa_printf(MSG_INFO, "TDLS: FTIE SNonce in TPK M3 does not "
2651 "match with FTIE SNonce used in TPK M1");
Sunil Duttadce9cf2013-09-15 11:51:00 -07002652 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002653 }
2654
2655 if (kde.key_lifetime == NULL) {
2656 wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M3");
Sunil Duttadce9cf2013-09-15 11:51:00 -07002657 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002658 }
2659 timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime;
2660 wpa_hexdump(MSG_DEBUG, "TDLS: Timeout IE Received from TPK M3",
2661 (u8 *) timeoutie, sizeof(*timeoutie));
2662 lifetime = WPA_GET_LE32(timeoutie->value);
2663 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds in TPK M3",
2664 lifetime);
2665 if (lifetime != peer->lifetime) {
2666 wpa_printf(MSG_INFO, "TDLS: Unexpected TPK lifetime %u in "
2667 "TPK M3 (expected %u)", lifetime, peer->lifetime);
Sunil Duttadce9cf2013-09-15 11:51:00 -07002668 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002669 }
2670
Sunil Ravi38ad1ed2023-01-17 23:58:31 +00002671 if (wpa_supplicant_verify_tdls_mic(3, peer, (const u8 *) lnkid,
2672 (const u8 *) timeoutie, ftie,
2673 kde.ftie_len) < 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002674 wpa_tdls_del_key(sm, peer);
Sunil Duttadce9cf2013-09-15 11:51:00 -07002675 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002676 }
2677
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002678 if (wpa_tdls_set_key(sm, peer) < 0) {
2679 /*
2680 * Some drivers may not be able to config the key prior to full
2681 * STA entry having been configured.
2682 */
2683 wpa_printf(MSG_DEBUG, "TDLS: Try to configure TPK again after "
2684 "STA entry is complete");
2685 peer->reconfig_key = 1;
2686 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002687
2688skip_rsn:
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002689 /* add supported rates, capabilities, and qos_info to the TDLS peer */
2690 if (wpa_tdls_addset_peer(sm, peer, 0) < 0)
2691 goto error;
2692
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002693 if (!peer->tpk_success) {
2694 /*
2695 * Enable Link only when tpk_success is 0, signifying that this
2696 * processing of TPK M3 frame is not because of a retransmission
2697 * during TDLS setup handshake.
2698 */
2699 ret = wpa_tdls_enable_link(sm, peer);
2700 if (ret < 0) {
2701 wpa_printf(MSG_DEBUG, "TDLS: Could not enable link");
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002702 goto error;
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002703 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002704 }
2705 return ret;
Sunil Duttadce9cf2013-09-15 11:51:00 -07002706error:
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002707 wpa_tdls_do_teardown(sm, peer, WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
Sunil Duttadce9cf2013-09-15 11:51:00 -07002708 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002709}
2710
2711
2712static u8 * wpa_add_tdls_timeoutie(u8 *pos, u8 *ie, size_t ie_len, u32 tsecs)
2713{
2714 struct wpa_tdls_timeoutie *lifetime = (struct wpa_tdls_timeoutie *) ie;
2715
2716 os_memset(lifetime, 0, ie_len);
2717 lifetime->ie_type = WLAN_EID_TIMEOUT_INTERVAL;
2718 lifetime->ie_len = sizeof(struct wpa_tdls_timeoutie) - 2;
2719 lifetime->interval_type = WLAN_TIMEOUT_KEY_LIFETIME;
2720 WPA_PUT_LE32(lifetime->value, tsecs);
2721 os_memcpy(pos, ie, ie_len);
2722 return pos + ie_len;
2723}
2724
2725
2726/**
2727 * wpa_tdls_start - Initiate TDLS handshake (send TPK Handshake Message 1)
2728 * @sm: Pointer to WPA state machine data from wpa_sm_init()
2729 * @peer: MAC address of the peer STA
2730 * Returns: 0 on success, or -1 on failure
2731 *
2732 * Send TPK Handshake Message 1 info to driver to start TDLS
2733 * handshake with the peer.
2734 */
2735int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr)
2736{
2737 struct wpa_tdls_peer *peer;
2738 int tdls_prohibited = sm->tdls_prohibited;
Hai Shalom60840252021-02-19 19:02:11 -08002739 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002740
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002741 if (sm->tdls_disabled || !sm->tdls_supported)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002742 return -1;
2743
2744#ifdef CONFIG_TDLS_TESTING
2745 if ((tdls_testing & TDLS_TESTING_IGNORE_AP_PROHIBIT) &&
2746 tdls_prohibited) {
2747 wpa_printf(MSG_DEBUG, "TDLS: Testing - ignore AP prohibition "
2748 "on TDLS");
2749 tdls_prohibited = 0;
2750 }
2751#endif /* CONFIG_TDLS_TESTING */
2752
2753 if (tdls_prohibited) {
2754 wpa_printf(MSG_DEBUG, "TDLS: TDLS is prohibited in this BSS - "
2755 "reject request to start setup");
2756 return -1;
2757 }
2758
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002759 peer = wpa_tdls_add_peer(sm, addr, NULL);
2760 if (peer == NULL)
2761 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002762
Sunil Dutt73b28cc2013-09-30 17:38:41 +03002763 if (peer->tpk_in_progress) {
2764 wpa_printf(MSG_DEBUG, "TDLS: Setup is already in progress with the peer");
2765 return 0;
2766 }
2767
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002768 peer->initiator = 1;
2769
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002770 /* add the peer to the driver as a "setup in progress" peer */
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002771 if (wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002772 NULL, NULL, 0, NULL, 0, 0, NULL, 0, NULL, 0,
2773 NULL, 0)) {
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002774 wpa_tdls_disable_peer_link(sm, peer);
2775 return -1;
2776 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002777
Sunil Dutt73b28cc2013-09-30 17:38:41 +03002778 peer->tpk_in_progress = 1;
2779
Hai Shalom60840252021-02-19 19:02:11 -08002780 res = wpa_tdls_send_tpk_m1(sm, peer);
2781 if (res < 0) {
2782 if (res != -2)
2783 wpa_tdls_disable_peer_link(sm, peer);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002784 return -1;
2785 }
2786
2787 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002788}
2789
2790
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002791void wpa_tdls_remove(struct wpa_sm *sm, const u8 *addr)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002792{
2793 struct wpa_tdls_peer *peer;
2794
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002795 if (sm->tdls_disabled || !sm->tdls_supported)
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002796 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002797
2798 for (peer = sm->tdls; peer; peer = peer->next) {
2799 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
2800 break;
2801 }
2802
2803 if (peer == NULL || !peer->tpk_success)
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002804 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002805
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002806 if (sm->tdls_external_setup) {
2807 /*
2808 * Disable previous link to allow renegotiation to be completed
2809 * on AP path.
2810 */
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07002811 wpa_tdls_do_teardown(sm, peer,
2812 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002813 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002814}
2815
2816
2817/**
2818 * wpa_supplicant_rx_tdls - Receive TDLS data frame
2819 *
2820 * This function is called to receive TDLS (ethertype = 0x890d) data frames.
2821 */
2822static void wpa_supplicant_rx_tdls(void *ctx, const u8 *src_addr,
2823 const u8 *buf, size_t len)
2824{
2825 struct wpa_sm *sm = ctx;
2826 struct wpa_tdls_frame *tf;
2827
2828 wpa_hexdump(MSG_DEBUG, "TDLS: Received Data frame encapsulation",
2829 buf, len);
2830
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002831 if (sm->tdls_disabled || !sm->tdls_supported) {
2832 wpa_printf(MSG_DEBUG, "TDLS: Discard message - TDLS disabled "
2833 "or unsupported by driver");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002834 return;
2835 }
2836
2837 if (os_memcmp(src_addr, sm->own_addr, ETH_ALEN) == 0) {
2838 wpa_printf(MSG_DEBUG, "TDLS: Discard copy of own message");
2839 return;
2840 }
2841
2842 if (len < sizeof(*tf)) {
2843 wpa_printf(MSG_INFO, "TDLS: Drop too short frame");
2844 return;
2845 }
2846
2847 /* Check to make sure its a valid encapsulated TDLS frame */
2848 tf = (struct wpa_tdls_frame *) buf;
2849 if (tf->payloadtype != 2 /* TDLS_RFTYPE */ ||
2850 tf->category != WLAN_ACTION_TDLS) {
2851 wpa_printf(MSG_INFO, "TDLS: Invalid frame - payloadtype=%u "
2852 "category=%u action=%u",
2853 tf->payloadtype, tf->category, tf->action);
2854 return;
2855 }
2856
2857 switch (tf->action) {
2858 case WLAN_TDLS_SETUP_REQUEST:
2859 wpa_tdls_process_tpk_m1(sm, src_addr, buf, len);
2860 break;
2861 case WLAN_TDLS_SETUP_RESPONSE:
2862 wpa_tdls_process_tpk_m2(sm, src_addr, buf, len);
2863 break;
2864 case WLAN_TDLS_SETUP_CONFIRM:
2865 wpa_tdls_process_tpk_m3(sm, src_addr, buf, len);
2866 break;
2867 case WLAN_TDLS_TEARDOWN:
2868 wpa_tdls_recv_teardown(sm, src_addr, buf, len);
2869 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002870 case WLAN_TDLS_DISCOVERY_REQUEST:
2871 wpa_tdls_process_discovery_request(sm, src_addr, buf, len);
2872 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002873 default:
2874 /* Kernel code will process remaining frames */
2875 wpa_printf(MSG_DEBUG, "TDLS: Ignore TDLS frame action code %u",
2876 tf->action);
2877 break;
2878 }
2879}
2880
2881
2882/**
2883 * wpa_tdls_init - Initialize driver interface parameters for TDLS
2884 * @wpa_s: Pointer to wpa_supplicant data
2885 * Returns: 0 on success, -1 on failure
2886 *
2887 * This function is called to initialize driver interface parameters for TDLS.
2888 * wpa_drv_init() must have been called before this function to initialize the
2889 * driver interface.
2890 */
2891int wpa_tdls_init(struct wpa_sm *sm)
2892{
2893 if (sm == NULL)
2894 return -1;
2895
Hai Shalom899fcc72020-10-19 14:38:18 -07002896 if (sm->l2_tdls) {
2897 l2_packet_deinit(sm->l2_tdls);
2898 sm->l2_tdls = NULL;
2899 }
2900
Dmitry Shmidt04949592012-07-19 12:16:46 -07002901 sm->l2_tdls = l2_packet_init(sm->bridge_ifname ? sm->bridge_ifname :
2902 sm->ifname,
2903 sm->own_addr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002904 ETH_P_80211_ENCAP, wpa_supplicant_rx_tdls,
2905 sm, 0);
2906 if (sm->l2_tdls == NULL) {
2907 wpa_printf(MSG_ERROR, "TDLS: Failed to open l2_packet "
2908 "connection");
2909 return -1;
2910 }
2911
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002912 /*
2913 * Drivers that support TDLS but don't implement the get_capa callback
2914 * are assumed to perform everything internally
2915 */
2916 if (wpa_sm_tdls_get_capa(sm, &sm->tdls_supported,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002917 &sm->tdls_external_setup,
2918 &sm->tdls_chan_switch) < 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002919 sm->tdls_supported = 1;
2920 sm->tdls_external_setup = 0;
2921 }
2922
2923 wpa_printf(MSG_DEBUG, "TDLS: TDLS operation%s supported by "
2924 "driver", sm->tdls_supported ? "" : " not");
2925 wpa_printf(MSG_DEBUG, "TDLS: Driver uses %s link setup",
2926 sm->tdls_external_setup ? "external" : "internal");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002927 wpa_printf(MSG_DEBUG, "TDLS: Driver %s TDLS channel switching",
2928 sm->tdls_chan_switch ? "supports" : "does not support");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002929
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002930 return 0;
2931}
2932
2933
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002934void wpa_tdls_teardown_peers(struct wpa_sm *sm)
2935{
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002936 struct wpa_tdls_peer *peer, *tmp;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002937
Dmitry Shmidtff787d52015-01-12 13:01:47 -08002938 if (!sm)
2939 return;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002940 peer = sm->tdls;
2941
2942 wpa_printf(MSG_DEBUG, "TDLS: Tear down peers");
2943
2944 while (peer) {
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002945 tmp = peer->next;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002946 wpa_printf(MSG_DEBUG, "TDLS: Tear down peer " MACSTR,
2947 MAC2STR(peer->addr));
2948 if (sm->tdls_external_setup)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07002949 wpa_tdls_do_teardown(sm, peer,
2950 WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002951 else
2952 wpa_sm_tdls_oper(sm, TDLS_TEARDOWN, peer->addr);
2953
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002954 peer = tmp;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002955 }
2956}
2957
2958
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002959static void wpa_tdls_remove_peers(struct wpa_sm *sm)
2960{
2961 struct wpa_tdls_peer *peer, *tmp;
2962
2963 peer = sm->tdls;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002964
2965 while (peer) {
2966 int res;
2967 tmp = peer->next;
2968 res = wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr);
2969 wpa_printf(MSG_DEBUG, "TDLS: Remove peer " MACSTR " (res=%d)",
2970 MAC2STR(peer->addr), res);
2971 wpa_tdls_peer_free(sm, peer);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002972 peer = tmp;
2973 }
2974}
2975
2976
2977/**
2978 * wpa_tdls_deinit - Deinitialize driver interface parameters for TDLS
2979 *
2980 * This function is called to recover driver interface parameters for TDLS
2981 * and frees resources allocated for it.
2982 */
2983void wpa_tdls_deinit(struct wpa_sm *sm)
2984{
2985 if (sm == NULL)
2986 return;
2987
2988 if (sm->l2_tdls)
2989 l2_packet_deinit(sm->l2_tdls);
2990 sm->l2_tdls = NULL;
2991
2992 wpa_tdls_remove_peers(sm);
2993}
2994
2995
2996void wpa_tdls_assoc(struct wpa_sm *sm)
2997{
2998 wpa_printf(MSG_DEBUG, "TDLS: Remove peers on association");
2999 wpa_tdls_remove_peers(sm);
3000}
3001
3002
3003void wpa_tdls_disassoc(struct wpa_sm *sm)
3004{
3005 wpa_printf(MSG_DEBUG, "TDLS: Remove peers on disassociation");
3006 wpa_tdls_remove_peers(sm);
3007}
3008
3009
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003010static int wpa_tdls_prohibited(struct ieee802_11_elems *elems)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003011{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003012 /* bit 38 - TDLS Prohibited */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003013 return !!(elems->ext_capab[4] & 0x40);
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003014}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003015
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003016
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003017static int wpa_tdls_chan_switch_prohibited(struct ieee802_11_elems *elems)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003018{
3019 /* bit 39 - TDLS Channel Switch Prohibited */
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003020 return !!(elems->ext_capab[4] & 0x80);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003021}
3022
3023
3024void wpa_tdls_ap_ies(struct wpa_sm *sm, const u8 *ies, size_t len)
3025{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003026 struct ieee802_11_elems elems;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003027
3028 sm->tdls_prohibited = 0;
3029 sm->tdls_chan_switch_prohibited = 0;
3030
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003031 if (ies == NULL ||
3032 ieee802_11_parse_elems(ies, len, &elems, 0) == ParseFailed ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003033 elems.ext_capab == NULL || elems.ext_capab_len < 5)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003034 return;
3035
3036 sm->tdls_prohibited = wpa_tdls_prohibited(&elems);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003037 wpa_printf(MSG_DEBUG, "TDLS: TDLS is %s in the target BSS",
3038 sm->tdls_prohibited ? "prohibited" : "allowed");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003039 sm->tdls_chan_switch_prohibited =
3040 wpa_tdls_chan_switch_prohibited(&elems);
3041 wpa_printf(MSG_DEBUG, "TDLS: TDLS channel switch %s in the target BSS",
3042 sm->tdls_chan_switch_prohibited ? "prohibited" : "allowed");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003043}
3044
3045
3046void wpa_tdls_assoc_resp_ies(struct wpa_sm *sm, const u8 *ies, size_t len)
3047{
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003048 struct ieee802_11_elems elems;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003049
Dmitry Shmidtd80a4012015-11-05 16:35:40 -08003050 if (ies == NULL ||
3051 ieee802_11_parse_elems(ies, len, &elems, 0) == ParseFailed ||
Dmitry Shmidt9839ecd2016-11-07 11:05:47 -08003052 elems.ext_capab == NULL || elems.ext_capab_len < 5)
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003053 return;
3054
3055 if (!sm->tdls_prohibited && wpa_tdls_prohibited(&elems)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003056 wpa_printf(MSG_DEBUG, "TDLS: TDLS prohibited based on "
3057 "(Re)Association Response IEs");
3058 sm->tdls_prohibited = 1;
3059 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003060
3061 if (!sm->tdls_chan_switch_prohibited &&
3062 wpa_tdls_chan_switch_prohibited(&elems)) {
3063 wpa_printf(MSG_DEBUG,
3064 "TDLS: TDLS channel switch prohibited based on (Re)Association Response IEs");
3065 sm->tdls_chan_switch_prohibited = 1;
3066 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003067}
3068
3069
3070void wpa_tdls_enable(struct wpa_sm *sm, int enabled)
3071{
3072 wpa_printf(MSG_DEBUG, "TDLS: %s", enabled ? "enabled" : "disabled");
3073 sm->tdls_disabled = !enabled;
3074}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003075
3076
3077int wpa_tdls_is_external_setup(struct wpa_sm *sm)
3078{
3079 return sm->tdls_external_setup;
3080}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08003081
3082
3083int wpa_tdls_enable_chan_switch(struct wpa_sm *sm, const u8 *addr,
3084 u8 oper_class,
3085 struct hostapd_freq_params *freq_params)
3086{
3087 struct wpa_tdls_peer *peer;
3088 int ret;
3089
3090 if (sm->tdls_disabled || !sm->tdls_supported)
3091 return -1;
3092
3093 if (!sm->tdls_chan_switch) {
3094 wpa_printf(MSG_DEBUG,
3095 "TDLS: Channel switching not supported by the driver");
3096 return -1;
3097 }
3098
3099 if (sm->tdls_chan_switch_prohibited) {
3100 wpa_printf(MSG_DEBUG,
3101 "TDLS: Channel switching is prohibited in this BSS - reject request to switch channel");
3102 return -1;
3103 }
3104
3105 for (peer = sm->tdls; peer; peer = peer->next) {
3106 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
3107 break;
3108 }
3109
3110 if (peer == NULL || !peer->tpk_success) {
3111 wpa_printf(MSG_ERROR, "TDLS: Peer " MACSTR
3112 " not found for channel switching", MAC2STR(addr));
3113 return -1;
3114 }
3115
3116 if (peer->chan_switch_enabled) {
3117 wpa_printf(MSG_DEBUG, "TDLS: Peer " MACSTR
3118 " already has channel switching enabled",
3119 MAC2STR(addr));
3120 return 0;
3121 }
3122
3123 ret = wpa_sm_tdls_enable_channel_switch(sm, peer->addr,
3124 oper_class, freq_params);
3125 if (!ret)
3126 peer->chan_switch_enabled = 1;
3127
3128 return ret;
3129}
3130
3131
3132int wpa_tdls_disable_chan_switch(struct wpa_sm *sm, const u8 *addr)
3133{
3134 struct wpa_tdls_peer *peer;
3135
3136 if (sm->tdls_disabled || !sm->tdls_supported)
3137 return -1;
3138
3139 for (peer = sm->tdls; peer; peer = peer->next) {
3140 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
3141 break;
3142 }
3143
3144 if (!peer || !peer->chan_switch_enabled) {
3145 wpa_printf(MSG_ERROR, "TDLS: Channel switching not enabled for "
3146 MACSTR, MAC2STR(addr));
3147 return -1;
3148 }
3149
3150 /* ignore the return value */
3151 wpa_sm_tdls_disable_channel_switch(sm, peer->addr);
3152
3153 peer->chan_switch_enabled = 0;
3154 return 0;
3155}