tdls.c revision 8d520ff1dc2da35cdca849e982051b86468016d8
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant - TDLS 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2010-2011, Atheros Communications 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This program is free software; you can redistribute it and/or modify 68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * it under the terms of the GNU General Public License version 2 as 78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * published by the Free Software Foundation. 88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Alternatively, this software may be distributed under the terms of BSD 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * license. 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * See README and COPYING for more details. 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/includes.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/common.h" 188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/eloop.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/os.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/sha256.h" 228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/crypto.h" 238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "crypto/aes_wrap.h" 248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "rsn_supp/wpa.h" 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "rsn_supp/wpa_ie.h" 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "rsn_supp/wpa_i.h" 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "drivers/driver.h" 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "l2_packet/l2_packet.h" 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_LONG_FRAME BIT(0) 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_ALT_RSN_IE BIT(1) 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_DIFF_BSSID BIT(2) 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_SHORT_LIFETIME BIT(3) 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_WRONG_LIFETIME_RESP BIT(4) 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_WRONG_LIFETIME_CONF BIT(5) 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_LONG_LIFETIME BIT(6) 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_CONCURRENT_INIT BIT(7) 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_NO_TPK_EXPIRATION BIT(8) 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_DECLINE_RESP BIT(9) 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TESTING_IGNORE_AP_PROHIBIT BIT(10) 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtunsigned int tdls_testing = 0; 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TPK_LIFETIME 43200 /* 12 hours */ 468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TPK_RETRY_COUNT 3 478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TPK_TIMEOUT 5000 /* in milliseconds */ 488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_MIC_LEN 16 508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_TIMEOUT_LEN 4 528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_tdls_ftie { 548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ie_type; /* FTIE */ 558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ie_len; 568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mic_ctrl[2]; 578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mic[TDLS_MIC_LEN]; 588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 Anonce[WPA_NONCE_LEN]; /* Responder Nonce in TDLS */ 598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 Snonce[WPA_NONCE_LEN]; /* Initiator Nonce in TDLS */ 608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* followed by optional elements */ 618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} STRUCT_PACKED; 628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_tdls_timeoutie { 648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ie_type; /* Timeout IE */ 658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ie_len; 668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 interval_type; 678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 value[TDLS_TIMEOUT_LEN]; 688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} STRUCT_PACKED; 698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_tdls_lnkid { 718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ie_type; /* Link Identifier IE */ 728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 ie_len; 738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 bssid[ETH_ALEN]; 748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 init_sta[ETH_ALEN]; 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 resp_sta[ETH_ALEN]; 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} STRUCT_PACKED; 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* TDLS frame headers as per IEEE Std 802.11z-2010 */ 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_tdls_frame { 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 payloadtype; /* IEEE80211_TDLS_RFTYPE */ 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 category; /* Category */ 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 action; /* Action (enum tdls_frame_type) */ 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} STRUCT_PACKED; 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * wpa_add_tdls_timeoutie(u8 *pos, u8 *ie, size_t ie_len, u32 tsecs); 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_tdls_tpk_retry_timeout(void *eloop_ctx, void *timeout_ctx); 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer); 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#define TDLS_MAX_IE_LEN 80 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstruct wpa_tdls_peer { 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *next; 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int initiator; /* whether this end was initiator for TDLS setup */ 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 addr[ETH_ALEN]; /* other end MAC address */ 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 inonce[WPA_NONCE_LEN]; /* Initiator Nonce */ 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rnonce[WPA_NONCE_LEN]; /* Responder Nonce */ 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rsnie_i[TDLS_MAX_IE_LEN]; /* Initiator RSN IE */ 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rsnie_i_len; 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rsnie_p[TDLS_MAX_IE_LEN]; /* Peer RSN IE */ 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t rsnie_p_len; 1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime; 1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int cipher; /* Selected cipher (WPA_CIPHER_*) */ 1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dtoken; 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tpk { 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 kck[16]; /* TPK-KCK */ 1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 tk[16]; /* TPK-TK; assuming only CCMP will be used */ 1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } tpk; 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tpk_set; 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tpk_success; 1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct tpk_timer { 1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dest[ETH_ALEN]; 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int count; /* Retry Count */ 1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int timer; /* Timeout in milliseconds */ 1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 action_code; /* TDLS frame type */ 1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dialog_token; 1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 status_code; 1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int buf_len; /* length of TPK message for retransmission */ 1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf; /* buffer for TPK message */ 1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } sm_tmr; 1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}; 1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_get_privacy(struct wpa_sm *sm) 1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Get info needed from supplicant to check if the current BSS supports 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * security. Other than OPEN mode, rest are considered secured 1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * WEP/WPA/WPA2 hence TDLS frames are processed for TPK handshake. 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return sm->pairwise_cipher != WPA_CIPHER_NONE; 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * wpa_add_ie(u8 *pos, const u8 *ie, size_t ie_len) 1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, ie, ie_len); 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos + ie_len; 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_del_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer) 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_set_key(sm, WPA_ALG_NONE, peer->addr, 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 0, 0, NULL, 0, NULL, 0) < 0) { 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "TDLS: Failed to delete TPK-TK from " 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "the driver"); 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_set_key(struct wpa_sm *sm, struct wpa_tdls_peer *peer) 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 key_len; 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 rsc[6]; 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt enum wpa_alg alg; 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(rsc, 0, 6); 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (peer->cipher) { 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_CCMP: 1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt alg = WPA_ALG_CCMP; 1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_len = 16; 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WPA_CIPHER_NONE: 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Pairwise Cipher Suite: " 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "NONE - do not use pairwise keys"); 1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "TDLS: Unsupported pairwise cipher %d", 1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->pairwise_cipher); 1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_sm_set_key(sm, alg, peer->addr, -1, 1, 1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsc, sizeof(rsc), peer->tpk.tk, key_len) < 0) { 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "TDLS: Failed to set TPK to the " 1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "driver"); 1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_send_tpk_msg(struct wpa_sm *sm, const u8 *dst, 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 action_code, u8 dialog_token, 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 status_code, const u8 *buf, size_t len) 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_sm_send_tdls_mgmt(sm, dst, action_code, dialog_token, 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status_code, buf, len); 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_tpk_send(struct wpa_sm *sm, const u8 *dest, u8 action_code, 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dialog_token, u16 status_code, 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *msg, size_t msg_len) 2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer; 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK send dest=" MACSTR " action_code=%u " 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dialog_token=%u status_code=%u msg_len=%u", 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(dest), action_code, dialog_token, status_code, 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (unsigned int) msg_len); 2088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_tdls_send_tpk_msg(sm, dest, action_code, dialog_token, 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status_code, msg, msg_len)) { 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Failed to send message " 2128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(action_code=%u)", action_code); 2138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (action_code == WLAN_TDLS_SETUP_CONFIRM || 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt action_code == WLAN_TDLS_TEARDOWN) 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; /* No retries */ 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peer->addr, dest, ETH_ALEN) == 0) 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer == NULL) { 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No matching entry found for " 2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "retry " MACSTR, MAC2STR(dest)); 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer); 2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.count = TPK_RETRY_COUNT; 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.timer = TPK_TIMEOUT; 2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Copy message to resend on timeout */ 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peer->sm_tmr.dest, dest, ETH_ALEN); 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.action_code = action_code; 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.dialog_token = dialog_token; 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.status_code = status_code; 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.buf_len = msg_len; 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(peer->sm_tmr.buf); 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.buf = os_malloc(msg_len); 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->sm_tmr.buf == NULL) 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peer->sm_tmr.buf, msg, msg_len); 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Retry timeout registered " 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(action_code=%u)", action_code); 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(peer->sm_tmr.timer / 1000, 0, 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_tpk_retry_timeout, sm, peer); 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_tdls_tpk_retry_timeout(void *eloop_ctx, void *timeout_ctx) 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm = eloop_ctx; 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer = timeout_ctx; 2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->sm_tmr.count) { 2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.count--; 2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.timer = TPK_TIMEOUT; 2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Retrying sending of message " 2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(action_code=%u)", 2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.action_code); 2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->sm_tmr.buf == NULL) { 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No retry buffer available " 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "for action_code=%u", 2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.action_code); 2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, 2758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer); 2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* resend TPK Handshake Message to Peer */ 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_tdls_send_tpk_msg(sm, peer->sm_tmr.dest, 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.action_code, 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.dialog_token, 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.status_code, 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.buf, 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.buf_len)) { 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Failed to retry " 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "transmission"); 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer); 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(peer->sm_tmr.timer / 1000, 0, 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_tpk_retry_timeout, sm, peer); 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "Sending Tear_Down Request"); 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_tdls_oper(sm, TDLS_TEARDOWN, peer->addr); 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "Clearing SM: Peerkey(" MACSTR ")", 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(peer->addr)); 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer); 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* clear the Peerkey statemachine */ 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_peer_free(sm, peer); 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_tdls_tpk_retry_timeout_cancel(struct wpa_sm *sm, 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer, 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 action_code) 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (action_code == peer->sm_tmr.action_code) { 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Retry timeout cancelled for " 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "action_code=%u", action_code); 3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Cancel Timeout registered */ 3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer); 3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* free all resources meant for retry */ 3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(peer->sm_tmr.buf); 3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.buf = NULL; 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.count = 0; 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.timer = 0; 3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.buf_len = 0; 3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.action_code = 0xff; 3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Error in cancelling retry timeout " 3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(Unknown action_code=%u)", action_code); 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_tdls_generate_tpk(struct wpa_tdls_peer *peer, 3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *own_addr, const u8 *bssid) 3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 key_input[SHA256_MAC_LEN]; 3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *nonce[2]; 3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t len[2]; 3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 data[3 * ETH_ALEN]; 3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* IEEE Std 802.11z-2010 8.5.9.1: 3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TPK-Key-Input = SHA-256(min(SNonce, ANonce) || max(SNonce, ANonce)) 3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[0] = WPA_NONCE_LEN; 3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len[1] = WPA_NONCE_LEN; 3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peer->inonce, peer->rnonce, WPA_NONCE_LEN) < 0) { 3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nonce[0] = peer->inonce; 3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nonce[1] = peer->rnonce; 3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nonce[0] = peer->rnonce; 3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt nonce[1] = peer->inonce; 3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: min(Nonce)", nonce[0], WPA_NONCE_LEN); 3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: max(Nonce)", nonce[1], WPA_NONCE_LEN); 3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_vector(2, nonce, len, key_input); 3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-Key-Input", 3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt key_input, SHA256_MAC_LEN); 3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TPK-Key-Data = KDF-N_KEY(TPK-Key-Input, "TDLS PMK", 3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * min(MAC_I, MAC_R) || max(MAC_I, MAC_R) || BSSID || N_KEY) 3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TODO: is N_KEY really included in KDF Context and if so, in which 3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * presentation format (little endian 16-bit?) is it used? It gets 3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * added by the KDF anyway.. 3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(own_addr, peer->addr, ETH_ALEN) < 0) { 3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data, own_addr, ETH_ALEN); 3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data + ETH_ALEN, peer->addr, ETH_ALEN); 3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data, peer->addr, ETH_ALEN); 3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data + ETH_ALEN, own_addr, ETH_ALEN); 3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(data + 2 * ETH_ALEN, bssid, ETH_ALEN); 3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: KDF Context", data, sizeof(data)); 3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sha256_prf(key_input, SHA256_MAC_LEN, "TDLS PMK", data, sizeof(data), 3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) &peer->tpk, sizeof(peer->tpk)); 3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-KCK", 3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->tpk.kck, sizeof(peer->tpk.kck)); 3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "TDLS: TPK-TK", 3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->tpk.tk, sizeof(peer->tpk.tk)); 3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->tpk_set = 1; 3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_tdls_ftie_mic - Calculate TDLS FTIE MIC 3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @kck: TPK-KCK 3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @lnkid: Pointer to the beginning of Link Identifier IE 3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @rsnie: Pointer to the beginning of RSN IE used for handshake 3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @timeoutie: Pointer to the beginning of Timeout IE used for handshake 3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ftie: Pointer to the beginning of FT IE 3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mic: Pointer for writing MIC 3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Calculate MIC for TDLS frame. 3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_ftie_mic(const u8 *kck, u8 trans_seq, const u8 *lnkid, 3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *rsnie, const u8 *timeoutie, 4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ftie, u8 *mic) 4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *pos; 4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *_ftie; 4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_tdls_lnkid *_lnkid; 4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int len = 2 * ETH_ALEN + 1 + 2 + lnkid[1] + 2 + rsnie[1] + 4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2 + timeoutie[1] + 2 + ftie[1]; 4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_zalloc(len); 4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!buf) { 4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "TDLS: No memory for MIC calculation"); 4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _lnkid = (const struct wpa_tdls_lnkid *) lnkid; 4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1) TDLS initiator STA MAC address */ 4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, _lnkid->init_sta, ETH_ALEN); 4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ETH_ALEN; 4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2) TDLS responder STA MAC address */ 4208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, _lnkid->resp_sta, ETH_ALEN); 4218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += ETH_ALEN; 4228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3) Transaction Sequence number */ 4238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = trans_seq; 4248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4) Link Identifier IE */ 4258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, lnkid, 2 + lnkid[1]); 4268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + lnkid[1]; 4278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 5) RSN IE */ 4288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, rsnie, 2 + rsnie[1]); 4298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + rsnie[1]; 4308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 6) Timeout Interval IE */ 4318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, timeoutie, 2 + timeoutie[1]); 4328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + timeoutie[1]; 4338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7) FTIE, with the MIC field of the FTIE set to 0 */ 4348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, ftie, 2 + ftie[1]); 4358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _ftie = (struct wpa_tdls_ftie *) pos; 4368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(_ftie->mic, 0, TDLS_MIC_LEN); 4378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + ftie[1]; 4388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Data for FTIE MIC", buf, pos - buf); 4408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "TDLS: KCK", kck, 16); 4418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = omac1_aes_128(kck, buf, pos - buf, mic); 4428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 4438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: FTIE MIC", mic, 16); 4448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 4458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 4498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_tdls_key_mic_teardown - Calculate TDLS FTIE MIC for Teardown frame 4508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @kck: TPK-KCK 4518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @trans_seq: Transaction Sequence Number (4 - Teardown) 4528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @rcode: Reason code for Teardown 4538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dtoken: Dialog Token used for that particular link 4548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @lnkid: Pointer to the beginning of Link Identifier IE 4558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @ftie: Pointer to the beginning of FT IE 4568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @mic: Pointer for writing MIC 4578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 4588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Calculate MIC for TDLS frame. 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_key_mic_teardown(const u8 *kck, u8 trans_seq, u16 rcode, 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dtoken, const u8 *lnkid, 4628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *ftie, u8 *mic) 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *buf, *pos; 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *_ftie; 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 4678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int len; 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (lnkid == NULL) 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt len = 2 + lnkid[1] + sizeof(rcode) + sizeof(dtoken) + 4738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(trans_seq) + 2 + ftie[1]; 4748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf = os_zalloc(len); 4768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!buf) { 4778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "TDLS: No memory for MIC calculation"); 4788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 4828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1) Link Identifier IE */ 4838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, lnkid, 2 + lnkid[1]); 4848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + lnkid[1]; 4858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 2) Reason Code */ 4868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(pos, rcode); 4878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += sizeof(rcode); 4888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 3) Dialog token */ 4898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = dtoken; 4908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 4) Transaction Sequence number */ 4918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = trans_seq; 4928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7) FTIE, with the MIC field of the FTIE set to 0 */ 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, ftie, 2 + ftie[1]); 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt _ftie = (struct wpa_tdls_ftie *) pos; 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(_ftie->mic, 0, TDLS_MIC_LEN); 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 + ftie[1]; 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Data for FTIE MIC", buf, pos - buf); 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump_key(MSG_DEBUG, "TDLS: KCK", kck, 16); 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = omac1_aes_128(kck, buf, pos - buf, mic); 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(buf); 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: FTIE MIC", mic, 16); 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_verify_tdls_mic(u8 trans_seq, 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer, 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *lnkid, const u8 *timeoutie, 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_tdls_ftie *ftie) 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mic[16]; 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->tpk_set) { 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_ftie_mic(peer->tpk.kck, trans_seq, lnkid, 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_p, timeoutie, (u8 *) ftie, 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mic); 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(mic, ftie->mic, 16) != 0) { 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Invalid MIC in FTIE - " 5208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dropping packet"); 5218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Received MIC", 5228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->mic, 16); 5238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Calculated MIC", 5248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mic, 16); 5258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_WARNING, "TDLS: Could not verify TDLS MIC, " 5298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK not set - dropping packet"); 5308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_supplicant_verify_tdls_mic_teardown( 5378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 trans_seq, u16 rcode, u8 dtoken, struct wpa_tdls_peer *peer, 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *lnkid, const struct wpa_tdls_ftie *ftie) 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 mic[16]; 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->tpk_set) { 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_key_mic_teardown(peer->tpk.kck, trans_seq, rcode, 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dtoken, lnkid, (u8 *) ftie, mic); 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(mic, ftie->mic, 16) != 0) { 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Invalid MIC in Teardown - " 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "dropping packet"); 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Could not verify TDLS Teardown " 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "MIC, TPK not set - dropping packet"); 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_tdls_tpk_timeout(void *eloop_ctx, void *timeout_ctx) 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm = eloop_ctx; 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer = timeout_ctx; 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * On TPK lifetime expiration, we have an option of either tearing down 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the direct link or trying to re-initiate it. The selection of what 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * to do is not strictly speaking controlled by our role in the expired 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * link, but for now, use that to select whether to renew or tear down 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the link. 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->initiator) { 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime expired for " MACSTR 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " - try to renew", MAC2STR(peer->addr)); 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_start(sm, peer->addr); 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime expired for " MACSTR 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " - tear down", MAC2STR(peer->addr)); 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_tdls_oper(sm, TDLS_TEARDOWN, peer->addr); 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_tdls_peer_free(struct wpa_sm *sm, struct wpa_tdls_peer *peer) 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Clear state for peer " MACSTR, 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(peer->addr)); 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer); 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_tdls_tpk_retry_timeout, sm, peer); 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->initiator = 0; 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(peer->sm_tmr.buf); 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->sm_tmr.buf = NULL; 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_i_len = peer->rsnie_p_len = 0; 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->cipher = 0; 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->tpk_set = peer->tpk_success = 0; 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(&peer->tpk, 0, sizeof(peer->tpk)); 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(peer->inonce, 0, WPA_NONCE_LEN); 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(peer->rnonce, 0, WPA_NONCE_LEN); 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_tdls_linkid(struct wpa_sm *sm, struct wpa_tdls_peer *peer, 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_lnkid *lnkid) 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lnkid->ie_type = WLAN_EID_LINK_ID; 6068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lnkid->ie_len = 3 * ETH_ALEN; 6078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(lnkid->bssid, sm->bssid, ETH_ALEN); 6088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->initiator) { 6098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(lnkid->init_sta, sm->own_addr, ETH_ALEN); 6108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(lnkid->resp_sta, peer->addr, ETH_ALEN); 6118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 6128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(lnkid->init_sta, peer->addr, ETH_ALEN); 6138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(lnkid->resp_sta, sm->own_addr, ETH_ALEN); 6148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_tdls_recv_teardown_notify(struct wpa_sm *sm, const u8 *addr, 6198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 reason_code) 6208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 6218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer; 6228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *ftie; 6238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_lnkid lnkid; 6248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dialog_token; 6258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rbuf, *pos; 6268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ielen; 6278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->tdls_disabled) 6298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Find the node and free from the list */ 6328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 6338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0) 6348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 6358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer == NULL) { 6388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No matching entry found for " 6398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Teardown " MACSTR, MAC2STR(addr)); 6408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dialog_token = peer->dtoken; 6448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TDLS Teardown for " MACSTR, 6468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(addr)); 6478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ielen = 0; 6498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_tdls_get_privacy(sm) && peer->tpk_set && peer->tpk_success) { 6508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* To add FTIE for Teardown request and compute MIC */ 6518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ielen += sizeof(*ftie); 6528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 6538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_LONG_FRAME) 6548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ielen += 170; 6558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 6568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = os_zalloc(ielen + 1); 6598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) 6608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 6618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = rbuf; 6628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success) 6648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_ies; 6658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie = (struct wpa_tdls_ftie *) pos; 6678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION; 6688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Using the recent nonce which should be for CONFIRM frame */ 6698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN); 6708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN); 6718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2; 6728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (ftie + 1); 6738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 6748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_LONG_FRAME) { 6758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to " 6768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FTIE"); 6778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_len += 170; 6788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 255; /* FTIE subelem */ 6798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 168; /* FTIE subelem length */ 6808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 6828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TDLS Teardown handshake", 6838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) ftie, sizeof(*ftie)); 6848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* compute MIC before sending */ 6868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_linkid(sm, peer, &lnkid); 6878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_key_mic_teardown(peer->tpk.kck, 4, reason_code, 6888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dialog_token, (u8 *) &lnkid, (u8 *) ftie, 6898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->mic); 6908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_ies: 6928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: register for a Timeout handler, if Teardown is not received at 6938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * the other end, then try again another time */ 6948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* request driver to send Teardown using this FTIE */ 6968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_tpk_send(sm, addr, WLAN_TDLS_TEARDOWN, 0, 6978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED, rbuf, 6988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos - rbuf); 6998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rbuf); 7008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* clear the Peerkey statemachine */ 7028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_peer_free(sm, peer); 7038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_recv_teardown(struct wpa_sm *sm, const u8 *src_addr, 7098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 7108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer = NULL; 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *ftie; 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_lnkid *lnkid; 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 reason_code; 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ielen; 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Find the node and free from the list */ 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0) 7228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 7238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer == NULL) { 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No matching entry found for " 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Teardown " MACSTR, MAC2STR(src_addr)); 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */; 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt reason_code = WPA_GET_LE16(pos); 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TDLS Teardown Request from " MACSTR 7388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " (reason code %u)", MAC2STR(src_addr), reason_code); 7398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ielen = len - (pos - buf); /* start of IE in buf */ 7418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_parse_ies((const u8 *) pos, ielen, &kde) < 0) { 7428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Failed to parse IEs in Teardown"); 7438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) { 7478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No Link Identifier IE in TDLS " 7488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Teardown"); 7498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lnkid = (struct wpa_tdls_lnkid *) kde.lnkid; 7528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm) || !peer->tpk_set || !peer->tpk_success) 7548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_ftie; 7558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie)) { 7578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No FTIE in TDLS Teardown"); 7588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie = (struct wpa_tdls_ftie *) kde.ftie; 7628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Process MIC check to see if TDLS Teardown is right */ 7648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_verify_tdls_mic_teardown(4, reason_code, 7658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->dtoken, peer, 7668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) lnkid, ftie) < 0) { 7678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: MIC failure for TDLS " 7688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Teardown Request from " MACSTR, MAC2STR(src_addr)); 7698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 7718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_ftie: 7738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 7748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Request the driver to disable the direct link and clear associated 7758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * keys. 7768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, src_addr); 7788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* clear the Peerkey statemachine */ 7808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_peer_free(sm, peer); 7818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 7878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_tdls_send_error - To send suitable TDLS status response with 7888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * appropriate status code mentioning reason for error/failure. 7898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @dst - MAC addr of Peer station 7908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @tdls_action - TDLS frame type for which error code is sent 7918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @status - status code mentioning reason 7928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 7938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_send_error(struct wpa_sm *sm, const u8 *dst, 7958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 tdls_action, u8 dialog_token, u16 status) 7968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Sending error to " MACSTR 7988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt " (action=%u status=%u)", 7998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(dst), tdls_action, status); 8008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_tdls_tpk_send(sm, dst, tdls_action, dialog_token, status, 8018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt NULL, 0); 8028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 8038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_send_tpk_m1(struct wpa_sm *sm, 8068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer) 8078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 8088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buf_len; 8098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_timeoutie timeoutie; 8108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 rsn_capab; 8118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *ftie; 8128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rbuf, *pos, *count_pos; 8138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 count; 8148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_ie_hdr *hdr; 8158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm)) { 8178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: No security used on the link"); 8188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_i_len = 0; 8198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_rsnie; 8208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 8238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TPK Handshake Message 1: 8248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * FTIE: ANonce=0, SNonce=initiator nonce MIC=0, DataKDs=(RSNIE_I, 8258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Timeout Interval IE)) 8268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Filling RSN IE */ 8298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct rsn_ie_hdr *) peer->rsnie_i; 8308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->elem_id = WLAN_EID_RSN; 8318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(hdr->version, RSN_VERSION); 8328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (hdr + 1); 8348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED); 8358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 8368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count_pos = pos; 8378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 8388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count = 0; 8408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 8428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AES-CCMP is the default Encryption preferred for TDLS, so 8438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * RSN IE is filled only with CCMP CIPHER 8448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Note: TKIP is not used to encrypt TDLS link. 8458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Regardless of the cipher used on the AP connection, select CCMP 8478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * here. 8488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); 8508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 8518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt count++; 8528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(count_pos, count); 8548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(pos, 1); 8568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 8578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE); 8588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 8598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED; 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2; 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 8638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_ALT_RSN_IE) { 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Use alternative RSN IE for " 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "testing"); 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED; 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(pos, rsn_capab); 8708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_ALT_RSN_IE) { 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Number of PMKIDs */ 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 0x00; 8758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 0x00; 8768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 8788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->len = (pos - peer->rsnie_i) - 2; 8808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_i_len = pos - peer->rsnie_i; 8818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for TPK handshake", 8828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_i, peer->rsnie_i_len); 8838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_rsnie: 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len = 0; 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_tdls_get_privacy(sm)) 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) + 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(struct wpa_tdls_timeoutie); 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_tdls_get_privacy(sm) && 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (tdls_testing & TDLS_TESTING_LONG_FRAME)) 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len += 170; 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_DIFF_BSSID) 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len += sizeof(struct wpa_tdls_lnkid); 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = os_zalloc(buf_len + 1); 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) { 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_peer_free(sm, peer); 8998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = rbuf; 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm)) 9048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_ies; 9058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Initiator RSN IE */ 9078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_ie(pos, peer->rsnie_i, peer->rsnie_i_len); 9088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie = (struct wpa_tdls_ftie *) pos; 9108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION; 9118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2; 9128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_get_random(peer->inonce, WPA_NONCE_LEN)) { 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TDLS: Failed to get random data for initiator Nonce"); 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rbuf); 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_peer_free(sm, peer); 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Initiator Nonce for TPK handshake", 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->inonce, WPA_NONCE_LEN); 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN); 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TPK Handshake M1", 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) ftie, sizeof(struct wpa_tdls_ftie)); 9268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (ftie + 1); 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_LONG_FRAME) { 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to " 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FTIE"); 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_len += 170; 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 255; /* FTIE subelem */ 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 168; /* FTIE subelem length */ 9368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 168; 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Lifetime */ 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->lifetime = TPK_LIFETIME; 9428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_SHORT_LIFETIME) { 9448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - use short TPK " 9458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "lifetime"); 9468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->lifetime = 301; 9478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_LONG_LIFETIME) { 9498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - use long TPK " 9508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "lifetime"); 9518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->lifetime = 0xffffffff; 9528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 9548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie, 9558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(timeoutie), peer->lifetime); 9568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", peer->lifetime); 9578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_ies: 9598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 9618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_DIFF_BSSID) { 9628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - use incorrect BSSID in " 9638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Link Identifier"); 9648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_lnkid *l = (struct wpa_tdls_lnkid *) pos; 9658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_linkid(sm, peer, l); 9668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l->bssid[5] ^= 0x01; 9678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += sizeof(*l); 9688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 9708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Request / TPK " 9728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Handshake Message 1 (peer " MACSTR ")", 9738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(peer->addr)); 9748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_tpk_send(sm, peer->addr, WLAN_TDLS_SETUP_REQUEST, 0, 0, 9768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf, pos - rbuf); 9778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rbuf); 9788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 9808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_send_tpk_m2(struct wpa_sm *sm, 9848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, u8 dtoken, 9858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_lnkid *lnkid, 9868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_tdls_peer *peer) 9878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rbuf, *pos; 9898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buf_len; 9908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime; 9918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_timeoutie timeoutie; 9928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *ftie; 9938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len = 0; 9958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_tdls_get_privacy(sm)) { 9968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Peer RSN IE, FTIE(Initiator Nonce, Responder Nonce), 9978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Lifetime */ 9988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) + 9998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(struct wpa_tdls_timeoutie); 10008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 10018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_LONG_FRAME) 10028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len += 170; 10038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 10048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = os_zalloc(buf_len + 1); 10078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) 10088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = rbuf; 10108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm)) 10128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_ies; 10138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Peer RSN IE */ 10158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_ie(pos, peer->rsnie_p, peer->rsnie_p_len); 10168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie = (struct wpa_tdls_ftie *) pos; 10188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION; 10198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: ftie->mic_control to set 2-RESPONSE */ 10208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN); 10218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN); 10228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2; 10238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: FTIE for TPK M2", 10248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) ftie, sizeof(*ftie)); 10258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (ftie + 1); 10278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 10298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_LONG_FRAME) { 10308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to " 10318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FTIE"); 10328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_len += 170; 10338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 255; /* FTIE subelem */ 10348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 168; /* FTIE subelem length */ 10358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 168; 10368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 10388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Lifetime */ 10408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = peer->lifetime; 10418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 10428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_WRONG_LIFETIME_RESP) { 10438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong TPK " 10448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "lifetime in response"); 10458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime++; 10468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 10488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie, 10498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(timeoutie), lifetime); 10508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds from initiator", 10518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime); 10528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* compute MIC before sending */ 10548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_ftie_mic(peer->tpk.kck, 2, (u8 *) lnkid, peer->rsnie_p, 10558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) &timeoutie, (u8 *) ftie, ftie->mic); 10568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_ies: 10588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE, dtoken, 0, 10598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf, pos - rbuf); 10608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rbuf); 10618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 10638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 10648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_send_tpk_m3(struct wpa_sm *sm, 10678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const unsigned char *src_addr, u8 dtoken, 10688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_lnkid *lnkid, 10698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const struct wpa_tdls_peer *peer) 10708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 10718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *rbuf, *pos; 10728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t buf_len; 10738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *ftie; 10748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_timeoutie timeoutie; 10758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime; 10768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len = 0; 10788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_tdls_get_privacy(sm)) { 10798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Peer RSN IE, FTIE(Initiator Nonce, Responder Nonce), 10808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Lifetime */ 10818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len += peer->rsnie_i_len + sizeof(struct wpa_tdls_ftie) + 10828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(struct wpa_tdls_timeoutie); 10838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 10848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_LONG_FRAME) 10858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf_len += 170; 10868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 10878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 10888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf = os_zalloc(buf_len + 1); 10908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rbuf == NULL) 10918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 10928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = rbuf; 10938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm)) 10958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_ies; 10968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 10978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Peer RSN IE */ 10988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_ie(pos, peer->rsnie_p, peer->rsnie_p_len); 10998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie = (struct wpa_tdls_ftie *) pos; 11018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_type = WLAN_EID_FAST_BSS_TRANSITION; 11028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /*TODO: ftie->mic_control to set 3-CONFIRM */ 11038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ftie->Anonce, peer->rnonce, WPA_NONCE_LEN); 11048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(ftie->Snonce, peer->inonce, WPA_NONCE_LEN); 11058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_len = sizeof(struct wpa_tdls_ftie) - 2; 11068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (ftie + 1); 11088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 11108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_LONG_FRAME) { 11118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - add extra subelem to " 11128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "FTIE"); 11138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie->ie_len += 170; 11148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 255; /* FTIE subelem */ 11158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *pos++ = 168; /* FTIE subelem length */ 11168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 168; 11178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 11198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Lifetime */ 11218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = peer->lifetime; 11228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 11238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_WRONG_LIFETIME_CONF) { 11248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - use wrong TPK " 11258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "lifetime in confirm"); 11268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime++; 11278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 11298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = wpa_add_tdls_timeoutie(pos, (u8 *) &timeoutie, 11308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sizeof(timeoutie), lifetime); 11318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", 11328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime); 11338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* compute MIC before sending */ 11358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_ftie_mic(peer->tpk.kck, 3, (u8 *) lnkid, peer->rsnie_p, 11368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) &timeoutie, (u8 *) ftie, ftie->mic); 11378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_ies: 11398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_tpk_send(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, dtoken, 0, 11408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rbuf, pos - rbuf); 11418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(rbuf); 11428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 11448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 11458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_process_tpk_m1(struct wpa_sm *sm, const u8 *src_addr, 11488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 11498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 11508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer; 11518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 11528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data ie; 11538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int cipher; 11548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *cpos; 11558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *ftie = NULL; 11568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_timeoutie *timeoutie; 11578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_lnkid *lnkid; 11588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime = 0; 11598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 11608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct rsn_ie_hdr *hdr; 11618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 *pos; 11628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 rsn_capab; 11638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 rsn_ver; 11648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 11658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dtoken; 11668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 ielen; 11678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 status = WLAN_STATUS_UNSPECIFIED_FAILURE; 11688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tdls_prohibited = sm->tdls_prohibited; 11698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < 3 + 3) 11718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 11728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cpos = buf; 11748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cpos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */; 11758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* driver had already verified the frame format */ 11778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dtoken = *cpos++; /* dialog token */ 11788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Dialog Token in TPK M1 %d", dtoken); 11808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cpos += 2; /* capability information */ 11828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ielen = len - (cpos - buf); /* start of IE in buf */ 11848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_parse_ies(cpos, ielen, &kde) < 0) { 11858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Failed to parse IEs in TPK M1"); 11868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 11878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 11898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) { 11908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No valid Link Identifier IE in " 11918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK M1"); 11928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 11938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 11948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M1", 11958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.lnkid, kde.lnkid_len); 11968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lnkid = (struct wpa_tdls_lnkid *) kde.lnkid; 11978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) { 11988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: TPK M1 from diff BSS"); 11998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_NOT_IN_SAME_BSS; 12008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 12018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK M1 - TPK initiator " MACSTR, 12048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(src_addr)); 12058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 12078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_CONCURRENT_INIT) { 12088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 12098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0) 12108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 12118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer == NULL) { 12138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer = os_zalloc(sizeof(*peer)); 12148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer == NULL) 12158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 12168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peer->addr, src_addr, ETH_ALEN); 12178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->next = sm->tdls; 12188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->tdls = peer; 12198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing concurrent initiation of " 12218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TDLS setup - send own request"); 12228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->initiator = 1; 12238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_send_tpk_m1(sm, peer); 12248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((tdls_testing & TDLS_TESTING_IGNORE_AP_PROHIBIT) && 12278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tdls_prohibited) { 12288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - ignore AP prohibition " 12298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "on TDLS"); 12308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tdls_prohibited = 0; 12318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 12338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_prohibited) { 12358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: TDLS prohibited in this BSS"); 12368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_REQUEST_DECLINED; 12378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 12388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm)) { 12418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie) { 12428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M1 while " 12438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "security is disabled"); 12448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_SECURITY_DISABLED; 12458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 12468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_rsn; 12488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie) || 12518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.rsn_ie == NULL) { 12528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No FTIE or RSN IE in TPK M1"); 12538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_INVALID_PARAMETERS; 12548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 12558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie_len > TDLS_MAX_IE_LEN) { 12588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Too long Initiator RSN IE in " 12598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK M1"); 12608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_INVALID_RSNIE; 12618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 12628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) { 12658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Failed to parse RSN IE in TPK M1"); 12668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_INVALID_RSNIE; 12678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 12688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = ie.pairwise_cipher; 12718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cipher & WPA_CIPHER_CCMP) { 12728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Using CCMP for direct link"); 12738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = WPA_CIPHER_CCMP; 12748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 12758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No acceptable cipher in TPK M1"); 12768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; 12778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 12788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((ie.capabilities & 12818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (WPA_CAPABILITY_NO_PAIRWISE | WPA_CAPABILITY_PEERKEY_ENABLED)) != 12828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_CAPABILITY_PEERKEY_ENABLED) { 12838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Invalid RSN Capabilities in " 12848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK M1"); 12858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_INVALID_RSN_IE_CAPAB; 12868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 12878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 12898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Lifetime */ 12908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.key_lifetime == NULL) { 12918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M1"); 12928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_UNACCEPTABLE_LIFETIME; 12938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 12948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 12958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime; 12968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = WPA_GET_LE32(timeoutie->value); 12978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds", lifetime); 12988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (lifetime < 300) { 12998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Too short TPK lifetime"); 13008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_UNACCEPTABLE_LIFETIME; 13018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 13028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_rsn: 13058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Find existing entry and if found, use that instead of adding 13068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * a new one; how to handle the case where both ends initiate at the 13078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * same time? */ 13088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 13098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0) 13108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 13118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer == NULL) { 13148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No matching entry found for " 13158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "peer, creating one for " MACSTR, 13168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(src_addr)); 13178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer = os_malloc(sizeof(*peer)); 13188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer == NULL) 13198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 13208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(peer, 0, sizeof(*peer)); 13218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peer->addr, src_addr, ETH_ALEN); 13228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->next = sm->tdls; 13238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->tdls = peer; 13248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 13258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->tpk_success) { 13268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TDLS Setup Request while " 13278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "direct link is enabled - tear down the " 13288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "old link first"); 13298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 13308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: Disabling the link would be more proper 13318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * operation here, but it seems to trigger a race with 13328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * some drivers handling the new request frame. */ 13338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, src_addr); 13348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#else 13358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_del_key(sm, peer); 13368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 13378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_peer_free(sm, peer); 13388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 13418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * An entry is already present, so check if we already sent a 13428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * TDLS Setup Request. If so, compare MAC addresses and let the 13438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * STA with the lower MAC address continue as the initiator. 13448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * The other negotiation is terminated. 13458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 13468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer->initiator) { 13478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(sm->own_addr, src_addr, ETH_ALEN) < 0) { 13488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Discard request " 13498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "from peer with higher address " 13508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR, MAC2STR(src_addr)); 13518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 13528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 13538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Accept request " 13548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "from peer with lower address " 13558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MACSTR " (terminate previously " 13568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "initiated negotiation", 13578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(src_addr)); 13588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_peer_free(sm, peer); 13598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->initiator = 0; /* Need to check */ 13648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->dtoken = dtoken; 13658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm)) { 13678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_i_len = 0; 13688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_p_len = 0; 13698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->cipher = WPA_CIPHER_NONE; 13708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_rsn_check; 13718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie = (struct wpa_tdls_ftie *) kde.ftie; 13748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peer->inonce, ftie->Snonce, WPA_NONCE_LEN); 13758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peer->rsnie_i, kde.rsn_ie, kde.rsn_ie_len); 13768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_i_len = kde.rsn_ie_len; 13778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->cipher = cipher; 13788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_get_random(peer->rnonce, WPA_NONCE_LEN)) { 13808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_msg(sm->ctx->ctx, MSG_WARNING, 13818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TDLS: Failed to get random data for responder nonce"); 13828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_peer_free(sm, peer); 13838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 13848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 13858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#if 0 13878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* get version info from RSNIE received from Peer */ 13888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct rsn_ie_hdr *) kde.rsn_ie; 13898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_ver = WPA_GET_LE16(hdr->version); 13908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* use min(peer's version, out version) */ 13928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (rsn_ver > RSN_VERSION) 13938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_ver = RSN_VERSION; 13948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr = (struct rsn_ie_hdr *) peer->rsnie_p; 13968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 13978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->elem_id = WLAN_EID_RSN; 13988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(hdr->version, rsn_ver); 13998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = (u8 *) (hdr + 1); 14008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED); 14028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 14038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Include only the selected cipher in pairwise cipher suite */ 14048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(pos, 1); 14058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 14068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cipher == WPA_CIPHER_CCMP) 14078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); 14088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 14098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(pos, 1); 14118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 14128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE); 14138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += RSN_SELECTOR_LEN; 14148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_capab = WPA_CAPABILITY_PEERKEY_ENABLED; 14168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rsn_capab |= RSN_NUM_REPLAY_COUNTERS_16 << 2; 14178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE16(pos, rsn_capab); 14188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; 14198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hdr->len = (pos - peer->rsnie_p) - 2; 14218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_p_len = pos - peer->rsnie_p; 14228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif 14238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* temp fix: validation of RSNIE later */ 14258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peer->rsnie_p, peer->rsnie_i, peer->rsnie_i_len); 14268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_p_len = peer->rsnie_i_len; 14278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE for TPK handshake", 14298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_p, peer->rsnie_p_len); 14308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->lifetime = lifetime; 14328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_generate_tpk(peer, sm->own_addr, sm->bssid); 14348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_rsn_check: 14368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Response / TPK M2"); 14378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_send_tpk_m2(sm, src_addr, dtoken, lnkid, peer); 14388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 14408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterror: 14428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_RESPONSE, dtoken, 14438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status); 14448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 14458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_tdls_enable_link(struct wpa_sm *sm, struct wpa_tdls_peer *peer) 14498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->tpk_success = 1; 14518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer); 14528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_tdls_get_privacy(sm)) { 14538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime = peer->lifetime; 14548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 14558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Start the initiator process a bit earlier to avoid race 14568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * condition with the responder sending teardown request. 14578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 14588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (lifetime > 3 && peer->initiator) 14598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime -= 3; 14608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_register_timeout(lifetime, 0, wpa_tdls_tpk_timeout, 14618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, peer); 14628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 14638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_NO_TPK_EXPIRATION) { 14648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - disable TPK " 14658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "expiration"); 14668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt eloop_cancel_timeout(wpa_tdls_tpk_timeout, sm, peer); 14678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 14698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_sm_tdls_oper(sm, TDLS_ENABLE_LINK, peer->addr); 14718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 14728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_process_tpk_m2(struct wpa_sm *sm, const u8 *src_addr, 14758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 14768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 14778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer; 14788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 14798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_ie_data ie; 14808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int cipher; 14818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *ftie; 14828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_timeoutie *timeoutie; 14838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_lnkid *lnkid; 14848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime; 14858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u8 dtoken; 14868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ielen; 14878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 status; 14888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 14898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 14908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Response / TPK M2 " 14918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(Peer " MACSTR ")", MAC2STR(src_addr)); 14928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 14938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0) 14948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 14958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 14968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer == NULL) { 14978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No matching peer found for " 14988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK M2: " MACSTR, MAC2STR(src_addr)); 14998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 15008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_tpk_retry_timeout_cancel(sm, peer, WLAN_TDLS_SETUP_REQUEST); 15028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < 3 + 2 + 1) 15048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 15058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 15068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */; 15078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WPA_GET_LE16(pos); 15088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 /* status code */; 15098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (status != WLAN_STATUS_SUCCESS) { 15118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Status code in TPK M2: %u", 15128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status); 15138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 15148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_UNSPECIFIED_FAILURE; 15178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* TODO: need to verify dialog token matches here or in kernel */ 15198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt dtoken = *pos++; /* dialog token */ 15208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Dialog Token in TPK M2 %d", dtoken); 15228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < 3 + 2 + 1 + 2) 15248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 15258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2; /* capability information */ 15268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ielen = len - (pos - buf); /* start of IE in buf */ 15288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_parse_ies(pos, ielen, &kde) < 0) { 15298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Failed to parse IEs in TPK M2"); 15308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 15318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 15348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_testing & TDLS_TESTING_DECLINE_RESP) { 15358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - decline response"); 15368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_REQUEST_DECLINED; 15378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 15388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 15408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) { 15428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No valid Link Identifier IE in " 15438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK M2"); 15448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 15458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M2", 15478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.lnkid, kde.lnkid_len); 15488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lnkid = (struct wpa_tdls_lnkid *) kde.lnkid; 15498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) { 15518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: TPK M2 from different BSS"); 15528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_NOT_IN_SAME_BSS; 15538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 15548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm)) { 15578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_p_len = 0; 15588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->cipher = WPA_CIPHER_NONE; 15598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_rsn; 15608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie) || 15638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.rsn_ie == NULL) { 15648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No FTIE or RSN IE in TPK M2"); 15658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_INVALID_PARAMETERS; 15668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 15678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M2", 15698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.rsn_ie, kde.rsn_ie_len); 15708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 15728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * FIX: bitwise comparison of RSN IE is not the correct way of 15738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * validation this. It can be different, but certain fields must 15748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * match. Since we list only a single pairwise cipher in TPK M1, the 15758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * memcmp is likely to work in most cases, though. 15768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 15778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie_len != peer->rsnie_i_len || 15788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(peer->rsnie_i, kde.rsn_ie, peer->rsnie_i_len) != 0) { 15798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M2 does " 15808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not match with RSN IE used in TPK M1"); 15818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Sent in TPK M1", 15828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_i, peer->rsnie_i_len); 15838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M2", 15848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.rsn_ie, kde.rsn_ie_len); 15858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_INVALID_RSNIE; 15868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 15878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_parse_wpa_ie_rsn(kde.rsn_ie, kde.rsn_ie_len, &ie) < 0) { 15908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Failed to parse RSN IE in TPK M2"); 15918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_INVALID_RSNIE; 15928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 15938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 15948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 15958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = ie.pairwise_cipher; 15968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (cipher == WPA_CIPHER_CCMP) { 15978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Using CCMP for direct link"); 15988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt cipher = WPA_CIPHER_CCMP; 15998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 16008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No acceptable cipher in TPK M2"); 16018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; 16028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 16038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: FTIE Received from TPK M2", 16068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.ftie, sizeof(*ftie)); 16078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie = (struct wpa_tdls_ftie *) kde.ftie; 16088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) == 0) { 16108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: FTIE SNonce in TPK M2 does " 16118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not match with FTIE SNonce used in TPK M1"); 16128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Silently discard the frame */ 16138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 16148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Responder Nonce and RSN IE */ 16178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peer->rnonce, ftie->Anonce, WPA_NONCE_LEN); 16188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peer->rsnie_p, kde.rsn_ie, kde.rsn_ie_len); 16198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->rsnie_p_len = kde.rsn_ie_len; 16208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->cipher = cipher; 16218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Lifetime */ 16238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.key_lifetime == NULL) { 16248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M2"); 16258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_UNACCEPTABLE_LIFETIME; 16268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 16278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime; 16298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = WPA_GET_LE32(timeoutie->value); 16308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds in TPK M2", 16318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime); 16328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (lifetime != peer->lifetime) { 16338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Unexpected TPK lifetime %u in " 16348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK M2 (expected %u)", lifetime, peer->lifetime); 16358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WLAN_STATUS_UNACCEPTABLE_LIFETIME; 16368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto error; 16378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_generate_tpk(peer, sm->own_addr, sm->bssid); 16408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Process MIC check to see if TPK M2 is right */ 16428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_verify_tdls_mic(2, peer, (u8 *) lnkid, 16438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) timeoutie, ftie) < 0) { 16448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Discard the frame */ 16458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_del_key(sm, peer); 16468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_peer_free(sm, peer); 16478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 16488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_set_key(sm, peer); 16518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_rsn: 16538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->dtoken = dtoken; 16548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Confirm / " 16568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK Handshake Message 3"); 16578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_send_tpk_m3(sm, src_addr, dtoken, lnkid, peer); 16588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_enable_link(sm, peer); 16608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 16628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidterror: 16648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_send_error(sm, src_addr, WLAN_TDLS_SETUP_CONFIRM, dtoken, 16658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status); 16668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 16678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 16688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_process_tpk_m3(struct wpa_sm *sm, const u8 *src_addr, 16718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 16728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 16738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer; 16748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse kde; 16758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_ftie *ftie; 16768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_timeoutie *timeoutie; 16778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_lnkid *lnkid; 16788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ielen; 16798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 status; 16808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *pos; 16818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u32 lifetime; 16828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Received TDLS Setup Confirm / TPK M3 " 16848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(Peer " MACSTR ")", MAC2STR(src_addr)); 16858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 16868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peer->addr, src_addr, ETH_ALEN) == 0) 16878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 16888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer == NULL) { 16908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No matching peer found for " 16918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK M3: " MACSTR, MAC2STR(src_addr)); 16928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 16938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 16948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_tpk_retry_timeout_cancel(sm, peer, WLAN_TDLS_SETUP_RESPONSE); 16958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 16968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < 3 + 3) 16978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 16988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos = buf; 16998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 1 /* pkt_type */ + 1 /* Category */ + 1 /* Action */; 17008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status = WPA_GET_LE16(pos); 17028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (status != 0) { 17048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Status code in TPK M3: %u", 17058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt status); 17068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pos += 2 /* status code */ + 1 /* dialog token */; 17098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ielen = len - (pos - buf); /* start of IE in buf */ 17118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_parse_ies((const u8 *) pos, ielen, &kde) < 0) { 17128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Failed to parse KDEs in TPK M3"); 17138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.lnkid == NULL || kde.lnkid_len < 3 * ETH_ALEN) { 17178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No Link Identifier IE in TPK M3"); 17188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Link ID Received from TPK M3", 17218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) kde.lnkid, kde.lnkid_len); 17228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lnkid = (struct wpa_tdls_lnkid *) kde.lnkid; 17238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(sm->bssid, lnkid->bssid, ETH_ALEN) != 0) { 17258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: TPK M3 from diff BSS"); 17268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!wpa_tdls_get_privacy(sm)) 17308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt goto skip_rsn; 17318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.ftie == NULL || kde.ftie_len < sizeof(*ftie)) { 17338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No FTIE in TPK M3"); 17348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: FTIE Received from TPK M3", 17378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.ftie, sizeof(*ftie)); 17388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ftie = (struct wpa_tdls_ftie *) kde.ftie; 17398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie == NULL) { 17418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No RSN IE in TPK M3"); 17428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: RSN IE Received from TPK M3", 17458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt kde.rsn_ie, kde.rsn_ie_len); 17468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.rsn_ie_len != peer->rsnie_p_len || 17478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcmp(kde.rsn_ie, peer->rsnie_p, peer->rsnie_p_len) != 0) { 17488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: RSN IE in TPK M3 does not match " 17498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "with the one sent in TPK M2"); 17508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!os_memcmp(peer->rnonce, ftie->Anonce, WPA_NONCE_LEN) == 0) { 17548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: FTIE ANonce in TPK M3 does " 17558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "not match with FTIE ANonce used in TPK M2"); 17568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!os_memcmp(peer->inonce, ftie->Snonce, WPA_NONCE_LEN) == 0) { 17608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: FTIE SNonce in TPK M3 does not " 17618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "match with FTIE SNonce used in TPK M1"); 17628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (kde.key_lifetime == NULL) { 17668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No Key Lifetime IE in TPK M3"); 17678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt timeoutie = (struct wpa_tdls_timeoutie *) kde.key_lifetime; 17708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Timeout IE Received from TPK M3", 17718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) timeoutie, sizeof(*timeoutie)); 17728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime = WPA_GET_LE32(timeoutie->value); 17738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TPK lifetime %u seconds in TPK M3", 17748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime); 17758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (lifetime != peer->lifetime) { 17768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Unexpected TPK lifetime %u in " 17778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "TPK M3 (expected %u)", lifetime, peer->lifetime); 17788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_verify_tdls_mic(3, peer, (u8 *) lnkid, 17828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (u8 *) timeoutie, ftie) < 0) { 17838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_del_key(sm, peer); 17848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_peer_free(sm, peer); 17858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 17878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_tdls_set_key(sm, peer) < 0) 17898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 17908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtskip_rsn: 17928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_enable_link(sm, peer); 17938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 17958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 17968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 17988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic u8 * wpa_add_tdls_timeoutie(u8 *pos, u8 *ie, size_t ie_len, u32 tsecs) 17998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_timeoutie *lifetime = (struct wpa_tdls_timeoutie *) ie; 18018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(lifetime, 0, ie_len); 18038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime->ie_type = WLAN_EID_TIMEOUT_INTERVAL; 18048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime->ie_len = sizeof(struct wpa_tdls_timeoutie) - 2; 18058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt lifetime->interval_type = WLAN_TIMEOUT_KEY_LIFETIME; 18068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt WPA_PUT_LE32(lifetime->value, tsecs); 18078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(pos, ie, ie_len); 18088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return pos + ie_len; 18098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 18138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_tdls_start - Initiate TDLS handshake (send TPK Handshake Message 1) 18148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @sm: Pointer to WPA state machine data from wpa_sm_init() 18158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @peer: MAC address of the peer STA 18168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, or -1 on failure 18178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 18188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Send TPK Handshake Message 1 info to driver to start TDLS 18198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * handshake with the peer. 18208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 18218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_tdls_start(struct wpa_sm *sm, const u8 *addr) 18228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer; 18248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int tdls_prohibited = sm->tdls_prohibited; 18258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->tdls_disabled) 18278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 18288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_TDLS_TESTING 18308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((tdls_testing & TDLS_TESTING_IGNORE_AP_PROHIBIT) && 18318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tdls_prohibited) { 18328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Testing - ignore AP prohibition " 18338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "on TDLS"); 18348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tdls_prohibited = 0; 18358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_TDLS_TESTING */ 18378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tdls_prohibited) { 18398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TDLS is prohibited in this BSS - " 18408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "reject request to start setup"); 18418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 18428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Find existing entry and if found, use that instead of adding 18458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * a new one */ 18468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 18478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0) 18488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 18498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer == NULL) { 18528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: No matching entry found for " 18538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "peer, creating one for " MACSTR, MAC2STR(addr)); 18548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer = os_malloc(sizeof(*peer)); 18558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer == NULL) 18568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 18578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(peer, 0, sizeof(*peer)); 18588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memcpy(peer->addr, addr, ETH_ALEN); 18598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->next = sm->tdls; 18608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->tdls = peer; 18618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer->initiator = 1; 18648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_tdls_send_tpk_m1(sm, peer); 18668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_tdls_reneg(struct wpa_sm *sm, const u8 *addr) 18708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer; 18728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->tdls_disabled) 18748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 18758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (peer = sm->tdls; peer; peer = peer->next) { 18778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0) 18788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 18798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 18808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (peer == NULL || !peer->tpk_success) 18828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 18838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return wpa_tdls_start(sm, addr); 18858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 18868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 18898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_supplicant_rx_tdls - Receive TDLS data frame 18908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 18918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called to receive TDLS (ethertype = 0x890d) data frames. 18928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 18938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_supplicant_rx_tdls(void *ctx, const u8 *src_addr, 18948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt const u8 *buf, size_t len) 18958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 18968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_sm *sm = ctx; 18978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_frame *tf; 18988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 18998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_hexdump(MSG_DEBUG, "TDLS: Received Data frame encapsulation", 19008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt buf, len); 19018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->tdls_disabled) { 19038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Discard message - TDLS disabled"); 19048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 19058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (os_memcmp(src_addr, sm->own_addr, ETH_ALEN) == 0) { 19088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Discard copy of own message"); 19098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 19108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (len < sizeof(*tf)) { 19138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Drop too short frame"); 19148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 19158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Check to make sure its a valid encapsulated TDLS frame */ 19188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tf = (struct wpa_tdls_frame *) buf; 19198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (tf->payloadtype != 2 /* TDLS_RFTYPE */ || 19208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tf->category != WLAN_ACTION_TDLS) { 19218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "TDLS: Invalid frame - payloadtype=%u " 19228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "category=%u action=%u", 19238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tf->payloadtype, tf->category, tf->action); 19248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 19258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (tf->action) { 19288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WLAN_TDLS_SETUP_REQUEST: 19298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_process_tpk_m1(sm, src_addr, buf, len); 19308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 19318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WLAN_TDLS_SETUP_RESPONSE: 19328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_process_tpk_m2(sm, src_addr, buf, len); 19338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 19348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WLAN_TDLS_SETUP_CONFIRM: 19358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_process_tpk_m3(sm, src_addr, buf, len); 19368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 19378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case WLAN_TDLS_TEARDOWN: 19388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_recv_teardown(sm, src_addr, buf, len); 19398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 19408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 19418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Kernel code will process remaining frames */ 19428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Ignore TDLS frame action code %u", 19438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tf->action); 19448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 19458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 19508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_tdls_init - Initialize driver interface parameters for TDLS 19518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @wpa_s: Pointer to wpa_supplicant data 19528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure 19538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 19548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called to initialize driver interface parameters for TDLS. 19558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_drv_init() must have been called before this function to initialize the 19568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * driver interface. 19578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 19588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wpa_tdls_init(struct wpa_sm *sm) 19598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 19618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 19628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->l2_tdls = l2_packet_init(sm->ifname, sm->own_addr, 19648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ETH_P_80211_ENCAP, wpa_supplicant_rx_tdls, 19658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm, 0); 19668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->l2_tdls == NULL) { 19678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "TDLS: Failed to open l2_packet " 19688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "connection"); 19698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 19708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 19738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void wpa_tdls_remove_peers(struct wpa_sm *sm) 19778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 19788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_tdls_peer *peer, *tmp; 19798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer = sm->tdls; 19818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->tdls = NULL; 19828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt while (peer) { 19848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 19858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt tmp = peer->next; 19868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = wpa_sm_tdls_oper(sm, TDLS_DISABLE_LINK, peer->addr); 19878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Remove peer " MACSTR " (res=%d)", 19888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt MAC2STR(peer->addr), res); 19898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_peer_free(sm, peer); 19908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(peer); 19918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt peer = tmp; 19928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 19938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 19948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 19968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 19978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * wpa_tdls_deinit - Deinitialize driver interface parameters for TDLS 19988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 19998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * This function is called to recover driver interface parameters for TDLS 20008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * and frees resources allocated for it. 20018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 20028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_tdls_deinit(struct wpa_sm *sm) 20038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm == NULL) 20058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 20068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (sm->l2_tdls) 20088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt l2_packet_deinit(sm->l2_tdls); 20098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->l2_tdls = NULL; 20108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_remove_peers(sm); 20128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_tdls_assoc(struct wpa_sm *sm) 20168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Remove peers on association"); 20188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_remove_peers(sm); 20198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_tdls_disassoc(struct wpa_sm *sm) 20238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: Remove peers on disassociation"); 20258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_tdls_remove_peers(sm); 20268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wpa_tdls_prohibited(const u8 *ies, size_t len) 20308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_eapol_ie_parse elems; 20328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ies == NULL) 20348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 20358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (wpa_supplicant_parse_ies(ies, len, &elems) < 0) 20378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 20388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (elems.ext_capab == NULL || elems.ext_capab_len < 2 + 5) 20408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 20418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* bit 38 - TDLS Prohibited */ 20438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return !!(elems.ext_capab[2 + 4] & 0x40); 20448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_tdls_ap_ies(struct wpa_sm *sm, const u8 *ies, size_t len) 20488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->tdls_prohibited = wpa_tdls_prohibited(ies, len); 20508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TDLS is %s in the target BSS", 20518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->tdls_prohibited ? "prohibited" : "allowed"); 20528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_tdls_assoc_resp_ies(struct wpa_sm *sm, const u8 *ies, size_t len) 20568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!sm->tdls_prohibited && wpa_tdls_prohibited(ies, len)) { 20588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: TDLS prohibited based on " 20598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "(Re)Association Response IEs"); 20608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->tdls_prohibited = 1; 20618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 20628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 20638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 20658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wpa_tdls_enable(struct wpa_sm *sm, int enabled) 20668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 20678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "TDLS: %s", enabled ? "enabled" : "disabled"); 20688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt sm->tdls_disabled = !enabled; 20698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2070