blob: 4baeb3b0d4312f731df482d731dd1a5353aaed68 [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;
114 int tpk_success;
Sunil Dutt73b28cc2013-09-30 17:38:41 +0300115 int tpk_in_progress;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700116
117 struct tpk_timer {
118 u8 dest[ETH_ALEN];
119 int count; /* Retry Count */
120 int timer; /* Timeout in milliseconds */
121 u8 action_code; /* TDLS frame type */
122 u8 dialog_token;
123 u16 status_code;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -0700124 u32 peer_capab;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700125 int buf_len; /* length of TPK message for retransmission */
126 u8 *buf; /* buffer for TPK message */
127 } sm_tmr;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800128
129 u16 capability;
130
131 u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
132 size_t supp_rates_len;
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800133
134 struct ieee80211_ht_capabilities *ht_capabilities;
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -0800135 struct ieee80211_vht_capabilities *vht_capabilities;
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800136
137 u8 qos_info;
138
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700139 u16 aid;
140
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800141 u8 *ext_capab;
142 size_t ext_capab_len;
Dmitry Shmidt344abd32014-01-14 13:17:00 -0800143
144 u8 *supp_channels;
145 size_t supp_channels_len;
146
147 u8 *supp_oper_classes;
148 size_t supp_oper_classes_len;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -0700149
150 u8 wmm_capable;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800151
152 /* channel switch currently enabled */
153 int chan_switch_enabled;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700154};
155
156
157static int wpa_tdls_get_privacy(struct wpa_sm *sm)
158{
159 /*
160 * Get info needed from supplicant to check if the current BSS supports
161 * security. Other than OPEN mode, rest are considered secured
162 * WEP/WPA/WPA2 hence TDLS frames are processed for TPK handshake.
163 */
164 return sm->pairwise_cipher != WPA_CIPHER_NONE;
165}
166
167
168static u8 * wpa_add_ie(u8 *pos, const u8 *ie, size_t ie_len)
169{
170 os_memcpy(pos, ie, ie_len);
171 return pos + ie_len;
172}
173
174
175static int wpa_tdls_del_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
176{
177 if (wpa_sm_set_key(sm, WPA_ALG_NONE, peer->addr,
178 0, 0, NULL, 0, NULL, 0) < 0) {
179 wpa_printf(MSG_WARNING, "TDLS: Failed to delete TPK-TK from "
180 "the driver");
181 return -1;
182 }
183
184 return 0;
185}
186
187
188static int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
189{
190 u8 key_len;
191 u8 rsc[6];
192 enum wpa_alg alg;
193
194 os_memset(rsc, 0, 6);
195
196 switch (peer->cipher) {
197 case WPA_CIPHER_CCMP:
198 alg = WPA_ALG_CCMP;
199 key_len = 16;
200 break;
201 case WPA_CIPHER_NONE:
202 wpa_printf(MSG_DEBUG, "TDLS: Pairwise Cipher Suite: "
203 "NONE - do not use pairwise keys");
204 return -1;
205 default:
206 wpa_printf(MSG_WARNING, "TDLS: Unsupported pairwise cipher %d",
207 sm->pairwise_cipher);
208 return -1;
209 }
210
211 if (wpa_sm_set_key(sm, alg, peer->addr, -1, 1,
212 rsc, sizeof(rsc), peer->tpk.tk, key_len) < 0) {
213 wpa_printf(MSG_WARNING, "TDLS: Failed to set TPK to the "
214 "driver");
215 return -1;
216 }
217 return 0;
218}
219
220
221static int wpa_tdls_send_tpk_msg(struct wpa_sm *sm, const u8 *dst,
222 u8 action_code, u8 dialog_token,
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -0700223 u16 status_code, u32 peer_capab,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700224 int initiator, const u8 *buf, size_t len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700225{
226 return wpa_sm_send_tdls_mgmt(sm, dst, action_code, dialog_token,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700227 status_code, peer_capab, initiator, buf,
228 len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700229}
230
231
232static int wpa_tdls_tpk_send(struct wpa_sm *sm, const u8 *dest, u8 action_code,
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -0700233 u8 dialog_token, u16 status_code, u32 peer_capab,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700234 int initiator, const u8 *msg, size_t msg_len)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700235{
236 struct wpa_tdls_peer *peer;
237
238 wpa_printf(MSG_DEBUG, "TDLS: TPK send dest=" MACSTR " action_code=%u "
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700239 "dialog_token=%u status_code=%u peer_capab=%u initiator=%d "
240 "msg_len=%u",
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700241 MAC2STR(dest), action_code, dialog_token, status_code,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700242 peer_capab, initiator, (unsigned int) msg_len);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700243
244 if (wpa_tdls_send_tpk_msg(sm, dest, action_code, dialog_token,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700245 status_code, peer_capab, initiator, msg,
246 msg_len)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700247 wpa_printf(MSG_INFO, "TDLS: Failed to send message "
248 "(action_code=%u)", action_code);
249 return -1;
250 }
251
252 if (action_code == WLAN_TDLS_SETUP_CONFIRM ||
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800253 action_code == WLAN_TDLS_TEARDOWN ||
254 action_code == WLAN_TDLS_DISCOVERY_REQUEST ||
255 action_code == WLAN_TDLS_DISCOVERY_RESPONSE)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700256 return 0; /* No retries */
257
258 for (peer = sm->tdls; peer; peer = peer->next) {
259 if (os_memcmp(peer->addr, dest, ETH_ALEN) == 0)
260 break;
261 }
262
263 if (peer == NULL) {
264 wpa_printf(MSG_INFO, "TDLS: No matching entry found for "
265 "retry " MACSTR, MAC2STR(dest));
266 return 0;
267 }
268
269 eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
270
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -0700271 if (action_code == WLAN_TDLS_SETUP_RESPONSE) {
272 peer->sm_tmr.count = TPK_M2_RETRY_COUNT;
273 peer->sm_tmr.timer = TPK_M2_TIMEOUT;
274 } else {
275 peer->sm_tmr.count = TPK_M1_RETRY_COUNT;
276 peer->sm_tmr.timer = TPK_M1_TIMEOUT;
277 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700278
279 /* Copy message to resend on timeout */
280 os_memcpy(peer->sm_tmr.dest, dest, ETH_ALEN);
281 peer->sm_tmr.action_code = action_code;
282 peer->sm_tmr.dialog_token = dialog_token;
283 peer->sm_tmr.status_code = status_code;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -0700284 peer->sm_tmr.peer_capab = peer_capab;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700285 peer->sm_tmr.buf_len = msg_len;
286 os_free(peer->sm_tmr.buf);
287 peer->sm_tmr.buf = os_malloc(msg_len);
288 if (peer->sm_tmr.buf == NULL)
289 return -1;
290 os_memcpy(peer->sm_tmr.buf, msg, msg_len);
291
292 wpa_printf(MSG_DEBUG, "TDLS: Retry timeout registered "
293 "(action_code=%u)", action_code);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -0700294 eloop_register_timeout(peer->sm_tmr.timer / 1000,
295 (peer->sm_tmr.timer % 1000) * 1000,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700296 wpa_tdls_tpk_retry_timeout, sm, peer);
297 return 0;
298}
299
300
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800301static int wpa_tdls_do_teardown(struct wpa_sm *sm, struct wpa_tdls_peer *peer,
Sunil Dutt6a9f5222013-09-30 17:10:18 +0300302 u16 reason_code)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800303{
304 int ret;
305
Sunil Dutt6a9f5222013-09-30 17:10:18 +0300306 ret = wpa_tdls_send_teardown(sm, peer->addr, reason_code);
307 /* disable the link after teardown was sent */
Sunil Duttd0ef38b2013-09-30 17:34:13 +0300308 wpa_tdls_disable_peer_link(sm, peer);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800309
310 return ret;
311}
312
313
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700314static void wpa_tdls_tpk_retry_timeout(void *eloop_ctx, void *timeout_ctx)
315{
316
317 struct wpa_sm *sm = eloop_ctx;
318 struct wpa_tdls_peer *peer = timeout_ctx;
319
320 if (peer->sm_tmr.count) {
321 peer->sm_tmr.count--;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700322
323 wpa_printf(MSG_INFO, "TDLS: Retrying sending of message "
324 "(action_code=%u)",
325 peer->sm_tmr.action_code);
326
327 if (peer->sm_tmr.buf == NULL) {
328 wpa_printf(MSG_INFO, "TDLS: No retry buffer available "
329 "for action_code=%u",
330 peer->sm_tmr.action_code);
331 eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm,
332 peer);
333 return;
334 }
335
336 /* resend TPK Handshake Message to Peer */
337 if (wpa_tdls_send_tpk_msg(sm, peer->sm_tmr.dest,
338 peer->sm_tmr.action_code,
339 peer->sm_tmr.dialog_token,
340 peer->sm_tmr.status_code,
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -0700341 peer->sm_tmr.peer_capab,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700342 peer->initiator,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700343 peer->sm_tmr.buf,
344 peer->sm_tmr.buf_len)) {
345 wpa_printf(MSG_INFO, "TDLS: Failed to retry "
346 "transmission");
347 }
348
349 eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -0700350 eloop_register_timeout(peer->sm_tmr.timer / 1000,
351 (peer->sm_tmr.timer % 1000) * 1000,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700352 wpa_tdls_tpk_retry_timeout, sm, peer);
353 } else {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700354 eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
355
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800356 wpa_printf(MSG_DEBUG, "TDLS: Sending Teardown Request");
357 wpa_tdls_do_teardown(sm, peer,
Sunil Dutt6a9f5222013-09-30 17:10:18 +0300358 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700359 }
360}
361
362
363static void wpa_tdls_tpk_retry_timeout_cancel(struct wpa_sm *sm,
364 struct wpa_tdls_peer *peer,
365 u8 action_code)
366{
367 if (action_code == peer->sm_tmr.action_code) {
368 wpa_printf(MSG_DEBUG, "TDLS: Retry timeout cancelled for "
369 "action_code=%u", action_code);
370
371 /* Cancel Timeout registered */
372 eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
373
374 /* free all resources meant for retry */
375 os_free(peer->sm_tmr.buf);
376 peer->sm_tmr.buf = NULL;
377
378 peer->sm_tmr.count = 0;
379 peer->sm_tmr.timer = 0;
380 peer->sm_tmr.buf_len = 0;
381 peer->sm_tmr.action_code = 0xff;
382 } else {
383 wpa_printf(MSG_INFO, "TDLS: Error in cancelling retry timeout "
384 "(Unknown action_code=%u)", action_code);
385 }
386}
387
388
389static void wpa_tdls_generate_tpk(struct wpa_tdls_peer *peer,
390 const u8 *own_addr, const u8 *bssid)
391{
392 u8 key_input[SHA256_MAC_LEN];
393 const u8 *nonce[2];
394 size_t len[2];
395 u8 data[3 * ETH_ALEN];
396
397 /* IEEE Std 802.11z-2010 8.5.9.1:
398 * TPK-Key-Input = SHA-256(min(SNonce, ANonce) || max(SNonce, ANonce))
399 */
400 len[0] = WPA_NONCE_LEN;
401 len[1] = WPA_NONCE_LEN;
402 if (os_memcmp(peer->inonce, peer->rnonce, WPA_NONCE_LEN) < 0) {
403 nonce[0] = peer->inonce;
404 nonce[1] = peer->rnonce;
405 } else {
406 nonce[0] = peer->rnonce;
407 nonce[1] = peer->inonce;
408 }
409 wpa_hexdump(MSG_DEBUG, "TDLS: min(Nonce)", nonce[0], WPA_NONCE_LEN);
410 wpa_hexdump(MSG_DEBUG, "TDLS: max(Nonce)", nonce[1], WPA_NONCE_LEN);
411 sha256_vector(2, nonce, len, key_input);
412 wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-Key-Input",
413 key_input, SHA256_MAC_LEN);
414
415 /*
416 * TPK-Key-Data = KDF-N_KEY(TPK-Key-Input, "TDLS PMK",
417 * min(MAC_I, MAC_R) || max(MAC_I, MAC_R) || BSSID || N_KEY)
418 * TODO: is N_KEY really included in KDF Context and if so, in which
419 * presentation format (little endian 16-bit?) is it used? It gets
420 * added by the KDF anyway..
421 */
422
423 if (os_memcmp(own_addr, peer->addr, ETH_ALEN) < 0) {
424 os_memcpy(data, own_addr, ETH_ALEN);
425 os_memcpy(data + ETH_ALEN, peer->addr, ETH_ALEN);
426 } else {
427 os_memcpy(data, peer->addr, ETH_ALEN);
428 os_memcpy(data + ETH_ALEN, own_addr, ETH_ALEN);
429 }
430 os_memcpy(data + 2 * ETH_ALEN, bssid, ETH_ALEN);
431 wpa_hexdump(MSG_DEBUG, "TDLS: KDF Context", data, sizeof(data));
432
433 sha256_prf(key_input, SHA256_MAC_LEN, "TDLS PMK", data, sizeof(data),
434 (u8 *) &peer->tpk, sizeof(peer->tpk));
435 wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-KCK",
436 peer->tpk.kck, sizeof(peer->tpk.kck));
437 wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-TK",
438 peer->tpk.tk, sizeof(peer->tpk.tk));
439 peer->tpk_set = 1;
440}
441
442
443/**
444 * wpa_tdls_ftie_mic - Calculate TDLS FTIE MIC
445 * @kck: TPK-KCK
446 * @lnkid: Pointer to the beginning of Link Identifier IE
447 * @rsnie: Pointer to the beginning of RSN IE used for handshake
448 * @timeoutie: Pointer to the beginning of Timeout IE used for handshake
449 * @ftie: Pointer to the beginning of FT IE
450 * @mic: Pointer for writing MIC
451 *
452 * Calculate MIC for TDLS frame.
453 */
454static int wpa_tdls_ftie_mic(const u8 *kck, u8 trans_seq, const u8 *lnkid,
455 const u8 *rsnie, const u8 *timeoutie,
456 const u8 *ftie, u8 *mic)
457{
458 u8 *buf, *pos;
459 struct wpa_tdls_ftie *_ftie;
460 const struct wpa_tdls_lnkid *_lnkid;
461 int ret;
462 int len = 2 * ETH_ALEN + 1 + 2 + lnkid[1] + 2 + rsnie[1] +
463 2 + timeoutie[1] + 2 + ftie[1];
464 buf = os_zalloc(len);
465 if (!buf) {
466 wpa_printf(MSG_WARNING, "TDLS: No memory for MIC calculation");
467 return -1;
468 }
469
470 pos = buf;
471 _lnkid = (const struct wpa_tdls_lnkid *) lnkid;
472 /* 1) TDLS initiator STA MAC address */
473 os_memcpy(pos, _lnkid->init_sta, ETH_ALEN);
474 pos += ETH_ALEN;
475 /* 2) TDLS responder STA MAC address */
476 os_memcpy(pos, _lnkid->resp_sta, ETH_ALEN);
477 pos += ETH_ALEN;
478 /* 3) Transaction Sequence number */
479 *pos++ = trans_seq;
480 /* 4) Link Identifier IE */
481 os_memcpy(pos, lnkid, 2 + lnkid[1]);
482 pos += 2 + lnkid[1];
483 /* 5) RSN IE */
484 os_memcpy(pos, rsnie, 2 + rsnie[1]);
485 pos += 2 + rsnie[1];
486 /* 6) Timeout Interval IE */
487 os_memcpy(pos, timeoutie, 2 + timeoutie[1]);
488 pos += 2 + timeoutie[1];
489 /* 7) FTIE, with the MIC field of the FTIE set to 0 */
490 os_memcpy(pos, ftie, 2 + ftie[1]);
491 _ftie = (struct wpa_tdls_ftie *) pos;
492 os_memset(_ftie->mic, 0, TDLS_MIC_LEN);
493 pos += 2 + ftie[1];
494
495 wpa_hexdump(MSG_DEBUG, "TDLS: Data for FTIE MIC", buf, pos - buf);
496 wpa_hexdump_key(MSG_DEBUG, "TDLS: KCK", kck, 16);
497 ret = omac1_aes_128(kck, buf, pos - buf, mic);
498 os_free(buf);
499 wpa_hexdump(MSG_DEBUG, "TDLS: FTIE MIC", mic, 16);
500 return ret;
501}
502
503
504/**
505 * wpa_tdls_key_mic_teardown - Calculate TDLS FTIE MIC for Teardown frame
506 * @kck: TPK-KCK
507 * @trans_seq: Transaction Sequence Number (4 - Teardown)
508 * @rcode: Reason code for Teardown
509 * @dtoken: Dialog Token used for that particular link
510 * @lnkid: Pointer to the beginning of Link Identifier IE
511 * @ftie: Pointer to the beginning of FT IE
512 * @mic: Pointer for writing MIC
513 *
514 * Calculate MIC for TDLS frame.
515 */
516static int wpa_tdls_key_mic_teardown(const u8 *kck, u8 trans_seq, u16 rcode,
517 u8 dtoken, const u8 *lnkid,
518 const u8 *ftie, u8 *mic)
519{
520 u8 *buf, *pos;
521 struct wpa_tdls_ftie *_ftie;
522 int ret;
523 int len;
524
525 if (lnkid == NULL)
526 return -1;
527
528 len = 2 + lnkid[1] + sizeof(rcode) + sizeof(dtoken) +
529 sizeof(trans_seq) + 2 + ftie[1];
530
531 buf = os_zalloc(len);
532 if (!buf) {
533 wpa_printf(MSG_WARNING, "TDLS: No memory for MIC calculation");
534 return -1;
535 }
536
537 pos = buf;
538 /* 1) Link Identifier IE */
539 os_memcpy(pos, lnkid, 2 + lnkid[1]);
540 pos += 2 + lnkid[1];
541 /* 2) Reason Code */
542 WPA_PUT_LE16(pos, rcode);
543 pos += sizeof(rcode);
544 /* 3) Dialog token */
545 *pos++ = dtoken;
546 /* 4) Transaction Sequence number */
547 *pos++ = trans_seq;
548 /* 7) FTIE, with the MIC field of the FTIE set to 0 */
549 os_memcpy(pos, ftie, 2 + ftie[1]);
550 _ftie = (struct wpa_tdls_ftie *) pos;
551 os_memset(_ftie->mic, 0, TDLS_MIC_LEN);
552 pos += 2 + ftie[1];
553
554 wpa_hexdump(MSG_DEBUG, "TDLS: Data for FTIE MIC", buf, pos - buf);
555 wpa_hexdump_key(MSG_DEBUG, "TDLS: KCK", kck, 16);
556 ret = omac1_aes_128(kck, buf, pos - buf, mic);
557 os_free(buf);
558 wpa_hexdump(MSG_DEBUG, "TDLS: FTIE MIC", mic, 16);
559 return ret;
560}
561
562
563static int wpa_supplicant_verify_tdls_mic(u8 trans_seq,
564 struct wpa_tdls_peer *peer,
565 const u8 *lnkid, const u8 *timeoutie,
566 const struct wpa_tdls_ftie *ftie)
567{
568 u8 mic[16];
569
570 if (peer->tpk_set) {
571 wpa_tdls_ftie_mic(peer->tpk.kck, trans_seq, lnkid,
572 peer->rsnie_p, timeoutie, (u8 *) ftie,
573 mic);
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700574 if (os_memcmp_const(mic, ftie->mic, 16) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700575 wpa_printf(MSG_INFO, "TDLS: Invalid MIC in FTIE - "
576 "dropping packet");
577 wpa_hexdump(MSG_DEBUG, "TDLS: Received MIC",
578 ftie->mic, 16);
579 wpa_hexdump(MSG_DEBUG, "TDLS: Calculated MIC",
580 mic, 16);
581 return -1;
582 }
583 } else {
584 wpa_printf(MSG_WARNING, "TDLS: Could not verify TDLS MIC, "
585 "TPK not set - dropping packet");
586 return -1;
587 }
588 return 0;
589}
590
591
592static int wpa_supplicant_verify_tdls_mic_teardown(
593 u8 trans_seq, u16 rcode, u8 dtoken, struct wpa_tdls_peer *peer,
594 const u8 *lnkid, const struct wpa_tdls_ftie *ftie)
595{
596 u8 mic[16];
597
598 if (peer->tpk_set) {
599 wpa_tdls_key_mic_teardown(peer->tpk.kck, trans_seq, rcode,
600 dtoken, lnkid, (u8 *) ftie, mic);
Dmitry Shmidtc2817022014-07-02 10:32:10 -0700601 if (os_memcmp_const(mic, ftie->mic, 16) != 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700602 wpa_printf(MSG_INFO, "TDLS: Invalid MIC in Teardown - "
603 "dropping packet");
604 return -1;
605 }
606 } else {
607 wpa_printf(MSG_INFO, "TDLS: Could not verify TDLS Teardown "
608 "MIC, TPK not set - dropping packet");
609 return -1;
610 }
611 return 0;
612}
613
614
615static void wpa_tdls_tpk_timeout(void *eloop_ctx, void *timeout_ctx)
616{
617 struct wpa_sm *sm = eloop_ctx;
618 struct wpa_tdls_peer *peer = timeout_ctx;
619
620 /*
621 * On TPK lifetime expiration, we have an option of either tearing down
622 * the direct link or trying to re-initiate it. The selection of what
623 * to do is not strictly speaking controlled by our role in the expired
624 * link, but for now, use that to select whether to renew or tear down
625 * the link.
626 */
627
628 if (peer->initiator) {
629 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime expired for " MACSTR
630 " - try to renew", MAC2STR(peer->addr));
631 wpa_tdls_start(sm, peer->addr);
632 } else {
633 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime expired for " MACSTR
634 " - tear down", MAC2STR(peer->addr));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800635 wpa_tdls_do_teardown(sm, peer,
Sunil Dutt6a9f5222013-09-30 17:10:18 +0300636 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700637 }
638}
639
640
Dmitry Shmidtd30ac602014-06-30 09:54:22 -0700641static void wpa_tdls_peer_remove_from_list(struct wpa_sm *sm,
642 struct wpa_tdls_peer *peer)
643{
644 struct wpa_tdls_peer *cur, *prev;
645
646 cur = sm->tdls;
647 prev = NULL;
648 while (cur && cur != peer) {
649 prev = cur;
650 cur = cur->next;
651 }
652
653 if (cur != peer) {
654 wpa_printf(MSG_ERROR, "TDLS: Could not find peer " MACSTR
655 " to remove it from the list",
656 MAC2STR(peer->addr));
657 return;
658 }
659
660 if (prev)
661 prev->next = peer->next;
662 else
663 sm->tdls = peer->next;
664}
665
666
667static void wpa_tdls_peer_clear(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700668{
669 wpa_printf(MSG_DEBUG, "TDLS: Clear state for peer " MACSTR,
670 MAC2STR(peer->addr));
671 eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer);
672 eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer);
Dmitry Shmidt8da800a2013-04-24 12:57:01 -0700673 peer->reconfig_key = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700674 peer->initiator = 0;
Sunil Dutt73b28cc2013-09-30 17:38:41 +0300675 peer->tpk_in_progress = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700676 os_free(peer->sm_tmr.buf);
677 peer->sm_tmr.buf = NULL;
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800678 os_free(peer->ht_capabilities);
679 peer->ht_capabilities = NULL;
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -0800680 os_free(peer->vht_capabilities);
681 peer->vht_capabilities = NULL;
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800682 os_free(peer->ext_capab);
683 peer->ext_capab = NULL;
Dmitry Shmidt344abd32014-01-14 13:17:00 -0800684 os_free(peer->supp_channels);
685 peer->supp_channels = NULL;
686 os_free(peer->supp_oper_classes);
687 peer->supp_oper_classes = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700688 peer->rsnie_i_len = peer->rsnie_p_len = 0;
689 peer->cipher = 0;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -0700690 peer->qos_info = 0;
691 peer->wmm_capable = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700692 peer->tpk_set = peer->tpk_success = 0;
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800693 peer->chan_switch_enabled = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700694 os_memset(&peer->tpk, 0, sizeof(peer->tpk));
695 os_memset(peer->inonce, 0, WPA_NONCE_LEN);
696 os_memset(peer->rnonce, 0, WPA_NONCE_LEN);
697}
698
699
Dmitry Shmidtd30ac602014-06-30 09:54:22 -0700700static void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
701{
702 wpa_tdls_peer_clear(sm, peer);
703 wpa_tdls_peer_remove_from_list(sm, peer);
704 os_free(peer);
705}
706
707
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700708static void wpa_tdls_linkid(struct wpa_sm *sm, struct wpa_tdls_peer *peer,
709 struct wpa_tdls_lnkid *lnkid)
710{
711 lnkid->ie_type = WLAN_EID_LINK_ID;
712 lnkid->ie_len = 3 * ETH_ALEN;
713 os_memcpy(lnkid->bssid, sm->bssid, ETH_ALEN);
714 if (peer->initiator) {
715 os_memcpy(lnkid->init_sta, sm->own_addr, ETH_ALEN);
716 os_memcpy(lnkid->resp_sta, peer->addr, ETH_ALEN);
717 } else {
718 os_memcpy(lnkid->init_sta, peer->addr, ETH_ALEN);
719 os_memcpy(lnkid->resp_sta, sm->own_addr, ETH_ALEN);
720 }
721}
722
723
Dmitry Shmidtb58836e2014-04-29 14:35:56 -0700724static int wpa_tdls_send_teardown(struct wpa_sm *sm, const u8 *addr,
725 u16 reason_code)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700726{
727 struct wpa_tdls_peer *peer;
728 struct wpa_tdls_ftie *ftie;
729 struct wpa_tdls_lnkid lnkid;
730 u8 dialog_token;
731 u8 *rbuf, *pos;
732 int ielen;
733
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800734 if (sm->tdls_disabled || !sm->tdls_supported)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700735 return -1;
736
737 /* Find the node and free from the list */
738 for (peer = sm->tdls; peer; peer = peer->next) {
739 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
740 break;
741 }
742
743 if (peer == NULL) {
744 wpa_printf(MSG_INFO, "TDLS: No matching entry found for "
745 "Teardown " MACSTR, MAC2STR(addr));
746 return 0;
747 }
748
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800749 /* Cancel active channel switch before teardown */
750 if (peer->chan_switch_enabled) {
751 wpa_printf(MSG_DEBUG, "TDLS: First returning link with " MACSTR
752 " to base channel", MAC2STR(addr));
753 wpa_sm_tdls_disable_channel_switch(sm, peer->addr);
754 }
755
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700756 dialog_token = peer->dtoken;
757
758 wpa_printf(MSG_DEBUG, "TDLS: TDLS Teardown for " MACSTR,
759 MAC2STR(addr));
760
761 ielen = 0;
762 if (wpa_tdls_get_privacy(sm) && peer->tpk_set && peer->tpk_success) {
763 /* To add FTIE for Teardown request and compute MIC */
764 ielen += sizeof(*ftie);
765#ifdef CONFIG_TDLS_TESTING
766 if (tdls_testing & TDLS_TESTING_LONG_FRAME)
767 ielen += 170;
768#endif /* CONFIG_TDLS_TESTING */
769 }
770
771 rbuf = os_zalloc(ielen + 1);
772 if (rbuf == NULL)
773 return -1;
774 pos = rbuf;
775
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700776 if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700777 goto skip_ies;
778
779 ftie = (struct wpa_tdls_ftie *) pos;
780 ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
781 /* Using the recent nonce which should be for CONFIRM frame */
782 os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN);
783 os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
784 ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2;
785 pos = (u8 *) (ftie + 1);
786#ifdef CONFIG_TDLS_TESTING
787 if (tdls_testing & TDLS_TESTING_LONG_FRAME) {
788 wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to "
789 "FTIE");
790 ftie->ie_len += 170;
791 *pos++ = 255; /* FTIE subelem */
792 *pos++ = 168; /* FTIE subelem length */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800793 pos += 168;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700794 }
795#endif /* CONFIG_TDLS_TESTING */
796 wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TDLS Teardown handshake",
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800797 (u8 *) ftie, pos - (u8 *) ftie);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700798
799 /* compute MIC before sending */
800 wpa_tdls_linkid(sm, peer, &lnkid);
801 wpa_tdls_key_mic_teardown(peer->tpk.kck, 4, reason_code,
802 dialog_token, (u8 *) &lnkid, (u8 *) ftie,
803 ftie->mic);
804
805skip_ies:
806 /* TODO: register for a Timeout handler, if Teardown is not received at
807 * the other end, then try again another time */
808
809 /* request driver to send Teardown using this FTIE */
810 wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_TEARDOWN, 0,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700811 reason_code, 0, peer->initiator, rbuf, pos - rbuf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700812 os_free(rbuf);
813
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700814 return 0;
815}
816
817
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800818int wpa_tdls_teardown_link(struct wpa_sm *sm, const u8 *addr, u16 reason_code)
819{
820 struct wpa_tdls_peer *peer;
821
822 if (sm->tdls_disabled || !sm->tdls_supported)
823 return -1;
824
825 for (peer = sm->tdls; peer; peer = peer->next) {
826 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
827 break;
828 }
829
830 if (peer == NULL) {
831 wpa_printf(MSG_DEBUG, "TDLS: Could not find peer " MACSTR
832 " for link Teardown", MAC2STR(addr));
833 return -1;
834 }
835
836 if (!peer->tpk_success) {
837 wpa_printf(MSG_DEBUG, "TDLS: Peer " MACSTR
838 " not connected - cannot Teardown link", MAC2STR(addr));
839 return -1;
840 }
841
Sunil Dutt6a9f5222013-09-30 17:10:18 +0300842 return wpa_tdls_do_teardown(sm, peer, reason_code);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800843}
844
845
Sunil Dutt38ffd882013-09-30 17:23:23 +0300846static void wpa_tdls_disable_peer_link(struct wpa_sm *sm,
847 struct wpa_tdls_peer *peer)
848{
849 wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr);
850 wpa_tdls_peer_free(sm, peer);
851}
852
853
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700854void wpa_tdls_disable_unreachable_link(struct wpa_sm *sm, const u8 *addr)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800855{
856 struct wpa_tdls_peer *peer;
857
858 for (peer = sm->tdls; peer; peer = peer->next) {
859 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
860 break;
861 }
862
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700863 if (!peer || !peer->tpk_success) {
864 wpa_printf(MSG_DEBUG, "TDLS: Peer " MACSTR
865 " not connected - cannot teardown unreachable link",
866 MAC2STR(addr));
867 return;
868 }
869
870 if (wpa_tdls_is_external_setup(sm)) {
871 /*
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800872 * Get us on the base channel, disable the link, send a
873 * teardown packet through the AP, and then reset link data.
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700874 */
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -0800875 if (peer->chan_switch_enabled)
876 wpa_sm_tdls_disable_channel_switch(sm, peer->addr);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700877 wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, addr);
878 wpa_tdls_send_teardown(sm, addr,
879 WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE);
880 wpa_tdls_peer_free(sm, peer);
881 } else {
Sunil Dutt38ffd882013-09-30 17:23:23 +0300882 wpa_tdls_disable_peer_link(sm, peer);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -0700883 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800884}
885
886
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -0800887const char * wpa_tdls_get_link_status(struct wpa_sm *sm, const u8 *addr)
888{
889 struct wpa_tdls_peer *peer;
890
891 if (sm->tdls_disabled || !sm->tdls_supported)
892 return "disabled";
893
894 for (peer = sm->tdls; peer; peer = peer->next) {
895 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
896 break;
897 }
898
899 if (peer == NULL)
900 return "peer does not exist";
901
902 if (!peer->tpk_success)
903 return "peer not connected";
904
905 return "connected";
906}
907
908
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700909static int wpa_tdls_recv_teardown(struct wpa_sm *sm, const u8 *src_addr,
910 const u8 *buf, size_t len)
911{
912 struct wpa_tdls_peer *peer = NULL;
913 struct wpa_tdls_ftie *ftie;
914 struct wpa_tdls_lnkid *lnkid;
915 struct wpa_eapol_ie_parse kde;
916 u16 reason_code;
917 const u8 *pos;
918 int ielen;
919
920 /* Find the node and free from the list */
921 for (peer = sm->tdls; peer; peer = peer->next) {
922 if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0)
923 break;
924 }
925
926 if (peer == NULL) {
927 wpa_printf(MSG_INFO, "TDLS: No matching entry found for "
928 "Teardown " MACSTR, MAC2STR(src_addr));
929 return 0;
930 }
931
932 pos = buf;
933 pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */;
934
935 reason_code = WPA_GET_LE16(pos);
936 pos += 2;
937
938 wpa_printf(MSG_DEBUG, "TDLS: TDLS Teardown Request from " MACSTR
939 " (reason code %u)", MAC2STR(src_addr), reason_code);
940
941 ielen = len - (pos - buf); /* start of IE in buf */
942 if (wpa_supplicant_parse_ies((const u8 *) pos, ielen, &kde) < 0) {
943 wpa_printf(MSG_INFO, "TDLS: Failed to parse IEs in Teardown");
944 return -1;
945 }
946
947 if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) {
948 wpa_printf(MSG_INFO, "TDLS: No Link Identifier IE in TDLS "
949 "Teardown");
950 return -1;
951 }
952 lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
953
954 if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success)
955 goto skip_ftie;
956
957 if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie)) {
958 wpa_printf(MSG_INFO, "TDLS: No FTIE in TDLS Teardown");
959 return -1;
960 }
961
962 ftie = (struct wpa_tdls_ftie *) kde.ftie;
963
964 /* Process MIC check to see if TDLS Teardown is right */
965 if (wpa_supplicant_verify_tdls_mic_teardown(4, reason_code,
966 peer->dtoken, peer,
967 (u8 *) lnkid, ftie) < 0) {
968 wpa_printf(MSG_DEBUG, "TDLS: MIC failure for TDLS "
969 "Teardown Request from " MACSTR, MAC2STR(src_addr));
970 return -1;
971 }
972
973skip_ftie:
974 /*
975 * Request the driver to disable the direct link and clear associated
976 * keys.
977 */
Sunil Dutt38ffd882013-09-30 17:23:23 +0300978 wpa_tdls_disable_peer_link(sm, peer);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700979 return 0;
980}
981
982
983/**
984 * wpa_tdls_send_error - To send suitable TDLS status response with
985 * appropriate status code mentioning reason for error/failure.
986 * @dst - MAC addr of Peer station
987 * @tdls_action - TDLS frame type for which error code is sent
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700988 * @initiator - was this end the initiator of the connection
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700989 * @status - status code mentioning reason
990 */
991
992static int wpa_tdls_send_error(struct wpa_sm *sm, const u8 *dst,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -0700993 u8 tdls_action, u8 dialog_token, int initiator,
994 u16 status)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700995{
996 wpa_printf(MSG_DEBUG, "TDLS: Sending error to " MACSTR
997 " (action=%u status=%u)",
998 MAC2STR(dst), tdls_action, status);
999 return wpa_tdls_tpk_send(sm, dst, tdls_action, dialog_token, status,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001000 0, initiator, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001001}
1002
1003
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001004static struct wpa_tdls_peer *
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001005wpa_tdls_add_peer(struct wpa_sm *sm, const u8 *addr, int *existing)
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001006{
1007 struct wpa_tdls_peer *peer;
1008
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001009 if (existing)
1010 *existing = 0;
1011 for (peer = sm->tdls; peer; peer = peer->next) {
1012 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0) {
1013 if (existing)
1014 *existing = 1;
1015 return peer; /* re-use existing entry */
1016 }
1017 }
1018
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001019 wpa_printf(MSG_INFO, "TDLS: Creating peer entry for " MACSTR,
1020 MAC2STR(addr));
1021
1022 peer = os_zalloc(sizeof(*peer));
1023 if (peer == NULL)
1024 return NULL;
1025
1026 os_memcpy(peer->addr, addr, ETH_ALEN);
1027 peer->next = sm->tdls;
1028 sm->tdls = peer;
1029
1030 return peer;
1031}
1032
1033
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001034static int wpa_tdls_send_tpk_m1(struct wpa_sm *sm,
1035 struct wpa_tdls_peer *peer)
1036{
1037 size_t buf_len;
1038 struct wpa_tdls_timeoutie timeoutie;
1039 u16 rsn_capab;
1040 struct wpa_tdls_ftie *ftie;
1041 u8 *rbuf, *pos, *count_pos;
1042 u16 count;
1043 struct rsn_ie_hdr *hdr;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07001044 int status;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001045
1046 if (!wpa_tdls_get_privacy(sm)) {
1047 wpa_printf(MSG_DEBUG, "TDLS: No security used on the link");
1048 peer->rsnie_i_len = 0;
1049 goto skip_rsnie;
1050 }
1051
1052 /*
1053 * TPK Handshake Message 1:
1054 * FTIE: ANonce=0, SNonce=initiator nonce MIC=0, DataKDs=(RSNIE_I,
1055 * Timeout Interval IE))
1056 */
1057
1058 /* Filling RSN IE */
1059 hdr = (struct rsn_ie_hdr *) peer->rsnie_i;
1060 hdr->elem_id = WLAN_EID_RSN;
1061 WPA_PUT_LE16(hdr->version, RSN_VERSION);
1062
1063 pos = (u8 *) (hdr + 1);
1064 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
1065 pos += RSN_SELECTOR_LEN;
1066 count_pos = pos;
1067 pos += 2;
1068
1069 count = 0;
1070
1071 /*
1072 * AES-CCMP is the default Encryption preferred for TDLS, so
1073 * RSN IE is filled only with CCMP CIPHER
1074 * Note: TKIP is not used to encrypt TDLS link.
1075 *
1076 * Regardless of the cipher used on the AP connection, select CCMP
1077 * here.
1078 */
1079 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
1080 pos += RSN_SELECTOR_LEN;
1081 count++;
1082
1083 WPA_PUT_LE16(count_pos, count);
1084
1085 WPA_PUT_LE16(pos, 1);
1086 pos += 2;
1087 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE);
1088 pos += RSN_SELECTOR_LEN;
1089
1090 rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
1091 rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2;
1092#ifdef CONFIG_TDLS_TESTING
1093 if (tdls_testing & TDLS_TESTING_ALT_RSN_IE) {
1094 wpa_printf(MSG_DEBUG, "TDLS: Use alternative RSN IE for "
1095 "testing");
1096 rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
1097 }
1098#endif /* CONFIG_TDLS_TESTING */
1099 WPA_PUT_LE16(pos, rsn_capab);
1100 pos += 2;
1101#ifdef CONFIG_TDLS_TESTING
1102 if (tdls_testing & TDLS_TESTING_ALT_RSN_IE) {
1103 /* Number of PMKIDs */
1104 *pos++ = 0x00;
1105 *pos++ = 0x00;
1106 }
1107#endif /* CONFIG_TDLS_TESTING */
1108
1109 hdr->len = (pos - peer->rsnie_i) - 2;
1110 peer->rsnie_i_len = pos - peer->rsnie_i;
1111 wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for TPK handshake",
1112 peer->rsnie_i, peer->rsnie_i_len);
1113
1114skip_rsnie:
1115 buf_len = 0;
1116 if (wpa_tdls_get_privacy(sm))
1117 buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) +
1118 sizeof(struct wpa_tdls_timeoutie);
1119#ifdef CONFIG_TDLS_TESTING
1120 if (wpa_tdls_get_privacy(sm) &&
1121 (tdls_testing & TDLS_TESTING_LONG_FRAME))
1122 buf_len += 170;
1123 if (tdls_testing & TDLS_TESTING_DIFF_BSSID)
1124 buf_len += sizeof(struct wpa_tdls_lnkid);
1125#endif /* CONFIG_TDLS_TESTING */
1126 rbuf = os_zalloc(buf_len + 1);
1127 if (rbuf == NULL) {
1128 wpa_tdls_peer_free(sm, peer);
1129 return -1;
1130 }
1131 pos = rbuf;
1132
1133 if (!wpa_tdls_get_privacy(sm))
1134 goto skip_ies;
1135
1136 /* Initiator RSN IE */
1137 pos = wpa_add_ie(pos, peer->rsnie_i, peer->rsnie_i_len);
1138
1139 ftie = (struct wpa_tdls_ftie *) pos;
1140 ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
1141 ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2;
1142
1143 if (os_get_random(peer->inonce, WPA_NONCE_LEN)) {
1144 wpa_msg(sm->ctx->msg_ctx, MSG_WARNING,
1145 "TDLS: Failed to get random data for initiator Nonce");
1146 os_free(rbuf);
1147 wpa_tdls_peer_free(sm, peer);
1148 return -1;
1149 }
1150 wpa_hexdump(MSG_DEBUG, "TDLS: Initiator Nonce for TPK handshake",
1151 peer->inonce, WPA_NONCE_LEN);
1152 os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
1153
1154 wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TPK Handshake M1",
1155 (u8 *) ftie, sizeof(struct wpa_tdls_ftie));
1156
1157 pos = (u8 *) (ftie + 1);
1158
1159#ifdef CONFIG_TDLS_TESTING
1160 if (tdls_testing & TDLS_TESTING_LONG_FRAME) {
1161 wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to "
1162 "FTIE");
1163 ftie->ie_len += 170;
1164 *pos++ = 255; /* FTIE subelem */
1165 *pos++ = 168; /* FTIE subelem length */
1166 pos += 168;
1167 }
1168#endif /* CONFIG_TDLS_TESTING */
1169
1170 /* Lifetime */
1171 peer->lifetime = TPK_LIFETIME;
1172#ifdef CONFIG_TDLS_TESTING
1173 if (tdls_testing & TDLS_TESTING_SHORT_LIFETIME) {
1174 wpa_printf(MSG_DEBUG, "TDLS: Testing - use short TPK "
1175 "lifetime");
1176 peer->lifetime = 301;
1177 }
1178 if (tdls_testing & TDLS_TESTING_LONG_LIFETIME) {
1179 wpa_printf(MSG_DEBUG, "TDLS: Testing - use long TPK "
1180 "lifetime");
1181 peer->lifetime = 0xffffffff;
1182 }
1183#endif /* CONFIG_TDLS_TESTING */
1184 pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie,
1185 sizeof(timeoutie), peer->lifetime);
1186 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", peer->lifetime);
1187
1188skip_ies:
1189
1190#ifdef CONFIG_TDLS_TESTING
1191 if (tdls_testing & TDLS_TESTING_DIFF_BSSID) {
1192 wpa_printf(MSG_DEBUG, "TDLS: Testing - use incorrect BSSID in "
1193 "Link Identifier");
1194 struct wpa_tdls_lnkid *l = (struct wpa_tdls_lnkid *) pos;
1195 wpa_tdls_linkid(sm, peer, l);
1196 l->bssid[5] ^= 0x01;
1197 pos += sizeof(*l);
1198 }
1199#endif /* CONFIG_TDLS_TESTING */
1200
1201 wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Request / TPK "
1202 "Handshake Message 1 (peer " MACSTR ")",
1203 MAC2STR(peer->addr));
1204
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07001205 status = wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_SETUP_REQUEST,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001206 1, 0, 0, peer->initiator, rbuf, pos - rbuf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001207 os_free(rbuf);
1208
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07001209 return status;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001210}
1211
1212
1213static int wpa_tdls_send_tpk_m2(struct wpa_sm *sm,
1214 const unsigned char *src_addr, u8 dtoken,
1215 struct wpa_tdls_lnkid *lnkid,
1216 const struct wpa_tdls_peer *peer)
1217{
1218 u8 *rbuf, *pos;
1219 size_t buf_len;
1220 u32 lifetime;
1221 struct wpa_tdls_timeoutie timeoutie;
1222 struct wpa_tdls_ftie *ftie;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07001223 int status;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001224
1225 buf_len = 0;
1226 if (wpa_tdls_get_privacy(sm)) {
1227 /* Peer RSN IE, FTIE(Initiator Nonce, Responder Nonce),
1228 * Lifetime */
1229 buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) +
1230 sizeof(struct wpa_tdls_timeoutie);
1231#ifdef CONFIG_TDLS_TESTING
1232 if (tdls_testing & TDLS_TESTING_LONG_FRAME)
1233 buf_len += 170;
1234#endif /* CONFIG_TDLS_TESTING */
1235 }
1236
1237 rbuf = os_zalloc(buf_len + 1);
1238 if (rbuf == NULL)
1239 return -1;
1240 pos = rbuf;
1241
1242 if (!wpa_tdls_get_privacy(sm))
1243 goto skip_ies;
1244
1245 /* Peer RSN IE */
1246 pos = wpa_add_ie(pos, peer->rsnie_p, peer->rsnie_p_len);
1247
1248 ftie = (struct wpa_tdls_ftie *) pos;
1249 ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
1250 /* TODO: ftie->mic_control to set 2-RESPONSE */
1251 os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN);
1252 os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
1253 ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2;
1254 wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TPK M2",
1255 (u8 *) ftie, sizeof(*ftie));
1256
1257 pos = (u8 *) (ftie + 1);
1258
1259#ifdef CONFIG_TDLS_TESTING
1260 if (tdls_testing & TDLS_TESTING_LONG_FRAME) {
1261 wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to "
1262 "FTIE");
1263 ftie->ie_len += 170;
1264 *pos++ = 255; /* FTIE subelem */
1265 *pos++ = 168; /* FTIE subelem length */
1266 pos += 168;
1267 }
1268#endif /* CONFIG_TDLS_TESTING */
1269
1270 /* Lifetime */
1271 lifetime = peer->lifetime;
1272#ifdef CONFIG_TDLS_TESTING
1273 if (tdls_testing & TDLS_TESTING_WRONG_LIFETIME_RESP) {
1274 wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong TPK "
1275 "lifetime in response");
1276 lifetime++;
1277 }
1278#endif /* CONFIG_TDLS_TESTING */
1279 pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie,
1280 sizeof(timeoutie), lifetime);
1281 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds from initiator",
1282 lifetime);
1283
1284 /* compute MIC before sending */
1285 wpa_tdls_ftie_mic(peer->tpk.kck, 2, (u8 *) lnkid, peer->rsnie_p,
1286 (u8 *) &timeoutie, (u8 *) ftie, ftie->mic);
Dmitry Shmidt21de2142014-04-08 10:50:52 -07001287#ifdef CONFIG_TDLS_TESTING
1288 if (tdls_testing & TDLS_TESTING_WRONG_MIC) {
1289 wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong MIC");
1290 ftie->mic[0] ^= 0x01;
1291 }
1292#endif /* CONFIG_TDLS_TESTING */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001293
1294skip_ies:
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07001295 status = wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001296 dtoken, 0, 0, peer->initiator, rbuf,
1297 pos - rbuf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001298 os_free(rbuf);
1299
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07001300 return status;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001301}
1302
1303
1304static int wpa_tdls_send_tpk_m3(struct wpa_sm *sm,
1305 const unsigned char *src_addr, u8 dtoken,
1306 struct wpa_tdls_lnkid *lnkid,
1307 const struct wpa_tdls_peer *peer)
1308{
1309 u8 *rbuf, *pos;
1310 size_t buf_len;
1311 struct wpa_tdls_ftie *ftie;
1312 struct wpa_tdls_timeoutie timeoutie;
1313 u32 lifetime;
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07001314 int status;
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07001315 u32 peer_capab = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001316
1317 buf_len = 0;
1318 if (wpa_tdls_get_privacy(sm)) {
1319 /* Peer RSN IE, FTIE(Initiator Nonce, Responder Nonce),
1320 * Lifetime */
1321 buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) +
1322 sizeof(struct wpa_tdls_timeoutie);
1323#ifdef CONFIG_TDLS_TESTING
1324 if (tdls_testing & TDLS_TESTING_LONG_FRAME)
1325 buf_len += 170;
1326#endif /* CONFIG_TDLS_TESTING */
1327 }
1328
1329 rbuf = os_zalloc(buf_len + 1);
1330 if (rbuf == NULL)
1331 return -1;
1332 pos = rbuf;
1333
1334 if (!wpa_tdls_get_privacy(sm))
1335 goto skip_ies;
1336
1337 /* Peer RSN IE */
1338 pos = wpa_add_ie(pos, peer->rsnie_p, peer->rsnie_p_len);
1339
1340 ftie = (struct wpa_tdls_ftie *) pos;
1341 ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION;
1342 /*TODO: ftie->mic_control to set 3-CONFIRM */
1343 os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN);
1344 os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN);
1345 ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2;
1346
1347 pos = (u8 *) (ftie + 1);
1348
1349#ifdef CONFIG_TDLS_TESTING
1350 if (tdls_testing & TDLS_TESTING_LONG_FRAME) {
1351 wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to "
1352 "FTIE");
1353 ftie->ie_len += 170;
1354 *pos++ = 255; /* FTIE subelem */
1355 *pos++ = 168; /* FTIE subelem length */
1356 pos += 168;
1357 }
1358#endif /* CONFIG_TDLS_TESTING */
1359
1360 /* Lifetime */
1361 lifetime = peer->lifetime;
1362#ifdef CONFIG_TDLS_TESTING
1363 if (tdls_testing & TDLS_TESTING_WRONG_LIFETIME_CONF) {
1364 wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong TPK "
1365 "lifetime in confirm");
1366 lifetime++;
1367 }
1368#endif /* CONFIG_TDLS_TESTING */
1369 pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie,
1370 sizeof(timeoutie), lifetime);
1371 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds",
1372 lifetime);
1373
1374 /* compute MIC before sending */
1375 wpa_tdls_ftie_mic(peer->tpk.kck, 3, (u8 *) lnkid, peer->rsnie_p,
1376 (u8 *) &timeoutie, (u8 *) ftie, ftie->mic);
Dmitry Shmidt21de2142014-04-08 10:50:52 -07001377#ifdef CONFIG_TDLS_TESTING
1378 if (tdls_testing & TDLS_TESTING_WRONG_MIC) {
1379 wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong MIC");
1380 ftie->mic[0] ^= 0x01;
1381 }
1382#endif /* CONFIG_TDLS_TESTING */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001383
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07001384skip_ies:
1385
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07001386 if (peer->vht_capabilities)
1387 peer_capab |= TDLS_PEER_VHT;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07001388 if (peer->ht_capabilities)
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07001389 peer_capab |= TDLS_PEER_HT;
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07001390 if (peer->wmm_capable)
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07001391 peer_capab |= TDLS_PEER_WMM;
1392
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07001393 status = wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001394 dtoken, 0, peer_capab, peer->initiator,
1395 rbuf, pos - rbuf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001396 os_free(rbuf);
1397
Dmitry Shmidtd5c075b2013-08-05 14:36:10 -07001398 return status;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001399}
1400
1401
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001402static int wpa_tdls_send_discovery_response(struct wpa_sm *sm,
1403 struct wpa_tdls_peer *peer,
1404 u8 dialog_token)
1405{
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001406 size_t buf_len = 0;
1407 struct wpa_tdls_timeoutie timeoutie;
1408 u16 rsn_capab;
1409 u8 *rbuf, *pos, *count_pos;
1410 u16 count;
1411 struct rsn_ie_hdr *hdr;
1412 int status;
1413
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001414 wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Discovery Response "
1415 "(peer " MACSTR ")", MAC2STR(peer->addr));
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001416 if (!wpa_tdls_get_privacy(sm))
1417 goto skip_rsn_ies;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001418
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001419 /* Filling RSN IE */
1420 hdr = (struct rsn_ie_hdr *) peer->rsnie_i;
1421 hdr->elem_id = WLAN_EID_RSN;
1422 WPA_PUT_LE16(hdr->version, RSN_VERSION);
1423 pos = (u8 *) (hdr + 1);
1424 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
1425 pos += RSN_SELECTOR_LEN;
1426 count_pos = pos;
1427 pos += 2;
1428 count = 0;
1429
1430 /*
1431 * AES-CCMP is the default encryption preferred for TDLS, so
1432 * RSN IE is filled only with CCMP cipher suite.
1433 * Note: TKIP is not used to encrypt TDLS link.
1434 *
1435 * Regardless of the cipher used on the AP connection, select CCMP
1436 * here.
1437 */
1438 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
1439 pos += RSN_SELECTOR_LEN;
1440 count++;
1441 WPA_PUT_LE16(count_pos, count);
1442 WPA_PUT_LE16(pos, 1);
1443 pos += 2;
1444 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE);
1445 pos += RSN_SELECTOR_LEN;
1446
1447 rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
1448 rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2;
1449 WPA_PUT_LE16(pos, rsn_capab);
1450 pos += 2;
1451 hdr->len = (pos - (u8 *) hdr) - 2;
1452 peer->rsnie_i_len = pos - peer->rsnie_i;
1453
1454 wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for Discovery Response",
1455 (u8 *) hdr, hdr->len + 2);
1456skip_rsn_ies:
1457 buf_len = 0;
1458 if (wpa_tdls_get_privacy(sm)) {
1459 /* Peer RSN IE, Lifetime */
1460 buf_len += peer->rsnie_i_len +
1461 sizeof(struct wpa_tdls_timeoutie);
1462 }
1463 rbuf = os_zalloc(buf_len + 1);
1464 if (rbuf == NULL) {
1465 wpa_tdls_peer_free(sm, peer);
1466 return -1;
1467 }
1468 pos = rbuf;
1469
1470 if (!wpa_tdls_get_privacy(sm))
1471 goto skip_ies;
1472 /* Initiator RSN IE */
1473 pos = wpa_add_ie(pos, peer->rsnie_i, peer->rsnie_i_len);
1474 /* Lifetime */
1475 peer->lifetime = TPK_LIFETIME;
1476 pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie,
1477 sizeof(timeoutie), peer->lifetime);
1478 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", peer->lifetime);
1479skip_ies:
1480 status = wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_DISCOVERY_RESPONSE,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001481 dialog_token, 0, 0, 0, rbuf, pos - rbuf);
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001482 os_free(rbuf);
1483
1484 return status;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001485}
1486
1487
1488static int
1489wpa_tdls_process_discovery_request(struct wpa_sm *sm, const u8 *addr,
1490 const u8 *buf, size_t len)
1491{
1492 struct wpa_eapol_ie_parse kde;
1493 const struct wpa_tdls_lnkid *lnkid;
1494 struct wpa_tdls_peer *peer;
1495 size_t min_req_len = sizeof(struct wpa_tdls_frame) +
1496 1 /* dialog token */ + sizeof(struct wpa_tdls_lnkid);
1497 u8 dialog_token;
1498
1499 wpa_printf(MSG_DEBUG, "TDLS: Discovery Request from " MACSTR,
1500 MAC2STR(addr));
1501
1502 if (len < min_req_len) {
1503 wpa_printf(MSG_DEBUG, "TDLS Discovery Request is too short: "
1504 "%d", (int) len);
1505 return -1;
1506 }
1507
1508 dialog_token = buf[sizeof(struct wpa_tdls_frame)];
1509
Dmitry Shmidt0c08fdc2014-06-20 10:16:40 -07001510 /*
1511 * Some APs will tack on a weird IE to the end of a TDLS
1512 * discovery request packet. This needn't fail the response,
1513 * since the required IE are verified separately.
1514 */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001515 if (wpa_supplicant_parse_ies(buf + sizeof(struct wpa_tdls_frame) + 1,
1516 len - (sizeof(struct wpa_tdls_frame) + 1),
Dmitry Shmidt0c08fdc2014-06-20 10:16:40 -07001517 &kde) < 0) {
1518 wpa_printf(MSG_DEBUG,
1519 "TDLS: Failed to parse IEs in Discovery Request - ignore as an interop workaround");
1520 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001521
1522 if (!kde.lnkid) {
1523 wpa_printf(MSG_DEBUG, "TDLS: Link ID not found in Discovery "
1524 "Request");
1525 return -1;
1526 }
1527
1528 lnkid = (const struct wpa_tdls_lnkid *) kde.lnkid;
1529
1530 if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) {
1531 wpa_printf(MSG_DEBUG, "TDLS: Discovery Request from different "
1532 " BSS " MACSTR, MAC2STR(lnkid->bssid));
1533 return -1;
1534 }
1535
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001536 peer = wpa_tdls_add_peer(sm, addr, NULL);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001537 if (peer == NULL)
1538 return -1;
1539
1540 return wpa_tdls_send_discovery_response(sm, peer, dialog_token);
1541}
1542
1543
1544int wpa_tdls_send_discovery_request(struct wpa_sm *sm, const u8 *addr)
1545{
1546 if (sm->tdls_disabled || !sm->tdls_supported)
1547 return -1;
1548
1549 wpa_printf(MSG_DEBUG, "TDLS: Sending Discovery Request to peer "
1550 MACSTR, MAC2STR(addr));
1551 return wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_DISCOVERY_REQUEST,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001552 1, 0, 0, 1, NULL, 0);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001553}
1554
1555
1556static int copy_supp_rates(const struct wpa_eapol_ie_parse *kde,
1557 struct wpa_tdls_peer *peer)
1558{
1559 if (!kde->supp_rates) {
1560 wpa_printf(MSG_DEBUG, "TDLS: No supported rates received");
1561 return -1;
1562 }
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08001563 peer->supp_rates_len = merge_byte_arrays(
1564 peer->supp_rates, sizeof(peer->supp_rates),
1565 kde->supp_rates + 2, kde->supp_rates_len - 2,
Dmitry Shmidt34af3062013-07-11 10:46:32 -07001566 kde->ext_supp_rates ? kde->ext_supp_rates + 2 : NULL,
1567 kde->ext_supp_rates_len - 2);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001568 return 0;
1569}
1570
1571
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001572static int copy_peer_ht_capab(const struct wpa_eapol_ie_parse *kde,
1573 struct wpa_tdls_peer *peer)
1574{
1575 if (!kde->ht_capabilities ||
1576 kde->ht_capabilities_len <
1577 sizeof(struct ieee80211_ht_capabilities) ) {
1578 wpa_printf(MSG_DEBUG, "TDLS: No supported ht capabilities "
1579 "received");
1580 return 0;
1581 }
1582
1583 if (!peer->ht_capabilities) {
1584 peer->ht_capabilities =
1585 os_zalloc(sizeof(struct ieee80211_ht_capabilities));
1586 if (peer->ht_capabilities == NULL)
1587 return -1;
1588 }
1589
1590 os_memcpy(peer->ht_capabilities, kde->ht_capabilities,
1591 sizeof(struct ieee80211_ht_capabilities));
1592 wpa_hexdump(MSG_DEBUG, "TDLS: Peer HT capabilities",
1593 (u8 *) peer->ht_capabilities,
1594 sizeof(struct ieee80211_ht_capabilities));
1595
1596 return 0;
1597}
1598
1599
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -08001600static int copy_peer_vht_capab(const struct wpa_eapol_ie_parse *kde,
1601 struct wpa_tdls_peer *peer)
1602{
1603 if (!kde->vht_capabilities ||
1604 kde->vht_capabilities_len <
1605 sizeof(struct ieee80211_vht_capabilities) ) {
1606 wpa_printf(MSG_DEBUG, "TDLS: No supported vht capabilities "
1607 "received");
1608 return 0;
1609 }
1610
1611 if (!peer->vht_capabilities) {
1612 peer->vht_capabilities =
1613 os_zalloc(sizeof(struct ieee80211_vht_capabilities));
1614 if (peer->vht_capabilities == NULL)
1615 return -1;
1616 }
1617
1618 os_memcpy(peer->vht_capabilities, kde->vht_capabilities,
1619 sizeof(struct ieee80211_vht_capabilities));
1620 wpa_hexdump(MSG_DEBUG, "TDLS: Peer VHT capabilities",
1621 (u8 *) peer->vht_capabilities,
1622 sizeof(struct ieee80211_vht_capabilities));
1623
1624 return 0;
1625}
1626
1627
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001628static int copy_peer_ext_capab(const struct wpa_eapol_ie_parse *kde,
1629 struct wpa_tdls_peer *peer)
1630{
1631 if (!kde->ext_capab) {
1632 wpa_printf(MSG_DEBUG, "TDLS: No extended capabilities "
1633 "received");
1634 return 0;
1635 }
1636
1637 if (!peer->ext_capab || peer->ext_capab_len < kde->ext_capab_len - 2) {
1638 /* Need to allocate buffer to fit the new information */
1639 os_free(peer->ext_capab);
1640 peer->ext_capab = os_zalloc(kde->ext_capab_len - 2);
1641 if (peer->ext_capab == NULL)
1642 return -1;
1643 }
1644
1645 peer->ext_capab_len = kde->ext_capab_len - 2;
1646 os_memcpy(peer->ext_capab, kde->ext_capab + 2, peer->ext_capab_len);
1647
1648 return 0;
1649}
1650
1651
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001652static int copy_peer_wmm_capab(const struct wpa_eapol_ie_parse *kde,
1653 struct wpa_tdls_peer *peer)
1654{
1655 struct wmm_information_element *wmm;
1656
1657 if (!kde->wmm) {
1658 wpa_printf(MSG_DEBUG, "TDLS: No supported WMM capabilities received");
1659 return 0;
1660 }
1661
1662 if (kde->wmm_len < sizeof(struct wmm_information_element)) {
1663 wpa_printf(MSG_DEBUG, "TDLS: Invalid supported WMM capabilities received");
1664 return -1;
1665 }
1666
1667 wmm = (struct wmm_information_element *) kde->wmm;
1668 peer->qos_info = wmm->qos_info;
1669
Dmitry Shmidtdf5a7e42014-04-02 12:59:59 -07001670 peer->wmm_capable = 1;
1671
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001672 wpa_printf(MSG_DEBUG, "TDLS: Peer WMM QOS Info 0x%x", peer->qos_info);
1673 return 0;
1674}
1675
1676
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001677static int copy_peer_supp_channels(const struct wpa_eapol_ie_parse *kde,
1678 struct wpa_tdls_peer *peer)
1679{
1680 if (!kde->supp_channels) {
1681 wpa_printf(MSG_DEBUG, "TDLS: No supported channels received");
1682 return 0;
1683 }
1684
1685 if (!peer->supp_channels ||
1686 peer->supp_channels_len < kde->supp_channels_len) {
1687 os_free(peer->supp_channels);
1688 peer->supp_channels = os_zalloc(kde->supp_channels_len);
1689 if (peer->supp_channels == NULL)
1690 return -1;
1691 }
1692
1693 peer->supp_channels_len = kde->supp_channels_len;
1694
1695 os_memcpy(peer->supp_channels, kde->supp_channels,
1696 peer->supp_channels_len);
1697 wpa_hexdump(MSG_DEBUG, "TDLS: Peer Supported Channels",
1698 (u8 *) peer->supp_channels, peer->supp_channels_len);
1699 return 0;
1700}
1701
1702
1703static int copy_peer_supp_oper_classes(const struct wpa_eapol_ie_parse *kde,
1704 struct wpa_tdls_peer *peer)
1705{
1706 if (!kde->supp_oper_classes) {
1707 wpa_printf(MSG_DEBUG, "TDLS: No supported operating classes received");
1708 return 0;
1709 }
1710
1711 if (!peer->supp_oper_classes ||
1712 peer->supp_oper_classes_len < kde->supp_oper_classes_len) {
1713 os_free(peer->supp_oper_classes);
1714 peer->supp_oper_classes = os_zalloc(kde->supp_oper_classes_len);
1715 if (peer->supp_oper_classes == NULL)
1716 return -1;
1717 }
1718
1719 peer->supp_oper_classes_len = kde->supp_oper_classes_len;
1720 os_memcpy(peer->supp_oper_classes, kde->supp_oper_classes,
1721 peer->supp_oper_classes_len);
1722 wpa_hexdump(MSG_DEBUG, "TDLS: Peer Supported Operating Classes",
1723 (u8 *) peer->supp_oper_classes,
1724 peer->supp_oper_classes_len);
1725 return 0;
1726}
1727
1728
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07001729static int wpa_tdls_addset_peer(struct wpa_sm *sm, struct wpa_tdls_peer *peer,
1730 int add)
1731{
1732 return wpa_sm_tdls_peer_addset(sm, peer->addr, add, peer->aid,
1733 peer->capability,
1734 peer->supp_rates, peer->supp_rates_len,
1735 peer->ht_capabilities,
1736 peer->vht_capabilities,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001737 peer->qos_info, peer->wmm_capable,
1738 peer->ext_capab, peer->ext_capab_len,
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07001739 peer->supp_channels,
1740 peer->supp_channels_len,
1741 peer->supp_oper_classes,
1742 peer->supp_oper_classes_len);
1743}
1744
1745
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001746static int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr,
1747 const u8 *buf, size_t len)
1748{
1749 struct wpa_tdls_peer *peer;
1750 struct wpa_eapol_ie_parse kde;
1751 struct wpa_ie_data ie;
1752 int cipher;
1753 const u8 *cpos;
1754 struct wpa_tdls_ftie *ftie = NULL;
1755 struct wpa_tdls_timeoutie *timeoutie;
1756 struct wpa_tdls_lnkid *lnkid;
1757 u32 lifetime = 0;
1758#if 0
1759 struct rsn_ie_hdr *hdr;
1760 u8 *pos;
1761 u16 rsn_capab;
1762 u16 rsn_ver;
1763#endif
1764 u8 dtoken;
1765 u16 ielen;
1766 u16 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
1767 int tdls_prohibited = sm->tdls_prohibited;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001768 int existing_peer = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001769
1770 if (len < 3 + 3)
1771 return -1;
1772
1773 cpos = buf;
1774 cpos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */;
1775
1776 /* driver had already verified the frame format */
1777 dtoken = *cpos++; /* dialog token */
1778
1779 wpa_printf(MSG_INFO, "TDLS: Dialog Token in TPK M1 %d", dtoken);
1780
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001781 peer = wpa_tdls_add_peer(sm, src_addr, &existing_peer);
1782 if (peer == NULL)
1783 goto error;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001784
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07001785 /* If found, use existing entry instead of adding a new one;
1786 * how to handle the case where both ends initiate at the
1787 * same time? */
1788 if (existing_peer) {
1789 if (peer->tpk_success) {
1790 wpa_printf(MSG_DEBUG, "TDLS: TDLS Setup Request while "
1791 "direct link is enabled - tear down the "
1792 "old link first");
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07001793 wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr);
1794 wpa_tdls_peer_clear(sm, peer);
1795 } else if (peer->initiator) {
1796 /*
1797 * An entry is already present, so check if we already
1798 * sent a TDLS Setup Request. If so, compare MAC
1799 * addresses and let the STA with the lower MAC address
1800 * continue as the initiator. The other negotiation is
1801 * terminated.
1802 */
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07001803 if (os_memcmp(sm->own_addr, src_addr, ETH_ALEN) < 0) {
1804 wpa_printf(MSG_DEBUG, "TDLS: Discard request "
1805 "from peer with higher address "
1806 MACSTR, MAC2STR(src_addr));
1807 return -1;
1808 } else {
1809 wpa_printf(MSG_DEBUG, "TDLS: Accept request "
1810 "from peer with lower address "
1811 MACSTR " (terminate previously "
1812 "initiated negotiation",
1813 MAC2STR(src_addr));
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07001814 wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK,
1815 peer->addr);
1816 wpa_tdls_peer_clear(sm, peer);
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07001817 }
1818 }
1819 }
1820
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001821 /* capability information */
1822 peer->capability = WPA_GET_LE16(cpos);
1823 cpos += 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001824
1825 ielen = len - (cpos - buf); /* start of IE in buf */
1826 if (wpa_supplicant_parse_ies(cpos, ielen, &kde) < 0) {
1827 wpa_printf(MSG_INFO, "TDLS: Failed to parse IEs in TPK M1");
1828 goto error;
1829 }
1830
1831 if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) {
1832 wpa_printf(MSG_INFO, "TDLS: No valid Link Identifier IE in "
1833 "TPK M1");
1834 goto error;
1835 }
1836 wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M1",
1837 kde.lnkid, kde.lnkid_len);
1838 lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
1839 if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) {
1840 wpa_printf(MSG_INFO, "TDLS: TPK M1 from diff BSS");
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07001841 status = WLAN_STATUS_REQUEST_DECLINED;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001842 goto error;
1843 }
1844
1845 wpa_printf(MSG_DEBUG, "TDLS: TPK M1 - TPK initiator " MACSTR,
1846 MAC2STR(src_addr));
1847
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001848 if (copy_supp_rates(&kde, peer) < 0)
1849 goto error;
1850
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001851 if (copy_peer_ht_capab(&kde, peer) < 0)
1852 goto error;
1853
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -08001854 if (copy_peer_vht_capab(&kde, peer) < 0)
1855 goto error;
1856
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001857 if (copy_peer_ext_capab(&kde, peer) < 0)
1858 goto error;
1859
Dmitry Shmidt344abd32014-01-14 13:17:00 -08001860 if (copy_peer_supp_channels(&kde, peer) < 0)
1861 goto error;
1862
1863 if (copy_peer_supp_oper_classes(&kde, peer) < 0)
1864 goto error;
1865
Dmitry Shmidtf8623282013-02-20 14:34:59 -08001866 peer->qos_info = kde.qosinfo;
1867
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07001868 /* Overwrite with the qos_info obtained in WMM IE */
1869 if (copy_peer_wmm_capab(&kde, peer) < 0)
1870 goto error;
1871
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07001872 peer->aid = kde.aid;
1873
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001874#ifdef CONFIG_TDLS_TESTING
1875 if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) {
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001876 peer = wpa_tdls_add_peer(sm, src_addr, NULL);
1877 if (peer == NULL)
1878 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001879 wpa_printf(MSG_DEBUG, "TDLS: Testing concurrent initiation of "
1880 "TDLS setup - send own request");
1881 peer->initiator = 1;
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07001882 wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL,
1883 NULL, 0, 0, NULL, 0, NULL, 0, NULL, 0);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001884 wpa_tdls_send_tpk_m1(sm, peer);
1885 }
1886
1887 if ((tdls_testing & TDLS_TESTING_IGNORE_AP_PROHIBIT) &&
1888 tdls_prohibited) {
1889 wpa_printf(MSG_DEBUG, "TDLS: Testing - ignore AP prohibition "
1890 "on TDLS");
1891 tdls_prohibited = 0;
1892 }
1893#endif /* CONFIG_TDLS_TESTING */
1894
1895 if (tdls_prohibited) {
1896 wpa_printf(MSG_INFO, "TDLS: TDLS prohibited in this BSS");
1897 status = WLAN_STATUS_REQUEST_DECLINED;
1898 goto error;
1899 }
1900
1901 if (!wpa_tdls_get_privacy(sm)) {
1902 if (kde.rsn_ie) {
1903 wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M1 while "
1904 "security is disabled");
1905 status = WLAN_STATUS_SECURITY_DISABLED;
1906 goto error;
1907 }
1908 goto skip_rsn;
1909 }
1910
1911 if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie) ||
1912 kde.rsn_ie == NULL) {
1913 wpa_printf(MSG_INFO, "TDLS: No FTIE or RSN IE in TPK M1");
1914 status = WLAN_STATUS_INVALID_PARAMETERS;
1915 goto error;
1916 }
1917
1918 if (kde.rsn_ie_len > TDLS_MAX_IE_LEN) {
1919 wpa_printf(MSG_INFO, "TDLS: Too long Initiator RSN IE in "
1920 "TPK M1");
1921 status = WLAN_STATUS_INVALID_RSNIE;
1922 goto error;
1923 }
1924
1925 if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) {
1926 wpa_printf(MSG_INFO, "TDLS: Failed to parse RSN IE in TPK M1");
1927 status = WLAN_STATUS_INVALID_RSNIE;
1928 goto error;
1929 }
1930
1931 cipher = ie.pairwise_cipher;
1932 if (cipher & WPA_CIPHER_CCMP) {
1933 wpa_printf(MSG_DEBUG, "TDLS: Using CCMP for direct link");
1934 cipher = WPA_CIPHER_CCMP;
1935 } else {
1936 wpa_printf(MSG_INFO, "TDLS: No acceptable cipher in TPK M1");
1937 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
1938 goto error;
1939 }
1940
1941 if ((ie.capabilities &
1942 (WPA_CAPABILITY_NO_PAIRWISE | WPA_CAPABILITY_PEERKEY_ENABLED)) !=
1943 WPA_CAPABILITY_PEERKEY_ENABLED) {
1944 wpa_printf(MSG_INFO, "TDLS: Invalid RSN Capabilities in "
1945 "TPK M1");
1946 status = WLAN_STATUS_INVALID_RSN_IE_CAPAB;
1947 goto error;
1948 }
1949
1950 /* Lifetime */
1951 if (kde.key_lifetime == NULL) {
1952 wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M1");
1953 status = WLAN_STATUS_UNACCEPTABLE_LIFETIME;
1954 goto error;
1955 }
1956 timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime;
1957 lifetime = WPA_GET_LE32(timeoutie->value);
1958 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", lifetime);
1959 if (lifetime < 300) {
1960 wpa_printf(MSG_INFO, "TDLS: Too short TPK lifetime");
1961 status = WLAN_STATUS_UNACCEPTABLE_LIFETIME;
1962 goto error;
1963 }
1964
1965skip_rsn:
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001966#ifdef CONFIG_TDLS_TESTING
1967 if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) {
1968 if (os_memcmp(sm->own_addr, peer->addr, ETH_ALEN) < 0) {
1969 /*
1970 * The request frame from us is going to win, so do not
1971 * replace information based on this request frame from
1972 * the peer.
1973 */
1974 goto skip_rsn_check;
1975 }
1976 }
1977#endif /* CONFIG_TDLS_TESTING */
1978
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001979 peer->initiator = 0; /* Need to check */
1980 peer->dtoken = dtoken;
1981
1982 if (!wpa_tdls_get_privacy(sm)) {
1983 peer->rsnie_i_len = 0;
1984 peer->rsnie_p_len = 0;
1985 peer->cipher = WPA_CIPHER_NONE;
1986 goto skip_rsn_check;
1987 }
1988
1989 ftie = (struct wpa_tdls_ftie *) kde.ftie;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001990 os_memcpy(peer->rsnie_i, kde.rsn_ie, kde.rsn_ie_len);
1991 peer->rsnie_i_len = kde.rsn_ie_len;
1992 peer->cipher = cipher;
1993
Sunil Dutt61024722013-09-15 12:09:40 -07001994 if (os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) != 0) {
1995 /*
1996 * There is no point in updating the RNonce for every obtained
1997 * TPK M1 frame (e.g., retransmission due to timeout) with the
1998 * same INonce (SNonce in FTIE). However, if the TPK M1 is
1999 * retransmitted with a different INonce, update the RNonce
2000 * since this is for a new TDLS session.
2001 */
2002 wpa_printf(MSG_DEBUG,
2003 "TDLS: New TPK M1 INonce - generate new RNonce");
2004 os_memcpy(peer->inonce, ftie->Snonce, WPA_NONCE_LEN);
2005 if (os_get_random(peer->rnonce, WPA_NONCE_LEN)) {
2006 wpa_msg(sm->ctx->ctx, MSG_WARNING,
2007 "TDLS: Failed to get random data for responder nonce");
Sunil Dutt61024722013-09-15 12:09:40 -07002008 goto error;
2009 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002010 }
2011
2012#if 0
2013 /* get version info from RSNIE received from Peer */
2014 hdr = (struct rsn_ie_hdr *) kde.rsn_ie;
2015 rsn_ver = WPA_GET_LE16(hdr->version);
2016
2017 /* use min(peer's version, out version) */
2018 if (rsn_ver > RSN_VERSION)
2019 rsn_ver = RSN_VERSION;
2020
2021 hdr = (struct rsn_ie_hdr *) peer->rsnie_p;
2022
2023 hdr->elem_id = WLAN_EID_RSN;
2024 WPA_PUT_LE16(hdr->version, rsn_ver);
2025 pos = (u8 *) (hdr + 1);
2026
2027 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED);
2028 pos += RSN_SELECTOR_LEN;
2029 /* Include only the selected cipher in pairwise cipher suite */
2030 WPA_PUT_LE16(pos, 1);
2031 pos += 2;
2032 if (cipher == WPA_CIPHER_CCMP)
2033 RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP);
2034 pos += RSN_SELECTOR_LEN;
2035
2036 WPA_PUT_LE16(pos, 1);
2037 pos += 2;
2038 RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE);
2039 pos += RSN_SELECTOR_LEN;
2040
2041 rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED;
2042 rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2;
2043 WPA_PUT_LE16(pos, rsn_capab);
2044 pos += 2;
2045
2046 hdr->len = (pos - peer->rsnie_p) - 2;
2047 peer->rsnie_p_len = pos - peer->rsnie_p;
2048#endif
2049
2050 /* temp fix: validation of RSNIE later */
2051 os_memcpy(peer->rsnie_p, peer->rsnie_i, peer->rsnie_i_len);
2052 peer->rsnie_p_len = peer->rsnie_i_len;
2053
2054 wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for TPK handshake",
2055 peer->rsnie_p, peer->rsnie_p_len);
2056
2057 peer->lifetime = lifetime;
2058
2059 wpa_tdls_generate_tpk(peer, sm->own_addr, sm->bssid);
2060
2061skip_rsn_check:
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002062#ifdef CONFIG_TDLS_TESTING
2063 if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT)
2064 goto skip_add_peer;
2065#endif /* CONFIG_TDLS_TESTING */
2066
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002067 /* add supported rates, capabilities, and qos_info to the TDLS peer */
2068 if (wpa_tdls_addset_peer(sm, peer, 1) < 0)
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002069 goto error;
2070
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002071#ifdef CONFIG_TDLS_TESTING
2072skip_add_peer:
2073#endif /* CONFIG_TDLS_TESTING */
Sunil Dutt73b28cc2013-09-30 17:38:41 +03002074 peer->tpk_in_progress = 1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002075
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002076 wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Response / TPK M2");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002077 if (wpa_tdls_send_tpk_m2(sm, src_addr, dtoken, lnkid, peer) < 0) {
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002078 wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002079 goto error;
2080 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002081
2082 return 0;
2083
2084error:
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002085 wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE, dtoken, 0,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002086 status);
Dmitry Shmidt43cb5782014-06-16 16:23:22 -07002087 if (peer)
2088 wpa_tdls_peer_free(sm, peer);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002089 return -1;
2090}
2091
2092
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002093static int wpa_tdls_enable_link(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002094{
2095 peer->tpk_success = 1;
Sunil Dutt73b28cc2013-09-30 17:38:41 +03002096 peer->tpk_in_progress = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002097 eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer);
2098 if (wpa_tdls_get_privacy(sm)) {
2099 u32 lifetime = peer->lifetime;
2100 /*
2101 * Start the initiator process a bit earlier to avoid race
2102 * condition with the responder sending teardown request.
2103 */
2104 if (lifetime > 3 && peer->initiator)
2105 lifetime -= 3;
2106 eloop_register_timeout(lifetime, 0, wpa_tdls_tpk_timeout,
2107 sm, peer);
2108#ifdef CONFIG_TDLS_TESTING
2109 if (tdls_testing & TDLS_TESTING_NO_TPK_EXPIRATION) {
2110 wpa_printf(MSG_DEBUG, "TDLS: Testing - disable TPK "
2111 "expiration");
2112 eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer);
2113 }
2114#endif /* CONFIG_TDLS_TESTING */
2115 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002116
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002117 if (peer->reconfig_key && wpa_tdls_set_key(sm, peer) < 0) {
2118 wpa_printf(MSG_INFO, "TDLS: Could not configure key to the "
2119 "driver");
2120 return -1;
2121 }
2122 peer->reconfig_key = 0;
2123
2124 return wpa_sm_tdls_oper(sm, TDLS_ENABLE_LINK, peer->addr);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002125}
2126
2127
2128static int wpa_tdls_process_tpk_m2(struct wpa_sm *sm, const u8 *src_addr,
2129 const u8 *buf, size_t len)
2130{
2131 struct wpa_tdls_peer *peer;
2132 struct wpa_eapol_ie_parse kde;
2133 struct wpa_ie_data ie;
2134 int cipher;
2135 struct wpa_tdls_ftie *ftie;
2136 struct wpa_tdls_timeoutie *timeoutie;
2137 struct wpa_tdls_lnkid *lnkid;
2138 u32 lifetime;
2139 u8 dtoken;
2140 int ielen;
2141 u16 status;
2142 const u8 *pos;
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002143 int ret = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002144
2145 wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Response / TPK M2 "
2146 "(Peer " MACSTR ")", MAC2STR(src_addr));
2147 for (peer = sm->tdls; peer; peer = peer->next) {
2148 if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0)
2149 break;
2150 }
2151 if (peer == NULL) {
2152 wpa_printf(MSG_INFO, "TDLS: No matching peer found for "
2153 "TPK M2: " MACSTR, MAC2STR(src_addr));
2154 return -1;
2155 }
Dmitry Shmidt0ccb66e2013-03-29 16:41:28 -07002156 if (!peer->initiator) {
2157 /*
2158 * This may happen if both devices try to initiate TDLS at the
2159 * same time and we accept the TPK M1 from the peer in
2160 * wpa_tdls_process_tpk_m1() and clear our previous state.
2161 */
2162 wpa_printf(MSG_INFO, "TDLS: We were not the initiator, so "
2163 "ignore TPK M2 from " MACSTR, MAC2STR(src_addr));
2164 return -1;
2165 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002166 wpa_tdls_tpk_retry_timeout_cancel(sm, peer, WLAN_TDLS_SETUP_REQUEST);
2167
Sunil Duttadce9cf2013-09-15 11:51:00 -07002168 if (len < 3 + 2 + 1) {
Sunil Duttd0ef38b2013-09-30 17:34:13 +03002169 wpa_tdls_disable_peer_link(sm, peer);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002170 return -1;
Sunil Duttadce9cf2013-09-15 11:51:00 -07002171 }
2172
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002173 pos = buf;
2174 pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */;
2175 status = WPA_GET_LE16(pos);
2176 pos += 2 /* status code */;
2177
2178 if (status != WLAN_STATUS_SUCCESS) {
2179 wpa_printf(MSG_INFO, "TDLS: Status code in TPK M2: %u",
2180 status);
Sunil Duttd0ef38b2013-09-30 17:34:13 +03002181 wpa_tdls_disable_peer_link(sm, peer);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002182 return -1;
2183 }
2184
2185 status = WLAN_STATUS_UNSPECIFIED_FAILURE;
2186
2187 /* TODO: need to verify dialog token matches here or in kernel */
2188 dtoken = *pos++; /* dialog token */
2189
2190 wpa_printf(MSG_DEBUG, "TDLS: Dialog Token in TPK M2 %d", dtoken);
2191
Sunil Duttadce9cf2013-09-15 11:51:00 -07002192 if (len < 3 + 2 + 1 + 2) {
Sunil Duttd0ef38b2013-09-30 17:34:13 +03002193 wpa_tdls_disable_peer_link(sm, peer);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002194 return -1;
Sunil Duttadce9cf2013-09-15 11:51:00 -07002195 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002196
2197 /* capability information */
2198 peer->capability = WPA_GET_LE16(pos);
2199 pos += 2;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002200
2201 ielen = len - (pos - buf); /* start of IE in buf */
2202 if (wpa_supplicant_parse_ies(pos, ielen, &kde) < 0) {
2203 wpa_printf(MSG_INFO, "TDLS: Failed to parse IEs in TPK M2");
2204 goto error;
2205 }
2206
2207#ifdef CONFIG_TDLS_TESTING
2208 if (tdls_testing & TDLS_TESTING_DECLINE_RESP) {
2209 wpa_printf(MSG_DEBUG, "TDLS: Testing - decline response");
2210 status = WLAN_STATUS_REQUEST_DECLINED;
2211 goto error;
2212 }
2213#endif /* CONFIG_TDLS_TESTING */
2214
2215 if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) {
2216 wpa_printf(MSG_INFO, "TDLS: No valid Link Identifier IE in "
2217 "TPK M2");
2218 goto error;
2219 }
2220 wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M2",
2221 kde.lnkid, kde.lnkid_len);
2222 lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
2223
2224 if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) {
2225 wpa_printf(MSG_INFO, "TDLS: TPK M2 from different BSS");
2226 status = WLAN_STATUS_NOT_IN_SAME_BSS;
2227 goto error;
2228 }
2229
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002230 if (copy_supp_rates(&kde, peer) < 0)
2231 goto error;
2232
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002233 if (copy_peer_ht_capab(&kde, peer) < 0)
2234 goto error;
2235
Dmitry Shmidt33e38bf2013-02-27 12:56:00 -08002236 if (copy_peer_vht_capab(&kde, peer) < 0)
2237 goto error;
2238
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002239 if (copy_peer_ext_capab(&kde, peer) < 0)
2240 goto error;
2241
Dmitry Shmidt344abd32014-01-14 13:17:00 -08002242 if (copy_peer_supp_channels(&kde, peer) < 0)
2243 goto error;
2244
2245 if (copy_peer_supp_oper_classes(&kde, peer) < 0)
2246 goto error;
2247
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002248 peer->qos_info = kde.qosinfo;
2249
Dmitry Shmidtb36ed7c2014-03-17 10:57:26 -07002250 /* Overwrite with the qos_info obtained in WMM IE */
2251 if (copy_peer_wmm_capab(&kde, peer) < 0)
2252 goto error;
2253
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002254 peer->aid = kde.aid;
2255
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002256 if (!wpa_tdls_get_privacy(sm)) {
2257 peer->rsnie_p_len = 0;
2258 peer->cipher = WPA_CIPHER_NONE;
2259 goto skip_rsn;
2260 }
2261
2262 if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie) ||
2263 kde.rsn_ie == NULL) {
2264 wpa_printf(MSG_INFO, "TDLS: No FTIE or RSN IE in TPK M2");
2265 status = WLAN_STATUS_INVALID_PARAMETERS;
2266 goto error;
2267 }
2268 wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M2",
2269 kde.rsn_ie, kde.rsn_ie_len);
2270
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -07002271 if (kde.rsn_ie_len > TDLS_MAX_IE_LEN) {
2272 wpa_printf(MSG_INFO,
2273 "TDLS: Too long Responder RSN IE in TPK M2");
2274 status = WLAN_STATUS_INVALID_RSNIE;
2275 goto error;
2276 }
2277
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002278 /*
2279 * FIX: bitwise comparison of RSN IE is not the correct way of
2280 * validation this. It can be different, but certain fields must
2281 * match. Since we list only a single pairwise cipher in TPK M1, the
2282 * memcmp is likely to work in most cases, though.
2283 */
2284 if (kde.rsn_ie_len != peer->rsnie_i_len ||
2285 os_memcmp(peer->rsnie_i, kde.rsn_ie, peer->rsnie_i_len) != 0) {
2286 wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M2 does "
2287 "not match with RSN IE used in TPK M1");
2288 wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Sent in TPK M1",
2289 peer->rsnie_i, peer->rsnie_i_len);
2290 wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M2",
2291 kde.rsn_ie, kde.rsn_ie_len);
2292 status = WLAN_STATUS_INVALID_RSNIE;
2293 goto error;
2294 }
2295
2296 if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) {
2297 wpa_printf(MSG_INFO, "TDLS: Failed to parse RSN IE in TPK M2");
2298 status = WLAN_STATUS_INVALID_RSNIE;
2299 goto error;
2300 }
2301
2302 cipher = ie.pairwise_cipher;
2303 if (cipher == WPA_CIPHER_CCMP) {
2304 wpa_printf(MSG_DEBUG, "TDLS: Using CCMP for direct link");
2305 cipher = WPA_CIPHER_CCMP;
2306 } else {
2307 wpa_printf(MSG_INFO, "TDLS: No acceptable cipher in TPK M2");
2308 status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID;
2309 goto error;
2310 }
2311
2312 wpa_hexdump(MSG_DEBUG, "TDLS: FTIE Received from TPK M2",
2313 kde.ftie, sizeof(*ftie));
2314 ftie = (struct wpa_tdls_ftie *) kde.ftie;
2315
2316 if (!os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) == 0) {
2317 wpa_printf(MSG_INFO, "TDLS: FTIE SNonce in TPK M2 does "
2318 "not match with FTIE SNonce used in TPK M1");
2319 /* Silently discard the frame */
2320 return -1;
2321 }
2322
2323 /* Responder Nonce and RSN IE */
2324 os_memcpy(peer->rnonce, ftie->Anonce, WPA_NONCE_LEN);
2325 os_memcpy(peer->rsnie_p, kde.rsn_ie, kde.rsn_ie_len);
2326 peer->rsnie_p_len = kde.rsn_ie_len;
2327 peer->cipher = cipher;
2328
2329 /* Lifetime */
2330 if (kde.key_lifetime == NULL) {
2331 wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M2");
2332 status = WLAN_STATUS_UNACCEPTABLE_LIFETIME;
2333 goto error;
2334 }
2335 timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime;
2336 lifetime = WPA_GET_LE32(timeoutie->value);
2337 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds in TPK M2",
2338 lifetime);
2339 if (lifetime != peer->lifetime) {
2340 wpa_printf(MSG_INFO, "TDLS: Unexpected TPK lifetime %u in "
2341 "TPK M2 (expected %u)", lifetime, peer->lifetime);
2342 status = WLAN_STATUS_UNACCEPTABLE_LIFETIME;
2343 goto error;
2344 }
2345
2346 wpa_tdls_generate_tpk(peer, sm->own_addr, sm->bssid);
2347
2348 /* Process MIC check to see if TPK M2 is right */
2349 if (wpa_supplicant_verify_tdls_mic(2, peer, (u8 *) lnkid,
2350 (u8 *) timeoutie, ftie) < 0) {
2351 /* Discard the frame */
2352 wpa_tdls_del_key(sm, peer);
Sunil Dutt38ffd882013-09-30 17:23:23 +03002353 wpa_tdls_disable_peer_link(sm, peer);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002354 return -1;
2355 }
2356
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002357 if (wpa_tdls_set_key(sm, peer) < 0) {
2358 /*
2359 * Some drivers may not be able to config the key prior to full
2360 * STA entry having been configured.
2361 */
2362 wpa_printf(MSG_DEBUG, "TDLS: Try to configure TPK again after "
2363 "STA entry is complete");
2364 peer->reconfig_key = 1;
2365 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002366
2367skip_rsn:
2368 peer->dtoken = dtoken;
2369
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002370 /* add supported rates, capabilities, and qos_info to the TDLS peer */
2371 if (wpa_tdls_addset_peer(sm, peer, 0) < 0)
2372 goto error;
2373
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002374 wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Confirm / "
2375 "TPK Handshake Message 3");
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002376 if (wpa_tdls_send_tpk_m3(sm, src_addr, dtoken, lnkid, peer) < 0)
2377 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002378
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002379 if (!peer->tpk_success) {
2380 /*
2381 * Enable Link only when tpk_success is 0, signifying that this
2382 * processing of TPK M2 frame is not because of a retransmission
2383 * during TDLS setup handshake.
2384 */
2385 ret = wpa_tdls_enable_link(sm, peer);
2386 if (ret < 0) {
2387 wpa_printf(MSG_DEBUG, "TDLS: Could not enable link");
2388 wpa_tdls_do_teardown(
2389 sm, peer,
2390 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
2391 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002392 }
2393 return ret;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002394
2395error:
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002396 wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, dtoken, 1,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002397 status);
Sunil Duttd0ef38b2013-09-30 17:34:13 +03002398 wpa_tdls_disable_peer_link(sm, peer);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002399 return -1;
2400}
2401
2402
2403static int wpa_tdls_process_tpk_m3(struct wpa_sm *sm, const u8 *src_addr,
2404 const u8 *buf, size_t len)
2405{
2406 struct wpa_tdls_peer *peer;
2407 struct wpa_eapol_ie_parse kde;
2408 struct wpa_tdls_ftie *ftie;
2409 struct wpa_tdls_timeoutie *timeoutie;
2410 struct wpa_tdls_lnkid *lnkid;
2411 int ielen;
2412 u16 status;
2413 const u8 *pos;
2414 u32 lifetime;
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002415 int ret = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002416
2417 wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Confirm / TPK M3 "
2418 "(Peer " MACSTR ")", MAC2STR(src_addr));
2419 for (peer = sm->tdls; peer; peer = peer->next) {
2420 if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0)
2421 break;
2422 }
2423 if (peer == NULL) {
2424 wpa_printf(MSG_INFO, "TDLS: No matching peer found for "
2425 "TPK M3: " MACSTR, MAC2STR(src_addr));
2426 return -1;
2427 }
2428 wpa_tdls_tpk_retry_timeout_cancel(sm, peer, WLAN_TDLS_SETUP_RESPONSE);
2429
2430 if (len < 3 + 3)
Sunil Duttadce9cf2013-09-15 11:51:00 -07002431 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002432 pos = buf;
2433 pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */;
2434
2435 status = WPA_GET_LE16(pos);
2436
2437 if (status != 0) {
2438 wpa_printf(MSG_INFO, "TDLS: Status code in TPK M3: %u",
2439 status);
Sunil Duttadce9cf2013-09-15 11:51:00 -07002440 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002441 }
2442 pos += 2 /* status code */ + 1 /* dialog token */;
2443
2444 ielen = len - (pos - buf); /* start of IE in buf */
Dmitry Shmidt0c08fdc2014-06-20 10:16:40 -07002445
2446 /*
2447 * Don't reject the message if failing to parse IEs. The IEs we need are
2448 * explicitly checked below. Some APs piggy-back broken IEs to the end
2449 * of a TDLS Confirm packet, which will fail the link if we don't ignore
2450 * this error.
2451 */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002452 if (wpa_supplicant_parse_ies((const u8 *) pos, ielen, &kde) < 0) {
Dmitry Shmidt0c08fdc2014-06-20 10:16:40 -07002453 wpa_printf(MSG_DEBUG,
2454 "TDLS: Failed to parse KDEs in TPK M3 - ignore as an interop workaround");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002455 }
2456
2457 if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) {
2458 wpa_printf(MSG_INFO, "TDLS: No Link Identifier IE in TPK M3");
Sunil Duttadce9cf2013-09-15 11:51:00 -07002459 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002460 }
2461 wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M3",
2462 (u8 *) kde.lnkid, kde.lnkid_len);
2463 lnkid = (struct wpa_tdls_lnkid *) kde.lnkid;
2464
2465 if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) {
2466 wpa_printf(MSG_INFO, "TDLS: TPK M3 from diff BSS");
Sunil Duttadce9cf2013-09-15 11:51:00 -07002467 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002468 }
2469
2470 if (!wpa_tdls_get_privacy(sm))
2471 goto skip_rsn;
2472
2473 if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie)) {
2474 wpa_printf(MSG_INFO, "TDLS: No FTIE in TPK M3");
Sunil Duttadce9cf2013-09-15 11:51:00 -07002475 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002476 }
2477 wpa_hexdump(MSG_DEBUG, "TDLS: FTIE Received from TPK M3",
2478 kde.ftie, sizeof(*ftie));
2479 ftie = (struct wpa_tdls_ftie *) kde.ftie;
2480
2481 if (kde.rsn_ie == NULL) {
2482 wpa_printf(MSG_INFO, "TDLS: No RSN IE in TPK M3");
Sunil Duttadce9cf2013-09-15 11:51:00 -07002483 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002484 }
2485 wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M3",
2486 kde.rsn_ie, kde.rsn_ie_len);
2487 if (kde.rsn_ie_len != peer->rsnie_p_len ||
2488 os_memcmp(kde.rsn_ie, peer->rsnie_p, peer->rsnie_p_len) != 0) {
2489 wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M3 does not match "
2490 "with the one sent in TPK M2");
Sunil Duttadce9cf2013-09-15 11:51:00 -07002491 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002492 }
2493
2494 if (!os_memcmp(peer->rnonce, ftie->Anonce, WPA_NONCE_LEN) == 0) {
2495 wpa_printf(MSG_INFO, "TDLS: FTIE ANonce in TPK M3 does "
2496 "not match with FTIE ANonce used in TPK M2");
Sunil Duttadce9cf2013-09-15 11:51:00 -07002497 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002498 }
2499
2500 if (!os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) == 0) {
2501 wpa_printf(MSG_INFO, "TDLS: FTIE SNonce in TPK M3 does not "
2502 "match with FTIE SNonce used in TPK M1");
Sunil Duttadce9cf2013-09-15 11:51:00 -07002503 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002504 }
2505
2506 if (kde.key_lifetime == NULL) {
2507 wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M3");
Sunil Duttadce9cf2013-09-15 11:51:00 -07002508 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002509 }
2510 timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime;
2511 wpa_hexdump(MSG_DEBUG, "TDLS: Timeout IE Received from TPK M3",
2512 (u8 *) timeoutie, sizeof(*timeoutie));
2513 lifetime = WPA_GET_LE32(timeoutie->value);
2514 wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds in TPK M3",
2515 lifetime);
2516 if (lifetime != peer->lifetime) {
2517 wpa_printf(MSG_INFO, "TDLS: Unexpected TPK lifetime %u in "
2518 "TPK M3 (expected %u)", lifetime, peer->lifetime);
Sunil Duttadce9cf2013-09-15 11:51:00 -07002519 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002520 }
2521
2522 if (wpa_supplicant_verify_tdls_mic(3, peer, (u8 *) lnkid,
2523 (u8 *) timeoutie, ftie) < 0) {
2524 wpa_tdls_del_key(sm, peer);
Sunil Duttadce9cf2013-09-15 11:51:00 -07002525 goto error;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002526 }
2527
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002528 if (wpa_tdls_set_key(sm, peer) < 0) {
2529 /*
2530 * Some drivers may not be able to config the key prior to full
2531 * STA entry having been configured.
2532 */
2533 wpa_printf(MSG_DEBUG, "TDLS: Try to configure TPK again after "
2534 "STA entry is complete");
2535 peer->reconfig_key = 1;
2536 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002537
2538skip_rsn:
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002539 /* add supported rates, capabilities, and qos_info to the TDLS peer */
2540 if (wpa_tdls_addset_peer(sm, peer, 0) < 0)
2541 goto error;
2542
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002543 if (!peer->tpk_success) {
2544 /*
2545 * Enable Link only when tpk_success is 0, signifying that this
2546 * processing of TPK M3 frame is not because of a retransmission
2547 * during TDLS setup handshake.
2548 */
2549 ret = wpa_tdls_enable_link(sm, peer);
2550 if (ret < 0) {
2551 wpa_printf(MSG_DEBUG, "TDLS: Could not enable link");
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002552 goto error;
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002553 }
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002554 }
2555 return ret;
Sunil Duttadce9cf2013-09-15 11:51:00 -07002556error:
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002557 wpa_tdls_do_teardown(sm, peer, WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
Sunil Duttadce9cf2013-09-15 11:51:00 -07002558 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002559}
2560
2561
2562static u8 * wpa_add_tdls_timeoutie(u8 *pos, u8 *ie, size_t ie_len, u32 tsecs)
2563{
2564 struct wpa_tdls_timeoutie *lifetime = (struct wpa_tdls_timeoutie *) ie;
2565
2566 os_memset(lifetime, 0, ie_len);
2567 lifetime->ie_type = WLAN_EID_TIMEOUT_INTERVAL;
2568 lifetime->ie_len = sizeof(struct wpa_tdls_timeoutie) - 2;
2569 lifetime->interval_type = WLAN_TIMEOUT_KEY_LIFETIME;
2570 WPA_PUT_LE32(lifetime->value, tsecs);
2571 os_memcpy(pos, ie, ie_len);
2572 return pos + ie_len;
2573}
2574
2575
2576/**
2577 * wpa_tdls_start - Initiate TDLS handshake (send TPK Handshake Message 1)
2578 * @sm: Pointer to WPA state machine data from wpa_sm_init()
2579 * @peer: MAC address of the peer STA
2580 * Returns: 0 on success, or -1 on failure
2581 *
2582 * Send TPK Handshake Message 1 info to driver to start TDLS
2583 * handshake with the peer.
2584 */
2585int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr)
2586{
2587 struct wpa_tdls_peer *peer;
2588 int tdls_prohibited = sm->tdls_prohibited;
2589
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002590 if (sm->tdls_disabled || !sm->tdls_supported)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002591 return -1;
2592
2593#ifdef CONFIG_TDLS_TESTING
2594 if ((tdls_testing & TDLS_TESTING_IGNORE_AP_PROHIBIT) &&
2595 tdls_prohibited) {
2596 wpa_printf(MSG_DEBUG, "TDLS: Testing - ignore AP prohibition "
2597 "on TDLS");
2598 tdls_prohibited = 0;
2599 }
2600#endif /* CONFIG_TDLS_TESTING */
2601
2602 if (tdls_prohibited) {
2603 wpa_printf(MSG_DEBUG, "TDLS: TDLS is prohibited in this BSS - "
2604 "reject request to start setup");
2605 return -1;
2606 }
2607
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002608 peer = wpa_tdls_add_peer(sm, addr, NULL);
2609 if (peer == NULL)
2610 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002611
Sunil Dutt73b28cc2013-09-30 17:38:41 +03002612 if (peer->tpk_in_progress) {
2613 wpa_printf(MSG_DEBUG, "TDLS: Setup is already in progress with the peer");
2614 return 0;
2615 }
2616
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002617 peer->initiator = 1;
2618
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002619 /* add the peer to the driver as a "setup in progress" peer */
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002620 if (wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, 0, NULL, 0, NULL,
Dmitry Shmidt9ead16e2014-10-07 13:15:23 -07002621 NULL, 0, 0, NULL, 0, NULL, 0, NULL, 0)) {
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002622 wpa_tdls_disable_peer_link(sm, peer);
2623 return -1;
2624 }
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002625
Sunil Dutt73b28cc2013-09-30 17:38:41 +03002626 peer->tpk_in_progress = 1;
2627
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002628 if (wpa_tdls_send_tpk_m1(sm, peer) < 0) {
Sunil Duttd0ef38b2013-09-30 17:34:13 +03002629 wpa_tdls_disable_peer_link(sm, peer);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002630 return -1;
2631 }
2632
2633 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002634}
2635
2636
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002637void wpa_tdls_remove(struct wpa_sm *sm, const u8 *addr)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002638{
2639 struct wpa_tdls_peer *peer;
2640
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002641 if (sm->tdls_disabled || !sm->tdls_supported)
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002642 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002643
2644 for (peer = sm->tdls; peer; peer = peer->next) {
2645 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
2646 break;
2647 }
2648
2649 if (peer == NULL || !peer->tpk_success)
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08002650 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002651
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002652 if (sm->tdls_external_setup) {
2653 /*
2654 * Disable previous link to allow renegotiation to be completed
2655 * on AP path.
2656 */
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07002657 wpa_tdls_do_teardown(sm, peer,
2658 WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002659 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002660}
2661
2662
2663/**
2664 * wpa_supplicant_rx_tdls - Receive TDLS data frame
2665 *
2666 * This function is called to receive TDLS (ethertype = 0x890d) data frames.
2667 */
2668static void wpa_supplicant_rx_tdls(void *ctx, const u8 *src_addr,
2669 const u8 *buf, size_t len)
2670{
2671 struct wpa_sm *sm = ctx;
2672 struct wpa_tdls_frame *tf;
2673
2674 wpa_hexdump(MSG_DEBUG, "TDLS: Received Data frame encapsulation",
2675 buf, len);
2676
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002677 if (sm->tdls_disabled || !sm->tdls_supported) {
2678 wpa_printf(MSG_DEBUG, "TDLS: Discard message - TDLS disabled "
2679 "or unsupported by driver");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002680 return;
2681 }
2682
2683 if (os_memcmp(src_addr, sm->own_addr, ETH_ALEN) == 0) {
2684 wpa_printf(MSG_DEBUG, "TDLS: Discard copy of own message");
2685 return;
2686 }
2687
2688 if (len < sizeof(*tf)) {
2689 wpa_printf(MSG_INFO, "TDLS: Drop too short frame");
2690 return;
2691 }
2692
2693 /* Check to make sure its a valid encapsulated TDLS frame */
2694 tf = (struct wpa_tdls_frame *) buf;
2695 if (tf->payloadtype != 2 /* TDLS_RFTYPE */ ||
2696 tf->category != WLAN_ACTION_TDLS) {
2697 wpa_printf(MSG_INFO, "TDLS: Invalid frame - payloadtype=%u "
2698 "category=%u action=%u",
2699 tf->payloadtype, tf->category, tf->action);
2700 return;
2701 }
2702
2703 switch (tf->action) {
2704 case WLAN_TDLS_SETUP_REQUEST:
2705 wpa_tdls_process_tpk_m1(sm, src_addr, buf, len);
2706 break;
2707 case WLAN_TDLS_SETUP_RESPONSE:
2708 wpa_tdls_process_tpk_m2(sm, src_addr, buf, len);
2709 break;
2710 case WLAN_TDLS_SETUP_CONFIRM:
2711 wpa_tdls_process_tpk_m3(sm, src_addr, buf, len);
2712 break;
2713 case WLAN_TDLS_TEARDOWN:
2714 wpa_tdls_recv_teardown(sm, src_addr, buf, len);
2715 break;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002716 case WLAN_TDLS_DISCOVERY_REQUEST:
2717 wpa_tdls_process_discovery_request(sm, src_addr, buf, len);
2718 break;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002719 default:
2720 /* Kernel code will process remaining frames */
2721 wpa_printf(MSG_DEBUG, "TDLS: Ignore TDLS frame action code %u",
2722 tf->action);
2723 break;
2724 }
2725}
2726
2727
2728/**
2729 * wpa_tdls_init - Initialize driver interface parameters for TDLS
2730 * @wpa_s: Pointer to wpa_supplicant data
2731 * Returns: 0 on success, -1 on failure
2732 *
2733 * This function is called to initialize driver interface parameters for TDLS.
2734 * wpa_drv_init() must have been called before this function to initialize the
2735 * driver interface.
2736 */
2737int wpa_tdls_init(struct wpa_sm *sm)
2738{
2739 if (sm == NULL)
2740 return -1;
2741
Dmitry Shmidt04949592012-07-19 12:16:46 -07002742 sm->l2_tdls = l2_packet_init(sm->bridge_ifname ? sm->bridge_ifname :
2743 sm->ifname,
2744 sm->own_addr,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002745 ETH_P_80211_ENCAP, wpa_supplicant_rx_tdls,
2746 sm, 0);
2747 if (sm->l2_tdls == NULL) {
2748 wpa_printf(MSG_ERROR, "TDLS: Failed to open l2_packet "
2749 "connection");
2750 return -1;
2751 }
2752
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002753 /*
2754 * Drivers that support TDLS but don't implement the get_capa callback
2755 * are assumed to perform everything internally
2756 */
2757 if (wpa_sm_tdls_get_capa(sm, &sm->tdls_supported,
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002758 &sm->tdls_external_setup,
2759 &sm->tdls_chan_switch) < 0) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002760 sm->tdls_supported = 1;
2761 sm->tdls_external_setup = 0;
2762 }
2763
2764 wpa_printf(MSG_DEBUG, "TDLS: TDLS operation%s supported by "
2765 "driver", sm->tdls_supported ? "" : " not");
2766 wpa_printf(MSG_DEBUG, "TDLS: Driver uses %s link setup",
2767 sm->tdls_external_setup ? "external" : "internal");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002768 wpa_printf(MSG_DEBUG, "TDLS: Driver %s TDLS channel switching",
2769 sm->tdls_chan_switch ? "supports" : "does not support");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002770
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002771 return 0;
2772}
2773
2774
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002775void wpa_tdls_teardown_peers(struct wpa_sm *sm)
2776{
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002777 struct wpa_tdls_peer *peer, *tmp;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002778
2779 peer = sm->tdls;
2780
2781 wpa_printf(MSG_DEBUG, "TDLS: Tear down peers");
2782
2783 while (peer) {
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002784 tmp = peer->next;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002785 wpa_printf(MSG_DEBUG, "TDLS: Tear down peer " MACSTR,
2786 MAC2STR(peer->addr));
2787 if (sm->tdls_external_setup)
Dmitry Shmidtb58836e2014-04-29 14:35:56 -07002788 wpa_tdls_do_teardown(sm, peer,
2789 WLAN_REASON_DEAUTH_LEAVING);
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002790 else
2791 wpa_sm_tdls_oper(sm, TDLS_TEARDOWN, peer->addr);
2792
Dmitry Shmidtd30ac602014-06-30 09:54:22 -07002793 peer = tmp;
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002794 }
2795}
2796
2797
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002798static void wpa_tdls_remove_peers(struct wpa_sm *sm)
2799{
2800 struct wpa_tdls_peer *peer, *tmp;
2801
2802 peer = sm->tdls;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002803
2804 while (peer) {
2805 int res;
2806 tmp = peer->next;
2807 res = wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr);
2808 wpa_printf(MSG_DEBUG, "TDLS: Remove peer " MACSTR " (res=%d)",
2809 MAC2STR(peer->addr), res);
2810 wpa_tdls_peer_free(sm, peer);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002811 peer = tmp;
2812 }
2813}
2814
2815
2816/**
2817 * wpa_tdls_deinit - Deinitialize driver interface parameters for TDLS
2818 *
2819 * This function is called to recover driver interface parameters for TDLS
2820 * and frees resources allocated for it.
2821 */
2822void wpa_tdls_deinit(struct wpa_sm *sm)
2823{
2824 if (sm == NULL)
2825 return;
2826
2827 if (sm->l2_tdls)
2828 l2_packet_deinit(sm->l2_tdls);
2829 sm->l2_tdls = NULL;
2830
2831 wpa_tdls_remove_peers(sm);
2832}
2833
2834
2835void wpa_tdls_assoc(struct wpa_sm *sm)
2836{
2837 wpa_printf(MSG_DEBUG, "TDLS: Remove peers on association");
2838 wpa_tdls_remove_peers(sm);
2839}
2840
2841
2842void wpa_tdls_disassoc(struct wpa_sm *sm)
2843{
2844 wpa_printf(MSG_DEBUG, "TDLS: Remove peers on disassociation");
2845 wpa_tdls_remove_peers(sm);
2846}
2847
2848
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002849static int wpa_tdls_prohibited(struct wpa_eapol_ie_parse *elems)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002850{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002851 /* bit 38 - TDLS Prohibited */
2852 return !!(elems->ext_capab[2 + 4] & 0x40);
2853}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002854
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002855
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002856static int wpa_tdls_chan_switch_prohibited(struct wpa_eapol_ie_parse *elems)
2857{
2858 /* bit 39 - TDLS Channel Switch Prohibited */
2859 return !!(elems->ext_capab[2 + 4] & 0x80);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002860}
2861
2862
2863void wpa_tdls_ap_ies(struct wpa_sm *sm, const u8 *ies, size_t len)
2864{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002865 struct wpa_eapol_ie_parse elems;
2866
2867 sm->tdls_prohibited = 0;
2868 sm->tdls_chan_switch_prohibited = 0;
2869
2870 if (ies == NULL || wpa_supplicant_parse_ies(ies, len, &elems) < 0 ||
2871 elems.ext_capab == NULL || elems.ext_capab_len < 2 + 5)
2872 return;
2873
2874 sm->tdls_prohibited = wpa_tdls_prohibited(&elems);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002875 wpa_printf(MSG_DEBUG, "TDLS: TDLS is %s in the target BSS",
2876 sm->tdls_prohibited ? "prohibited" : "allowed");
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002877 sm->tdls_chan_switch_prohibited =
2878 wpa_tdls_chan_switch_prohibited(&elems);
2879 wpa_printf(MSG_DEBUG, "TDLS: TDLS channel switch %s in the target BSS",
2880 sm->tdls_chan_switch_prohibited ? "prohibited" : "allowed");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002881}
2882
2883
2884void wpa_tdls_assoc_resp_ies(struct wpa_sm *sm, const u8 *ies, size_t len)
2885{
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002886 struct wpa_eapol_ie_parse elems;
2887
2888 if (ies == NULL || wpa_supplicant_parse_ies(ies, len, &elems) < 0 ||
2889 elems.ext_capab == NULL || elems.ext_capab_len < 2 + 5)
2890 return;
2891
2892 if (!sm->tdls_prohibited && wpa_tdls_prohibited(&elems)) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002893 wpa_printf(MSG_DEBUG, "TDLS: TDLS prohibited based on "
2894 "(Re)Association Response IEs");
2895 sm->tdls_prohibited = 1;
2896 }
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002897
2898 if (!sm->tdls_chan_switch_prohibited &&
2899 wpa_tdls_chan_switch_prohibited(&elems)) {
2900 wpa_printf(MSG_DEBUG,
2901 "TDLS: TDLS channel switch prohibited based on (Re)Association Response IEs");
2902 sm->tdls_chan_switch_prohibited = 1;
2903 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002904}
2905
2906
2907void wpa_tdls_enable(struct wpa_sm *sm, int enabled)
2908{
2909 wpa_printf(MSG_DEBUG, "TDLS: %s", enabled ? "enabled" : "disabled");
2910 sm->tdls_disabled = !enabled;
2911}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002912
2913
2914int wpa_tdls_is_external_setup(struct wpa_sm *sm)
2915{
2916 return sm->tdls_external_setup;
2917}
Dmitry Shmidt6c0da2b2015-01-05 13:08:17 -08002918
2919
2920int wpa_tdls_enable_chan_switch(struct wpa_sm *sm, const u8 *addr,
2921 u8 oper_class,
2922 struct hostapd_freq_params *freq_params)
2923{
2924 struct wpa_tdls_peer *peer;
2925 int ret;
2926
2927 if (sm->tdls_disabled || !sm->tdls_supported)
2928 return -1;
2929
2930 if (!sm->tdls_chan_switch) {
2931 wpa_printf(MSG_DEBUG,
2932 "TDLS: Channel switching not supported by the driver");
2933 return -1;
2934 }
2935
2936 if (sm->tdls_chan_switch_prohibited) {
2937 wpa_printf(MSG_DEBUG,
2938 "TDLS: Channel switching is prohibited in this BSS - reject request to switch channel");
2939 return -1;
2940 }
2941
2942 for (peer = sm->tdls; peer; peer = peer->next) {
2943 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
2944 break;
2945 }
2946
2947 if (peer == NULL || !peer->tpk_success) {
2948 wpa_printf(MSG_ERROR, "TDLS: Peer " MACSTR
2949 " not found for channel switching", MAC2STR(addr));
2950 return -1;
2951 }
2952
2953 if (peer->chan_switch_enabled) {
2954 wpa_printf(MSG_DEBUG, "TDLS: Peer " MACSTR
2955 " already has channel switching enabled",
2956 MAC2STR(addr));
2957 return 0;
2958 }
2959
2960 ret = wpa_sm_tdls_enable_channel_switch(sm, peer->addr,
2961 oper_class, freq_params);
2962 if (!ret)
2963 peer->chan_switch_enabled = 1;
2964
2965 return ret;
2966}
2967
2968
2969int wpa_tdls_disable_chan_switch(struct wpa_sm *sm, const u8 *addr)
2970{
2971 struct wpa_tdls_peer *peer;
2972
2973 if (sm->tdls_disabled || !sm->tdls_supported)
2974 return -1;
2975
2976 for (peer = sm->tdls; peer; peer = peer->next) {
2977 if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0)
2978 break;
2979 }
2980
2981 if (!peer || !peer->chan_switch_enabled) {
2982 wpa_printf(MSG_ERROR, "TDLS: Channel switching not enabled for "
2983 MACSTR, MAC2STR(addr));
2984 return -1;
2985 }
2986
2987 /* ignore the return value */
2988 wpa_sm_tdls_disable_channel_switch(sm, peer->addr);
2989
2990 peer->chan_switch_enabled = 0;
2991 return 0;
2992}