blob: e814b45468ca575da30cb20c988a6792d87cb2ce [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"
15#include "crypto/sha256.h"
16#include "crypto/crypto.h"
17#include "crypto/aes_wrap.h"
18#include "rsn_supp/wpa.h"
19#include "rsn_supp/wpa_ie.h"
20#include "rsn_supp/wpa_i.h"
21#include "drivers/driver.h"
22#include "l2_packet/l2_packet.h"
23
24#ifdef CONFIG_TDLS_TESTING
25#define TDLS_TESTING_LONG_FRAME BIT(0)
26#define TDLS_TESTING_ALT_RSN_IE BIT(1)
27#define TDLS_TESTING_DIFF_BSSID BIT(2)
28#define TDLS_TESTING_SHORT_LIFETIME BIT(3)
29#define TDLS_TESTING_WRONG_LIFETIME_RESP BIT(4)
30#define TDLS_TESTING_WRONG_LIFETIME_CONF BIT(5)
31#define TDLS_TESTING_LONG_LIFETIME BIT(6)
32#define TDLS_TESTING_CONCURRENT_INIT BIT(7)
33#define TDLS_TESTING_NO_TPK_EXPIRATION BIT(8)
34#define TDLS_TESTING_DECLINE_RESP BIT(9)
35#define TDLS_TESTING_IGNORE_AP_PROHIBIT BIT(10)
Dmitry Shmidt21de2142014-04-08 10:50:52 -070036#define TDLS_TESTING_WRONG_MIC BIT(11)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070037unsigned int tdls_testing = 0;
38#endif /* CONFIG_TDLS_TESTING */
39
40#define TPK_LIFETIME 43200 /* 12 hours */
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -070041#define TPK_M1_RETRY_COUNT 3
42#define TPK_M1_TIMEOUT 5000 /* in milliseconds */
43#define TPK_M2_RETRY_COUNT 10
44#define TPK_M2_TIMEOUT 500 /* in milliseconds */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070045
46#define TDLS_MIC_LEN 16
47
48#define TDLS_TIMEOUT_LEN 4
49
50struct wpa_tdls_ftie {
51 u8 ie_type; /* FTIE */
52 u8 ie_len;
53 u8 mic_ctrl[2];
54 u8 mic[TDLS_MIC_LEN];
55 u8 Anonce[WPA_NONCE_LEN]; /* Responder Nonce in TDLS */
56 u8 Snonce[WPA_NONCE_LEN]; /* Initiator Nonce in TDLS */
57 /* followed by optional elements */
58} STRUCT_PACKED;
59
60struct wpa_tdls_timeoutie {
61 u8 ie_type; /* Timeout IE */
62 u8 ie_len;
63 u8 interval_type;
64 u8 value[TDLS_TIMEOUT_LEN];
65} STRUCT_PACKED;
66
67struct wpa_tdls_lnkid {
68 u8 ie_type; /* Link Identifier IE */
69 u8 ie_len;
70 u8 bssid[ETH_ALEN];
71 u8 init_sta[ETH_ALEN];
72 u8 resp_sta[ETH_ALEN];
73} STRUCT_PACKED;
74
75/* TDLS frame headers as per IEEE Std 802.11z-2010 */
76struct wpa_tdls_frame {
77 u8 payloadtype; /* IEEE80211_TDLS_RFTYPE */
78 u8 category; /* Category */
79 u8 action; /* Action (enum tdls_frame_type) */
80} STRUCT_PACKED;
81
82static u8 * wpa_add_tdls_timeoutie(u8 *pos, u8 *ie, size_t ie_len, u32 tsecs);
83static void wpa_tdls_tpk_retry_timeout(void *eloop_ctx, void *timeout_ctx);
84static void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer);
Sunil Duttd0ef38b2013-09-30 17:34:13 +030085static void wpa_tdls_disable_peer_link(struct wpa_sm *sm,
86 struct wpa_tdls_peer *peer);
Dmitry Shmidtb58836e2014-04-29 14:35:56 -070087static int wpa_tdls_send_teardown(struct wpa_sm *sm, const u8 *addr,
88 u16 reason_code);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070089
90
91#define TDLS_MAX_IE_LEN 80
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080092#define IEEE80211_MAX_SUPP_RATES 32
93
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070094struct wpa_tdls_peer {
95 struct wpa_tdls_peer *next;
Dmitry Shmidt8da800a2013-04-24 12:57:01 -070096 unsigned int reconfig_key:1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070097 int initiator; /* whether this end was initiator for TDLS setup */
98 u8 addr[ETH_ALEN]; /* other end MAC address */
99 u8 inonce[WPA_NONCE_LEN]; /* Initiator Nonce */
100 u8 rnonce[WPA_NONCE_LEN]; /* Responder Nonce */
101 u8 rsnie_i[TDLS_MAX_IE_LEN]; /* Initiator RSN IE */
102 size_t rsnie_i_len;
103 u8 rsnie_p[TDLS_MAX_IE_LEN]; /* Peer RSN IE */
104 size_t rsnie_p_len;
105 u32 lifetime;
106 int cipher; /* Selected cipher (WPA_CIPHER_*) */
107 u8 dtoken;
108
109 struct tpk {
110 u8 kck[16]; /* TPK-KCK */
111 u8 tk[16]; /* TPK-TK; assuming only CCMP will be used */
112 } tpk;
113 int tpk_set;
Jouni Malinen4c527402017-09-22 11:03:15 +0300114 int tk_set; /* TPK-TK configured to the driver */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700115 int tpk_success;
Sunil Dutt73b28cc2013-09-30 17:38:41 +0300116 int tpk_in_progress;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700117
118 struct tpk_timer {
119 u8 dest[ETH_ALEN];
120 int count; /* Retry Count */
121 int timer; /* Timeout in milliseconds */
122 u8 action_code; /* TDLS frame type */
123 u8 dialog_token;
124 u16 status_code;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -0700125 u32 peer_capab;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700126 int buf_len; /* length of TPK message for retransmission */
127 u8 *buf; /* buffer for TPK message */
128 } sm_tmr;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800129
130 u16 capability;
131
132 u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
133 size_t supp_rates_len;
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800134
135 struct ieee80211_ht_capabilities *ht_capabilities;
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -0800136 struct ieee80211_vht_capabilities *vht_capabilities;
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800137
138 u8 qos_info;
139
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700140 u16 aid;
141
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800142 u8 *ext_capab;
143 size_t ext_capab_len;
Dmitry Shmidt344abd32014-01-14 13:17:00 -0800144
145 u8 *supp_channels;
146 size_t supp_channels_len;
147
148 u8 *supp_oper_classes;
149 size_t supp_oper_classes_len;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -0700150
151 u8 wmm_capable;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700152};
153
154
155static int wpa_tdls_get_privacy(struct wpa_sm *sm)
156{
157 /*
158 * Get info needed from supplicant to check if the current BSS supports
159 * security. Other than OPEN mode, rest are considered secured
160 * WEP/WPA/WPA2 hence TDLS frames are processed for TPK handshake.
161 */
162 return sm->pairwise_cipher != WPA_CIPHER_NONE;
163}
164
165
166static u8 * wpa_add_ie(u8 *pos, const u8 *ie, size_t ie_len)
167{
168 os_memcpy(pos, ie, ie_len);
169 return pos + ie_len;
170}
171
172
173static int wpa_tdls_del_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
174{
175 if (wpa_sm_set_key(sm, WPA_ALG_NONE, peer->addr,
176 0, 0, NULL, 0, NULL, 0) < 0) {
177 wpa_printf(MSG_WARNING, "TDLS: Failed to delete TPK-TK from "
178 "the driver");
179 return -1;
180 }
181
182 return 0;
183}
184
185
186static int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
187{
188 u8 key_len;
189 u8 rsc[6];
190 enum wpa_alg alg;
191
Jouni Malinen4c527402017-09-22 11:03:15 +0300192 if (peer->tk_set) {
193 /*
194 * This same TPK-TK has already been configured to the driver
195 * and this new configuration attempt (likely due to an
196 * unexpected retransmitted frame) would result in clearing
197 * the TX/RX sequence number which can break security, so must
198 * not allow that to happen.
199 */
200 wpa_printf(MSG_INFO, "TDLS: TPK-TK for the peer " MACSTR
201 " has already been configured to the driver - do not reconfigure",
202 MAC2STR(peer->addr));
203 return -1;
204 }
205
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700206 os_memset(rsc, 0, 6);
207
208 switch (peer->cipher) {
209 case WPA_CIPHER_CCMP:
210 alg = WPA_ALG_CCMP;
211 key_len = 16;
212 break;
213 case WPA_CIPHER_NONE:
214 wpa_printf(MSG_DEBUG, "TDLS: Pairwise Cipher Suite: "
215 "NONE - do not use pairwise keys");
216 return -1;
217 default:
218 wpa_printf(MSG_WARNING, "TDLS: Unsupported pairwise cipher %d",
219 sm->pairwise_cipher);
220 return -1;
221 }
222
Jouni Malinen4c527402017-09-22 11:03:15 +0300223 wpa_printf(MSG_DEBUG, "TDLS: Configure pairwise key for peer " MACSTR,
224 MAC2STR(peer->addr));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700225 if (wpa_sm_set_key(sm, alg, peer->addr, -1, 1,
226 rsc, sizeof(rsc), peer->tpk.tk, key_len) < 0) {
227 wpa_printf(MSG_WARNING, "TDLS: Failed to set TPK to the "
228 "driver");
229 return -1;
230 }
Jouni Malinen4c527402017-09-22 11:03:15 +0300231 peer->tk_set = 1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700232 return 0;
233}
234
235
236static int wpa_tdls_send_tpk_msg(struct wpa_sm *sm, const u8 *dst,
237 u8 action_code, u8 dialog_token,
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -0700238 u16 status_code, u32 peer_capab,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700239 int initiator, const u8 *buf, size_t len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700240{
241 return wpa_sm_send_tdls_mgmt(sm, dst, action_code, dialog_token,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700242 status_code, peer_capab, initiator, buf,
243 len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700244}
245
246
247static int wpa_tdls_tpk_send(struct wpa_sm *sm, const u8 *dest, u8 action_code,
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -0700248 u8 dialog_token, u16 status_code, u32 peer_capab,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700249 int initiator, const u8 *msg, size_t msg_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700250{
251 struct wpa_tdls_peer *peer;
252
253 wpa_printf(MSG_DEBUG, "TDLS: TPK send dest=" MACSTR " action_code=%u "
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700254 "dialog_token=%u status_code=%u peer_capab=%u initiator=%d "
255 "msg_len=%u",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700256 MAC2STR(dest), action_code, dialog_token, status_code,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700257 peer_capab, initiator, (unsigned int) msg_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700258
259 if (wpa_tdls_send_tpk_msg(sm, dest, action_code, dialog_token,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700260 status_code, peer_capab, initiator, msg,
261 msg_len)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700262 wpa_printf(MSG_INFO, "TDLS: Failed to send message "
263 "(action_code=%u)", action_code);
264 return -1;
265 }
266
267 if (action_code == WLAN_TDLS_SETUP_CONFIRM ||
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800268 action_code == WLAN_TDLS_TEARDOWN ||
269 action_code == WLAN_TDLS_DISCOVERY_REQUEST ||
270 action_code == WLAN_TDLS_DISCOVERY_RESPONSE)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700271 return 0; /* No retries */
272
273 for (peer = sm->tdls; peer; peer = peer->next) {
274 if (os_memcmp(peer->addr, dest, ETH_ALEN) == 0)
275 break;
276 }
277
278 if (peer == NULL) {
279 wpa_printf(MSG_INFO, "TDLS: No matching entry found for "
280 "retry " MACSTR, MAC2STR(dest));
281 return 0;
282 }
283
284 eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
285
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -0700286 if (action_code == WLAN_TDLS_SETUP_RESPONSE) {
287 peer->sm_tmr.count = TPK_M2_RETRY_COUNT;
288 peer->sm_tmr.timer = TPK_M2_TIMEOUT;
289 } else {
290 peer->sm_tmr.count = TPK_M1_RETRY_COUNT;
291 peer->sm_tmr.timer = TPK_M1_TIMEOUT;
292 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700293
294 /* Copy message to resend on timeout */
295 os_memcpy(peer->sm_tmr.dest, dest, ETH_ALEN);
296 peer->sm_tmr.action_code = action_code;
297 peer->sm_tmr.dialog_token = dialog_token;
298 peer->sm_tmr.status_code = status_code;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -0700299 peer->sm_tmr.peer_capab = peer_capab;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700300 peer->sm_tmr.buf_len = msg_len;
301 os_free(peer->sm_tmr.buf);
302 peer->sm_tmr.buf = os_malloc(msg_len);
303 if (peer->sm_tmr.buf == NULL)
304 return -1;
305 os_memcpy(peer->sm_tmr.buf, msg, msg_len);
306
307 wpa_printf(MSG_DEBUG, "TDLS: Retry timeout registered "
308 "(action_code=%u)", action_code);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -0700309 eloop_register_timeout(peer->sm_tmr.timer / 1000,
310 (peer->sm_tmr.timer % 1000) * 1000,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700311 wpa_tdls_tpk_retry_timeout, sm, peer);
312 return 0;
313}
314
315
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800316static int wpa_tdls_do_teardown(struct wpa_sm *sm, struct wpa_tdls_peer *peer,
Sunil Dutt6a9f5222013-09-30 17:10:18 +0300317 u16 reason_code)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800318{
319 int ret;
320
Sunil Dutt6a9f5222013-09-30 17:10:18 +0300321 ret = wpa_tdls_send_teardown(sm, peer->addr, reason_code);
322 /* disable the link after teardown was sent */
Sunil Duttd0ef38b2013-09-30 17:34:13 +0300323 wpa_tdls_disable_peer_link(sm, peer);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800324
325 return ret;
326}
327
328
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700329static void wpa_tdls_tpk_retry_timeout(void *eloop_ctx, void *timeout_ctx)
330{
331
332 struct wpa_sm *sm = eloop_ctx;
333 struct wpa_tdls_peer *peer = timeout_ctx;
334
335 if (peer->sm_tmr.count) {
336 peer->sm_tmr.count--;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700337
338 wpa_printf(MSG_INFO, "TDLS: Retrying sending of message "
339 "(action_code=%u)",
340 peer->sm_tmr.action_code);
341
342 if (peer->sm_tmr.buf == NULL) {
343 wpa_printf(MSG_INFO, "TDLS: No retry buffer available "
344 "for action_code=%u",
345 peer->sm_tmr.action_code);
346 eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm,
347 peer);
348 return;
349 }
350
351 /* resend TPK Handshake Message to Peer */
352 if (wpa_tdls_send_tpk_msg(sm, peer->sm_tmr.dest,
353 peer->sm_tmr.action_code,
354 peer->sm_tmr.dialog_token,
355 peer->sm_tmr.status_code,
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -0700356 peer->sm_tmr.peer_capab,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700357 peer->initiator,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700358 peer->sm_tmr.buf,
359 peer->sm_tmr.buf_len)) {
360 wpa_printf(MSG_INFO, "TDLS: Failed to retry "
361 "transmission");
362 }
363
364 eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -0700365 eloop_register_timeout(peer->sm_tmr.timer / 1000,
366 (peer->sm_tmr.timer % 1000) * 1000,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700367 wpa_tdls_tpk_retry_timeout, sm, peer);
368 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700369 eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
370
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800371 wpa_printf(MSG_DEBUG, "TDLS: Sending Teardown Request");
372 wpa_tdls_do_teardown(sm, peer,
Sunil Dutt6a9f5222013-09-30 17:10:18 +0300373 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700374 }
375}
376
377
378static void wpa_tdls_tpk_retry_timeout_cancel(struct wpa_sm *sm,
379 struct wpa_tdls_peer *peer,
380 u8 action_code)
381{
382 if (action_code == peer->sm_tmr.action_code) {
383 wpa_printf(MSG_DEBUG, "TDLS: Retry timeout cancelled for "
384 "action_code=%u", action_code);
385
386 /* Cancel Timeout registered */
387 eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
388
389 /* free all resources meant for retry */
390 os_free(peer->sm_tmr.buf);
391 peer->sm_tmr.buf = NULL;
392
393 peer->sm_tmr.count = 0;
394 peer->sm_tmr.timer = 0;
395 peer->sm_tmr.buf_len = 0;
396 peer->sm_tmr.action_code = 0xff;
397 } else {
398 wpa_printf(MSG_INFO, "TDLS: Error in cancelling retry timeout "
399 "(Unknown action_code=%u)", action_code);
400 }
401}
402
403
404static void wpa_tdls_generate_tpk(struct wpa_tdls_peer *peer,
405 const u8 *own_addr, const u8 *bssid)
406{
407 u8 key_input[SHA256_MAC_LEN];
408 const u8 *nonce[2];
409 size_t len[2];
410 u8 data[3 * ETH_ALEN];
411
412 /* IEEE Std 802.11z-2010 8.5.9.1:
413 * TPK-Key-Input = SHA-256(min(SNonce, ANonce) || max(SNonce, ANonce))
414 */
415 len[0] = WPA_NONCE_LEN;
416 len[1] = WPA_NONCE_LEN;
417 if (os_memcmp(peer->inonce, peer->rnonce, WPA_NONCE_LEN) < 0) {
418 nonce[0] = peer->inonce;
419 nonce[1] = peer->rnonce;
420 } else {
421 nonce[0] = peer->rnonce;
422 nonce[1] = peer->inonce;
423 }
424 wpa_hexdump(MSG_DEBUG, "TDLS: min(Nonce)", nonce[0], WPA_NONCE_LEN);
425 wpa_hexdump(MSG_DEBUG, "TDLS: max(Nonce)", nonce[1], WPA_NONCE_LEN);
426 sha256_vector(2, nonce, len, key_input);
427 wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-Key-Input",
428 key_input, SHA256_MAC_LEN);
429
430 /*
431 * TPK-Key-Data = KDF-N_KEY(TPK-Key-Input, "TDLS PMK",
432 * min(MAC_I, MAC_R) || max(MAC_I, MAC_R) || BSSID || N_KEY)
433 * TODO: is N_KEY really included in KDF Context and if so, in which
434 * presentation format (little endian 16-bit?) is it used? It gets
435 * added by the KDF anyway..
436 */
437
438 if (os_memcmp(own_addr, peer->addr, ETH_ALEN) < 0) {
439 os_memcpy(data, own_addr, ETH_ALEN);
440 os_memcpy(data + ETH_ALEN, peer->addr, ETH_ALEN);
441 } else {
442 os_memcpy(data, peer->addr, ETH_ALEN);
443 os_memcpy(data + ETH_ALEN, own_addr, ETH_ALEN);
444 }
445 os_memcpy(data + 2 * ETH_ALEN, bssid, ETH_ALEN);
446 wpa_hexdump(MSG_DEBUG, "TDLS: KDF Context", data, sizeof(data));
447
448 sha256_prf(key_input, SHA256_MAC_LEN, "TDLS PMK", data, sizeof(data),
449 (u8 *) &peer->tpk, sizeof(peer->tpk));
450 wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-KCK",
451 peer->tpk.kck, sizeof(peer->tpk.kck));
452 wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-TK",
453 peer->tpk.tk, sizeof(peer->tpk.tk));
454 peer->tpk_set = 1;
455}
456
457
458/**
459 * wpa_tdls_ftie_mic - Calculate TDLS FTIE MIC
460 * @kck: TPK-KCK
461 * @lnkid: Pointer to the beginning of Link Identifier IE
462 * @rsnie: Pointer to the beginning of RSN IE used for handshake
463 * @timeoutie: Pointer to the beginning of Timeout IE used for handshake
464 * @ftie: Pointer to the beginning of FT IE
465 * @mic: Pointer for writing MIC
466 *
467 * Calculate MIC for TDLS frame.
468 */
469static int wpa_tdls_ftie_mic(const u8 *kck, u8 trans_seq, const u8 *lnkid,
470 const u8 *rsnie, const u8 *timeoutie,
471 const u8 *ftie, u8 *mic)
472{
473 u8 *buf, *pos;
474 struct wpa_tdls_ftie *_ftie;
475 const struct wpa_tdls_lnkid *_lnkid;
476 int ret;
477 int len = 2 * ETH_ALEN + 1 + 2 + lnkid[1] + 2 + rsnie[1] +
478 2 + timeoutie[1] + 2 + ftie[1];
479 buf = os_zalloc(len);
480 if (!buf) {
481 wpa_printf(MSG_WARNING, "TDLS: No memory for MIC calculation");
482 return -1;
483 }
484
485 pos = buf;
486 _lnkid = (const struct wpa_tdls_lnkid *) lnkid;
487 /* 1) TDLS initiator STA MAC address */
488 os_memcpy(pos, _lnkid->init_sta, ETH_ALEN);
489 pos += ETH_ALEN;
490 /* 2) TDLS responder STA MAC address */
491 os_memcpy(pos, _lnkid->resp_sta, ETH_ALEN);
492 pos += ETH_ALEN;
493 /* 3) Transaction Sequence number */
494 *pos++ = trans_seq;
495 /* 4) Link Identifier IE */
496 os_memcpy(pos, lnkid, 2 + lnkid[1]);
497 pos += 2 + lnkid[1];
498 /* 5) RSN IE */
499 os_memcpy(pos, rsnie, 2 + rsnie[1]);
500 pos += 2 + rsnie[1];
501 /* 6) Timeout Interval IE */
502 os_memcpy(pos, timeoutie, 2 + timeoutie[1]);
503 pos += 2 + timeoutie[1];
504 /* 7) FTIE, with the MIC field of the FTIE set to 0 */
505 os_memcpy(pos, ftie, 2 + ftie[1]);
506 _ftie = (struct wpa_tdls_ftie *) pos;
507 os_memset(_ftie->mic, 0, TDLS_MIC_LEN);
508 pos += 2 + ftie[1];
509
510 wpa_hexdump(MSG_DEBUG, "TDLS: Data for FTIE MIC", buf, pos - buf);
511 wpa_hexdump_key(MSG_DEBUG, "TDLS: KCK", kck, 16);
512 ret = omac1_aes_128(kck, buf, pos - buf, mic);
513 os_free(buf);
514 wpa_hexdump(MSG_DEBUG, "TDLS: FTIE MIC", mic, 16);
515 return ret;
516}
517
518
519/**
520 * wpa_tdls_key_mic_teardown - Calculate TDLS FTIE MIC for Teardown frame
521 * @kck: TPK-KCK
522 * @trans_seq: Transaction Sequence Number (4 - Teardown)
523 * @rcode: Reason code for Teardown
524 * @dtoken: Dialog Token used for that particular link
525 * @lnkid: Pointer to the beginning of Link Identifier IE
526 * @ftie: Pointer to the beginning of FT IE
527 * @mic: Pointer for writing MIC
528 *
529 * Calculate MIC for TDLS frame.
530 */
531static int wpa_tdls_key_mic_teardown(const u8 *kck, u8 trans_seq, u16 rcode,
532 u8 dtoken, const u8 *lnkid,
533 const u8 *ftie, u8 *mic)
534{
535 u8 *buf, *pos;
536 struct wpa_tdls_ftie *_ftie;
537 int ret;
538 int len;
539
540 if (lnkid == NULL)
541 return -1;
542
543 len = 2 + lnkid[1] + sizeof(rcode) + sizeof(dtoken) +
544 sizeof(trans_seq) + 2 + ftie[1];
545
546 buf = os_zalloc(len);
547 if (!buf) {
548 wpa_printf(MSG_WARNING, "TDLS: No memory for MIC calculation");
549 return -1;
550 }
551
552 pos = buf;
553 /* 1) Link Identifier IE */
554 os_memcpy(pos, lnkid, 2 + lnkid[1]);
555 pos += 2 + lnkid[1];
556 /* 2) Reason Code */
557 WPA_PUT_LE16(pos, rcode);
558 pos += sizeof(rcode);
559 /* 3) Dialog token */
560 *pos++ = dtoken;
561 /* 4) Transaction Sequence number */
562 *pos++ = trans_seq;
563 /* 7) FTIE, with the MIC field of the FTIE set to 0 */
564 os_memcpy(pos, ftie, 2 + ftie[1]);
565 _ftie = (struct wpa_tdls_ftie *) pos;
566 os_memset(_ftie->mic, 0, TDLS_MIC_LEN);
567 pos += 2 + ftie[1];
568
569 wpa_hexdump(MSG_DEBUG, "TDLS: Data for FTIE MIC", buf, pos - buf);
570 wpa_hexdump_key(MSG_DEBUG, "TDLS: KCK", kck, 16);
571 ret = omac1_aes_128(kck, buf, pos - buf, mic);
572 os_free(buf);
573 wpa_hexdump(MSG_DEBUG, "TDLS: FTIE MIC", mic, 16);
574 return ret;
575}
576
577
578static int wpa_supplicant_verify_tdls_mic(u8 trans_seq,
579 struct wpa_tdls_peer *peer,
580 const u8 *lnkid, const u8 *timeoutie,
581 const struct wpa_tdls_ftie *ftie)
582{
583 u8 mic[16];
584
585 if (peer->tpk_set) {
586 wpa_tdls_ftie_mic(peer->tpk.kck, trans_seq, lnkid,
587 peer->rsnie_p, timeoutie, (u8 *) ftie,
588 mic);
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700589 if (os_memcmp_const(mic, ftie->mic, 16) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700590 wpa_printf(MSG_INFO, "TDLS: Invalid MIC in FTIE - "
591 "dropping packet");
592 wpa_hexdump(MSG_DEBUG, "TDLS: Received MIC",
593 ftie->mic, 16);
594 wpa_hexdump(MSG_DEBUG, "TDLS: Calculated MIC",
595 mic, 16);
596 return -1;
597 }
598 } else {
599 wpa_printf(MSG_WARNING, "TDLS: Could not verify TDLS MIC, "
600 "TPK not set - dropping packet");
601 return -1;
602 }
603 return 0;
604}
605
606
607static int wpa_supplicant_verify_tdls_mic_teardown(
608 u8 trans_seq, u16 rcode, u8 dtoken, struct wpa_tdls_peer *peer,
609 const u8 *lnkid, const struct wpa_tdls_ftie *ftie)
610{
611 u8 mic[16];
612
613 if (peer->tpk_set) {
614 wpa_tdls_key_mic_teardown(peer->tpk.kck, trans_seq, rcode,
615 dtoken, lnkid, (u8 *) ftie, mic);
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700616 if (os_memcmp_const(mic, ftie->mic, 16) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700617 wpa_printf(MSG_INFO, "TDLS: Invalid MIC in Teardown - "
618 "dropping packet");
619 return -1;
620 }
621 } else {
622 wpa_printf(MSG_INFO, "TDLS: Could not verify TDLS Teardown "
623 "MIC, TPK not set - dropping packet");
624 return -1;
625 }
626 return 0;
627}
628
629
630static void wpa_tdls_tpk_timeout(void *eloop_ctx, void *timeout_ctx)
631{
632 struct wpa_sm *sm = eloop_ctx;
633 struct wpa_tdls_peer *peer = timeout_ctx;
634
635 /*
636 * On TPK lifetime expiration, we have an option of either tearing down
637 * the direct link or trying to re-initiate it. The selection of what
638 * to do is not strictly speaking controlled by our role in the expired
639 * link, but for now, use that to select whether to renew or tear down
640 * the link.
641 */
642
643 if (peer->initiator) {
644 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime expired for " MACSTR
645 " - try to renew", MAC2STR(peer->addr));
646 wpa_tdls_start(sm, peer->addr);
647 } else {
648 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime expired for " MACSTR
649 " - tear down", MAC2STR(peer->addr));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800650 wpa_tdls_do_teardown(sm, peer,
Sunil Dutt6a9f5222013-09-30 17:10:18 +0300651 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700652 }
653}
654
655
Dmitry Shmidtd30ac602014-06-30 09:54:22 -0700656static void wpa_tdls_peer_remove_from_list(struct wpa_sm *sm,
657 struct wpa_tdls_peer *peer)
658{
659 struct wpa_tdls_peer *cur, *prev;
660
661 cur = sm->tdls;
662 prev = NULL;
663 while (cur && cur != peer) {
664 prev = cur;
665 cur = cur->next;
666 }
667
668 if (cur != peer) {
669 wpa_printf(MSG_ERROR, "TDLS: Could not find peer " MACSTR
670 " to remove it from the list",
671 MAC2STR(peer->addr));
672 return;
673 }
674
675 if (prev)
676 prev->next = peer->next;
677 else
678 sm->tdls = peer->next;
679}
680
681
682static void wpa_tdls_peer_clear(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700683{
684 wpa_printf(MSG_DEBUG, "TDLS: Clear state for peer " MACSTR,
685 MAC2STR(peer->addr));
686 eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer);
687 eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
Dmitry Shmidt8da800a2013-04-24 12:57:01 -0700688 peer->reconfig_key = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700689 peer->initiator = 0;
Sunil Dutt73b28cc2013-09-30 17:38:41 +0300690 peer->tpk_in_progress = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700691 os_free(peer->sm_tmr.buf);
692 peer->sm_tmr.buf = NULL;
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800693 os_free(peer->ht_capabilities);
694 peer->ht_capabilities = NULL;
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -0800695 os_free(peer->vht_capabilities);
696 peer->vht_capabilities = NULL;
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800697 os_free(peer->ext_capab);
698 peer->ext_capab = NULL;
Dmitry Shmidt344abd32014-01-14 13:17:00 -0800699 os_free(peer->supp_channels);
700 peer->supp_channels = NULL;
701 os_free(peer->supp_oper_classes);
702 peer->supp_oper_classes = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700703 peer->rsnie_i_len = peer->rsnie_p_len = 0;
704 peer->cipher = 0;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -0700705 peer->qos_info = 0;
706 peer->wmm_capable = 0;
Jouni Malinen4c527402017-09-22 11:03:15 +0300707 peer->tk_set = peer->tpk_set = peer->tpk_success = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700708 os_memset(&peer->tpk, 0, sizeof(peer->tpk));
709 os_memset(peer->inonce, 0, WPA_NONCE_LEN);
710 os_memset(peer->rnonce, 0, WPA_NONCE_LEN);
711}
712
713
Dmitry Shmidtd30ac602014-06-30 09:54:22 -0700714static void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
715{
716 wpa_tdls_peer_clear(sm, peer);
717 wpa_tdls_peer_remove_from_list(sm, peer);
718 os_free(peer);
719}
720
721
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700722static void wpa_tdls_linkid(struct wpa_sm *sm, struct wpa_tdls_peer *peer,
723 struct wpa_tdls_lnkid *lnkid)
724{
725 lnkid->ie_type = WLAN_EID_LINK_ID;
726 lnkid->ie_len = 3 * ETH_ALEN;
727 os_memcpy(lnkid->bssid, sm->bssid, ETH_ALEN);
728 if (peer->initiator) {
729 os_memcpy(lnkid->init_sta, sm->own_addr, ETH_ALEN);
730 os_memcpy(lnkid->resp_sta, peer->addr, ETH_ALEN);
731 } else {
732 os_memcpy(lnkid->init_sta, peer->addr, ETH_ALEN);
733 os_memcpy(lnkid->resp_sta, sm->own_addr, ETH_ALEN);
734 }
735}
736
737
Dmitry Shmidtb58836e2014-04-29 14:35:56 -0700738static int wpa_tdls_send_teardown(struct wpa_sm *sm, const u8 *addr,
739 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700740{
741 struct wpa_tdls_peer *peer;
742 struct wpa_tdls_ftie *ftie;
743 struct wpa_tdls_lnkid lnkid;
744 u8 dialog_token;
745 u8 *rbuf, *pos;
746 int ielen;
747
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800748 if (sm->tdls_disabled || !sm->tdls_supported)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700749 return -1;
750
751 /* Find the node and free from the list */
752 for (peer = sm->tdls; peer; peer = peer->next) {
753 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
754 break;
755 }
756
757 if (peer == NULL) {
758 wpa_printf(MSG_INFO, "TDLS: No matching entry found for "
759 "Teardown " MACSTR, MAC2STR(addr));
760 return 0;
761 }
762
763 dialog_token = peer->dtoken;
764
765 wpa_printf(MSG_DEBUG, "TDLS: TDLS Teardown for " MACSTR,
766 MAC2STR(addr));
767
768 ielen = 0;
769 if (wpa_tdls_get_privacy(sm) && peer->tpk_set && peer->tpk_success) {
770 /* To add FTIE for Teardown request and compute MIC */
771 ielen += sizeof(*ftie);
772#ifdef CONFIG_TDLS_TESTING
773 if (tdls_testing & TDLS_TESTING_LONG_FRAME)
774 ielen += 170;
775#endif /* CONFIG_TDLS_TESTING */
776 }
777
778 rbuf = os_zalloc(ielen + 1);
779 if (rbuf == NULL)
780 return -1;
781 pos = rbuf;
782
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700783 if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700784 goto skip_ies;
785
786 ftie = (struct wpa_tdls_ftie *) pos;
787 ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
788 /* Using the recent nonce which should be for CONFIRM frame */
789 os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN);
790 os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
791 ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2;
792 pos = (u8 *) (ftie + 1);
793#ifdef CONFIG_TDLS_TESTING
794 if (tdls_testing & TDLS_TESTING_LONG_FRAME) {
795 wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to "
796 "FTIE");
797 ftie->ie_len += 170;
798 *pos++ = 255; /* FTIE subelem */
799 *pos++ = 168; /* FTIE subelem length */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800800 pos += 168;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700801 }
802#endif /* CONFIG_TDLS_TESTING */
803 wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TDLS Teardown handshake",
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800804 (u8 *) ftie, pos - (u8 *) ftie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700805
806 /* compute MIC before sending */
807 wpa_tdls_linkid(sm, peer, &lnkid);
808 wpa_tdls_key_mic_teardown(peer->tpk.kck, 4, reason_code,
809 dialog_token, (u8 *) &lnkid, (u8 *) ftie,
810 ftie->mic);
811
812skip_ies:
813 /* TODO: register for a Timeout handler, if Teardown is not received at
814 * the other end, then try again another time */
815
816 /* request driver to send Teardown using this FTIE */
817 wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_TEARDOWN, 0,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700818 reason_code, 0, peer->initiator, rbuf, pos - rbuf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700819 os_free(rbuf);
820
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700821 return 0;
822}
823
824
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800825int wpa_tdls_teardown_link(struct wpa_sm *sm, const u8 *addr, u16 reason_code)
826{
827 struct wpa_tdls_peer *peer;
828
829 if (sm->tdls_disabled || !sm->tdls_supported)
830 return -1;
831
832 for (peer = sm->tdls; peer; peer = peer->next) {
833 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
834 break;
835 }
836
837 if (peer == NULL) {
838 wpa_printf(MSG_DEBUG, "TDLS: Could not find peer " MACSTR
839 " for link Teardown", MAC2STR(addr));
840 return -1;
841 }
842
843 if (!peer->tpk_success) {
844 wpa_printf(MSG_DEBUG, "TDLS: Peer " MACSTR
845 " not connected - cannot Teardown link", MAC2STR(addr));
846 return -1;
847 }
848
Sunil Dutt6a9f5222013-09-30 17:10:18 +0300849 return wpa_tdls_do_teardown(sm, peer, reason_code);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800850}
851
852
Sunil Dutt38ffd882013-09-30 17:23:23 +0300853static void wpa_tdls_disable_peer_link(struct wpa_sm *sm,
854 struct wpa_tdls_peer *peer)
855{
856 wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr);
857 wpa_tdls_peer_free(sm, peer);
858}
859
860
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700861void wpa_tdls_disable_unreachable_link(struct wpa_sm *sm, const u8 *addr)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800862{
863 struct wpa_tdls_peer *peer;
864
865 for (peer = sm->tdls; peer; peer = peer->next) {
866 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
867 break;
868 }
869
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700870 if (!peer || !peer->tpk_success) {
871 wpa_printf(MSG_DEBUG, "TDLS: Peer " MACSTR
872 " not connected - cannot teardown unreachable link",
873 MAC2STR(addr));
874 return;
875 }
876
877 if (wpa_tdls_is_external_setup(sm)) {
878 /*
879 * Disable the link, send a teardown packet through the
880 * AP, and then reset link data.
881 */
882 wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, addr);
883 wpa_tdls_send_teardown(sm, addr,
884 WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE);
885 wpa_tdls_peer_free(sm, peer);
886 } else {
Sunil Dutt38ffd882013-09-30 17:23:23 +0300887 wpa_tdls_disable_peer_link(sm, peer);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700888 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800889}
890
891
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -0800892const char * wpa_tdls_get_link_status(struct wpa_sm *sm, const u8 *addr)
893{
894 struct wpa_tdls_peer *peer;
895
896 if (sm->tdls_disabled || !sm->tdls_supported)
897 return "disabled";
898
899 for (peer = sm->tdls; peer; peer = peer->next) {
900 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
901 break;
902 }
903
904 if (peer == NULL)
905 return "peer does not exist";
906
907 if (!peer->tpk_success)
908 return "peer not connected";
909
910 return "connected";
911}
912
913
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700914static int wpa_tdls_recv_teardown(struct wpa_sm *sm, const u8 *src_addr,
915 const u8 *buf, size_t len)
916{
917 struct wpa_tdls_peer *peer = NULL;
918 struct wpa_tdls_ftie *ftie;
919 struct wpa_tdls_lnkid *lnkid;
920 struct wpa_eapol_ie_parse kde;
921 u16 reason_code;
922 const u8 *pos;
923 int ielen;
924
925 /* Find the node and free from the list */
926 for (peer = sm->tdls; peer; peer = peer->next) {
927 if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0)
928 break;
929 }
930
931 if (peer == NULL) {
932 wpa_printf(MSG_INFO, "TDLS: No matching entry found for "
933 "Teardown " MACSTR, MAC2STR(src_addr));
934 return 0;
935 }
936
937 pos = buf;
938 pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */;
939
940 reason_code = WPA_GET_LE16(pos);
941 pos += 2;
942
943 wpa_printf(MSG_DEBUG, "TDLS: TDLS Teardown Request from " MACSTR
944 " (reason code %u)", MAC2STR(src_addr), reason_code);
945
946 ielen = len - (pos - buf); /* start of IE in buf */
947 if (wpa_supplicant_parse_ies((const u8 *) pos, ielen, &kde) < 0) {
948 wpa_printf(MSG_INFO, "TDLS: Failed to parse IEs in Teardown");
949 return -1;
950 }
951
952 if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) {
953 wpa_printf(MSG_INFO, "TDLS: No Link Identifier IE in TDLS "
954 "Teardown");
955 return -1;
956 }
957 lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
958
959 if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success)
960 goto skip_ftie;
961
962 if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie)) {
963 wpa_printf(MSG_INFO, "TDLS: No FTIE in TDLS Teardown");
964 return -1;
965 }
966
967 ftie = (struct wpa_tdls_ftie *) kde.ftie;
968
969 /* Process MIC check to see if TDLS Teardown is right */
970 if (wpa_supplicant_verify_tdls_mic_teardown(4, reason_code,
971 peer->dtoken, peer,
972 (u8 *) lnkid, ftie) < 0) {
973 wpa_printf(MSG_DEBUG, "TDLS: MIC failure for TDLS "
974 "Teardown Request from " MACSTR, MAC2STR(src_addr));
975 return -1;
976 }
977
978skip_ftie:
979 /*
980 * Request the driver to disable the direct link and clear associated
981 * keys.
982 */
Sunil Dutt38ffd882013-09-30 17:23:23 +0300983 wpa_tdls_disable_peer_link(sm, peer);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700984 return 0;
985}
986
987
988/**
989 * wpa_tdls_send_error - To send suitable TDLS status response with
990 * appropriate status code mentioning reason for error/failure.
991 * @dst - MAC addr of Peer station
992 * @tdls_action - TDLS frame type for which error code is sent
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700993 * @initiator - was this end the initiator of the connection
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700994 * @status - status code mentioning reason
995 */
996
997static int wpa_tdls_send_error(struct wpa_sm *sm, const u8 *dst,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700998 u8 tdls_action, u8 dialog_token, int initiator,
999 u16 status)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001000{
1001 wpa_printf(MSG_DEBUG, "TDLS: Sending error to " MACSTR
1002 " (action=%u status=%u)",
1003 MAC2STR(dst), tdls_action, status);
1004 return wpa_tdls_tpk_send(sm, dst, tdls_action, dialog_token, status,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001005 0, initiator, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001006}
1007
1008
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001009static struct wpa_tdls_peer *
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001010wpa_tdls_add_peer(struct wpa_sm *sm, const u8 *addr, int *existing)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001011{
1012 struct wpa_tdls_peer *peer;
1013
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001014 if (existing)
1015 *existing = 0;
1016 for (peer = sm->tdls; peer; peer = peer->next) {
1017 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0) {
1018 if (existing)
1019 *existing = 1;
1020 return peer; /* re-use existing entry */
1021 }
1022 }
1023
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001024 wpa_printf(MSG_INFO, "TDLS: Creating peer entry for " MACSTR,
1025 MAC2STR(addr));
1026
1027 peer = os_zalloc(sizeof(*peer));
1028 if (peer == NULL)
1029 return NULL;
1030
1031 os_memcpy(peer->addr, addr, ETH_ALEN);
1032 peer->next = sm->tdls;
1033 sm->tdls = peer;
1034
1035 return peer;
1036}
1037
1038
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001039static int wpa_tdls_send_tpk_m1(struct wpa_sm *sm,
1040 struct wpa_tdls_peer *peer)
1041{
1042 size_t buf_len;
1043 struct wpa_tdls_timeoutie timeoutie;
1044 u16 rsn_capab;
1045 struct wpa_tdls_ftie *ftie;
1046 u8 *rbuf, *pos, *count_pos;
1047 u16 count;
1048 struct rsn_ie_hdr *hdr;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07001049 int status;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001050
1051 if (!wpa_tdls_get_privacy(sm)) {
1052 wpa_printf(MSG_DEBUG, "TDLS: No security used on the link");
1053 peer->rsnie_i_len = 0;
1054 goto skip_rsnie;
1055 }
1056
1057 /*
1058 * TPK Handshake Message 1:
1059 * FTIE: ANonce=0, SNonce=initiator nonce MIC=0, DataKDs=(RSNIE_I,
1060 * Timeout Interval IE))
1061 */
1062
1063 /* Filling RSN IE */
1064 hdr = (struct rsn_ie_hdr *) peer->rsnie_i;
1065 hdr->elem_id = WLAN_EID_RSN;
1066 WPA_PUT_LE16(hdr->version, RSN_VERSION);
1067
1068 pos = (u8 *) (hdr + 1);
1069 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
1070 pos += RSN_SELECTOR_LEN;
1071 count_pos = pos;
1072 pos += 2;
1073
1074 count = 0;
1075
1076 /*
1077 * AES-CCMP is the default Encryption preferred for TDLS, so
1078 * RSN IE is filled only with CCMP CIPHER
1079 * Note: TKIP is not used to encrypt TDLS link.
1080 *
1081 * Regardless of the cipher used on the AP connection, select CCMP
1082 * here.
1083 */
1084 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
1085 pos += RSN_SELECTOR_LEN;
1086 count++;
1087
1088 WPA_PUT_LE16(count_pos, count);
1089
1090 WPA_PUT_LE16(pos, 1);
1091 pos += 2;
1092 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE);
1093 pos += RSN_SELECTOR_LEN;
1094
1095 rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
1096 rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2;
1097#ifdef CONFIG_TDLS_TESTING
1098 if (tdls_testing & TDLS_TESTING_ALT_RSN_IE) {
1099 wpa_printf(MSG_DEBUG, "TDLS: Use alternative RSN IE for "
1100 "testing");
1101 rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
1102 }
1103#endif /* CONFIG_TDLS_TESTING */
1104 WPA_PUT_LE16(pos, rsn_capab);
1105 pos += 2;
1106#ifdef CONFIG_TDLS_TESTING
1107 if (tdls_testing & TDLS_TESTING_ALT_RSN_IE) {
1108 /* Number of PMKIDs */
1109 *pos++ = 0x00;
1110 *pos++ = 0x00;
1111 }
1112#endif /* CONFIG_TDLS_TESTING */
1113
1114 hdr->len = (pos - peer->rsnie_i) - 2;
1115 peer->rsnie_i_len = pos - peer->rsnie_i;
1116 wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for TPK handshake",
1117 peer->rsnie_i, peer->rsnie_i_len);
1118
1119skip_rsnie:
1120 buf_len = 0;
1121 if (wpa_tdls_get_privacy(sm))
1122 buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) +
1123 sizeof(struct wpa_tdls_timeoutie);
1124#ifdef CONFIG_TDLS_TESTING
1125 if (wpa_tdls_get_privacy(sm) &&
1126 (tdls_testing & TDLS_TESTING_LONG_FRAME))
1127 buf_len += 170;
1128 if (tdls_testing & TDLS_TESTING_DIFF_BSSID)
1129 buf_len += sizeof(struct wpa_tdls_lnkid);
1130#endif /* CONFIG_TDLS_TESTING */
1131 rbuf = os_zalloc(buf_len + 1);
1132 if (rbuf == NULL) {
1133 wpa_tdls_peer_free(sm, peer);
1134 return -1;
1135 }
1136 pos = rbuf;
1137
1138 if (!wpa_tdls_get_privacy(sm))
1139 goto skip_ies;
1140
1141 /* Initiator RSN IE */
1142 pos = wpa_add_ie(pos, peer->rsnie_i, peer->rsnie_i_len);
1143
1144 ftie = (struct wpa_tdls_ftie *) pos;
1145 ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
1146 ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2;
1147
1148 if (os_get_random(peer->inonce, WPA_NONCE_LEN)) {
1149 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1150 "TDLS: Failed to get random data for initiator Nonce");
1151 os_free(rbuf);
1152 wpa_tdls_peer_free(sm, peer);
1153 return -1;
1154 }
Jouni Malinen4c527402017-09-22 11:03:15 +03001155 peer->tk_set = 0; /* A new nonce results in a new TK */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001156 wpa_hexdump(MSG_DEBUG, "TDLS: Initiator Nonce for TPK handshake",
1157 peer->inonce, WPA_NONCE_LEN);
1158 os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
1159
1160 wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TPK Handshake M1",
1161 (u8 *) ftie, sizeof(struct wpa_tdls_ftie));
1162
1163 pos = (u8 *) (ftie + 1);
1164
1165#ifdef CONFIG_TDLS_TESTING
1166 if (tdls_testing & TDLS_TESTING_LONG_FRAME) {
1167 wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to "
1168 "FTIE");
1169 ftie->ie_len += 170;
1170 *pos++ = 255; /* FTIE subelem */
1171 *pos++ = 168; /* FTIE subelem length */
1172 pos += 168;
1173 }
1174#endif /* CONFIG_TDLS_TESTING */
1175
1176 /* Lifetime */
1177 peer->lifetime = TPK_LIFETIME;
1178#ifdef CONFIG_TDLS_TESTING
1179 if (tdls_testing & TDLS_TESTING_SHORT_LIFETIME) {
1180 wpa_printf(MSG_DEBUG, "TDLS: Testing - use short TPK "
1181 "lifetime");
1182 peer->lifetime = 301;
1183 }
1184 if (tdls_testing & TDLS_TESTING_LONG_LIFETIME) {
1185 wpa_printf(MSG_DEBUG, "TDLS: Testing - use long TPK "
1186 "lifetime");
1187 peer->lifetime = 0xffffffff;
1188 }
1189#endif /* CONFIG_TDLS_TESTING */
1190 pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie,
1191 sizeof(timeoutie), peer->lifetime);
1192 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", peer->lifetime);
1193
1194skip_ies:
1195
1196#ifdef CONFIG_TDLS_TESTING
1197 if (tdls_testing & TDLS_TESTING_DIFF_BSSID) {
1198 wpa_printf(MSG_DEBUG, "TDLS: Testing - use incorrect BSSID in "
1199 "Link Identifier");
1200 struct wpa_tdls_lnkid *l = (struct wpa_tdls_lnkid *) pos;
1201 wpa_tdls_linkid(sm, peer, l);
1202 l->bssid[5] ^= 0x01;
1203 pos += sizeof(*l);
1204 }
1205#endif /* CONFIG_TDLS_TESTING */
1206
1207 wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Request / TPK "
1208 "Handshake Message 1 (peer " MACSTR ")",
1209 MAC2STR(peer->addr));
1210
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07001211 status = wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_SETUP_REQUEST,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001212 1, 0, 0, peer->initiator, rbuf, pos - rbuf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001213 os_free(rbuf);
1214
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07001215 return status;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001216}
1217
1218
1219static int wpa_tdls_send_tpk_m2(struct wpa_sm *sm,
1220 const unsigned char *src_addr, u8 dtoken,
1221 struct wpa_tdls_lnkid *lnkid,
1222 const struct wpa_tdls_peer *peer)
1223{
1224 u8 *rbuf, *pos;
1225 size_t buf_len;
1226 u32 lifetime;
1227 struct wpa_tdls_timeoutie timeoutie;
1228 struct wpa_tdls_ftie *ftie;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07001229 int status;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001230
1231 buf_len = 0;
1232 if (wpa_tdls_get_privacy(sm)) {
1233 /* Peer RSN IE, FTIE(Initiator Nonce, Responder Nonce),
1234 * Lifetime */
1235 buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) +
1236 sizeof(struct wpa_tdls_timeoutie);
1237#ifdef CONFIG_TDLS_TESTING
1238 if (tdls_testing & TDLS_TESTING_LONG_FRAME)
1239 buf_len += 170;
1240#endif /* CONFIG_TDLS_TESTING */
1241 }
1242
1243 rbuf = os_zalloc(buf_len + 1);
1244 if (rbuf == NULL)
1245 return -1;
1246 pos = rbuf;
1247
1248 if (!wpa_tdls_get_privacy(sm))
1249 goto skip_ies;
1250
1251 /* Peer RSN IE */
1252 pos = wpa_add_ie(pos, peer->rsnie_p, peer->rsnie_p_len);
1253
1254 ftie = (struct wpa_tdls_ftie *) pos;
1255 ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
1256 /* TODO: ftie->mic_control to set 2-RESPONSE */
1257 os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN);
1258 os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
1259 ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2;
1260 wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TPK M2",
1261 (u8 *) ftie, sizeof(*ftie));
1262
1263 pos = (u8 *) (ftie + 1);
1264
1265#ifdef CONFIG_TDLS_TESTING
1266 if (tdls_testing & TDLS_TESTING_LONG_FRAME) {
1267 wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to "
1268 "FTIE");
1269 ftie->ie_len += 170;
1270 *pos++ = 255; /* FTIE subelem */
1271 *pos++ = 168; /* FTIE subelem length */
1272 pos += 168;
1273 }
1274#endif /* CONFIG_TDLS_TESTING */
1275
1276 /* Lifetime */
1277 lifetime = peer->lifetime;
1278#ifdef CONFIG_TDLS_TESTING
1279 if (tdls_testing & TDLS_TESTING_WRONG_LIFETIME_RESP) {
1280 wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong TPK "
1281 "lifetime in response");
1282 lifetime++;
1283 }
1284#endif /* CONFIG_TDLS_TESTING */
1285 pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie,
1286 sizeof(timeoutie), lifetime);
1287 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds from initiator",
1288 lifetime);
1289
1290 /* compute MIC before sending */
1291 wpa_tdls_ftie_mic(peer->tpk.kck, 2, (u8 *) lnkid, peer->rsnie_p,
1292 (u8 *) &timeoutie, (u8 *) ftie, ftie->mic);
Dmitry Shmidt21de2142014-04-08 10:50:52 -07001293#ifdef CONFIG_TDLS_TESTING
1294 if (tdls_testing & TDLS_TESTING_WRONG_MIC) {
1295 wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong MIC");
1296 ftie->mic[0] ^= 0x01;
1297 }
1298#endif /* CONFIG_TDLS_TESTING */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001299
1300skip_ies:
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07001301 status = wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001302 dtoken, 0, 0, peer->initiator, rbuf,
1303 pos - rbuf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001304 os_free(rbuf);
1305
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07001306 return status;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001307}
1308
1309
1310static int wpa_tdls_send_tpk_m3(struct wpa_sm *sm,
1311 const unsigned char *src_addr, u8 dtoken,
1312 struct wpa_tdls_lnkid *lnkid,
1313 const struct wpa_tdls_peer *peer)
1314{
1315 u8 *rbuf, *pos;
1316 size_t buf_len;
1317 struct wpa_tdls_ftie *ftie;
1318 struct wpa_tdls_timeoutie timeoutie;
1319 u32 lifetime;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07001320 int status;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07001321 u32 peer_capab = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001322
1323 buf_len = 0;
1324 if (wpa_tdls_get_privacy(sm)) {
1325 /* Peer RSN IE, FTIE(Initiator Nonce, Responder Nonce),
1326 * Lifetime */
1327 buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) +
1328 sizeof(struct wpa_tdls_timeoutie);
1329#ifdef CONFIG_TDLS_TESTING
1330 if (tdls_testing & TDLS_TESTING_LONG_FRAME)
1331 buf_len += 170;
1332#endif /* CONFIG_TDLS_TESTING */
1333 }
1334
1335 rbuf = os_zalloc(buf_len + 1);
1336 if (rbuf == NULL)
1337 return -1;
1338 pos = rbuf;
1339
1340 if (!wpa_tdls_get_privacy(sm))
1341 goto skip_ies;
1342
1343 /* Peer RSN IE */
1344 pos = wpa_add_ie(pos, peer->rsnie_p, peer->rsnie_p_len);
1345
1346 ftie = (struct wpa_tdls_ftie *) pos;
1347 ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
1348 /*TODO: ftie->mic_control to set 3-CONFIRM */
1349 os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN);
1350 os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
1351 ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2;
1352
1353 pos = (u8 *) (ftie + 1);
1354
1355#ifdef CONFIG_TDLS_TESTING
1356 if (tdls_testing & TDLS_TESTING_LONG_FRAME) {
1357 wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to "
1358 "FTIE");
1359 ftie->ie_len += 170;
1360 *pos++ = 255; /* FTIE subelem */
1361 *pos++ = 168; /* FTIE subelem length */
1362 pos += 168;
1363 }
1364#endif /* CONFIG_TDLS_TESTING */
1365
1366 /* Lifetime */
1367 lifetime = peer->lifetime;
1368#ifdef CONFIG_TDLS_TESTING
1369 if (tdls_testing & TDLS_TESTING_WRONG_LIFETIME_CONF) {
1370 wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong TPK "
1371 "lifetime in confirm");
1372 lifetime++;
1373 }
1374#endif /* CONFIG_TDLS_TESTING */
1375 pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie,
1376 sizeof(timeoutie), lifetime);
1377 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds",
1378 lifetime);
1379
1380 /* compute MIC before sending */
1381 wpa_tdls_ftie_mic(peer->tpk.kck, 3, (u8 *) lnkid, peer->rsnie_p,
1382 (u8 *) &timeoutie, (u8 *) ftie, ftie->mic);
Dmitry Shmidt21de2142014-04-08 10:50:52 -07001383#ifdef CONFIG_TDLS_TESTING
1384 if (tdls_testing & TDLS_TESTING_WRONG_MIC) {
1385 wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong MIC");
1386 ftie->mic[0] ^= 0x01;
1387 }
1388#endif /* CONFIG_TDLS_TESTING */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001389
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07001390skip_ies:
1391
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07001392 if (peer->vht_capabilities)
1393 peer_capab |= TDLS_PEER_VHT;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07001394 if (peer->ht_capabilities)
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07001395 peer_capab |= TDLS_PEER_HT;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07001396 if (peer->wmm_capable)
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07001397 peer_capab |= TDLS_PEER_WMM;
1398
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07001399 status = wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001400 dtoken, 0, peer_capab, peer->initiator,
1401 rbuf, pos - rbuf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001402 os_free(rbuf);
1403
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07001404 return status;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001405}
1406
1407
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001408static int wpa_tdls_send_discovery_response(struct wpa_sm *sm,
1409 struct wpa_tdls_peer *peer,
1410 u8 dialog_token)
1411{
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001412 size_t buf_len = 0;
1413 struct wpa_tdls_timeoutie timeoutie;
1414 u16 rsn_capab;
1415 u8 *rbuf, *pos, *count_pos;
1416 u16 count;
1417 struct rsn_ie_hdr *hdr;
1418 int status;
1419
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001420 wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Discovery Response "
1421 "(peer " MACSTR ")", MAC2STR(peer->addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001422 if (!wpa_tdls_get_privacy(sm))
1423 goto skip_rsn_ies;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001424
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001425 /* Filling RSN IE */
1426 hdr = (struct rsn_ie_hdr *) peer->rsnie_i;
1427 hdr->elem_id = WLAN_EID_RSN;
1428 WPA_PUT_LE16(hdr->version, RSN_VERSION);
1429 pos = (u8 *) (hdr + 1);
1430 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
1431 pos += RSN_SELECTOR_LEN;
1432 count_pos = pos;
1433 pos += 2;
1434 count = 0;
1435
1436 /*
1437 * AES-CCMP is the default encryption preferred for TDLS, so
1438 * RSN IE is filled only with CCMP cipher suite.
1439 * Note: TKIP is not used to encrypt TDLS link.
1440 *
1441 * Regardless of the cipher used on the AP connection, select CCMP
1442 * here.
1443 */
1444 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
1445 pos += RSN_SELECTOR_LEN;
1446 count++;
1447 WPA_PUT_LE16(count_pos, count);
1448 WPA_PUT_LE16(pos, 1);
1449 pos += 2;
1450 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE);
1451 pos += RSN_SELECTOR_LEN;
1452
1453 rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
1454 rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2;
1455 WPA_PUT_LE16(pos, rsn_capab);
1456 pos += 2;
1457 hdr->len = (pos - (u8 *) hdr) - 2;
1458 peer->rsnie_i_len = pos - peer->rsnie_i;
1459
1460 wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for Discovery Response",
1461 (u8 *) hdr, hdr->len + 2);
1462skip_rsn_ies:
1463 buf_len = 0;
1464 if (wpa_tdls_get_privacy(sm)) {
1465 /* Peer RSN IE, Lifetime */
1466 buf_len += peer->rsnie_i_len +
1467 sizeof(struct wpa_tdls_timeoutie);
1468 }
1469 rbuf = os_zalloc(buf_len + 1);
1470 if (rbuf == NULL) {
1471 wpa_tdls_peer_free(sm, peer);
1472 return -1;
1473 }
1474 pos = rbuf;
1475
1476 if (!wpa_tdls_get_privacy(sm))
1477 goto skip_ies;
1478 /* Initiator RSN IE */
1479 pos = wpa_add_ie(pos, peer->rsnie_i, peer->rsnie_i_len);
1480 /* Lifetime */
1481 peer->lifetime = TPK_LIFETIME;
1482 pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie,
1483 sizeof(timeoutie), peer->lifetime);
1484 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", peer->lifetime);
1485skip_ies:
1486 status = wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_DISCOVERY_RESPONSE,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001487 dialog_token, 0, 0, 0, rbuf, pos - rbuf);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001488 os_free(rbuf);
1489
1490 return status;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001491}
1492
1493
1494static int
1495wpa_tdls_process_discovery_request(struct wpa_sm *sm, const u8 *addr,
1496 const u8 *buf, size_t len)
1497{
1498 struct wpa_eapol_ie_parse kde;
1499 const struct wpa_tdls_lnkid *lnkid;
1500 struct wpa_tdls_peer *peer;
1501 size_t min_req_len = sizeof(struct wpa_tdls_frame) +
1502 1 /* dialog token */ + sizeof(struct wpa_tdls_lnkid);
1503 u8 dialog_token;
1504
1505 wpa_printf(MSG_DEBUG, "TDLS: Discovery Request from " MACSTR,
1506 MAC2STR(addr));
1507
1508 if (len < min_req_len) {
1509 wpa_printf(MSG_DEBUG, "TDLS Discovery Request is too short: "
1510 "%d", (int) len);
1511 return -1;
1512 }
1513
1514 dialog_token = buf[sizeof(struct wpa_tdls_frame)];
1515
Dmitry Shmidt0c08fdc2014-06-20 10:16:40 -07001516 /*
1517 * Some APs will tack on a weird IE to the end of a TDLS
1518 * discovery request packet. This needn't fail the response,
1519 * since the required IE are verified separately.
1520 */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001521 if (wpa_supplicant_parse_ies(buf + sizeof(struct wpa_tdls_frame) + 1,
1522 len - (sizeof(struct wpa_tdls_frame) + 1),
Dmitry Shmidt0c08fdc2014-06-20 10:16:40 -07001523 &kde) < 0) {
1524 wpa_printf(MSG_DEBUG,
1525 "TDLS: Failed to parse IEs in Discovery Request - ignore as an interop workaround");
1526 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001527
1528 if (!kde.lnkid) {
1529 wpa_printf(MSG_DEBUG, "TDLS: Link ID not found in Discovery "
1530 "Request");
1531 return -1;
1532 }
1533
1534 lnkid = (const struct wpa_tdls_lnkid *) kde.lnkid;
1535
1536 if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) {
1537 wpa_printf(MSG_DEBUG, "TDLS: Discovery Request from different "
1538 " BSS " MACSTR, MAC2STR(lnkid->bssid));
1539 return -1;
1540 }
1541
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001542 peer = wpa_tdls_add_peer(sm, addr, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001543 if (peer == NULL)
1544 return -1;
1545
1546 return wpa_tdls_send_discovery_response(sm, peer, dialog_token);
1547}
1548
1549
1550int wpa_tdls_send_discovery_request(struct wpa_sm *sm, const u8 *addr)
1551{
1552 if (sm->tdls_disabled || !sm->tdls_supported)
1553 return -1;
1554
1555 wpa_printf(MSG_DEBUG, "TDLS: Sending Discovery Request to peer "
1556 MACSTR, MAC2STR(addr));
1557 return wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_DISCOVERY_REQUEST,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001558 1, 0, 0, 1, NULL, 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001559}
1560
1561
1562static int copy_supp_rates(const struct wpa_eapol_ie_parse *kde,
1563 struct wpa_tdls_peer *peer)
1564{
1565 if (!kde->supp_rates) {
1566 wpa_printf(MSG_DEBUG, "TDLS: No supported rates received");
1567 return -1;
1568 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001569 peer->supp_rates_len = merge_byte_arrays(
1570 peer->supp_rates, sizeof(peer->supp_rates),
1571 kde->supp_rates + 2, kde->supp_rates_len - 2,
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001572 kde->ext_supp_rates ? kde->ext_supp_rates + 2 : NULL,
1573 kde->ext_supp_rates_len - 2);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001574 return 0;
1575}
1576
1577
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001578static int copy_peer_ht_capab(const struct wpa_eapol_ie_parse *kde,
1579 struct wpa_tdls_peer *peer)
1580{
1581 if (!kde->ht_capabilities ||
1582 kde->ht_capabilities_len <
1583 sizeof(struct ieee80211_ht_capabilities) ) {
1584 wpa_printf(MSG_DEBUG, "TDLS: No supported ht capabilities "
1585 "received");
1586 return 0;
1587 }
1588
1589 if (!peer->ht_capabilities) {
1590 peer->ht_capabilities =
1591 os_zalloc(sizeof(struct ieee80211_ht_capabilities));
1592 if (peer->ht_capabilities == NULL)
1593 return -1;
1594 }
1595
1596 os_memcpy(peer->ht_capabilities, kde->ht_capabilities,
1597 sizeof(struct ieee80211_ht_capabilities));
1598 wpa_hexdump(MSG_DEBUG, "TDLS: Peer HT capabilities",
1599 (u8 *) peer->ht_capabilities,
1600 sizeof(struct ieee80211_ht_capabilities));
1601
1602 return 0;
1603}
1604
1605
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -08001606static int copy_peer_vht_capab(const struct wpa_eapol_ie_parse *kde,
1607 struct wpa_tdls_peer *peer)
1608{
1609 if (!kde->vht_capabilities ||
1610 kde->vht_capabilities_len <
1611 sizeof(struct ieee80211_vht_capabilities) ) {
1612 wpa_printf(MSG_DEBUG, "TDLS: No supported vht capabilities "
1613 "received");
1614 return 0;
1615 }
1616
1617 if (!peer->vht_capabilities) {
1618 peer->vht_capabilities =
1619 os_zalloc(sizeof(struct ieee80211_vht_capabilities));
1620 if (peer->vht_capabilities == NULL)
1621 return -1;
1622 }
1623
1624 os_memcpy(peer->vht_capabilities, kde->vht_capabilities,
1625 sizeof(struct ieee80211_vht_capabilities));
1626 wpa_hexdump(MSG_DEBUG, "TDLS: Peer VHT capabilities",
1627 (u8 *) peer->vht_capabilities,
1628 sizeof(struct ieee80211_vht_capabilities));
1629
1630 return 0;
1631}
1632
1633
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001634static int copy_peer_ext_capab(const struct wpa_eapol_ie_parse *kde,
1635 struct wpa_tdls_peer *peer)
1636{
1637 if (!kde->ext_capab) {
1638 wpa_printf(MSG_DEBUG, "TDLS: No extended capabilities "
1639 "received");
1640 return 0;
1641 }
1642
1643 if (!peer->ext_capab || peer->ext_capab_len < kde->ext_capab_len - 2) {
1644 /* Need to allocate buffer to fit the new information */
1645 os_free(peer->ext_capab);
1646 peer->ext_capab = os_zalloc(kde->ext_capab_len - 2);
1647 if (peer->ext_capab == NULL)
1648 return -1;
1649 }
1650
1651 peer->ext_capab_len = kde->ext_capab_len - 2;
1652 os_memcpy(peer->ext_capab, kde->ext_capab + 2, peer->ext_capab_len);
1653
1654 return 0;
1655}
1656
1657
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001658static int copy_peer_wmm_capab(const struct wpa_eapol_ie_parse *kde,
1659 struct wpa_tdls_peer *peer)
1660{
1661 struct wmm_information_element *wmm;
1662
1663 if (!kde->wmm) {
1664 wpa_printf(MSG_DEBUG, "TDLS: No supported WMM capabilities received");
1665 return 0;
1666 }
1667
1668 if (kde->wmm_len < sizeof(struct wmm_information_element)) {
1669 wpa_printf(MSG_DEBUG, "TDLS: Invalid supported WMM capabilities received");
1670 return -1;
1671 }
1672
1673 wmm = (struct wmm_information_element *) kde->wmm;
1674 peer->qos_info = wmm->qos_info;
1675
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07001676 peer->wmm_capable = 1;
1677
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001678 wpa_printf(MSG_DEBUG, "TDLS: Peer WMM QOS Info 0x%x", peer->qos_info);
1679 return 0;
1680}
1681
1682
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001683static int copy_peer_supp_channels(const struct wpa_eapol_ie_parse *kde,
1684 struct wpa_tdls_peer *peer)
1685{
1686 if (!kde->supp_channels) {
1687 wpa_printf(MSG_DEBUG, "TDLS: No supported channels received");
1688 return 0;
1689 }
1690
1691 if (!peer->supp_channels ||
1692 peer->supp_channels_len < kde->supp_channels_len) {
1693 os_free(peer->supp_channels);
1694 peer->supp_channels = os_zalloc(kde->supp_channels_len);
1695 if (peer->supp_channels == NULL)
1696 return -1;
1697 }
1698
1699 peer->supp_channels_len = kde->supp_channels_len;
1700
1701 os_memcpy(peer->supp_channels, kde->supp_channels,
1702 peer->supp_channels_len);
1703 wpa_hexdump(MSG_DEBUG, "TDLS: Peer Supported Channels",
1704 (u8 *) peer->supp_channels, peer->supp_channels_len);
1705 return 0;
1706}
1707
1708
1709static int copy_peer_supp_oper_classes(const struct wpa_eapol_ie_parse *kde,
1710 struct wpa_tdls_peer *peer)
1711{
1712 if (!kde->supp_oper_classes) {
1713 wpa_printf(MSG_DEBUG, "TDLS: No supported operating classes received");
1714 return 0;
1715 }
1716
1717 if (!peer->supp_oper_classes ||
1718 peer->supp_oper_classes_len < kde->supp_oper_classes_len) {
1719 os_free(peer->supp_oper_classes);
1720 peer->supp_oper_classes = os_zalloc(kde->supp_oper_classes_len);
1721 if (peer->supp_oper_classes == NULL)
1722 return -1;
1723 }
1724
1725 peer->supp_oper_classes_len = kde->supp_oper_classes_len;
1726 os_memcpy(peer->supp_oper_classes, kde->supp_oper_classes,
1727 peer->supp_oper_classes_len);
1728 wpa_hexdump(MSG_DEBUG, "TDLS: Peer Supported Operating Classes",
1729 (u8 *) peer->supp_oper_classes,
1730 peer->supp_oper_classes_len);
1731 return 0;
1732}
1733
1734
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07001735static int wpa_tdls_addset_peer(struct wpa_sm *sm, struct wpa_tdls_peer *peer,
1736 int add)
1737{
1738 return wpa_sm_tdls_peer_addset(sm, peer->addr, add, peer->aid,
1739 peer->capability,
1740 peer->supp_rates, peer->supp_rates_len,
1741 peer->ht_capabilities,
1742 peer->vht_capabilities,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001743 peer->qos_info, peer->wmm_capable,
1744 peer->ext_capab, peer->ext_capab_len,
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07001745 peer->supp_channels,
1746 peer->supp_channels_len,
1747 peer->supp_oper_classes,
1748 peer->supp_oper_classes_len);
1749}
1750
1751
Jouni Malinen4c527402017-09-22 11:03:15 +03001752static int tdls_nonce_set(const u8 *nonce)
1753{
1754 int i;
1755
1756 for (i = 0; i < WPA_NONCE_LEN; i++) {
1757 if (nonce[i])
1758 return 1;
1759 }
1760
1761 return 0;
1762}
1763
1764
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001765static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
1766 const u8 *buf, size_t len)
1767{
1768 struct wpa_tdls_peer *peer;
1769 struct wpa_eapol_ie_parse kde;
1770 struct wpa_ie_data ie;
1771 int cipher;
1772 const u8 *cpos;
1773 struct wpa_tdls_ftie *ftie = NULL;
1774 struct wpa_tdls_timeoutie *timeoutie;
1775 struct wpa_tdls_lnkid *lnkid;
1776 u32 lifetime = 0;
1777#if 0
1778 struct rsn_ie_hdr *hdr;
1779 u8 *pos;
1780 u16 rsn_capab;
1781 u16 rsn_ver;
1782#endif
1783 u8 dtoken;
1784 u16 ielen;
1785 u16 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1786 int tdls_prohibited = sm->tdls_prohibited;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001787 int existing_peer = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001788
1789 if (len < 3 + 3)
1790 return -1;
1791
1792 cpos = buf;
1793 cpos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */;
1794
1795 /* driver had already verified the frame format */
1796 dtoken = *cpos++; /* dialog token */
1797
1798 wpa_printf(MSG_INFO, "TDLS: Dialog Token in TPK M1 %d", dtoken);
1799
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001800 peer = wpa_tdls_add_peer(sm, src_addr, &existing_peer);
1801 if (peer == NULL)
1802 goto error;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001803
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07001804 /* If found, use existing entry instead of adding a new one;
1805 * how to handle the case where both ends initiate at the
1806 * same time? */
1807 if (existing_peer) {
1808 if (peer->tpk_success) {
1809 wpa_printf(MSG_DEBUG, "TDLS: TDLS Setup Request while "
1810 "direct link is enabled - tear down the "
1811 "old link first");
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07001812 wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr);
1813 wpa_tdls_peer_clear(sm, peer);
1814 } else if (peer->initiator) {
1815 /*
1816 * An entry is already present, so check if we already
1817 * sent a TDLS Setup Request. If so, compare MAC
1818 * addresses and let the STA with the lower MAC address
1819 * continue as the initiator. The other negotiation is
1820 * terminated.
1821 */
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07001822 if (os_memcmp(sm->own_addr, src_addr, ETH_ALEN) < 0) {
1823 wpa_printf(MSG_DEBUG, "TDLS: Discard request "
1824 "from peer with higher address "
1825 MACSTR, MAC2STR(src_addr));
1826 return -1;
1827 } else {
1828 wpa_printf(MSG_DEBUG, "TDLS: Accept request "
1829 "from peer with lower address "
1830 MACSTR " (terminate previously "
1831 "initiated negotiation",
1832 MAC2STR(src_addr));
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07001833 wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK,
1834 peer->addr);
1835 wpa_tdls_peer_clear(sm, peer);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07001836 }
1837 }
1838 }
1839
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001840 /* capability information */
1841 peer->capability = WPA_GET_LE16(cpos);
1842 cpos += 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001843
1844 ielen = len - (cpos - buf); /* start of IE in buf */
1845 if (wpa_supplicant_parse_ies(cpos, ielen, &kde) < 0) {
1846 wpa_printf(MSG_INFO, "TDLS: Failed to parse IEs in TPK M1");
1847 goto error;
1848 }
1849
1850 if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) {
1851 wpa_printf(MSG_INFO, "TDLS: No valid Link Identifier IE in "
1852 "TPK M1");
1853 goto error;
1854 }
1855 wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M1",
1856 kde.lnkid, kde.lnkid_len);
1857 lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
1858 if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) {
1859 wpa_printf(MSG_INFO, "TDLS: TPK M1 from diff BSS");
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001860 status = WLAN_STATUS_REQUEST_DECLINED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001861 goto error;
1862 }
1863
1864 wpa_printf(MSG_DEBUG, "TDLS: TPK M1 - TPK initiator " MACSTR,
1865 MAC2STR(src_addr));
1866
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001867 if (copy_supp_rates(&kde, peer) < 0)
1868 goto error;
1869
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001870 if (copy_peer_ht_capab(&kde, peer) < 0)
1871 goto error;
1872
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -08001873 if (copy_peer_vht_capab(&kde, peer) < 0)
1874 goto error;
1875
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001876 if (copy_peer_ext_capab(&kde, peer) < 0)
1877 goto error;
1878
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001879 if (copy_peer_supp_channels(&kde, peer) < 0)
1880 goto error;
1881
1882 if (copy_peer_supp_oper_classes(&kde, peer) < 0)
1883 goto error;
1884
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001885 peer->qos_info = kde.qosinfo;
1886
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001887 /* Overwrite with the qos_info obtained in WMM IE */
1888 if (copy_peer_wmm_capab(&kde, peer) < 0)
1889 goto error;
1890
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001891 peer->aid = kde.aid;
1892
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001893#ifdef CONFIG_TDLS_TESTING
1894 if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) {
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001895 peer = wpa_tdls_add_peer(sm, src_addr, NULL);
1896 if (peer == NULL)
1897 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001898 wpa_printf(MSG_DEBUG, "TDLS: Testing concurrent initiation of "
1899 "TDLS setup - send own request");
1900 peer->initiator = 1;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001901 wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL,
1902 NULL, 0, 0, NULL, 0, NULL, 0, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001903 wpa_tdls_send_tpk_m1(sm, peer);
1904 }
1905
1906 if ((tdls_testing & TDLS_TESTING_IGNORE_AP_PROHIBIT) &&
1907 tdls_prohibited) {
1908 wpa_printf(MSG_DEBUG, "TDLS: Testing - ignore AP prohibition "
1909 "on TDLS");
1910 tdls_prohibited = 0;
1911 }
1912#endif /* CONFIG_TDLS_TESTING */
1913
1914 if (tdls_prohibited) {
1915 wpa_printf(MSG_INFO, "TDLS: TDLS prohibited in this BSS");
1916 status = WLAN_STATUS_REQUEST_DECLINED;
1917 goto error;
1918 }
1919
1920 if (!wpa_tdls_get_privacy(sm)) {
1921 if (kde.rsn_ie) {
1922 wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M1 while "
1923 "security is disabled");
1924 status = WLAN_STATUS_SECURITY_DISABLED;
1925 goto error;
1926 }
1927 goto skip_rsn;
1928 }
1929
1930 if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie) ||
1931 kde.rsn_ie == NULL) {
1932 wpa_printf(MSG_INFO, "TDLS: No FTIE or RSN IE in TPK M1");
1933 status = WLAN_STATUS_INVALID_PARAMETERS;
1934 goto error;
1935 }
1936
1937 if (kde.rsn_ie_len > TDLS_MAX_IE_LEN) {
1938 wpa_printf(MSG_INFO, "TDLS: Too long Initiator RSN IE in "
1939 "TPK M1");
1940 status = WLAN_STATUS_INVALID_RSNIE;
1941 goto error;
1942 }
1943
1944 if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) {
1945 wpa_printf(MSG_INFO, "TDLS: Failed to parse RSN IE in TPK M1");
1946 status = WLAN_STATUS_INVALID_RSNIE;
1947 goto error;
1948 }
1949
1950 cipher = ie.pairwise_cipher;
1951 if (cipher & WPA_CIPHER_CCMP) {
1952 wpa_printf(MSG_DEBUG, "TDLS: Using CCMP for direct link");
1953 cipher = WPA_CIPHER_CCMP;
1954 } else {
1955 wpa_printf(MSG_INFO, "TDLS: No acceptable cipher in TPK M1");
1956 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
1957 goto error;
1958 }
1959
1960 if ((ie.capabilities &
1961 (WPA_CAPABILITY_NO_PAIRWISE | WPA_CAPABILITY_PEERKEY_ENABLED)) !=
1962 WPA_CAPABILITY_PEERKEY_ENABLED) {
1963 wpa_printf(MSG_INFO, "TDLS: Invalid RSN Capabilities in "
1964 "TPK M1");
1965 status = WLAN_STATUS_INVALID_RSN_IE_CAPAB;
1966 goto error;
1967 }
1968
1969 /* Lifetime */
1970 if (kde.key_lifetime == NULL) {
1971 wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M1");
1972 status = WLAN_STATUS_UNACCEPTABLE_LIFETIME;
1973 goto error;
1974 }
1975 timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime;
1976 lifetime = WPA_GET_LE32(timeoutie->value);
1977 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", lifetime);
1978 if (lifetime < 300) {
1979 wpa_printf(MSG_INFO, "TDLS: Too short TPK lifetime");
1980 status = WLAN_STATUS_UNACCEPTABLE_LIFETIME;
1981 goto error;
1982 }
1983
1984skip_rsn:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001985#ifdef CONFIG_TDLS_TESTING
1986 if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) {
1987 if (os_memcmp(sm->own_addr, peer->addr, ETH_ALEN) < 0) {
1988 /*
1989 * The request frame from us is going to win, so do not
1990 * replace information based on this request frame from
1991 * the peer.
1992 */
1993 goto skip_rsn_check;
1994 }
1995 }
1996#endif /* CONFIG_TDLS_TESTING */
1997
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001998 peer->initiator = 0; /* Need to check */
1999 peer->dtoken = dtoken;
2000
2001 if (!wpa_tdls_get_privacy(sm)) {
2002 peer->rsnie_i_len = 0;
2003 peer->rsnie_p_len = 0;
2004 peer->cipher = WPA_CIPHER_NONE;
2005 goto skip_rsn_check;
2006 }
2007
2008 ftie = (struct wpa_tdls_ftie *) kde.ftie;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002009 os_memcpy(peer->rsnie_i, kde.rsn_ie, kde.rsn_ie_len);
2010 peer->rsnie_i_len = kde.rsn_ie_len;
2011 peer->cipher = cipher;
2012
Jouni Malinen4c527402017-09-22 11:03:15 +03002013 if (os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) != 0 ||
2014 !tdls_nonce_set(peer->inonce)) {
Sunil Dutt61024722013-09-15 12:09:40 -07002015 /*
2016 * There is no point in updating the RNonce for every obtained
2017 * TPK M1 frame (e.g., retransmission due to timeout) with the
2018 * same INonce (SNonce in FTIE). However, if the TPK M1 is
2019 * retransmitted with a different INonce, update the RNonce
2020 * since this is for a new TDLS session.
2021 */
2022 wpa_printf(MSG_DEBUG,
2023 "TDLS: New TPK M1 INonce - generate new RNonce");
2024 os_memcpy(peer->inonce, ftie->Snonce, WPA_NONCE_LEN);
2025 if (os_get_random(peer->rnonce, WPA_NONCE_LEN)) {
2026 wpa_msg(sm->ctx->ctx, MSG_WARNING,
2027 "TDLS: Failed to get random data for responder nonce");
Sunil Dutt61024722013-09-15 12:09:40 -07002028 goto error;
2029 }
Jouni Malinen4c527402017-09-22 11:03:15 +03002030 peer->tk_set = 0; /* A new nonce results in a new TK */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002031 }
2032
2033#if 0
2034 /* get version info from RSNIE received from Peer */
2035 hdr = (struct rsn_ie_hdr *) kde.rsn_ie;
2036 rsn_ver = WPA_GET_LE16(hdr->version);
2037
2038 /* use min(peer's version, out version) */
2039 if (rsn_ver > RSN_VERSION)
2040 rsn_ver = RSN_VERSION;
2041
2042 hdr = (struct rsn_ie_hdr *) peer->rsnie_p;
2043
2044 hdr->elem_id = WLAN_EID_RSN;
2045 WPA_PUT_LE16(hdr->version, rsn_ver);
2046 pos = (u8 *) (hdr + 1);
2047
2048 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
2049 pos += RSN_SELECTOR_LEN;
2050 /* Include only the selected cipher in pairwise cipher suite */
2051 WPA_PUT_LE16(pos, 1);
2052 pos += 2;
2053 if (cipher == WPA_CIPHER_CCMP)
2054 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
2055 pos += RSN_SELECTOR_LEN;
2056
2057 WPA_PUT_LE16(pos, 1);
2058 pos += 2;
2059 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE);
2060 pos += RSN_SELECTOR_LEN;
2061
2062 rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
2063 rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2;
2064 WPA_PUT_LE16(pos, rsn_capab);
2065 pos += 2;
2066
2067 hdr->len = (pos - peer->rsnie_p) - 2;
2068 peer->rsnie_p_len = pos - peer->rsnie_p;
2069#endif
2070
2071 /* temp fix: validation of RSNIE later */
2072 os_memcpy(peer->rsnie_p, peer->rsnie_i, peer->rsnie_i_len);
2073 peer->rsnie_p_len = peer->rsnie_i_len;
2074
2075 wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for TPK handshake",
2076 peer->rsnie_p, peer->rsnie_p_len);
2077
2078 peer->lifetime = lifetime;
2079
2080 wpa_tdls_generate_tpk(peer, sm->own_addr, sm->bssid);
2081
2082skip_rsn_check:
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002083#ifdef CONFIG_TDLS_TESTING
2084 if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT)
2085 goto skip_add_peer;
2086#endif /* CONFIG_TDLS_TESTING */
2087
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002088 /* add supported rates, capabilities, and qos_info to the TDLS peer */
2089 if (wpa_tdls_addset_peer(sm, peer, 1) < 0)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002090 goto error;
2091
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002092#ifdef CONFIG_TDLS_TESTING
2093skip_add_peer:
2094#endif /* CONFIG_TDLS_TESTING */
Sunil Dutt73b28cc2013-09-30 17:38:41 +03002095 peer->tpk_in_progress = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002096
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002097 wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Response / TPK M2");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002098 if (wpa_tdls_send_tpk_m2(sm, src_addr, dtoken, lnkid, peer) < 0) {
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002099 wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002100 goto error;
2101 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002102
2103 return 0;
2104
2105error:
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002106 wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE, dtoken, 0,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002107 status);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002108 if (peer)
2109 wpa_tdls_peer_free(sm, peer);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002110 return -1;
2111}
2112
2113
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002114static int wpa_tdls_enable_link(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002115{
2116 peer->tpk_success = 1;
Sunil Dutt73b28cc2013-09-30 17:38:41 +03002117 peer->tpk_in_progress = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002118 eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer);
2119 if (wpa_tdls_get_privacy(sm)) {
2120 u32 lifetime = peer->lifetime;
2121 /*
2122 * Start the initiator process a bit earlier to avoid race
2123 * condition with the responder sending teardown request.
2124 */
2125 if (lifetime > 3 && peer->initiator)
2126 lifetime -= 3;
2127 eloop_register_timeout(lifetime, 0, wpa_tdls_tpk_timeout,
2128 sm, peer);
2129#ifdef CONFIG_TDLS_TESTING
2130 if (tdls_testing & TDLS_TESTING_NO_TPK_EXPIRATION) {
2131 wpa_printf(MSG_DEBUG, "TDLS: Testing - disable TPK "
2132 "expiration");
2133 eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer);
2134 }
2135#endif /* CONFIG_TDLS_TESTING */
2136 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002137
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002138 if (peer->reconfig_key && wpa_tdls_set_key(sm, peer) < 0) {
2139 wpa_printf(MSG_INFO, "TDLS: Could not configure key to the "
2140 "driver");
2141 return -1;
2142 }
2143 peer->reconfig_key = 0;
2144
2145 return wpa_sm_tdls_oper(sm, TDLS_ENABLE_LINK, peer->addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002146}
2147
2148
2149static int wpa_tdls_process_tpk_m2(struct wpa_sm *sm, const u8 *src_addr,
2150 const u8 *buf, size_t len)
2151{
2152 struct wpa_tdls_peer *peer;
2153 struct wpa_eapol_ie_parse kde;
2154 struct wpa_ie_data ie;
2155 int cipher;
2156 struct wpa_tdls_ftie *ftie;
2157 struct wpa_tdls_timeoutie *timeoutie;
2158 struct wpa_tdls_lnkid *lnkid;
2159 u32 lifetime;
2160 u8 dtoken;
2161 int ielen;
2162 u16 status;
2163 const u8 *pos;
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002164 int ret = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002165
2166 wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Response / TPK M2 "
2167 "(Peer " MACSTR ")", MAC2STR(src_addr));
2168 for (peer = sm->tdls; peer; peer = peer->next) {
2169 if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0)
2170 break;
2171 }
2172 if (peer == NULL) {
2173 wpa_printf(MSG_INFO, "TDLS: No matching peer found for "
2174 "TPK M2: " MACSTR, MAC2STR(src_addr));
2175 return -1;
2176 }
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07002177 if (!peer->initiator) {
2178 /*
2179 * This may happen if both devices try to initiate TDLS at the
2180 * same time and we accept the TPK M1 from the peer in
2181 * wpa_tdls_process_tpk_m1() and clear our previous state.
2182 */
2183 wpa_printf(MSG_INFO, "TDLS: We were not the initiator, so "
2184 "ignore TPK M2 from " MACSTR, MAC2STR(src_addr));
2185 return -1;
2186 }
Arik Nemtsova7baabb2015-12-10 12:56:07 +02002187
2188 if (peer->tpk_success) {
2189 wpa_printf(MSG_INFO, "TDLS: Ignore incoming TPK M2 retry, from "
2190 MACSTR " as TPK M3 was already sent",
2191 MAC2STR(src_addr));
2192 return 0;
2193 }
2194
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002195 wpa_tdls_tpk_retry_timeout_cancel(sm, peer, WLAN_TDLS_SETUP_REQUEST);
2196
Sunil Duttadce9cf2013-09-15 11:51:00 -07002197 if (len < 3 + 2 + 1) {
Sunil Duttd0ef38b2013-09-30 17:34:13 +03002198 wpa_tdls_disable_peer_link(sm, peer);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002199 return -1;
Sunil Duttadce9cf2013-09-15 11:51:00 -07002200 }
2201
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002202 pos = buf;
2203 pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */;
2204 status = WPA_GET_LE16(pos);
2205 pos += 2 /* status code */;
2206
2207 if (status != WLAN_STATUS_SUCCESS) {
2208 wpa_printf(MSG_INFO, "TDLS: Status code in TPK M2: %u",
2209 status);
Sunil Duttd0ef38b2013-09-30 17:34:13 +03002210 wpa_tdls_disable_peer_link(sm, peer);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002211 return -1;
2212 }
2213
2214 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
2215
2216 /* TODO: need to verify dialog token matches here or in kernel */
2217 dtoken = *pos++; /* dialog token */
2218
2219 wpa_printf(MSG_DEBUG, "TDLS: Dialog Token in TPK M2 %d", dtoken);
2220
Sunil Duttadce9cf2013-09-15 11:51:00 -07002221 if (len < 3 + 2 + 1 + 2) {
Sunil Duttd0ef38b2013-09-30 17:34:13 +03002222 wpa_tdls_disable_peer_link(sm, peer);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002223 return -1;
Sunil Duttadce9cf2013-09-15 11:51:00 -07002224 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002225
2226 /* capability information */
2227 peer->capability = WPA_GET_LE16(pos);
2228 pos += 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002229
2230 ielen = len - (pos - buf); /* start of IE in buf */
2231 if (wpa_supplicant_parse_ies(pos, ielen, &kde) < 0) {
2232 wpa_printf(MSG_INFO, "TDLS: Failed to parse IEs in TPK M2");
2233 goto error;
2234 }
2235
2236#ifdef CONFIG_TDLS_TESTING
2237 if (tdls_testing & TDLS_TESTING_DECLINE_RESP) {
2238 wpa_printf(MSG_DEBUG, "TDLS: Testing - decline response");
2239 status = WLAN_STATUS_REQUEST_DECLINED;
2240 goto error;
2241 }
2242#endif /* CONFIG_TDLS_TESTING */
2243
2244 if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) {
2245 wpa_printf(MSG_INFO, "TDLS: No valid Link Identifier IE in "
2246 "TPK M2");
2247 goto error;
2248 }
2249 wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M2",
2250 kde.lnkid, kde.lnkid_len);
2251 lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
2252
2253 if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) {
2254 wpa_printf(MSG_INFO, "TDLS: TPK M2 from different BSS");
2255 status = WLAN_STATUS_NOT_IN_SAME_BSS;
2256 goto error;
2257 }
2258
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002259 if (copy_supp_rates(&kde, peer) < 0)
2260 goto error;
2261
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002262 if (copy_peer_ht_capab(&kde, peer) < 0)
2263 goto error;
2264
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -08002265 if (copy_peer_vht_capab(&kde, peer) < 0)
2266 goto error;
2267
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002268 if (copy_peer_ext_capab(&kde, peer) < 0)
2269 goto error;
2270
Dmitry Shmidt344abd32014-01-14 13:17:00 -08002271 if (copy_peer_supp_channels(&kde, peer) < 0)
2272 goto error;
2273
2274 if (copy_peer_supp_oper_classes(&kde, peer) < 0)
2275 goto error;
2276
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002277 peer->qos_info = kde.qosinfo;
2278
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002279 /* Overwrite with the qos_info obtained in WMM IE */
2280 if (copy_peer_wmm_capab(&kde, peer) < 0)
2281 goto error;
2282
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002283 peer->aid = kde.aid;
2284
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002285 if (!wpa_tdls_get_privacy(sm)) {
2286 peer->rsnie_p_len = 0;
2287 peer->cipher = WPA_CIPHER_NONE;
2288 goto skip_rsn;
2289 }
2290
2291 if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie) ||
2292 kde.rsn_ie == NULL) {
2293 wpa_printf(MSG_INFO, "TDLS: No FTIE or RSN IE in TPK M2");
2294 status = WLAN_STATUS_INVALID_PARAMETERS;
2295 goto error;
2296 }
2297 wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M2",
2298 kde.rsn_ie, kde.rsn_ie_len);
2299
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002300 if (kde.rsn_ie_len > TDLS_MAX_IE_LEN) {
2301 wpa_printf(MSG_INFO,
2302 "TDLS: Too long Responder RSN IE in TPK M2");
2303 status = WLAN_STATUS_INVALID_RSNIE;
2304 goto error;
2305 }
2306
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002307 /*
2308 * FIX: bitwise comparison of RSN IE is not the correct way of
2309 * validation this. It can be different, but certain fields must
2310 * match. Since we list only a single pairwise cipher in TPK M1, the
2311 * memcmp is likely to work in most cases, though.
2312 */
2313 if (kde.rsn_ie_len != peer->rsnie_i_len ||
2314 os_memcmp(peer->rsnie_i, kde.rsn_ie, peer->rsnie_i_len) != 0) {
2315 wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M2 does "
2316 "not match with RSN IE used in TPK M1");
2317 wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Sent in TPK M1",
2318 peer->rsnie_i, peer->rsnie_i_len);
2319 wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M2",
2320 kde.rsn_ie, kde.rsn_ie_len);
2321 status = WLAN_STATUS_INVALID_RSNIE;
2322 goto error;
2323 }
2324
2325 if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) {
2326 wpa_printf(MSG_INFO, "TDLS: Failed to parse RSN IE in TPK M2");
2327 status = WLAN_STATUS_INVALID_RSNIE;
2328 goto error;
2329 }
2330
2331 cipher = ie.pairwise_cipher;
2332 if (cipher == WPA_CIPHER_CCMP) {
2333 wpa_printf(MSG_DEBUG, "TDLS: Using CCMP for direct link");
2334 cipher = WPA_CIPHER_CCMP;
2335 } else {
2336 wpa_printf(MSG_INFO, "TDLS: No acceptable cipher in TPK M2");
2337 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
2338 goto error;
2339 }
2340
2341 wpa_hexdump(MSG_DEBUG, "TDLS: FTIE Received from TPK M2",
2342 kde.ftie, sizeof(*ftie));
2343 ftie = (struct wpa_tdls_ftie *) kde.ftie;
2344
2345 if (!os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) == 0) {
2346 wpa_printf(MSG_INFO, "TDLS: FTIE SNonce in TPK M2 does "
2347 "not match with FTIE SNonce used in TPK M1");
2348 /* Silently discard the frame */
2349 return -1;
2350 }
2351
2352 /* Responder Nonce and RSN IE */
2353 os_memcpy(peer->rnonce, ftie->Anonce, WPA_NONCE_LEN);
2354 os_memcpy(peer->rsnie_p, kde.rsn_ie, kde.rsn_ie_len);
2355 peer->rsnie_p_len = kde.rsn_ie_len;
2356 peer->cipher = cipher;
2357
2358 /* Lifetime */
2359 if (kde.key_lifetime == NULL) {
2360 wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M2");
2361 status = WLAN_STATUS_UNACCEPTABLE_LIFETIME;
2362 goto error;
2363 }
2364 timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime;
2365 lifetime = WPA_GET_LE32(timeoutie->value);
2366 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds in TPK M2",
2367 lifetime);
2368 if (lifetime != peer->lifetime) {
2369 wpa_printf(MSG_INFO, "TDLS: Unexpected TPK lifetime %u in "
2370 "TPK M2 (expected %u)", lifetime, peer->lifetime);
2371 status = WLAN_STATUS_UNACCEPTABLE_LIFETIME;
2372 goto error;
2373 }
2374
2375 wpa_tdls_generate_tpk(peer, sm->own_addr, sm->bssid);
2376
2377 /* Process MIC check to see if TPK M2 is right */
2378 if (wpa_supplicant_verify_tdls_mic(2, peer, (u8 *) lnkid,
2379 (u8 *) timeoutie, ftie) < 0) {
2380 /* Discard the frame */
2381 wpa_tdls_del_key(sm, peer);
Sunil Dutt38ffd882013-09-30 17:23:23 +03002382 wpa_tdls_disable_peer_link(sm, peer);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002383 return -1;
2384 }
2385
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002386 if (wpa_tdls_set_key(sm, peer) < 0) {
2387 /*
2388 * Some drivers may not be able to config the key prior to full
2389 * STA entry having been configured.
2390 */
2391 wpa_printf(MSG_DEBUG, "TDLS: Try to configure TPK again after "
2392 "STA entry is complete");
2393 peer->reconfig_key = 1;
2394 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002395
2396skip_rsn:
2397 peer->dtoken = dtoken;
2398
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002399 /* add supported rates, capabilities, and qos_info to the TDLS peer */
2400 if (wpa_tdls_addset_peer(sm, peer, 0) < 0)
2401 goto error;
2402
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002403 wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Confirm / "
2404 "TPK Handshake Message 3");
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002405 if (wpa_tdls_send_tpk_m3(sm, src_addr, dtoken, lnkid, peer) < 0)
2406 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002407
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002408 if (!peer->tpk_success) {
2409 /*
2410 * Enable Link only when tpk_success is 0, signifying that this
2411 * processing of TPK M2 frame is not because of a retransmission
2412 * during TDLS setup handshake.
2413 */
2414 ret = wpa_tdls_enable_link(sm, peer);
2415 if (ret < 0) {
2416 wpa_printf(MSG_DEBUG, "TDLS: Could not enable link");
2417 wpa_tdls_do_teardown(
2418 sm, peer,
2419 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
2420 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002421 }
2422 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002423
2424error:
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002425 wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, dtoken, 1,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002426 status);
Sunil Duttd0ef38b2013-09-30 17:34:13 +03002427 wpa_tdls_disable_peer_link(sm, peer);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002428 return -1;
2429}
2430
2431
2432static int wpa_tdls_process_tpk_m3(struct wpa_sm *sm, const u8 *src_addr,
2433 const u8 *buf, size_t len)
2434{
2435 struct wpa_tdls_peer *peer;
2436 struct wpa_eapol_ie_parse kde;
2437 struct wpa_tdls_ftie *ftie;
2438 struct wpa_tdls_timeoutie *timeoutie;
2439 struct wpa_tdls_lnkid *lnkid;
2440 int ielen;
2441 u16 status;
2442 const u8 *pos;
2443 u32 lifetime;
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002444 int ret = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002445
2446 wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Confirm / TPK M3 "
2447 "(Peer " MACSTR ")", MAC2STR(src_addr));
2448 for (peer = sm->tdls; peer; peer = peer->next) {
2449 if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0)
2450 break;
2451 }
2452 if (peer == NULL) {
2453 wpa_printf(MSG_INFO, "TDLS: No matching peer found for "
2454 "TPK M3: " MACSTR, MAC2STR(src_addr));
2455 return -1;
2456 }
2457 wpa_tdls_tpk_retry_timeout_cancel(sm, peer, WLAN_TDLS_SETUP_RESPONSE);
2458
2459 if (len < 3 + 3)
Sunil Duttadce9cf2013-09-15 11:51:00 -07002460 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002461 pos = buf;
2462 pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */;
2463
2464 status = WPA_GET_LE16(pos);
2465
2466 if (status != 0) {
2467 wpa_printf(MSG_INFO, "TDLS: Status code in TPK M3: %u",
2468 status);
Sunil Duttadce9cf2013-09-15 11:51:00 -07002469 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002470 }
2471 pos += 2 /* status code */ + 1 /* dialog token */;
2472
2473 ielen = len - (pos - buf); /* start of IE in buf */
Dmitry Shmidt0c08fdc2014-06-20 10:16:40 -07002474
2475 /*
2476 * Don't reject the message if failing to parse IEs. The IEs we need are
2477 * explicitly checked below. Some APs piggy-back broken IEs to the end
2478 * of a TDLS Confirm packet, which will fail the link if we don't ignore
2479 * this error.
2480 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002481 if (wpa_supplicant_parse_ies((const u8 *) pos, ielen, &kde) < 0) {
Dmitry Shmidt0c08fdc2014-06-20 10:16:40 -07002482 wpa_printf(MSG_DEBUG,
2483 "TDLS: Failed to parse KDEs in TPK M3 - ignore as an interop workaround");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002484 }
2485
2486 if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) {
2487 wpa_printf(MSG_INFO, "TDLS: No Link Identifier IE in TPK M3");
Sunil Duttadce9cf2013-09-15 11:51:00 -07002488 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002489 }
2490 wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M3",
2491 (u8 *) kde.lnkid, kde.lnkid_len);
2492 lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
2493
2494 if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) {
2495 wpa_printf(MSG_INFO, "TDLS: TPK M3 from diff BSS");
Sunil Duttadce9cf2013-09-15 11:51:00 -07002496 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002497 }
2498
2499 if (!wpa_tdls_get_privacy(sm))
2500 goto skip_rsn;
2501
2502 if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie)) {
2503 wpa_printf(MSG_INFO, "TDLS: No FTIE in TPK M3");
Sunil Duttadce9cf2013-09-15 11:51:00 -07002504 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002505 }
2506 wpa_hexdump(MSG_DEBUG, "TDLS: FTIE Received from TPK M3",
2507 kde.ftie, sizeof(*ftie));
2508 ftie = (struct wpa_tdls_ftie *) kde.ftie;
2509
2510 if (kde.rsn_ie == NULL) {
2511 wpa_printf(MSG_INFO, "TDLS: No RSN IE in TPK M3");
Sunil Duttadce9cf2013-09-15 11:51:00 -07002512 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002513 }
2514 wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M3",
2515 kde.rsn_ie, kde.rsn_ie_len);
2516 if (kde.rsn_ie_len != peer->rsnie_p_len ||
2517 os_memcmp(kde.rsn_ie, peer->rsnie_p, peer->rsnie_p_len) != 0) {
2518 wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M3 does not match "
2519 "with the one sent in TPK M2");
Sunil Duttadce9cf2013-09-15 11:51:00 -07002520 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002521 }
2522
2523 if (!os_memcmp(peer->rnonce, ftie->Anonce, WPA_NONCE_LEN) == 0) {
2524 wpa_printf(MSG_INFO, "TDLS: FTIE ANonce in TPK M3 does "
2525 "not match with FTIE ANonce used in TPK M2");
Sunil Duttadce9cf2013-09-15 11:51:00 -07002526 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002527 }
2528
2529 if (!os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) == 0) {
2530 wpa_printf(MSG_INFO, "TDLS: FTIE SNonce in TPK M3 does not "
2531 "match with FTIE SNonce used in TPK M1");
Sunil Duttadce9cf2013-09-15 11:51:00 -07002532 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002533 }
2534
2535 if (kde.key_lifetime == NULL) {
2536 wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M3");
Sunil Duttadce9cf2013-09-15 11:51:00 -07002537 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002538 }
2539 timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime;
2540 wpa_hexdump(MSG_DEBUG, "TDLS: Timeout IE Received from TPK M3",
2541 (u8 *) timeoutie, sizeof(*timeoutie));
2542 lifetime = WPA_GET_LE32(timeoutie->value);
2543 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds in TPK M3",
2544 lifetime);
2545 if (lifetime != peer->lifetime) {
2546 wpa_printf(MSG_INFO, "TDLS: Unexpected TPK lifetime %u in "
2547 "TPK M3 (expected %u)", lifetime, peer->lifetime);
Sunil Duttadce9cf2013-09-15 11:51:00 -07002548 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002549 }
2550
2551 if (wpa_supplicant_verify_tdls_mic(3, peer, (u8 *) lnkid,
2552 (u8 *) timeoutie, ftie) < 0) {
2553 wpa_tdls_del_key(sm, peer);
Sunil Duttadce9cf2013-09-15 11:51:00 -07002554 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002555 }
2556
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002557 if (wpa_tdls_set_key(sm, peer) < 0) {
2558 /*
2559 * Some drivers may not be able to config the key prior to full
2560 * STA entry having been configured.
2561 */
2562 wpa_printf(MSG_DEBUG, "TDLS: Try to configure TPK again after "
2563 "STA entry is complete");
2564 peer->reconfig_key = 1;
2565 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002566
2567skip_rsn:
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002568 /* add supported rates, capabilities, and qos_info to the TDLS peer */
2569 if (wpa_tdls_addset_peer(sm, peer, 0) < 0)
2570 goto error;
2571
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002572 if (!peer->tpk_success) {
2573 /*
2574 * Enable Link only when tpk_success is 0, signifying that this
2575 * processing of TPK M3 frame is not because of a retransmission
2576 * during TDLS setup handshake.
2577 */
2578 ret = wpa_tdls_enable_link(sm, peer);
2579 if (ret < 0) {
2580 wpa_printf(MSG_DEBUG, "TDLS: Could not enable link");
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002581 goto error;
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002582 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002583 }
2584 return ret;
Sunil Duttadce9cf2013-09-15 11:51:00 -07002585error:
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002586 wpa_tdls_do_teardown(sm, peer, WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
Sunil Duttadce9cf2013-09-15 11:51:00 -07002587 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002588}
2589
2590
2591static u8 * wpa_add_tdls_timeoutie(u8 *pos, u8 *ie, size_t ie_len, u32 tsecs)
2592{
2593 struct wpa_tdls_timeoutie *lifetime = (struct wpa_tdls_timeoutie *) ie;
2594
2595 os_memset(lifetime, 0, ie_len);
2596 lifetime->ie_type = WLAN_EID_TIMEOUT_INTERVAL;
2597 lifetime->ie_len = sizeof(struct wpa_tdls_timeoutie) - 2;
2598 lifetime->interval_type = WLAN_TIMEOUT_KEY_LIFETIME;
2599 WPA_PUT_LE32(lifetime->value, tsecs);
2600 os_memcpy(pos, ie, ie_len);
2601 return pos + ie_len;
2602}
2603
2604
2605/**
2606 * wpa_tdls_start - Initiate TDLS handshake (send TPK Handshake Message 1)
2607 * @sm: Pointer to WPA state machine data from wpa_sm_init()
2608 * @peer: MAC address of the peer STA
2609 * Returns: 0 on success, or -1 on failure
2610 *
2611 * Send TPK Handshake Message 1 info to driver to start TDLS
2612 * handshake with the peer.
2613 */
2614int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr)
2615{
2616 struct wpa_tdls_peer *peer;
2617 int tdls_prohibited = sm->tdls_prohibited;
2618
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002619 if (sm->tdls_disabled || !sm->tdls_supported)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002620 return -1;
2621
2622#ifdef CONFIG_TDLS_TESTING
2623 if ((tdls_testing & TDLS_TESTING_IGNORE_AP_PROHIBIT) &&
2624 tdls_prohibited) {
2625 wpa_printf(MSG_DEBUG, "TDLS: Testing - ignore AP prohibition "
2626 "on TDLS");
2627 tdls_prohibited = 0;
2628 }
2629#endif /* CONFIG_TDLS_TESTING */
2630
2631 if (tdls_prohibited) {
2632 wpa_printf(MSG_DEBUG, "TDLS: TDLS is prohibited in this BSS - "
2633 "reject request to start setup");
2634 return -1;
2635 }
2636
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002637 peer = wpa_tdls_add_peer(sm, addr, NULL);
2638 if (peer == NULL)
2639 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002640
Sunil Dutt73b28cc2013-09-30 17:38:41 +03002641 if (peer->tpk_in_progress) {
2642 wpa_printf(MSG_DEBUG, "TDLS: Setup is already in progress with the peer");
2643 return 0;
2644 }
2645
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002646 peer->initiator = 1;
2647
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002648 /* add the peer to the driver as a "setup in progress" peer */
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002649 if (wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002650 NULL, 0, 0, NULL, 0, NULL, 0, NULL, 0)) {
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002651 wpa_tdls_disable_peer_link(sm, peer);
2652 return -1;
2653 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002654
Sunil Dutt73b28cc2013-09-30 17:38:41 +03002655 peer->tpk_in_progress = 1;
2656
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002657 if (wpa_tdls_send_tpk_m1(sm, peer) < 0) {
Sunil Duttd0ef38b2013-09-30 17:34:13 +03002658 wpa_tdls_disable_peer_link(sm, peer);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002659 return -1;
2660 }
2661
2662 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002663}
2664
2665
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002666void wpa_tdls_remove(struct wpa_sm *sm, const u8 *addr)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002667{
2668 struct wpa_tdls_peer *peer;
2669
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002670 if (sm->tdls_disabled || !sm->tdls_supported)
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002671 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002672
2673 for (peer = sm->tdls; peer; peer = peer->next) {
2674 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
2675 break;
2676 }
2677
2678 if (peer == NULL || !peer->tpk_success)
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002679 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002680
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002681 if (sm->tdls_external_setup) {
2682 /*
2683 * Disable previous link to allow renegotiation to be completed
2684 * on AP path.
2685 */
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07002686 wpa_tdls_do_teardown(sm, peer,
2687 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002688 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002689}
2690
2691
2692/**
2693 * wpa_supplicant_rx_tdls - Receive TDLS data frame
2694 *
2695 * This function is called to receive TDLS (ethertype = 0x890d) data frames.
2696 */
2697static void wpa_supplicant_rx_tdls(void *ctx, const u8 *src_addr,
2698 const u8 *buf, size_t len)
2699{
2700 struct wpa_sm *sm = ctx;
2701 struct wpa_tdls_frame *tf;
2702
2703 wpa_hexdump(MSG_DEBUG, "TDLS: Received Data frame encapsulation",
2704 buf, len);
2705
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002706 if (sm->tdls_disabled || !sm->tdls_supported) {
2707 wpa_printf(MSG_DEBUG, "TDLS: Discard message - TDLS disabled "
2708 "or unsupported by driver");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002709 return;
2710 }
2711
2712 if (os_memcmp(src_addr, sm->own_addr, ETH_ALEN) == 0) {
2713 wpa_printf(MSG_DEBUG, "TDLS: Discard copy of own message");
2714 return;
2715 }
2716
2717 if (len < sizeof(*tf)) {
2718 wpa_printf(MSG_INFO, "TDLS: Drop too short frame");
2719 return;
2720 }
2721
2722 /* Check to make sure its a valid encapsulated TDLS frame */
2723 tf = (struct wpa_tdls_frame *) buf;
2724 if (tf->payloadtype != 2 /* TDLS_RFTYPE */ ||
2725 tf->category != WLAN_ACTION_TDLS) {
2726 wpa_printf(MSG_INFO, "TDLS: Invalid frame - payloadtype=%u "
2727 "category=%u action=%u",
2728 tf->payloadtype, tf->category, tf->action);
2729 return;
2730 }
2731
2732 switch (tf->action) {
2733 case WLAN_TDLS_SETUP_REQUEST:
2734 wpa_tdls_process_tpk_m1(sm, src_addr, buf, len);
2735 break;
2736 case WLAN_TDLS_SETUP_RESPONSE:
2737 wpa_tdls_process_tpk_m2(sm, src_addr, buf, len);
2738 break;
2739 case WLAN_TDLS_SETUP_CONFIRM:
2740 wpa_tdls_process_tpk_m3(sm, src_addr, buf, len);
2741 break;
2742 case WLAN_TDLS_TEARDOWN:
2743 wpa_tdls_recv_teardown(sm, src_addr, buf, len);
2744 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002745 case WLAN_TDLS_DISCOVERY_REQUEST:
2746 wpa_tdls_process_discovery_request(sm, src_addr, buf, len);
2747 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002748 default:
2749 /* Kernel code will process remaining frames */
2750 wpa_printf(MSG_DEBUG, "TDLS: Ignore TDLS frame action code %u",
2751 tf->action);
2752 break;
2753 }
2754}
2755
2756
2757/**
2758 * wpa_tdls_init - Initialize driver interface parameters for TDLS
2759 * @wpa_s: Pointer to wpa_supplicant data
2760 * Returns: 0 on success, -1 on failure
2761 *
2762 * This function is called to initialize driver interface parameters for TDLS.
2763 * wpa_drv_init() must have been called before this function to initialize the
2764 * driver interface.
2765 */
2766int wpa_tdls_init(struct wpa_sm *sm)
2767{
2768 if (sm == NULL)
2769 return -1;
2770
Dmitry Shmidt04949592012-07-19 12:16:46 -07002771 sm->l2_tdls = l2_packet_init(sm->bridge_ifname ? sm->bridge_ifname :
2772 sm->ifname,
2773 sm->own_addr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002774 ETH_P_80211_ENCAP, wpa_supplicant_rx_tdls,
2775 sm, 0);
2776 if (sm->l2_tdls == NULL) {
2777 wpa_printf(MSG_ERROR, "TDLS: Failed to open l2_packet "
2778 "connection");
2779 return -1;
2780 }
2781
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002782 /*
2783 * Drivers that support TDLS but don't implement the get_capa callback
2784 * are assumed to perform everything internally
2785 */
2786 if (wpa_sm_tdls_get_capa(sm, &sm->tdls_supported,
2787 &sm->tdls_external_setup) < 0) {
2788 sm->tdls_supported = 1;
2789 sm->tdls_external_setup = 0;
2790 }
2791
2792 wpa_printf(MSG_DEBUG, "TDLS: TDLS operation%s supported by "
2793 "driver", sm->tdls_supported ? "" : " not");
2794 wpa_printf(MSG_DEBUG, "TDLS: Driver uses %s link setup",
2795 sm->tdls_external_setup ? "external" : "internal");
2796
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002797 return 0;
2798}
2799
2800
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002801void wpa_tdls_teardown_peers(struct wpa_sm *sm)
2802{
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002803 struct wpa_tdls_peer *peer, *tmp;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002804
2805 peer = sm->tdls;
2806
2807 wpa_printf(MSG_DEBUG, "TDLS: Tear down peers");
2808
2809 while (peer) {
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002810 tmp = peer->next;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002811 wpa_printf(MSG_DEBUG, "TDLS: Tear down peer " MACSTR,
2812 MAC2STR(peer->addr));
2813 if (sm->tdls_external_setup)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07002814 wpa_tdls_do_teardown(sm, peer,
2815 WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002816 else
2817 wpa_sm_tdls_oper(sm, TDLS_TEARDOWN, peer->addr);
2818
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002819 peer = tmp;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002820 }
2821}
2822
2823
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002824static void wpa_tdls_remove_peers(struct wpa_sm *sm)
2825{
2826 struct wpa_tdls_peer *peer, *tmp;
2827
2828 peer = sm->tdls;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002829
2830 while (peer) {
2831 int res;
2832 tmp = peer->next;
2833 res = wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr);
2834 wpa_printf(MSG_DEBUG, "TDLS: Remove peer " MACSTR " (res=%d)",
2835 MAC2STR(peer->addr), res);
2836 wpa_tdls_peer_free(sm, peer);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002837 peer = tmp;
2838 }
2839}
2840
2841
2842/**
2843 * wpa_tdls_deinit - Deinitialize driver interface parameters for TDLS
2844 *
2845 * This function is called to recover driver interface parameters for TDLS
2846 * and frees resources allocated for it.
2847 */
2848void wpa_tdls_deinit(struct wpa_sm *sm)
2849{
2850 if (sm == NULL)
2851 return;
2852
2853 if (sm->l2_tdls)
2854 l2_packet_deinit(sm->l2_tdls);
2855 sm->l2_tdls = NULL;
2856
2857 wpa_tdls_remove_peers(sm);
2858}
2859
2860
2861void wpa_tdls_assoc(struct wpa_sm *sm)
2862{
2863 wpa_printf(MSG_DEBUG, "TDLS: Remove peers on association");
2864 wpa_tdls_remove_peers(sm);
2865}
2866
2867
2868void wpa_tdls_disassoc(struct wpa_sm *sm)
2869{
2870 wpa_printf(MSG_DEBUG, "TDLS: Remove peers on disassociation");
2871 wpa_tdls_remove_peers(sm);
2872}
2873
2874
2875static int wpa_tdls_prohibited(const u8 *ies, size_t len)
2876{
2877 struct wpa_eapol_ie_parse elems;
2878
2879 if (ies == NULL)
2880 return 0;
2881
2882 if (wpa_supplicant_parse_ies(ies, len, &elems) < 0)
2883 return 0;
2884
2885 if (elems.ext_capab == NULL || elems.ext_capab_len < 2 + 5)
2886 return 0;
2887
2888 /* bit 38 - TDLS Prohibited */
2889 return !!(elems.ext_capab[2 + 4] & 0x40);
2890}
2891
2892
2893void wpa_tdls_ap_ies(struct wpa_sm *sm, const u8 *ies, size_t len)
2894{
2895 sm->tdls_prohibited = wpa_tdls_prohibited(ies, len);
2896 wpa_printf(MSG_DEBUG, "TDLS: TDLS is %s in the target BSS",
2897 sm->tdls_prohibited ? "prohibited" : "allowed");
2898}
2899
2900
2901void wpa_tdls_assoc_resp_ies(struct wpa_sm *sm, const u8 *ies, size_t len)
2902{
2903 if (!sm->tdls_prohibited && wpa_tdls_prohibited(ies, len)) {
2904 wpa_printf(MSG_DEBUG, "TDLS: TDLS prohibited based on "
2905 "(Re)Association Response IEs");
2906 sm->tdls_prohibited = 1;
2907 }
2908}
2909
2910
2911void wpa_tdls_enable(struct wpa_sm *sm, int enabled)
2912{
2913 wpa_printf(MSG_DEBUG, "TDLS: %s", enabled ? "enabled" : "disabled");
2914 sm->tdls_disabled = !enabled;
2915}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002916
2917
2918int wpa_tdls_is_external_setup(struct wpa_sm *sm)
2919{
2920 return sm->tdls_external_setup;
2921}